From be04ef844d441c00ff46b9e22ff5ab633ac0fb0b Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Fri, 4 Aug 2023 15:23:13 +0100 Subject: [PATCH 001/577] chore: Start V2 branch (#1346) * Initial commit * Add warning --- README.md | 4 +- docs/utilities/large_messages.md | 6 - docs/utilities/sqs_batch.md | 489 ------------- docs/utilities/sqs_large_message_handling.md | 296 -------- examples/pom.xml | 1 - examples/powertools-examples-sqs/README.md | 56 -- .../powertools-examples-sqs/events/event.json | 63 -- examples/powertools-examples-sqs/pom.xml | 196 ------ .../java/org/demo/sqs/SqsMessageSender.java | 92 --- .../src/main/java/org/demo/sqs/SqsPoller.java | 76 -- .../src/main/resources/log4j2.xml | 16 - .../powertools-examples-sqs/template.yaml | 148 ---- mkdocs.yml | 3 - pom.xml | 2 - powertools-sqs/pom.xml | 144 ---- .../sqs/SQSBatchProcessingException.java | 93 --- .../lambda/powertools/sqs/SqsBatch.java | 104 --- .../powertools/sqs/SqsLargeMessage.java | 85 --- .../powertools/sqs/SqsMessageHandler.java | 44 -- .../lambda/powertools/sqs/SqsUtils.java | 653 ------------------ ...ippedMessageDueToFailedBatchException.java | 26 - .../powertools/sqs/internal/BatchContext.java | 281 -------- .../sqs/internal/SqsLargeMessageAspect.java | 170 ----- .../SqsMessageBatchProcessorAspect.java | 55 -- .../powertools/sqs/SampleSqsHandler.java | 26 - .../sqs/SqsUtilsBatchProcessorTest.java | 386 ----------- .../sqs/SqsUtilsFifoBatchProcessorTest.java | 188 ----- .../sqs/SqsUtilsLargeMessageTest.java | 228 ------ .../sqs/handlers/LambdaHandlerApiGateway.java | 32 - .../PartialBatchFailureSuppressedHandler.java | 46 -- .../PartialBatchPartialFailureHandler.java | 46 -- .../handlers/PartialBatchSuccessHandler.java | 42 -- .../sqs/handlers/SqsMessageHandler.java | 29 - ...MessageHandlerWithNonRetryableHandler.java | 52 -- ...dlerWithNonRetryableHandlerWithDelete.java | 53 -- .../handlers/SqsNoDeleteMessageHandler.java | 29 - .../internal/SqsLargeMessageAspectTest.java | 222 ------ .../SqsMessageBatchProcessorAspectTest.java | 331 --------- .../src/test/resources/SqsFifoBatchEvent.json | 73 -- .../test/resources/sampleSqsBatchEvent.json | 36 - .../sampleSqsBatchEventBatchSize25.json | 404 ----------- .../resources/threeMessageSqsBatchEvent.json | 70 -- powertools-test-suite/pom.xml | 164 ----- .../testsuite/LoggingOrderTest.java | 193 ------ .../handler/LoggingOrderMessageHandler.java | 31 - .../TracingLoggingStreamMessageHandler.java | 36 - .../src/test/resources/log4j2.xml | 20 - 47 files changed, 3 insertions(+), 5837 deletions(-) delete mode 100644 docs/utilities/sqs_batch.md delete mode 100644 docs/utilities/sqs_large_message_handling.md delete mode 100644 examples/powertools-examples-sqs/README.md delete mode 100644 examples/powertools-examples-sqs/events/event.json delete mode 100644 examples/powertools-examples-sqs/pom.xml delete mode 100644 examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsMessageSender.java delete mode 100644 examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsPoller.java delete mode 100644 examples/powertools-examples-sqs/src/main/resources/log4j2.xml delete mode 100644 examples/powertools-examples-sqs/template.yaml delete mode 100644 powertools-sqs/pom.xml delete mode 100644 powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SQSBatchProcessingException.java delete mode 100644 powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsBatch.java delete mode 100644 powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java delete mode 100644 powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsMessageHandler.java delete mode 100644 powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java delete mode 100644 powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/exception/SkippedMessageDueToFailedBatchException.java delete mode 100644 powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java delete mode 100644 powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspect.java delete mode 100644 powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspect.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SampleSqsHandler.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsFifoBatchProcessorTest.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsLargeMessageTest.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/LambdaHandlerApiGateway.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchFailureSuppressedHandler.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchPartialFailureHandler.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchSuccessHandler.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandler.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandler.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandlerWithDelete.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsNoDeleteMessageHandler.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspectTest.java delete mode 100644 powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java delete mode 100644 powertools-sqs/src/test/resources/SqsFifoBatchEvent.json delete mode 100644 powertools-sqs/src/test/resources/sampleSqsBatchEvent.json delete mode 100644 powertools-sqs/src/test/resources/sampleSqsBatchEventBatchSize25.json delete mode 100644 powertools-sqs/src/test/resources/threeMessageSqsBatchEvent.json delete mode 100644 powertools-test-suite/pom.xml delete mode 100644 powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/LoggingOrderTest.java delete mode 100644 powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/LoggingOrderMessageHandler.java delete mode 100644 powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/TracingLoggingStreamMessageHandler.java delete mode 100644 powertools-test-suite/src/test/resources/log4j2.xml diff --git a/README.md b/README.md index 70cfab314..47fb59bd7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# Powertools for AWS Lambda (Java) +# Powertools for AWS Lambda (Java) V2 + +**This is pre-release code for Powertools for AWS Lambda (Java) V2! Please check out the `main` branch for the stable release** ![aws provider](https://img.shields.io/badge/provider-AWS-orange?logo=amazon-aws&color=ff9900) ![Build status](https://github.com/aws-powertools/powertools-lambda-java/actions/workflows/build.yml/badge.svg) ![Maven Central](https://img.shields.io/maven-central/v/software.amazon.lambda/powertools-parent) [![codecov.io](https://codecov.io/github/aws-powertools/powertools-lambda-java/branch/main/graphs/badge.svg)](https://app.codecov.io/gh/aws-powertools/powertools-lambda-java) diff --git a/docs/utilities/large_messages.md b/docs/utilities/large_messages.md index c4947a6e8..c0c1cd599 100644 --- a/docs/utilities/large_messages.md +++ b/docs/utilities/large_messages.md @@ -6,12 +6,6 @@ description: Utility The large message utility handles SQS and SNS messages which have had their payloads offloaded to S3 if they are larger than the maximum allowed size (256 KB). -!!! Notice - The large message utility (available in the `powertools-sqs` module for versions v1.16.1 and earlier) is now deprecated - and replaced by the `powertools-large-messages` described in this page. - You can still get the documentation [here](sqs_large_message_handling.md) - and the migration guide [here](#migration-from-the-sqs-large-message-utility). - ## Features - Automatically retrieve the content of S3 objects when SQS or SNS messages have been offloaded to S3. diff --git a/docs/utilities/sqs_batch.md b/docs/utilities/sqs_batch.md deleted file mode 100644 index 658f7b085..000000000 --- a/docs/utilities/sqs_batch.md +++ /dev/null @@ -1,489 +0,0 @@ ---- -title: SQS Batch Processing (Deprecated) -description: Utility ---- - -!!! warning - The SQS batch module is now deprecated and will be removed in v2 of the library. Use the [batch module](batch.md), - and check out **[migrating to the batch library](#migrating-to-the-batch-library)** for migration instructions. - -The SQS batch processing utility provides a way to handle partial failures when processing batches of messages from SQS. -The utility handles batch processing for both -[standard](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/standard-queues.html) and -[FIFO](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/FIFO-queues.html) SQS queues. - -**Key Features** - -* Prevent successfully processed messages from being returned to SQS -* A simple interface for individually processing messages from a batch - -**Background** - -When using SQS as a Lambda event source mapping, Lambda functions can be triggered with a batch of messages from SQS. -If your function fails to process any message from the batch, the entire batch returns to your SQS queue, and your -Lambda function will be triggered with the same batch again. With this utility, messages within a batch will be handled individually - only messages that were not successfully processed -are returned to the queue. - -!!! warning - While this utility lowers the chance of processing messages more than once, it is not guaranteed. We recommend implementing processing logic in an idempotent manner wherever possible. - More details on how Lambda works with SQS can be found in the [AWS documentation](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html) - -## Install - -Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. - -=== "Maven Java 11+" - - ```xml hl_lines="3-7 16 18 24-27"" - - ... - - software.amazon.lambda - powertools-sqs - {{ powertools.version }} - - ... - - ... - - - - ... - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - 11 - 11 - 11 - - - software.amazon.lambda - powertools-sqs - - - - - - - compile - - - - - ... - - - ``` - -=== "Maven Java 1.8" - - ```xml hl_lines="3-7 16 18 24-27" - - ... - - software.amazon.lambda - powertools-sqs - {{ powertools.version }} - - ... - - ... - - - - ... - - org.codehaus.mojo - aspectj-maven-plugin - 1.14.0 - - 1.8 - 1.8 - 1.8 - - - software.amazon.lambda - powertools-sqs - - - - - - - compile - - - - - ... - - - ``` - -=== "Gradle Java 11+" - - ```groovy hl_lines="3 11" - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' - } - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-sqs:{{ powertools.version }}' - } - - sourceCompatibility = 11 // or higher - targetCompatibility = 11 // or higher - ``` - -=== "Gradle Java 1.8" - - ```groovy hl_lines="3 11" - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' - } - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-sqs:{{ powertools.version }}' - } - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - ``` - -## IAM Permissions - -This utility requires additional permissions to work as expected. Lambda functions using this utility require the `sqs:DeleteMessageBatch` permission. - -If you are also using [nonRetryableExceptions](#move-non-retryable-messages-to-a-dead-letter-queue) attribute, utility will need additional permission of `sqs:GetQueueAttributes` on source SQS. -It also needs `sqs:SendMessage` and `sqs:SendMessageBatch` on configured dead letter queue. - -If source or dead letter queue is configured to use encryption at rest using [AWS Key Management Service (KMS)](https://aws.amazon.com/kms/), function will need additional permissions of -`kms:GenerateDataKey` and `kms:Decrypt` on the KMS key being used for encryption. Refer [docs](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-key-management.html#compatibility-with-aws-services) for more details. - -Refer [example project](https://github.com/aws-samples/aws-lambda-powertools-examples/blob/main/java/SqsBatchProcessing/template.yaml#L105) for policy details example. - - -## Processing messages from SQS - -You can use either **[SqsBatch annotation](#sqsbatch-annotation)**, or **[SqsUtils Utility API](#sqsutils-utility-api)** as a fluent API. - -Both have nearly the same behaviour when it comes to processing messages from the batch: - -* **Entire batch has been successfully processed**, where your Lambda handler returned successfully, we will let SQS delete the batch to optimize your cost -* **Entire Batch has been partially processed successfully**, where exceptions were raised within your `SqsMessageHandler` interface implementation, we will: - - **1)** Delete successfully processed messages from the queue by directly calling `sqs:DeleteMessageBatch` - - **2)** If a message with a [message group ID](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/using-messagegroupid-property.html) fails, - the processing of the batch will be stopped and the remainder of the messages will be returned to SQS. - This behaviour [is required to handle SQS FIFO queues](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting). - - **3)** if non retryable exceptions occur, messages resulting in configured exceptions during processing will be immediately moved to the dead letter queue associated to the source SQS queue or deleted from the source SQS queue if `deleteNonRetryableMessageFromQueue` is set to `true`. - - **4)** Raise `SQSBatchProcessingException` to ensure failed messages return to your SQS queue - -The only difference is that **SqsUtils Utility API** will give you access to return from the processed messages if you need. Exception `SQSBatchProcessingException` thrown from the -utility will have access to both successful and failed messaged along with failure exceptions. - -## Functional Interface SqsMessageHandler - -Both [annotation](#sqsbatch-annotation) and [SqsUtils Utility API](#sqsutils-utility-api) requires an implementation of functional interface `SqsMessageHandler`. - -This implementation is responsible for processing each individual message from the batch, and to raise an exception if unable to process any of the messages sent. - -**Any non-exception/successful return from your record handler function** will instruct utility to queue up each individual message for deletion. - -### SqsBatch annotation - -When using this annotation, you need provide a class implementation of `SqsMessageHandler` that will process individual messages from the batch - It should raise an exception if it is unable to process the record. - -All records in the batch will be passed to this handler for processing, even if exceptions are thrown - Here's the behaviour after completing the batch: - -* **Any successfully processed messages**, we will delete them from the queue via `sqs:DeleteMessageBatch`. -* **if, nonRetryableExceptions attribute is used**, messages resulting in configured exceptions during processing will be immediately moved to the dead letter queue associated to the source SQS queue or deleted from the source SQS queue if `deleteNonRetryableMessageFromQueue` is set to `true`. -* **Any unprocessed messages detected**, we will raise `SQSBatchProcessingException` to ensure failed messages return to your SQS queue. - -!!! warning - You will not have access to the **processed messages** within the Lambda Handler - all processing logic will and should be performed by the implemented `#!java SqsMessageHandler#process()` function. - -=== "AppSqsEvent.java" - - ```java hl_lines="7" - import software.amazon.lambda.powertools.sqs.SqsBatch; - import software.amazon.lambda.powertools.sqs.SqsMessageHandler; - import software.amazon.lambda.powertools.sqs.SqsUtils; - - public class AppSqsEvent implements RequestHandler { - @Override - @SqsBatch(SampleMessageHandler.class) - public String handleRequest(SQSEvent input, Context context) { - return "{\"statusCode\": 200}"; - } - - public class SampleMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - // This will be called for each individual message from a batch - // It should raise an exception if the message was not processed successfully - String returnVal = doSomething(message.getBody()); - return returnVal; - } - } - } - ``` - -=== "AppSqsEventWithNonRetryableExceptions.java" - - ```java hl_lines="7 21" - import software.amazon.lambda.powertools.sqs.SqsBatch; - import software.amazon.lambda.powertools.sqs.SqsMessageHandler; - import software.amazon.lambda.powertools.sqs.SqsUtils; - - public class AppSqsEvent implements RequestHandler { - @Override - @SqsBatch(value = SampleMessageHandler.class, nonRetryableExceptions = {IllegalArgumentException.class}) - public String handleRequest(SQSEvent input, Context context) { - return "{\"statusCode\": 200}"; - } - - public class SampleMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - // This will be called for each individual message from a batch - // It should raise an exception if the message was not processed successfully - String returnVal = doSomething(message.getBody()); - - if(/**Business validation failure**/) { - throw new IllegalArgumentException("Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId()); - } - - return returnVal; - } - } - } - ``` - - -### SqsUtils Utility API - -If you require access to the result of processed messages, you can use this utility. The result from calling **`#!java SqsUtils#batchProcessor()`** on the context manager will be a list of all the return values -from your **`#!java SqsMessageHandler#process()`** function. - -You can also use the utility in functional way by providing inline implementation of functional interface **`#!java SqsMessageHandler#process()`** - - -=== "Utility API" - - ```java hl_lines="4" - public class AppSqsEvent implements RequestHandler> { - @Override - public List handleRequest(SQSEvent input, Context context) { - List returnValues = SqsUtils.batchProcessor(input, SampleMessageHandler.class); - - return returnValues; - } - - public class SampleMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - // This will be called for each individual message from a batch - // It should raise an exception if the message was not processed successfully - String returnVal = doSomething(message.getBody()); - return returnVal; - } - } - } - ``` - -=== "Function implementation" - - ```java hl_lines="5 6 7 8 9 10" - public class AppSqsEvent implements RequestHandler> { - - @Override - public List handleRequest(SQSEvent input, Context context) { - List returnValues = SqsUtils.batchProcessor(input, (message) -> { - // This will be called for each individual message from a batch - // It should raise an exception if the message was not processed successfully - String returnVal = doSomething(message.getBody()); - return returnVal; - }); - - return returnValues; - } - } - ``` - -## Passing custom SqsClient - -If you need to pass custom SqsClient such as region to the SDK, you can pass your own `SqsClient` to be used by utility either for -**[SqsBatch annotation](#sqsbatch-annotation)**, or **[SqsUtils Utility API](#sqsutils-utility-api)**. - -=== "App.java" - - ```java hl_lines="3 4" - public class AppSqsEvent implements RequestHandler> { - static { - SqsUtils.overrideSqsClient(SqsClient.builder() - .build()); - } - - @Override - public List handleRequest(SQSEvent input, Context context) { - List returnValues = SqsUtils.batchProcessor(input, SampleMessageHandler.class); - - return returnValues; - } - - public class SampleMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - // This will be called for each individual message from a batch - // It should raise an exception if the message was not processed successfully - String returnVal = doSomething(message.getBody()); - return returnVal; - } - } - } - ``` - -## Suppressing exceptions - -If you want to disable the default behavior where `SQSBatchProcessingException` is raised if there are any exception, you can pass the `suppressException` boolean argument. - -=== "Within SqsBatch annotation" - - ```java hl_lines="2" - @Override - @SqsBatch(value = SampleMessageHandler.class, suppressException = true) - public String handleRequest(SQSEvent input, Context context) { - return "{\"statusCode\": 200}"; - } - ``` - -=== "Within SqsUtils Utility API" - - ```java hl_lines="3" - @Override - public List handleRequest(SQSEvent input, Context context) { - List returnValues = SqsUtils.batchProcessor(input, true, SampleMessageHandler.class); - - return returnValues; - } - ``` - -## Move non retryable messages to a dead letter queue - -If you want certain exceptions to be treated as permanent failures during batch processing, i.e. exceptions where the result of retrying will -always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue, you can use `SqsBatch#nonRetryableExceptions()` -to configure such exceptions. - -If you want such messages to be deleted instead, set `SqsBatch#deleteNonRetryableMessageFromQueue()` to `true`. By default, its value is `false`. - -Same capability is also provided by [SqsUtils Utility API](#sqsutils-utility-api). - -!!! info - Make sure the lambda function has required permissions needed by utility. Refer [this section](#iam-permissions). - -=== "SqsBatch annotation" - - ```java hl_lines="7 21" - import software.amazon.lambda.powertools.sqs.SqsBatch; - import software.amazon.lambda.powertools.sqs.SqsMessageHandler; - import software.amazon.lambda.powertools.sqs.SqsUtils; - - public class AppSqsEvent implements RequestHandler { - @Override - @SqsBatch(value = SampleMessageHandler.class, nonRetryableExceptions = {IllegalArgumentException.class}) - public String handleRequest(SQSEvent input, Context context) { - return "{\"statusCode\": 200}"; - } - - public class SampleMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - // This will be called for each individual message from a batch - // It should raise an exception if the message was not processed successfully - String returnVal = doSomething(message.getBody()); - - if(/**Business validation failure**/) { - throw new IllegalArgumentException("Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId()); - } - - return returnVal; - } - } - } - ``` - -=== "SqsBatch API" - - ```java hl_lines="9 23" - import software.amazon.lambda.powertools.sqs.SqsBatch; - import software.amazon.lambda.powertools.sqs.SqsMessageHandler; - import software.amazon.lambda.powertools.sqs.SqsUtils; - - public class AppSqsEvent implements RequestHandler { - @Override - public String handleRequest(SQSEvent input, Context context) { - - SqsUtils.batchProcessor(input, BatchProcessor.class, IllegalArgumentException.class); - - return "{\"statusCode\": 200}"; - } - - public class SampleMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - // This will be called for each individual message from a batch - // It should raise an exception if the message was not processed successfully - String returnVal = doSomething(message.getBody()); - - if(/**Business validation failure**/) { - throw new IllegalArgumentException("Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId()); - } - - return returnVal; - } - } - } - ``` - -## Migrating to the Batch Library -The [batch processing library](batch.md) provides a way to process messages and gracefully handle partial failures for -SQS, Kinesis Streams, and DynamoDB Streams batch sources. In comparison the legacy SQS Batch library, it relies on -[Lambda partial batch responses](https://aws.amazon.com/about-aws/whats-new/2021/11/aws-lambda-partial-batch-response-sqs-event-source/), -which allows the library to provide a simpler, reliable interface for processing batches. - -In order to get started, check out the [processing messages from SQS](batch/#processing-messages-from-sqs) documentation. -In most cases, you will simply be able to retain your existing batch message handler function, and wrap it with the new -batch processing interface. Unlike this module, As the batch processor uses *partial batch responses* to communicate to -Lambda which messages have been processed and must be removed from the queue, the return of the handler's process function -must be returned to Lambda. - -The new library also no longer requires the `SQS:DeleteMessage` action on the Lambda function's role policy, as Lambda -itself now manages removal of messages from the queue. - -!!! info - Some tuneables from this library are no longer provided. - - * **Non-retryable Exceptions** - there is no mechanism to indicate in a partial batch response that a particular message - should not be retried and instead moved to DLQ - a message either succeeds, or fails and is retried. A message - will be moved to the DLQ once the normal retry process has expired. - * **Suppress Exception** - The new batch processor does not throw an exception on failure of a handler. Instead, - its result must be returned by your code from your message handler to Lambda, so that Lambda can manage - the completed messages and retry behaviour. \ No newline at end of file diff --git a/docs/utilities/sqs_large_message_handling.md b/docs/utilities/sqs_large_message_handling.md deleted file mode 100644 index 0924d01cf..000000000 --- a/docs/utilities/sqs_large_message_handling.md +++ /dev/null @@ -1,296 +0,0 @@ ---- -title: SQS Large Message Handling (Deprecated) -description: Utility ---- - -!!! warning - This module is now deprecated and will be removed in version 2. - See [Large Message Handling](large_messages.md) and - [the migration guide](http://localhost:8000/lambda-java/utilities/large_messages/#migration-from-the-sqs-large-message-utility) - for the new module (`powertools-large-messages`) documentation - -The large message handling utility handles SQS messages which have had their payloads -offloaded to S3 due to them being larger than the SQS maximum. - -The utility automatically retrieves messages which have been offloaded to S3 using the -[amazon-sqs-java-extended-client-lib](https://github.com/awslabs/amazon-sqs-java-extended-client-lib) -client library. Once the message payloads have been processed successful the -utility can delete the message payloads from S3. - -This utility is compatible with versions *[1.1.0+](https://github.com/awslabs/amazon-sqs-java-extended-client-lib)* of -amazon-sqs-java-extended-client-lib. - -=== "Maven" - -```xml - - - com.amazonaws - amazon-sqs-java-extended-client-lib - 1.1.0 - -``` -=== "Gradle" - - ```groovy - dependencies { - implementation 'com.amazonaws:amazon-sqs-java-extended-client-lib:1.1.0' - } - ``` - -## Install -Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. - -=== "Maven Java 11+" - -```xml hl_lines="3-7 16 18 24-27" - -... - -software.amazon.lambda -powertools-sqs -{{ powertools.version }} - -... - -... - - - -... - -dev.aspectj -aspectj-maven-plugin -1.13.1 - -11 -11 -11 - - -software.amazon.lambda -powertools-sqs - - - - - - -compile - - - - -... - - -``` - -=== "Maven Java 1.8" - - ```xml hl_lines="3-7 16 18 24-27" - - ... - - software.amazon.lambda - powertools-sqs - {{ powertools.version }} - - ... - - ... - - - - ... - - org.codehaus.mojo - aspectj-maven-plugin - 1.14.0 - - 1.8 - 1.8 - 1.8 - - - software.amazon.lambda - powertools-sqs - - - - - - - compile - - - - - ... - - - ``` - -=== "Gradle Java 11+" - - ```groovy hl_lines="3 11" - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' - } - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-sqs:{{ powertools.version }}' - } - - sourceCompatibility = 11 // or higher - targetCompatibility = 11 // or higher - ``` - -=== "Gradle Java 1.8" - - ```groovy hl_lines="3 11" - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' - } - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-sqs:{{ powertools.version }}' - } - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - ``` - -## Lambda handler - -The annotation `@SqsLargeMessage` should be used with the handleRequest method of a class -which implements `com.amazonaws.services.lambda.runtime.RequestHandler` with -`com.amazonaws.services.lambda.runtime.events.SQSEvent` as the first parameter. - -=== "SqsMessageHandler.java" - - ```java hl_lines="6" - import software.amazon.lambda.powertools.sqs.SqsLargeMessage; - - public class SqsMessageHandler implements RequestHandler { - - @Override - @SqsLargeMessage - public String handleRequest(SQSEvent sqsEvent, Context context) { - // process messages - - return "ok"; - } - } - ``` - -`@SqsLargeMessage` creates a default S3 Client `AmazonS3 amazonS3 = AmazonS3ClientBuilder.defaultClient()`. - -!!! tip -When the Lambda function is invoked with an event from SQS, each received record -in the SQSEvent is checked to see to validate if it is offloaded to S3. -If it does then `getObject(bucket, key)` will be called, and the payload retrieved. -If there is an error during this process then the function will fail with a `FailedProcessingLargePayloadException` -exception. - - If the request handler method returns without error then each payload will be - deleted from S3 using `deleteObject(bucket, key)` - -To disable deletion of payloads setting the following annotation parameter: - -=== "Disable payload deletion" - - ```java hl_lines="3" - import software.amazon.lambda.powertools.sqs.SqsLargeMessage; - - @SqsLargeMessage(deletePayloads=false) - public class SqsMessageHandler implements RequestHandler { - - } - ``` - -## Utility - -If you want to avoid using annotation and have control over error that can happen during payload enrichment use `SqsUtils.enrichedMessageFromS3()`. -It provides you access with a list of `SQSMessage` object enriched from S3 payload. - -Original `SQSEvent` object is never mutated. You can also control if the S3 payload should be deleted after successful -processing. - -=== "Functional API without annotation" - - ```java hl_lines="9 10 11 14 15 16 17 18 19 20 21 22 27 28 29" - import software.amazon.lambda.powertools.sqs.SqsLargeMessage; - import software.amazon.lambda.powertools.sqs.SqsUtils; - - public class SqsMessageHandler implements RequestHandler { - - @Override - public String handleRequest(SQSEvent sqsEvent, Context context) { - - Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, sqsMessages -> { - // Some business logic - Map someBusinessLogic = new HashMap<>(); - someBusinessLogic.put("Message", sqsMessages.get(0).getBody()); - return someBusinessLogic; - }); - - // Do not delete payload after processing. - Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, false, sqsMessages -> { - // Some business logic - Map someBusinessLogic = new HashMap<>(); - someBusinessLogic.put("Message", sqsMessages.get(0).getBody()); - return someBusinessLogic; - }); - - // Better control over exception during enrichment - try { - // Do not delete payload after processing. - SqsUtils.enrichedMessageFromS3(sqsEvent, false, sqsMessages -> { - // Some business logic - }); - } catch (FailedProcessingLargePayloadException e) { - // handle any exception. - } - - return "ok"; - } - } - ``` - -## Overriding the default S3Client - -If you require customisations to the default S3Client, you can create your own `S3Client` and pass it to be used by utility either for -**[SqsLargeMessage annotation](#lambda-handler)**, or **[SqsUtils Utility API](#utility)**. - -=== "App.java" - - ```java hl_lines="4 5 11" - import software.amazon.lambda.powertools.sqs.SqsLargeMessage; - - static { - SqsUtils.overrideS3Client(S3Client.builder() - .build()); - } - - public class SqsMessageHandler implements RequestHandler { - - @Override - @SqsLargeMessage - public String handleRequest(SQSEvent sqsEvent, Context context) { - // process messages - - return "ok"; - } - } - ``` \ No newline at end of file diff --git a/examples/pom.xml b/examples/pom.xml index 5d19a20fb..0cd62e326 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -33,7 +33,6 @@ powertools-examples-idempotency powertools-examples-parameters powertools-examples-serialization - powertools-examples-sqs powertools-examples-batch powertools-examples-validation powertools-examples-cloudformation diff --git a/examples/powertools-examples-sqs/README.md b/examples/powertools-examples-sqs/README.md deleted file mode 100644 index 45f4a4a74..000000000 --- a/examples/powertools-examples-sqs/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# Powertools for AWS Lambda (Java) - SQS Batch Processing Example - -This project contains an example of Lambda function using the batch processing utilities module of Powertools for AWS Lambda (Java). -For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda/java/utilities/batch/). - -The project contains two functions: - -* [SqsMessageSender](src/main/java/org/demo/sqs/SqsMessageSender.java) - Sends a set of messages to an SQS queue. -This function is triggered every 5 minutes by an EventBridge schedule rule. -* [SqsPoller](src/main/java/org/demo/sqs/SqsPoller.java) - Listens to the same queue, processing items off in batches - -The poller intentionally fails intermittently processing messages to demonstrate the replay behaviour of the batch -module: - -
- -SqsPoller.java - -[SqsPoller.java:43](src/main/java/org/demo/sqs/SqsPoller.java) - -```java - public String process(SQSMessage message) { - log.info("Processing message with id {}", message.getMessageId()); - - int nextInt = random.nextInt(100); - - if(nextInt <= 10) { - log.info("Randomly picked message with id {} as business validation failure.", message.getMessageId()); - throw new IllegalArgumentException("Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId()); - } - - if(nextInt > 90) { - log.info("Randomly picked message with id {} as intermittent failure.", message.getMessageId()); - throw new RuntimeException("Failed due to intermittent issue. Will be sent back for retry." + message.getMessageId()); - } - - return "Success"; - } -``` - -
- -## Deploy the sample application - -This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting -started with SAM in [the examples directory](../README.md) - -## Test the application - -As the test is pushing through a batch every 5 minutes, we can simply watch the logs to see the batches being processed: - -```bash - sam logs --tail --stack-name $MY_STACK -``` - -As the handler intentionally introduces intermittent failures, we should expect to see error messages too! diff --git a/examples/powertools-examples-sqs/events/event.json b/examples/powertools-examples-sqs/events/event.json deleted file mode 100644 index 3822fadaa..000000000 --- a/examples/powertools-examples-sqs/events/event.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "body": "{\"message\": \"hello world\"}", - "resource": "/{proxy+}", - "path": "/path/to/resource", - "httpMethod": "POST", - "isBase64Encoded": false, - "queryStringParameters": { - "foo": "bar" - }, - "pathParameters": { - "proxy": "/path/to/resource" - }, - "stageVariables": { - "baz": "qux" - }, - "headers": { - "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", - "Accept-Encoding": "gzip, deflate, sdch", - "Accept-Language": "en-US,en;q=0.8", - "Cache-Control": "max-age=0", - "CloudFront-Forwarded-Proto": "https", - "CloudFront-Is-Desktop-Viewer": "true", - "CloudFront-Is-Mobile-Viewer": "false", - "CloudFront-Is-SmartTV-Viewer": "false", - "CloudFront-Is-Tablet-Viewer": "false", - "CloudFront-Viewer-Country": "US", - "Host": "1234567890.execute-api.us-east-1.amazonaws.com", - "Upgrade-Insecure-Requests": "1", - "User-Agent": "Custom User Agent String", - "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", - "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", - "X-Forwarded-For": "127.0.0.1, 127.0.0.2", - "X-Forwarded-Port": "443", - "X-Forwarded-Proto": "https" - }, - "requestContext": { - "accountId": "123456789012", - "resourceId": "123456", - "stage": "prod", - "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", - "requestTime": "09/Apr/2015:12:34:56 +0000", - "requestTimeEpoch": 1428582896000, - "identity": { - "cognitoIdentityPoolId": null, - "accountId": null, - "cognitoIdentityId": null, - "caller": null, - "accessKey": null, - "sourceIp": "127.0.0.1", - "cognitoAuthenticationType": null, - "cognitoAuthenticationProvider": null, - "userArn": null, - "userAgent": "Custom User Agent String", - "user": null - }, - "path": "/prod/path/to/resource", - "resourcePath": "/{proxy+}", - "httpMethod": "POST", - "apiId": "1234567890", - "protocol": "HTTP/1.1" - } - } - \ No newline at end of file diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml deleted file mode 100644 index aeffcac40..000000000 --- a/examples/powertools-examples-sqs/pom.xml +++ /dev/null @@ -1,196 +0,0 @@ - - 4.0.0 - software.amazon.lambda.examples - 1.17.0-SNAPSHOT - powertools-examples-sqs - jar - Powertools for AWS Lambda (Java) library Examples - SQS - - - 2.20.0 - 1.8 - 1.8 - true - - - - - software.amazon.lambda - powertools-logging - ${project.version} - - - software.amazon.lambda - powertools-sqs - ${project.version} - - - software.amazon.awssdk - url-connection-client - 2.20.119 - - - com.amazonaws - aws-lambda-java-core - 1.2.2 - - - com.amazonaws - aws-lambda-java-events - 3.11.2 - - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - - - com.fasterxml.jackson.datatype - jackson-datatype-joda - 2.15.2 - - - - junit - junit - 4.13.2 - test - - - - - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-sqs - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 - - - - - - - - - jdk8 - - (,11) - - - 1.9.7 - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-sqs - - - - - - - compile - test-compile - - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - - diff --git a/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsMessageSender.java b/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsMessageSender.java deleted file mode 100644 index 701d6808f..000000000 --- a/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsMessageSender.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.demo.sqs; - -import static java.util.stream.Collectors.toList; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.ScheduledEvent; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.joda.JodaModule; -import java.security.SecureRandom; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.stream.IntStream; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; -import software.amazon.awssdk.services.sqs.SqsClient; -import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; -import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; -import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry; -import software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; - -public class SqsMessageSender implements RequestHandler { - - private static final Logger log = LogManager.getLogger(SqsMessageSender.class); - - private static final SqsClient sqsClient = SqsClient.builder() - .httpClient(UrlConnectionHttpClient.create()) - .build(); - - private static final Random random = new SecureRandom(); - - private static final ObjectMapper objectMapper; - - static { - objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JodaModule()); - LoggingUtils.defaultObjectMapper(objectMapper); - } - - @Logging(logEvent = true) - public String handleRequest(final ScheduledEvent input, final Context context) { - String queueUrl = System.getenv("QUEUE_URL"); - - // Push 5 messages on each invoke. - List batchRequestEntries = IntStream.range(0, 5) - .mapToObj(value -> - { - Map attributeValueHashMap = new HashMap<>(); - attributeValueHashMap.put("Key" + value, MessageAttributeValue.builder() - .dataType("String") - .stringValue("Value" + value) - .build()); - - byte[] array = new byte[7]; - random.nextBytes(array); - - return SendMessageBatchRequestEntry.builder() - .messageAttributes(attributeValueHashMap) - .id(input.getId() + value) - .messageBody("Sample Message " + value) - .build(); - }).collect(toList()); - - SendMessageBatchResponse sendMessageBatchResponse = sqsClient.sendMessageBatch(SendMessageBatchRequest.builder() - .queueUrl(queueUrl) - .entries(batchRequestEntries) - .build()); - - log.info("Sent Message {}", sendMessageBatchResponse); - - return "Success"; - } -} \ No newline at end of file diff --git a/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsPoller.java b/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsPoller.java deleted file mode 100644 index 9ad5c7868..000000000 --- a/examples/powertools-examples-sqs/src/main/java/org/demo/sqs/SqsPoller.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.demo.sqs; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import java.security.SecureRandom; -import java.util.Random; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; -import software.amazon.awssdk.services.sqs.SqsClient; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.sqs.SqsBatch; -import software.amazon.lambda.powertools.sqs.SqsMessageHandler; -import software.amazon.lambda.powertools.sqs.SqsUtils; - -/** - * Handler for requests to Lambda function. - */ -public class SqsPoller implements RequestHandler { - - static { - // https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/lambda-optimize-starttime.html - SqsUtils.overrideSqsClient(SqsClient.builder() - .httpClient(UrlConnectionHttpClient.create()) - .build()); - } - - Logger log = LogManager.getLogger(SqsPoller.class); - Random random = new SecureRandom(); - - @SqsBatch(value = BatchProcessor.class, nonRetryableExceptions = {IllegalArgumentException.class}) - @Logging(logEvent = true) - public String handleRequest(final SQSEvent input, final Context context) { - return "Success"; - } - - private class BatchProcessor implements SqsMessageHandler { - @Override - public String process(SQSMessage message) { - log.info("Processing message with id {}", message.getMessageId()); - - int nextInt = random.nextInt(100); - - if (nextInt <= 10) { - log.info("Randomly picked message with id {} as business validation failure.", message.getMessageId()); - throw new IllegalArgumentException( - "Failed business validation. No point of retrying. Move me to DLQ." + message.getMessageId()); - } - - if (nextInt > 90) { - log.info("Randomly picked message with id {} as intermittent failure.", message.getMessageId()); - throw new RuntimeException( - "Failed due to intermittent issue. Will be sent back for retry." + message.getMessageId()); - } - - return "Success"; - } - } -} \ No newline at end of file diff --git a/examples/powertools-examples-sqs/src/main/resources/log4j2.xml b/examples/powertools-examples-sqs/src/main/resources/log4j2.xml deleted file mode 100644 index e1fd14cea..000000000 --- a/examples/powertools-examples-sqs/src/main/resources/log4j2.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/powertools-examples-sqs/template.yaml b/examples/powertools-examples-sqs/template.yaml deleted file mode 100644 index 50327de18..000000000 --- a/examples/powertools-examples-sqs/template.yaml +++ /dev/null @@ -1,148 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: > - sqs batch processing demo - -Globals: - Function: - Timeout: 20 - Runtime: java11 - MemorySize: 512 - Tracing: Active - Environment: - Variables: - # Powertools for AWS Lambda (Java) env vars: https://docs.powertools.aws.dev/lambda/java/#environment-variables - POWERTOOLS_LOG_LEVEL: INFO - POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 - POWERTOOLS_LOGGER_LOG_EVENT: true - -Resources: - CustomerKey: - Type: AWS::KMS::Key - Properties: - Description: KMS key for encrypted queues - Enabled: true - KeyPolicy: - Version: '2012-10-17' - Statement: - - Sid: Enable IAM User Permissions - Effect: Allow - Principal: - AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root' - Action: 'kms:*' - Resource: '*' - - Sid: Allow use of the key - Effect: Allow - Principal: - Service: lambda.amazonaws.com - Action: - - kms:Decrypt - - kms:GenerateDataKey - Resource: '*' - - CustomerKeyAlias: - Type: AWS::KMS::Alias - Properties: - AliasName: alias/sqs-key - TargetKeyId: !Ref CustomerKey - - DemoDlqSqsQueue: - Type: AWS::SQS::Queue - Properties: - KmsMasterKeyId: !Ref CustomerKey - - DemoSqsQueue: - Type: AWS::SQS::Queue - Properties: - RedrivePolicy: - deadLetterTargetArn: - Fn::GetAtt: - - "DemoDlqSqsQueue" - - "Arn" - maxReceiveCount: 2 - KmsMasterKeyId: !Ref CustomerKey - - DemoSQSSenderFunction: - Type: AWS::Serverless::Function - Properties: - CodeUri: . - Handler: org.demo.sqs.SqsMessageSender::handleRequest - Environment: - Variables: - POWERTOOLS_SERVICE_NAME: sqs-demo - QUEUE_URL: !Ref DemoSqsQueue - Policies: - - Statement: - - Sid: SQSSendMessageBatch - Effect: Allow - Action: - - sqs:SendMessageBatch - - sqs:SendMessage - Resource: !GetAtt DemoSqsQueue.Arn - - Sid: SQSKMSKey - Effect: Allow - Action: - - kms:GenerateDataKey - - kms:Decrypt - Resource: !GetAtt CustomerKey.Arn - Events: - CWSchedule: - Type: Schedule - Properties: - Schedule: 'rate(5 minutes)' - Name: !Join ["-", ["message-producer-schedule", !Select [0, !Split [-, !Select [2, !Split [/, !Ref AWS::StackId ]]]]]] - Description: Produce message to SQS via a Lambda function - Enabled: true - - DemoSQSConsumerFunction: - Type: AWS::Serverless::Function - Properties: - CodeUri: . - Handler: org.demo.sqs.SqsPoller::handleRequest - Environment: - Variables: - POWERTOOLS_SERVICE_NAME: sqs-demo - Policies: - - Statement: - - Sid: SQSDeleteGetAttribute - Effect: Allow - Action: - - sqs:DeleteMessageBatch - - sqs:GetQueueAttributes - Resource: !GetAtt DemoSqsQueue.Arn - - Sid: SQSSendMessageBatch - Effect: Allow - Action: - - sqs:SendMessageBatch - - sqs:SendMessage - Resource: !GetAtt DemoDlqSqsQueue.Arn - - Sid: SQSKMSKey - Effect: Allow - Action: - - kms:GenerateDataKey - - kms:Decrypt - Resource: !GetAtt CustomerKey.Arn - Events: - MySQSEvent: - Type: SQS - Properties: - Queue: !GetAtt DemoSqsQueue.Arn - BatchSize: 2 - MaximumBatchingWindowInSeconds: 300 - -Outputs: - DemoSqsQueue: - Description: "ARN for main SQS queue" - Value: !GetAtt DemoSqsQueue.Arn - DemoDlqSqsQueue: - Description: "ARN for DLQ" - Value: !GetAtt DemoDlqSqsQueue.Arn - DemoSQSSenderFunction: - Description: "Sender SQS Lambda Function ARN" - Value: !GetAtt DemoSQSSenderFunction.Arn - DemoSQSConsumerFunction: - Description: "Consumer SQS Lambda Function ARN" - Value: !GetAtt DemoSQSConsumerFunction.Arn - DemoSQSConsumerFunctionRole: - Description: "Implicit IAM Role created for SQS Lambda Function ARN" - Value: !GetAtt DemoSQSConsumerFunctionRole.Arn diff --git a/mkdocs.yml b/mkdocs.yml index d54ece508..62d8d75ce 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -18,9 +18,6 @@ nav: - utilities/validation.md - utilities/custom_resources.md - utilities/serialization.md - - Deprecated: - - utilities/sqs_large_message_handling.md - - utilities/sqs_batch.md - Processes: - processes/maintainers.md diff --git a/pom.xml b/pom.xml index 8c9e540f5..bebb2493f 100644 --- a/pom.xml +++ b/pom.xml @@ -45,11 +45,9 @@ powertools-serialization powertools-logging powertools-tracing - powertools-sqs powertools-metrics powertools-parameters powertools-validation - powertools-test-suite powertools-cloudformation powertools-idempotency powertools-large-messages diff --git a/powertools-sqs/pom.xml b/powertools-sqs/pom.xml deleted file mode 100644 index c21943fba..000000000 --- a/powertools-sqs/pom.xml +++ /dev/null @@ -1,144 +0,0 @@ - - - - - 4.0.0 - - powertools-sqs - jar - - - powertools-parent - software.amazon.lambda - 1.17.0-SNAPSHOT - - - Powertools for AWS Lambda (Java) library SQS - - Deprecated: Batch processing is now handled in powertools-batch and large messages in powertools-large-messages modules. - A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. - - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - - - - - software.amazon.lambda - powertools-core - - - com.amazonaws - aws-lambda-java-tests - - - com.amazonaws - aws-lambda-java-core - - - software.amazon.payloadoffloading - payloadoffloading-common - - - com.amazonaws - aws-lambda-java-events - - - software.amazon.awssdk - sqs - - - software.amazon.awssdk - s3 - - - com.fasterxml.jackson.core - jackson-databind - - - - org.aspectj - aspectjrt - - - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.junit.jupiter - junit-jupiter-params - test - - - org.apache.commons - commons-lang3 - test - - - org.mockito - mockito-core - test - - - org.aspectj - aspectjweaver - test - - - org.assertj - assertj-core - test - - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - - - - \ No newline at end of file diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SQSBatchProcessingException.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SQSBatchProcessingException.java deleted file mode 100644 index 7adc2afe5..000000000 --- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SQSBatchProcessingException.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static java.util.Collections.unmodifiableList; -import static java.util.stream.Collectors.joining; - -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import java.util.ArrayList; -import java.util.List; - -/** - *

- * When one or more {@link SQSMessage} fails and if any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)} - * during processing of a messages, this exception is with all the details of successful and failed messages. - *

- * - *

- * This exception can be thrown form: - *

    - *
  • {@link SqsBatch}
  • - *
  • {@link SqsUtils#batchProcessor(SQSEvent, Class)}
  • - *
  • {@link SqsUtils#batchProcessor(SQSEvent, boolean, Class)}
  • - *
  • {@link SqsUtils#batchProcessor(SQSEvent, SqsMessageHandler)}
  • - *
  • {@link SqsUtils#batchProcessor(SQSEvent, boolean, SqsMessageHandler)}
  • - *
- *

- */ -public class SQSBatchProcessingException extends RuntimeException { - - private final List exceptions; - private final List failures; - private final List returnValues; - - public SQSBatchProcessingException(final List exceptions, - final List failures, - final List successReturns) { - super(exceptions.stream() - .map(Throwable::toString) - .collect(joining("\n"))); - - this.exceptions = new ArrayList<>(exceptions); - this.failures = new ArrayList<>(failures); - this.returnValues = new ArrayList<>(successReturns); - } - - /** - * Details for exceptions that occurred while processing messages in {@link SqsMessageHandler#process(SQSMessage)} - * - * @return List of exceptions that occurred while processing messages - */ - public List getExceptions() { - return unmodifiableList(exceptions); - } - - /** - * List of returns from {@link SqsMessageHandler#process(SQSMessage)} that were successfully processed. - * - * @return List of returns from successfully processed messages - */ - public List successMessageReturnValues() { - return unmodifiableList(returnValues); - } - - /** - * Details of {@link SQSMessage} that failed in {@link SqsMessageHandler#process(SQSMessage)} - * - * @return List of failed messages - */ - public List getFailures() { - return unmodifiableList(failures); - } - - @Override - public void printStackTrace() { - for (Exception exception : exceptions) { - exception.printStackTrace(); - } - } -} diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsBatch.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsBatch.java deleted file mode 100644 index 4378fa707..000000000 --- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsBatch.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; - -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * @deprecated - * @see software.amazon.lambda.powertools.batch in powertools-batch module. - * Will be removed in V2. - * - * {@link SqsBatch} is used to process batch messages in {@link SQSEvent} - * - *

- * When using the annotation, implementation of {@link SqsMessageHandler} is required. Annotation will take care of - * calling {@link SqsMessageHandler#process(SQSMessage)} method for each {@link SQSMessage} in the received {@link SQSEvent} - *

- * - *

- * If any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)} during processing of a messages, Utility - * will take care of deleting all the successful messages from SQS. When one or more single message fails processing due - * to exception thrown from {@link SqsMessageHandler#process(SQSMessage)}, Lambda execution will fail - * with {@link SQSBatchProcessingException}. - *

- * If all the messages are successfully processes, No SQS messages are deleted explicitly but is rather delegated to - * Lambda execution context for deletion. - *

- * - *

- * If you want to suppress the exception even if any message in batch fails, set - * {@link SqsBatch#suppressException()} to true. By default its value is false - *

- * - *

- * If you want certain exceptions to be treated as permanent failures, i.e. exceptions where the result of retrying will - * always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue, - *

- * you can use {@link SqsBatch#nonRetryableExceptions()} to configure such exceptions. - * Make sure function execution role has sqs:GetQueueAttributes permission on source SQS queue and sqs:SendMessage, - * sqs:SendMessageBatch permission for configured DLQ. - *

- * If you want such messages to be deleted instead, set {@link SqsBatch#deleteNonRetryableMessageFromQueue()} to true. - * By default its value is false. - *

- * If there is no DLQ configured on source SQS queue and {@link SqsBatch#nonRetryableExceptions()} attribute is set, if - * nonRetryableExceptions occurs from {@link SqsMessageHandler}, such exceptions will still be treated as temporary - * exceptions and the message will be moved back to source SQS queue for reprocessing. The same behaviour will occur if - * for some reason the utility is unable to move the message to the DLQ. An example of this could be because the function - * is missing the correct permissions. - *

- * - *
- * public class SqsMessageHandler implements RequestHandler {
- *
- *    {@literal @}Override
- *    {@literal @}{@link SqsBatch (SqsMessageHandler)}
- *     public String handleRequest(SQSEvent sqsEvent, Context context) {
- *
- *         return "ok";
- *     }
- *
- *     public class DummySqsMessageHandler implements SqsMessageHandler{
- *     @Override
- *     public Object process(SQSEvent.SQSMessage message) {
- *         throw new UnsupportedOperationException();
- *     }
- * }
- *
- *     ...
- * 
- *
- * @see Amazon SQS dead-letter queues
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-@Deprecated
-public @interface SqsBatch {
-
-    Class> value();
-
-    boolean suppressException() default false;
-
-    Class[] nonRetryableExceptions() default {};
-
-    boolean deleteNonRetryableMessageFromQueue() default false;
-}
diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java
deleted file mode 100644
index a3a92cea1..000000000
--- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsLargeMessage.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2023 Amazon.com, Inc. or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *     http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package software.amazon.lambda.powertools.sqs;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * @deprecated See software.amazon.lambda.powertools.largemessages.LargeMessage in powertools-large-messages module.
- * Will be removed in version 2.
- *
- * 

{@code SqsLargeMessage} is used to signal that the annotated method - * should be extended to handle large SQS messages which have been offloaded - * to S3

- * - *

{@code SqsLargeMessage} automatically retrieves and deletes messages - * which have been offloaded to S3 using the {@code amazon-sqs-java-extended-client-lib} - * client library.

- * - *

This version of the {@code SqsLargeMessage} is compatible with version - * 1.1.0+ of {@code amazon-sqs-java-extended-client-lib}.

- * - *
- * <dependency>
- *   <groupId>com.amazonaws</groupId>
- *   <artifactId>amazon-sqs-java-extended-client-lib</artifactId>
- *   <version>1.1.0</version>
- * </dependency>
- * 
- * - *

{@code SqsLargeMessage} should be used with the handleRequest method of a class - * which implements {@code com.amazonaws.services.lambda.runtime.RequestHandler} with - * {@code com.amazonaws.services.lambda.runtime.events.SQSEvent} as the first parameter.

- * - *
- * public class SqsMessageHandler implements RequestHandler {
- *
- *    {@literal @}Override
- *    {@literal @}SqsLargeMessage
- *     public String handleRequest(SQSEvent sqsEvent, Context context) {
- *
- *         // process messages
- *
- *         return "ok";
- *     }
- *
- *     ...
- * 
- * - *

Using the default S3 Client {@code AmazonS3 amazonS3 = AmazonS3ClientBuilder.defaultClient();} - * each record received in the SQSEvent {@code SqsLargeMessage} will checked - * to see if it's body contains a payload which has been offloaded to S3. If it - * does then {@code getObject(bucket, key)} will be called and the payload - * retrieved.

- * - *

Note: Retreiving payloads from S3 will increase the duration of the - * Lambda function.

- * - *

If the request handler method returns then each payload will be deleted - * from S3 using {@code deleteObject(bucket, key)}

- * - *

To disable deletion of payloads setting the following annotation parameter - * {@code @SqsLargeMessage(deletePayloads=false)}

- */ -@Deprecated -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface SqsLargeMessage { - - boolean deletePayloads() default true; -} diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsMessageHandler.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsMessageHandler.java deleted file mode 100644 index 0c8f03ee9..000000000 --- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsMessageHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; - -import com.amazonaws.services.lambda.runtime.events.SQSEvent; - -/** - *

- * This interface should be implemented for processing {@link SQSMessage} inside {@link SQSEvent} received by lambda - * function. - *

- * - *

- * It is required by utilities: - *

    - *
  • {@link SqsBatch}
  • - *
  • {@link SqsUtils#batchProcessor(SQSEvent, Class)}
  • - *
  • {@link SqsUtils#batchProcessor(SQSEvent, boolean, Class)}
  • - *
  • {@link SqsUtils#batchProcessor(SQSEvent, SqsMessageHandler)}
  • - *
  • {@link SqsUtils#batchProcessor(SQSEvent, boolean, SqsMessageHandler)}
  • - *
- *

- * - * @param Return value type from {@link SqsMessageHandler#process(SQSMessage)} - */ -@FunctionalInterface -public interface SqsMessageHandler { - - R process(SQSMessage message); -} diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java deleted file mode 100644 index d89642780..000000000 --- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/SqsUtils.java +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect.processMessages; - -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.sqs.SqsClient; -import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; -import software.amazon.lambda.powertools.sqs.exception.SkippedMessageDueToFailedBatchException; -import software.amazon.lambda.powertools.sqs.internal.BatchContext; -import software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect; -import software.amazon.payloadoffloading.PayloadS3Pointer; - -/** - * A class of helper functions to add additional functionality to {@link SQSEvent} processing. - * - * @deprecated Batch processing is now handled in powertools-batch and large messages in powertools-large-messages. - * This class will no longer be available in version 2. - */ -@Deprecated -public final class SqsUtils { - - public static final String SQS = "sqs"; - private static final Logger LOG = LoggerFactory.getLogger(SqsUtils.class); - private static final ObjectMapper objectMapper = new ObjectMapper(); - private static final String MESSAGE_GROUP_ID = "MessageGroupId"; - private static SqsClient client; - private static S3Client s3Client; - - private SqsUtils() { - } - - /** - * This is a utility method when you want to avoid using {@code SqsLargeMessage} annotation. - * Gives you access to enriched messages from S3 in the SQS event produced via extended client lib. - * If all the large S3 payload are successfully retrieved, it will delete them from S3 post success. - * - * @param sqsEvent Event received from SQS Extended client library - * @param messageFunction Function to execute you business logic which provides access to enriched messages from S3 when needed. - * @return Return value from the function. - */ - public static R enrichedMessageFromS3(final SQSEvent sqsEvent, - final Function, R> messageFunction) { - return enrichedMessageFromS3(sqsEvent, true, messageFunction); - } - - /** - * This is a utility method when you want to avoid using {@code SqsLargeMessage} annotation. - * Gives you access to enriched messages from S3 in the SQS event produced via extended client lib. - * if all the large S3 payload are successfully retrieved, Control if it will delete payload from S3 post success. - * - * @param sqsEvent Event received from SQS Extended client library - * @param messageFunction Function to execute you business logic which provides access to enriched messages from S3 when needed. - * @return Return value from the function. - */ - public static R enrichedMessageFromS3(final SQSEvent sqsEvent, - final boolean deleteS3Payload, - final Function, R> messageFunction) { - - List sqsMessages = sqsEvent.getRecords().stream() - .map(SqsUtils::clonedMessage) - .collect(Collectors.toList()); - - List s3Pointers = processMessages(sqsMessages); - - R returnValue = messageFunction.apply(sqsMessages); - - if (deleteS3Payload) { - s3Pointers.forEach(SqsLargeMessageAspect::deleteMessage); - } - - return returnValue; - } - - /** - * Provides ability to set default {@link SqsClient} to be used by utility. - * If no default configuration is provided, client is instantiated via {@link SqsClient#create()} - * - * @param client {@link SqsClient} to be used by utility - */ - public static void overrideSqsClient(SqsClient client) { - SqsUtils.client = client; - } - - /** - * By default, the S3Client is instantiated via {@link S3Client#create()}. - * This method provides the ability to override the S3Client with your own custom version. - * - * @param s3Client {@link S3Client} to be used by utility - */ - public static void overrideS3Client(S3Client s3Client) { - SqsUtils.s3Client = s3Client; - } - - /** - * - * @deprecated - * @see software.amazon.lambda.powertools.batch in powertools-batch module. - * Will be removed in V2. - * - * This utility method is used to process each {@link SQSMessage} inside the received {@link SQSEvent} - * - *

- * The Utility will call {@link SqsMessageHandler#process(SQSMessage)} method for each {@link SQSMessage} - * in the received {@link SQSEvent} - *

- * - *

- * If any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)} during processing of a message, - * the utility will take care of deleting all the successful messages from SQS. When one or more single message fails - * processing due to exception thrown from {@link SqsMessageHandler#process(SQSMessage)} - * {@link SQSBatchProcessingException} is thrown with all the details of successful and failed messages. - *

- * If all the messages are successfully processes, No SQS messages are deleted explicitly but is rather delegated to - * Lambda execution context for deletion. - *

- * - *

- * If you dont want the utility to throw {@link SQSBatchProcessingException} in case of failures but rather suppress - * it, Refer {@link SqsUtils#batchProcessor(SQSEvent, boolean, Class)} - *

- * - * @param event {@link SQSEvent} received by lambda function. - * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event. - * @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message. - * @throws SQSBatchProcessingException if some messages fail during processing. - */ - @Deprecated - public static List batchProcessor(final SQSEvent event, - final Class> handler) { - return batchProcessor(event, false, handler); - } - - /** - * @deprecated - * @see software.amazon.lambda.powertools.batch in powertools-batch module. - * Will be removed in V2. - * - * This utility method is used to process each {@link SQSMessage} inside the received {@link SQSEvent} - * - *

- * The Utility will call {@link SqsMessageHandler#process(SQSMessage)} method for each {@link SQSMessage} - * in the received {@link SQSEvent} - *

- *

- * If any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)} during processing of a message, - * the utility will take care of deleting all the successful messages from SQS. When one or more single message fails - * processing due to exception thrown from {@link SqsMessageHandler#process(SQSMessage)} - * {@link SQSBatchProcessingException} is thrown with all the details of successful and failed messages. - * - *

- * - *

- * If all the messages are successfully processes, No SQS messages are deleted explicitly but is rather delegated to - * Lambda execution context for deletion. - *

- * - *

- * If you dont want the utility to throw {@link SQSBatchProcessingException} in case of failures but rather suppress - * it, Refer {@link SqsUtils#batchProcessor(SQSEvent, boolean, Class)} - *

- * - *

- * If you want certain exceptions to be treated as permanent failures, i.e. exceptions where the result of retrying will - * always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue, - * you can use nonRetryableExceptions parameter to configure such exceptions. - *

- * Make sure function execution role has sqs:GetQueueAttributes permission on source SQS queue and sqs:SendMessage, - * sqs:SendMessageBatch permission for configured DLQ. - *

- * If there is no DLQ configured on source SQS queue and {@link SqsBatch#nonRetryableExceptions()} attribute is set, if - * nonRetryableExceptions occurs from {@link SqsMessageHandler}, such exceptions will still be treated as temporary - * exceptions and the message will be moved back to source SQS queue for reprocessing. The same behaviour will occur if - * for some reason the utility is unable to move the message to the DLQ. An example of this could be because the function - * is missing the correct permissions. - *

- * - * @param event {@link SQSEvent} received by lambda function. - * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event. - * @param nonRetryableExceptions exception classes that are to be treated as permanent exceptions and to be moved - * to DLQ. - * @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message. - * @throws SQSBatchProcessingException if some messages fail during processing. - * @see Amazon SQS dead-letter queues - */ - @SafeVarargs - @Deprecated - public static List batchProcessor(final SQSEvent event, - final Class> handler, - final Class... nonRetryableExceptions) { - return batchProcessor(event, false, handler, nonRetryableExceptions); - } - - /** - * @deprecated - * @see software.amazon.lambda.powertools.batch in powertools-batch module. - * Will be removed in V2. - * - * This utility method is used to process each {@link SQSMessage} inside the received {@link SQSEvent} - * - *

- * The Utility will call {@link SqsMessageHandler#process(SQSMessage)} method for each {@link SQSMessage} - * in the received {@link SQSEvent} - *

- *

- * If any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)} during processing of a message, - * the utility will take care of deleting all the successful messages from SQS. When one or more single message fails - * processing due to exception thrown from {@link SqsMessageHandler#process(SQSMessage)} - * {@link SQSBatchProcessingException} is thrown with all the details of successful and failed messages. - *

- * Exception can also be suppressed if desired. - *

- * If all the messages are successfully processes, No SQS messages are deleted explicitly but is rather delegated to - * Lambda execution context for deletion. - *

- * - * @param event {@link SQSEvent} received by lambda function. - * @param suppressException if this is set to true, No {@link SQSBatchProcessingException} is thrown even on failed - * messages. - * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event. - * @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message. - * @throws SQSBatchProcessingException if some messages fail during processing and no suppression enabled. - */ - @Deprecated - public static List batchProcessor(final SQSEvent event, - final boolean suppressException, - final Class> handler) { - - SqsMessageHandler handlerInstance = instantiatedHandler(handler); - return batchProcessor(event, suppressException, handlerInstance); - } - - /** - * @deprecated - * @see software.amazon.lambda.powertools.batch in powertools-batch module. - * Will be removed in V2. - * - * This utility method is used to process each {@link SQSMessage} inside the received {@link SQSEvent} - * - *

- * The Utility will call {@link SqsMessageHandler#process(SQSMessage)} method for each {@link SQSMessage} - * in the received {@link SQSEvent} - *

- *

- * If any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)} during processing of a message, - * the utility will take care of deleting all the successful messages from SQS. When one or more single message fails - * processing due to exception thrown from {@link SqsMessageHandler#process(SQSMessage)} - * {@link SQSBatchProcessingException} is thrown with all the details of successful and failed messages. - * - *

- * - *

- * If all the messages are successfully processes, No SQS messages are deleted explicitly but is rather delegated to - * Lambda execution context for deletion. - *

- * - *

- * If you dont want the utility to throw {@link SQSBatchProcessingException} in case of failures but rather suppress - * it, Refer {@link SqsUtils#batchProcessor(SQSEvent, boolean, Class)} - *

- * - *

- * If you want certain exceptions to be treated as permanent failures, i.e. exceptions where the result of retrying will - * always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue, - * you can use nonRetryableExceptions parameter to configure such exceptions. - *

- * Make sure function execution role has sqs:GetQueueAttributes permission on source SQS queue and sqs:SendMessage, - * sqs:SendMessageBatch permission for configured DLQ. - *

- * If there is no DLQ configured on source SQS queue and {@link SqsBatch#nonRetryableExceptions()} attribute is set, if - * nonRetryableExceptions occurs from {@link SqsMessageHandler}, such exceptions will still be treated as temporary - * exceptions and the message will be moved back to source SQS queue for reprocessing. The same behaviour will occur if - * for some reason the utility is unable to move the message to the DLQ. An example of this could be because the function - * is missing the correct permissions. - *

- * - * @param event {@link SQSEvent} received by lambda function. - * @param suppressException if this is set to true, No {@link SQSBatchProcessingException} is thrown even on failed - * messages. - * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event. - * @param nonRetryableExceptions exception classes that are to be treated as permanent exceptions and to be moved - * to DLQ. - * @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message. - * @throws SQSBatchProcessingException if some messages fail during processing. - * @see Amazon SQS dead-letter queues - */ - @SafeVarargs - @Deprecated - public static List batchProcessor(final SQSEvent event, - final boolean suppressException, - final Class> handler, - final Class... nonRetryableExceptions) { - - SqsMessageHandler handlerInstance = instantiatedHandler(handler); - return batchProcessor(event, suppressException, handlerInstance, false, nonRetryableExceptions); - } - - /** - * @deprecated - * @see software.amazon.lambda.powertools.batch in powertools-batch module. - * Will be removed in V2. - * - * This utility method is used to process each {@link SQSMessage} inside the received {@link SQSEvent} - * - *

- * The Utility will call {@link SqsMessageHandler#process(SQSMessage)} method for each {@link SQSMessage} - * in the received {@link SQSEvent} - *

- * - *

- * If any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)} during processing of a message, - * the utility will take care of deleting all the successful messages from SQS. When one or more single message fails - * processing due to exception thrown from {@link SqsMessageHandler#process(SQSMessage)} - * {@link SQSBatchProcessingException} is thrown with all the details of successful and failed messages. - * - *

- * - *

- * If all the messages are successfully processes, No SQS messages are deleted explicitly but is rather delegated to - * Lambda execution context for deletion. - *

- * - *

- * If you dont want the utility to throw {@link SQSBatchProcessingException} in case of failures but rather suppress - * it, Refer {@link SqsUtils#batchProcessor(SQSEvent, boolean, Class)} - *

- * - *

- * If you want certain exceptions to be treated as permanent failures, i.e. exceptions where the result of retrying will - * always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue, - * you can use nonRetryableExceptions parameter to configure such exceptions. - *

- * Make sure function execution role has sqs:GetQueueAttributes permission on source SQS queue and sqs:SendMessage, - * sqs:SendMessageBatch permission for configured DLQ. - *

- * If you want such messages to be deleted instead, set deleteNonRetryableMessageFromQueue to true. - *

- * If there is no DLQ configured on source SQS queue and {@link SqsBatch#nonRetryableExceptions()} attribute is set, if - * nonRetryableExceptions occurs from {@link SqsMessageHandler}, such exceptions will still be treated as temporary - * exceptions and the message will be moved back to source SQS queue for reprocessing. The same behaviour will occur if - * for some reason the utility is unable to move the message to the DLQ. An example of this could be because the function - * is missing the correct permissions. - *

- * - * @param event {@link SQSEvent} received by lambda function. - * @param suppressException if this is set to true, No {@link SQSBatchProcessingException} is thrown even on failed - * messages. - * @param handler Class implementing {@link SqsMessageHandler} which will be called for each message in event. - * @param deleteNonRetryableMessageFromQueue If messages with nonRetryableExceptions are to be deleted from SQS queue. - * @param nonRetryableExceptions exception classes that are to be treated as permanent exceptions and to be moved - * to DLQ. - * @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message. - * @throws SQSBatchProcessingException if some messages fail during processing. - * @see Amazon SQS dead-letter queues - */ - @SafeVarargs - @Deprecated - public static List batchProcessor(final SQSEvent event, - final boolean suppressException, - final Class> handler, - final boolean deleteNonRetryableMessageFromQueue, - final Class... nonRetryableExceptions) { - - SqsMessageHandler handlerInstance = instantiatedHandler(handler); - return batchProcessor(event, suppressException, handlerInstance, deleteNonRetryableMessageFromQueue, - nonRetryableExceptions); - } - - /** - * @deprecated - * @see software.amazon.lambda.powertools.batch in powertools-batch module. - * Will be removed in V2. - * - * This utility method is used to process each {@link SQSMessage} inside the received {@link SQSEvent} - * - *

- * The Utility will call {@link SqsMessageHandler#process(SQSMessage)} method for each {@link SQSMessage} - * in the received {@link SQSEvent} - *

- * - *

- * If any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)} during processing of a messages, - * Utility will take care of deleting all the successful messages from SQS. When one or more single message fails - * processing due to exception thrown from {@link SqsMessageHandler#process(SQSMessage)} - * {@link SQSBatchProcessingException} is thrown with all the details of successful and failed messages. - *

- * If all the messages are successfully processes, No SQS messages are deleted explicitly but is rather delegated to - * Lambda execution context for deletion. - *

- * - *

- * If you dont want the utility to throw {@link SQSBatchProcessingException} in case of failures but rather suppress - * it, Refer {@link SqsUtils#batchProcessor(SQSEvent, boolean, SqsMessageHandler)} - *

- * - * @param event {@link SQSEvent} received by lambda function. - * @param handler Instance of class implementing {@link SqsMessageHandler} which will be called for each message in event. - * @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message- - * @throws SQSBatchProcessingException if some messages fail during processing. - */ - @Deprecated - public static List batchProcessor(final SQSEvent event, - final SqsMessageHandler handler) { - return batchProcessor(event, false, handler); - } - - - /** - * @deprecated - * @see software.amazon.lambda.powertools.batch in powertools-batch module. - * Will be removed in V2. - * - * This utility method is used to process each {@link SQSMessage} inside the received {@link SQSEvent} - * - *

- * The Utility will call {@link SqsMessageHandler#process(SQSMessage)} method for each {@link SQSMessage} - * in the received {@link SQSEvent} - *

- * - *

- * If any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)} during processing of a message, - * the utility will take care of deleting all the successful messages from SQS. When one or more single message fails - * processing due to exception thrown from {@link SqsMessageHandler#process(SQSMessage)} - * {@link SQSBatchProcessingException} is thrown with all the details of successful and failed messages. - * - *

- * - *

- * If all the messages are successfully processes, No SQS messages are deleted explicitly but is rather delegated to - * Lambda execution context for deletion. - *

- * - *

- * If you dont want the utility to throw {@link SQSBatchProcessingException} in case of failures but rather suppress - * it, Refer {@link SqsUtils#batchProcessor(SQSEvent, boolean, Class)} - *

- * - *

- * If you want certain exceptions to be treated as permanent failures, i.e. exceptions where the result of retrying will - * always be a failure and want these can be immediately moved to the dead letter queue associated to the source SQS queue, - * you can use nonRetryableExceptions parameter to configure such exceptions. - *

- * Make sure function execution role has sqs:GetQueueAttributes permission on source SQS queue and sqs:SendMessage, - * sqs:SendMessageBatch permission for configured DLQ. - *

- * If there is no DLQ configured on source SQS queue and {@link SqsBatch#nonRetryableExceptions()} attribute is set, if - * nonRetryableExceptions occurs from {@link SqsMessageHandler}, such exceptions will still be treated as temporary - * exceptions and the message will be moved back to source SQS queue for reprocessing.The same behaviour will occur if - * for some reason the utility is unable to moved the message to the DLQ. An example of this could be because the function - * is missing the correct permissions. - *

- * - * @param event {@link SQSEvent} received by lambda function. - * @param handler Instance of class implementing {@link SqsMessageHandler} which will be called for each message in event. - * @param nonRetryableExceptions exception classes that are to be treated as permanent exceptions and to be moved - * to DLQ. - * @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message. - * @throws SQSBatchProcessingException if some messages fail during processing. - * @see Amazon SQS dead-letter queues - */ - @SafeVarargs - @Deprecated - public static List batchProcessor(final SQSEvent event, - final SqsMessageHandler handler, - final Class... nonRetryableExceptions) { - return batchProcessor(event, false, handler, false, nonRetryableExceptions); - } - - - /** - * @deprecated - * @see software.amazon.lambda.powertools.batch in powertools-batch module. - * Will be removed in V2. - * - * This utility method is used to process each {@link SQSMessage} inside the received {@link SQSEvent} - * - *

- * The Utility will call {@link SqsMessageHandler#process(SQSMessage)} method for each {@link SQSMessage} - * in the received {@link SQSEvent} - *

- * - *

- * If any exception is thrown from {@link SqsMessageHandler#process(SQSMessage)} during processing of a messages, - * the utility will take care of deleting all the successful messages from SQS. When one or more single message fails - * processing due to exception thrown from {@link SqsMessageHandler#process(SQSMessage)} - * {@link SQSBatchProcessingException} is thrown with all the details of successful and failed messages. - *

- * Exception can also be suppressed if desired. - *

- * If all the messages are successfully processes, No SQS messages are deleted explicitly but is rather delegated to - * Lambda execution context for deletion. - *

- * - * @param event {@link SQSEvent} received by lambda function. - * @param suppressException if this is set to true, No {@link SQSBatchProcessingException} is thrown even on failed - * messages. - * @param handler Instance of class implementing {@link SqsMessageHandler} which will be called for each message in event. - * @return List of values returned by {@link SqsMessageHandler#process(SQSMessage)} while processing each message. - * @throws SQSBatchProcessingException if some messages fail during processing and no suppression enabled. - */ - @Deprecated - public static List batchProcessor(final SQSEvent event, - final boolean suppressException, - final SqsMessageHandler handler) { - return batchProcessor(event, suppressException, handler, false); - - } - - /** - * @deprecated - * @see software.amazon.lambda.powertools.batch in powertools-batch module. - * Will be removed in V2. - */ - @SafeVarargs - @Deprecated - public static List batchProcessor(final SQSEvent event, - final boolean suppressException, - final SqsMessageHandler handler, - final boolean deleteNonRetryableMessageFromQueue, - final Class... nonRetryableExceptions) { - final List handlerReturn = new ArrayList<>(); - - if (client == null) { - client = (SqsClient) SqsClient.builder() - .overrideConfiguration(ClientOverrideConfiguration.builder() - .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, - UserAgentConfigurator.getUserAgent(SQS)) - .build()); - } - - BatchContext batchContext = new BatchContext(client); - int offset = 0; - boolean failedBatch = false; - while (offset < event.getRecords().size() && !failedBatch) { - // Get the current message and advance to the next. Doing this here - // makes it easier for us to know where we are up to if we have to - // break out of here early. - SQSMessage message = event.getRecords().get(offset); - offset++; - - // If the batch hasn't failed, try process the message - try { - handlerReturn.add(handler.process(message)); - batchContext.addSuccess(message); - } catch (Exception e) { - - // Record the failure - batchContext.addFailure(message, e); - - // If we are trying to process a message that has a messageGroupId, we are on a FIFO queue. A failure - // now stops us from processing the rest of the batch; we break out of the loop leaving unprocessed - // messages in the queue - // https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting - String messageGroupId = message.getAttributes() != null ? - message.getAttributes().get(MESSAGE_GROUP_ID) : null; - if (messageGroupId != null) { - LOG.info( - "A message in a message batch with messageGroupId {} and messageId {} failed; failing the rest of the batch too" - , messageGroupId, message.getMessageId()); - failedBatch = true; - } - LOG.error("Encountered issue processing message: {}", message.getMessageId(), e); - } - } - - // If we have a FIFO batch failure, unprocessed messages will remain on the queue - // past the failed message. We have to add these to the errors - if (offset < event.getRecords().size()) { - event.getRecords() - .subList(offset, event.getRecords().size()) - .forEach(message -> - { - LOG.info("Skipping message {} as another message with a message group failed in this batch", - message.getMessageId()); - batchContext.addFailure(message, new SkippedMessageDueToFailedBatchException()); - }); - } - - batchContext.processSuccessAndHandleFailed(handlerReturn, suppressException, deleteNonRetryableMessageFromQueue, - nonRetryableExceptions); - return handlerReturn; - } - - private static SqsMessageHandler instantiatedHandler(final Class> handler) { - - try { - if (null == handler.getDeclaringClass()) { - return handler.getDeclaredConstructor().newInstance(); - } - - final Constructor> constructor = - handler.getDeclaredConstructor(handler.getDeclaringClass()); - constructor.setAccessible(true); - return constructor.newInstance(handler.getDeclaringClass().getDeclaredConstructor().newInstance()); - } catch (Exception e) { - LOG.error("Failed creating handler instance", e); - throw new RuntimeException("Unexpected error occurred. Please raise issue at " + - "https://github.com/aws-powertools/powertools-lambda-java/issues", e); - } - } - - private static SQSMessage clonedMessage(final SQSMessage sqsMessage) { - try { - return objectMapper - .readValue(objectMapper.writeValueAsString(sqsMessage), SQSMessage.class); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - public static ObjectMapper objectMapper() { - return objectMapper; - } - - public static S3Client s3Client() { - if (null == s3Client) { - s3Client = (S3Client) S3Client.builder() - .overrideConfiguration(ClientOverrideConfiguration.builder() - .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, - UserAgentConfigurator.getUserAgent(SQS)) - .build()); - SqsUtils.s3Client = S3Client.create(); - } - - return s3Client; - } -} diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/exception/SkippedMessageDueToFailedBatchException.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/exception/SkippedMessageDueToFailedBatchException.java deleted file mode 100644 index fbb4289d8..000000000 --- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/exception/SkippedMessageDueToFailedBatchException.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.exception; - -/** - * Indicates that a message has been skipped due to the batch it is - * within failing. - */ -public class SkippedMessageDueToFailedBatchException extends Exception { - - public SkippedMessageDueToFailedBatchException() { - } - -} diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java deleted file mode 100644 index 70cf04fb8..000000000 --- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/BatchContext.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.internal; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static java.lang.String.format; -import static java.util.Optional.ofNullable; -import static java.util.stream.Collectors.toList; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import software.amazon.awssdk.core.SdkBytes; -import software.amazon.awssdk.services.sqs.SqsClient; -import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequest; -import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequestEntry; -import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchResponse; -import software.amazon.awssdk.services.sqs.model.GetQueueAttributesRequest; -import software.amazon.awssdk.services.sqs.model.GetQueueAttributesResponse; -import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; -import software.amazon.awssdk.services.sqs.model.QueueAttributeName; -import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; -import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry; -import software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse; -import software.amazon.lambda.powertools.sqs.SQSBatchProcessingException; -import software.amazon.lambda.powertools.sqs.SqsUtils; - -public final class BatchContext { - private static final Logger LOG = LoggerFactory.getLogger(BatchContext.class); - private static final Map QUEUE_ARN_TO_DLQ_URL_MAPPING = new HashMap<>(); - - private final Map messageToException = new HashMap<>(); - private final List success = new ArrayList<>(); - - private final SqsClient client; - - public BatchContext(SqsClient client) { - this.client = client; - } - - public void addSuccess(SQSMessage event) { - success.add(event); - } - - public void addFailure(SQSMessage event, Exception e) { - messageToException.put(event, e); - } - - @SafeVarargs - public final void processSuccessAndHandleFailed(final List successReturns, - final boolean suppressException, - final boolean deleteNonRetryableMessageFromQueue, - final Class... nonRetryableExceptions) { - if (hasFailures()) { - - List exceptions = new ArrayList<>(); - List failedMessages = new ArrayList<>(); - Map nonRetryableMessageToException = new HashMap<>(); - - if (nonRetryableExceptions.length == 0) { - exceptions.addAll(messageToException.values()); - failedMessages.addAll(messageToException.keySet()); - } else { - messageToException.forEach((sqsMessage, exception) -> - { - boolean nonRetryableException = isNonRetryableException(exception, nonRetryableExceptions); - - if (nonRetryableException) { - nonRetryableMessageToException.put(sqsMessage, exception); - } else { - exceptions.add(exception); - failedMessages.add(sqsMessage); - } - }); - } - - List messagesToBeDeleted = new ArrayList<>(success); - - if (!nonRetryableMessageToException.isEmpty() && deleteNonRetryableMessageFromQueue) { - messagesToBeDeleted.addAll(nonRetryableMessageToException.keySet()); - } else if (!nonRetryableMessageToException.isEmpty()) { - - boolean isMovedToDlq = moveNonRetryableMessagesToDlqIfConfigured(nonRetryableMessageToException); - - if (!isMovedToDlq) { - exceptions.addAll(nonRetryableMessageToException.values()); - failedMessages.addAll(nonRetryableMessageToException.keySet()); - } - } - - deleteMessagesFromQueue(messagesToBeDeleted); - - processFailedMessages(successReturns, suppressException, exceptions, failedMessages); - } - } - - private void processFailedMessages(List successReturns, - boolean suppressException, - List exceptions, - List failedMessages) { - if (failedMessages.isEmpty()) { - return; - } - - if (suppressException) { - List messageIds = failedMessages.stream(). - map(SQSMessage::getMessageId) - .collect(toList()); - - LOG.debug(format("[%d] records failed processing, but exceptions are suppressed. " + - "Failed messages %s", failedMessages.size(), messageIds)); - } else { - throw new SQSBatchProcessingException(exceptions, failedMessages, successReturns); - } - } - - private boolean isNonRetryableException(Exception exception, Class[] nonRetryableExceptions) { - return Arrays.stream(nonRetryableExceptions) - .anyMatch(aClass -> aClass.isInstance(exception)); - } - - private boolean moveNonRetryableMessagesToDlqIfConfigured( - Map nonRetryableMessageToException) { - Optional dlqUrl = fetchDlqUrl(nonRetryableMessageToException); - - if (!dlqUrl.isPresent()) { - return false; - } - - List dlqMessages = nonRetryableMessageToException.keySet().stream() - .map(sqsMessage -> - { - Map messageAttributesMap = new HashMap<>(); - - sqsMessage.getMessageAttributes().forEach((s, messageAttribute) -> - { - MessageAttributeValue.Builder builder = MessageAttributeValue.builder(); - - builder - .dataType(messageAttribute.getDataType()) - .stringValue(messageAttribute.getStringValue()); - - if (null != messageAttribute.getBinaryValue()) { - builder.binaryValue(SdkBytes.fromByteBuffer(messageAttribute.getBinaryValue())); - } - - messageAttributesMap.put(s, builder.build()); - }); - - return SendMessageBatchRequestEntry.builder() - .messageBody(sqsMessage.getBody()) - .id(sqsMessage.getMessageId()) - .messageAttributes(messageAttributesMap) - .build(); - }) - .collect(toList()); - - List sendMessageBatchResponses = batchRequest(dlqMessages, 10, entriesToSend -> - { - - SendMessageBatchResponse sendMessageBatchResponse = - client.sendMessageBatch(SendMessageBatchRequest.builder() - .entries(entriesToSend) - .queueUrl(dlqUrl.get()) - .build()); - - - LOG.debug("Response from send batch message to DLQ request {}", sendMessageBatchResponse); - - return sendMessageBatchResponse; - }); - - return sendMessageBatchResponses.stream() - .filter(response -> null != response && response.hasFailed()) - .peek(sendMessageBatchResponse -> LOG.error( - "Failed sending message to the DLQ. Entire batch will be re processed. Check if needed permissions are configured for the function. Response: {}", - sendMessageBatchResponse)) - .count() == 0; - } - - - private Optional fetchDlqUrl(Map nonRetryableMessageToException) { - return nonRetryableMessageToException.keySet().stream() - .findFirst() - .map(sqsMessage -> QUEUE_ARN_TO_DLQ_URL_MAPPING.computeIfAbsent(sqsMessage.getEventSourceArn(), - sourceArn -> - { - String queueUrl = url(sourceArn); - - GetQueueAttributesResponse queueAttributes = - client.getQueueAttributes(GetQueueAttributesRequest.builder() - .attributeNames(QueueAttributeName.REDRIVE_POLICY) - .queueUrl(queueUrl) - .build()); - - return ofNullable(queueAttributes.attributes().get(QueueAttributeName.REDRIVE_POLICY)) - .map(policy -> - { - try { - return SqsUtils.objectMapper().readTree(policy); - } catch (JsonProcessingException e) { - LOG.debug( - "Unable to parse Re drive policy for queue {}. Even if DLQ exists, failed messages will be send back to main queue.", - queueUrl, e); - return null; - } - }) - .map(node -> node.get("deadLetterTargetArn")) - .map(JsonNode::asText) - .map(this::url) - .orElse(null); - })); - } - - private boolean hasFailures() { - return !messageToException.isEmpty(); - } - - private void deleteMessagesFromQueue(final List messages) { - if (!messages.isEmpty()) { - - List entries = - messages.stream().map(m -> DeleteMessageBatchRequestEntry.builder() - .id(m.getMessageId()) - .receiptHandle(m.getReceiptHandle()) - .build()).collect(toList()); - - batchRequest(entries, 10, entriesToDelete -> - { - DeleteMessageBatchRequest request = DeleteMessageBatchRequest.builder() - .queueUrl(url(messages.get(0).getEventSourceArn())) - .entries(entriesToDelete) - .build(); - - DeleteMessageBatchResponse deleteMessageBatchResponse = client.deleteMessageBatch(request); - - LOG.debug("Response from delete request {}", deleteMessageBatchResponse); - - return deleteMessageBatchResponse; - }); - } - } - - private List batchRequest(final List listOFEntries, - final int size, - final Function, R> batchLogic) { - - return IntStream.range(0, listOFEntries.size()) - .filter(index -> index % size == 0) - .mapToObj(index -> listOFEntries.subList(index, Math.min(index + size, listOFEntries.size()))) - .map(batchLogic) - .collect(Collectors.toList()); - } - - private String url(String queueArn) { - String[] arnArray = queueArn.split(":"); - return String.format("https://sqs.%s.amazonaws.com/%s/%s", arnArray[3], arnArray[4], arnArray[5]); - } -} diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspect.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspect.java deleted file mode 100644 index e5176e13a..000000000 --- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspect.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.internal; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static java.lang.String.format; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod; -import static software.amazon.lambda.powertools.sqs.SqsUtils.s3Client; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import software.amazon.awssdk.core.ResponseInputStream; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; -import software.amazon.awssdk.services.s3.model.GetObjectRequest; -import software.amazon.awssdk.services.s3.model.GetObjectResponse; -import software.amazon.awssdk.services.s3.model.S3Exception; -import software.amazon.awssdk.utils.IoUtils; -import software.amazon.lambda.powertools.sqs.SqsLargeMessage; -import software.amazon.payloadoffloading.PayloadS3Pointer; - -@Aspect -public class SqsLargeMessageAspect { - - private static final Logger LOG = LoggerFactory.getLogger(SqsLargeMessageAspect.class); - - public static List processMessages(final List records) { - List s3Pointers = new ArrayList<>(); - for (SQSMessage sqsMessage : records) { - if (isBodyLargeMessagePointer(sqsMessage.getBody())) { - - PayloadS3Pointer s3Pointer = Optional.ofNullable(PayloadS3Pointer.fromJson(sqsMessage.getBody())) - .orElseThrow(() -> new FailedProcessingLargePayloadException( - format("Failed processing SQS body to extract S3 details. [ %s ].", - sqsMessage.getBody()))); - - ResponseInputStream s3Object = callS3Gracefully(s3Pointer, pointer -> - { - ResponseInputStream response = - s3Client().getObject(GetObjectRequest.builder() - .bucket(pointer.getS3BucketName()) - .key(pointer.getS3Key()) - .build()); - - LOG.debug("Object downloaded with key: " + s3Pointer.getS3Key()); - return response; - }); - - sqsMessage.setBody(readStringFromS3Object(s3Object, s3Pointer)); - s3Pointers.add(s3Pointer); - } - } - - return s3Pointers; - } - - private static boolean isBodyLargeMessagePointer(String record) { - return record.startsWith("[\"software.amazon.payloadoffloading.PayloadS3Pointer\""); - } - - private static String readStringFromS3Object(ResponseInputStream response, - PayloadS3Pointer s3Pointer) { - try (ResponseInputStream content = response) { - return IoUtils.toUtf8String(content); - } catch (IOException e) { - LOG.error("Error converting S3 object to String", e); - throw new FailedProcessingLargePayloadException( - format("Failed processing S3 record with [Bucket Name: %s Bucket Key: %s]", - s3Pointer.getS3BucketName(), s3Pointer.getS3Key()), e); - } - } - - public static void deleteMessage(PayloadS3Pointer s3Pointer) { - callS3Gracefully(s3Pointer, pointer -> - { - s3Client().deleteObject(DeleteObjectRequest.builder() - .bucket(pointer.getS3BucketName()) - .key(pointer.getS3Key()) - .build()); - LOG.info("Message deleted from S3: " + s3Pointer.toJson()); - return null; - }); - } - - private static R callS3Gracefully(final PayloadS3Pointer pointer, - final Function function) { - try { - return function.apply(pointer); - } catch (S3Exception e) { - LOG.error("A service exception", e); - throw new FailedProcessingLargePayloadException( - format("Failed processing S3 record with [Bucket Name: %s Bucket Key: %s]", - pointer.getS3BucketName(), pointer.getS3Key()), e); - } catch (SdkClientException e) { - LOG.error("Some sort of client exception", e); - throw new FailedProcessingLargePayloadException( - format("Failed processing S3 record with [Bucket Name: %s Bucket Key: %s]", - pointer.getS3BucketName(), pointer.getS3Key()), e); - } - } - - public static boolean placedOnSqsEventRequestHandler(ProceedingJoinPoint pjp) { - return pjp.getArgs().length == 2 - && pjp.getArgs()[0] instanceof SQSEvent - && pjp.getArgs()[1] instanceof Context; - } - - @SuppressWarnings({"EmptyMethod"}) - @Pointcut("@annotation(sqsLargeMessage)") - public void callAt(SqsLargeMessage sqsLargeMessage) { - } - - @Around(value = "callAt(sqsLargeMessage) && execution(@SqsLargeMessage * *.*(..))", argNames = "pjp,sqsLargeMessage") - public Object around(ProceedingJoinPoint pjp, - SqsLargeMessage sqsLargeMessage) throws Throwable { - Object[] proceedArgs = pjp.getArgs(); - - if (isHandlerMethod(pjp) - && placedOnSqsEventRequestHandler(pjp)) { - List pointersToDelete = rewriteMessages((SQSEvent) proceedArgs[0]); - - Object proceed = pjp.proceed(proceedArgs); - - if (sqsLargeMessage.deletePayloads()) { - pointersToDelete.forEach(SqsLargeMessageAspect::deleteMessage); - } - return proceed; - } - - return pjp.proceed(proceedArgs); - } - - private List rewriteMessages(SQSEvent sqsEvent) { - List records = sqsEvent.getRecords(); - return processMessages(records); - } - - public static class FailedProcessingLargePayloadException extends RuntimeException { - public FailedProcessingLargePayloadException(String message, Throwable cause) { - super(message, cause); - } - - public FailedProcessingLargePayloadException(String message) { - super(message); - } - } -} diff --git a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspect.java b/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspect.java deleted file mode 100644 index ff0b5b014..000000000 --- a/powertools-sqs/src/main/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspect.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.internal; - -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod; -import static software.amazon.lambda.powertools.sqs.SqsUtils.batchProcessor; -import static software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect.placedOnSqsEventRequestHandler; - -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import software.amazon.lambda.powertools.sqs.SqsBatch; - -@Aspect -public class SqsMessageBatchProcessorAspect { - - @SuppressWarnings({"EmptyMethod"}) - @Pointcut("@annotation(sqsBatch)") - public void callAt(SqsBatch sqsBatch) { - } - - @Around(value = "callAt(sqsBatch) && execution(@SqsBatch * *.*(..))", argNames = "pjp,sqsBatch") - public Object around(ProceedingJoinPoint pjp, - SqsBatch sqsBatch) throws Throwable { - Object[] proceedArgs = pjp.getArgs(); - - if (isHandlerMethod(pjp) - && placedOnSqsEventRequestHandler(pjp)) { - - SQSEvent sqsEvent = (SQSEvent) proceedArgs[0]; - - batchProcessor(sqsEvent, - sqsBatch.suppressException(), - sqsBatch.value(), - sqsBatch.deleteNonRetryableMessageFromQueue(), - sqsBatch.nonRetryableExceptions()); - } - - return pjp.proceed(proceedArgs); - } -} diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SampleSqsHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SampleSqsHandler.java deleted file mode 100644 index 557aa214d..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SampleSqsHandler.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs; - -import com.amazonaws.services.lambda.runtime.events.SQSEvent; - -public class SampleSqsHandler implements SqsMessageHandler { - private int counter; - - @Override - public String process(SQSEvent.SQSMessage message) { - return String.valueOf(counter++); - } -} diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java deleted file mode 100644 index c0c334e78..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsBatchProcessorTest.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; -import static software.amazon.lambda.powertools.sqs.SqsUtils.batchProcessor; -import static software.amazon.lambda.powertools.sqs.SqsUtils.overrideSqsClient; - -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.ArgumentCaptor; -import software.amazon.awssdk.services.sqs.SqsClient; -import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequest; -import software.amazon.awssdk.services.sqs.model.GetQueueAttributesRequest; -import software.amazon.awssdk.services.sqs.model.GetQueueAttributesResponse; -import software.amazon.awssdk.services.sqs.model.QueueAttributeName; -import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; - -class SqsUtilsBatchProcessorTest { - - private static final SqsClient sqsClient = mock(SqsClient.class); - private static final SqsClient interactionClient = mock(SqsClient.class); - private static final ObjectMapper MAPPER = new ObjectMapper(); - private SQSEvent event; - - @BeforeEach - void setUp() throws IOException { - reset(sqsClient, interactionClient); - event = MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEvent.json"), SQSEvent.class); - overrideSqsClient(sqsClient); - } - - @Test - void shouldBatchProcessAndNotDeleteMessagesWhenAllSuccess() { - List returnValues = batchProcessor(event, false, (message) -> - { - interactionClient.listQueues(); - return "Success"; - }); - - assertThat(returnValues) - .hasSize(2) - .containsExactly("Success", "Success"); - - verify(interactionClient, times(2)).listQueues(); - verifyNoInteractions(sqsClient); - } - - @ParameterizedTest - @ValueSource(classes = {SampleInnerSqsHandler.class, SampleSqsHandler.class}) - void shouldBatchProcessViaClassAndNotDeleteMessagesWhenAllSuccess( - Class> handler) { - List returnValues = batchProcessor(event, handler); - - assertThat(returnValues) - .hasSize(2) - .containsExactly("0", "1"); - - verifyNoInteractions(sqsClient); - } - - @Test - void shouldBatchProcessAndDeleteSuccessMessageOnPartialFailures() { - String failedId = "2e1424d4-f796-459a-8184-9c92662be6da"; - - SqsMessageHandler failedHandler = (message) -> - { - if (failedId.equals(message.getMessageId())) { - throw new RuntimeException("Failed processing"); - } - - interactionClient.listQueues(); - return "Success"; - }; - - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> batchProcessor(event, failedHandler)) - .satisfies(e -> - { - - assertThat(e.successMessageReturnValues()) - .hasSize(1) - .contains("Success"); - - assertThat(e.getFailures()) - .hasSize(1) - .extracting("messageId") - .contains(failedId); - - assertThat(e.getExceptions()) - .hasSize(1) - .extracting("detailMessage") - .contains("Failed processing"); - }); - - verify(interactionClient).listQueues(); - - ArgumentCaptor captor = ArgumentCaptor.forClass(DeleteMessageBatchRequest.class); - verify(sqsClient).deleteMessageBatch(captor.capture()); - - assertThat(captor.getValue()) - .hasFieldOrPropertyWithValue("queueUrl", "https://sqs.us-east-2.amazonaws.com/123456789012/my-queue"); - } - - @Test - void shouldBatchProcessAndFullFailuresInBatch() { - SqsMessageHandler failedHandler = (message) -> - { - throw new RuntimeException(message.getMessageId()); - }; - - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> batchProcessor(event, failedHandler)) - .satisfies(e -> - { - - assertThat(e.successMessageReturnValues()) - .isEmpty(); - - assertThat(e.getFailures()) - .hasSize(2) - .extracting("messageId") - .containsExactly("059f36b4-87a3-44ab-83d2-661975830a7d", - "2e1424d4-f796-459a-8184-9c92662be6da"); - - assertThat(e.getExceptions()) - .hasSize(2) - .extracting("detailMessage") - .containsExactly("059f36b4-87a3-44ab-83d2-661975830a7d", - "2e1424d4-f796-459a-8184-9c92662be6da"); - }); - - verifyNoInteractions(sqsClient); - } - - @Test - void shouldBatchProcessViaClassAndDeleteSuccessMessageOnPartialFailures() { - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> batchProcessor(event, FailureSampleInnerSqsHandler.class)) - .satisfies(e -> - { - - assertThat(e.successMessageReturnValues()) - .hasSize(1) - .contains("Success"); - - assertThat(e.getFailures()) - .hasSize(1) - .extracting("messageId") - .contains("2e1424d4-f796-459a-8184-9c92662be6da"); - - assertThat(e.getExceptions()) - .hasSize(1) - .extracting("detailMessage") - .contains("Failed processing"); - }); - - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - } - - - @Test - void shouldBatchProcessAndSuppressExceptions() { - String failedId = "2e1424d4-f796-459a-8184-9c92662be6da"; - - SqsMessageHandler failedHandler = (message) -> - { - if (failedId.equals(message.getMessageId())) { - throw new RuntimeException("Failed processing"); - } - - interactionClient.listQueues(); - return "Success"; - }; - - List returnValues = batchProcessor(event, true, failedHandler); - - assertThat(returnValues) - .hasSize(1) - .contains("Success"); - - verify(interactionClient).listQueues(); - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - } - - @Test - void shouldBatchProcessViaClassAndSuppressExceptions() { - List returnValues = batchProcessor(event, true, FailureSampleInnerSqsHandler.class); - - assertThat(returnValues) - .hasSize(1) - .contains("Success"); - - verify(interactionClient).listQueues(); - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - } - - @Test - void shouldBatchProcessAndMoveNonRetryableExceptionToDlq() { - String failedId = "2e1424d4-f796-459a-8184-9c92662be6da"; - HashMap attributes = new HashMap<>(); - - attributes.put(QueueAttributeName.REDRIVE_POLICY, "{\n" + - " \"deadLetterTargetArn\": \"arn:aws:sqs:us-east-2:123456789012:retry-queue\",\n" + - " \"maxReceiveCount\": 2\n" + - "}"); - - when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn( - GetQueueAttributesResponse.builder() - .attributes(attributes) - .build()); - - List batchProcessor = batchProcessor(event, (message) -> - { - if (failedId.equals(message.getMessageId())) { - throw new IllegalStateException("Failed processing"); - } - - interactionClient.listQueues(); - return "Success"; - }, IllegalStateException.class, IllegalArgumentException.class); - - assertThat(batchProcessor) - .hasSize(1); - - verify(sqsClient).sendMessageBatch(any(SendMessageBatchRequest.class)); - } - - @Test - void shouldBatchProcessAndDeleteNonRetryableException() { - String failedId = "2e1424d4-f796-459a-8184-9c92662be6da"; - HashMap attributes = new HashMap<>(); - - attributes.put(QueueAttributeName.REDRIVE_POLICY, "{\n" + - " \"deadLetterTargetArn\": \"arn:aws:sqs:us-east-2:123456789012:retry-queue\",\n" + - " \"maxReceiveCount\": 2\n" + - "}"); - - when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn( - GetQueueAttributesResponse.builder() - .attributes(attributes) - .build()); - - List batchProcessor = batchProcessor(event, false, (message) -> - { - if (failedId.equals(message.getMessageId())) { - throw new IllegalStateException("Failed processing"); - } - - interactionClient.listQueues(); - return "Success"; - }, true, IllegalStateException.class, IllegalArgumentException.class); - - assertThat(batchProcessor) - .hasSize(1); - - verify(sqsClient, times(0)).sendMessageBatch(any(SendMessageBatchRequest.class)); - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - } - - @Test - void shouldDeleteSuccessfulMessageInBatchesOfT10orLess() throws IOException { - SQSEvent batch25Message = - MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEventBatchSize25.json"), SQSEvent.class); - - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> batchProcessor(batch25Message, FailureSampleInnerSqsHandler.class)) - .satisfies(e -> - { - - assertThat(e.successMessageReturnValues()) - .hasSize(24) - .contains("Success"); - - assertThat(e.getFailures()) - .hasSize(1) - .extracting("messageId") - .contains("2e1424d4-f796-459a-8184-9c92662be6da"); - - assertThat(e.getExceptions()) - .hasSize(1) - .extracting("detailMessage") - .contains("Failed processing"); - }); - - ArgumentCaptor captor = ArgumentCaptor.forClass(DeleteMessageBatchRequest.class); - - verify(sqsClient, times(3)).deleteMessageBatch(captor.capture()); - - assertThat(captor.getAllValues()) - .hasSize(3) - .flatMap(DeleteMessageBatchRequest::entries) - .hasSize(24); - } - - @Test - void shouldBatchProcessAndMoveNonRetryableExceptionToDlqInBatchesOfT10orLess() throws IOException { - SQSEvent batch25Message = - MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEventBatchSize25.json"), SQSEvent.class); - - HashMap attributes = new HashMap<>(); - - attributes.put(QueueAttributeName.REDRIVE_POLICY, "{\n" + - " \"deadLetterTargetArn\": \"arn:aws:sqs:us-east-2:123456789012:retry-queue\",\n" + - " \"maxReceiveCount\": 2\n" + - "}"); - - when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn( - GetQueueAttributesResponse.builder() - .attributes(attributes) - .build()); - - List batchProcessor = batchProcessor(batch25Message, (message) -> - { - if ("2e1424d4-f796-459a-8184-9c92662be6da".equals(message.getMessageId())) { - interactionClient.listQueues(); - return "Success"; - } - - throw new IllegalStateException("Failed processing"); - }, IllegalStateException.class, IllegalArgumentException.class); - - assertThat(batchProcessor) - .hasSize(1); - - ArgumentCaptor captor = ArgumentCaptor.forClass(SendMessageBatchRequest.class); - - - verify(sqsClient, times(3)).sendMessageBatch(captor.capture()); - - assertThat(captor.getAllValues()) - .hasSize(3) - .flatMap(SendMessageBatchRequest::entries) - .hasSize(24); - } - - public class SampleInnerSqsHandler implements SqsMessageHandler { - private int counter; - - @Override - public String process(SQSMessage message) { - interactionClient.listQueues(); - return String.valueOf(counter++); - } - } - - public class FailureSampleInnerSqsHandler implements SqsMessageHandler { - @Override - public String process(SQSEvent.SQSMessage message) { - if ("2e1424d4-f796-459a-8184-9c92662be6da".equals(message.getMessageId())) { - throw new RuntimeException("Failed processing"); - } - - interactionClient.listQueues(); - return "Success"; - } - } -} \ No newline at end of file diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsFifoBatchProcessorTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsFifoBatchProcessorTest.java deleted file mode 100644 index bfc555405..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsFifoBatchProcessorTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static software.amazon.lambda.powertools.sqs.SqsUtils.batchProcessor; -import static software.amazon.lambda.powertools.sqs.SqsUtils.overrideSqsClient; - -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import com.amazonaws.services.lambda.runtime.tests.EventLoader; -import java.io.IOException; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoSession; -import org.mockito.quality.Strictness; -import software.amazon.awssdk.services.sqs.SqsClient; -import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequest; -import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequestEntry; -import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchResponse; - -public class SqsUtilsFifoBatchProcessorTest { - - private static SQSEvent sqsBatchEvent; - private MockitoSession session; - - @Mock - private SqsClient sqsClient; - - @Captor - private ArgumentCaptor deleteMessageBatchCaptor; - - public SqsUtilsFifoBatchProcessorTest() throws IOException { - sqsBatchEvent = EventLoader.loadSQSEvent("SqsFifoBatchEvent.json"); - } - - @BeforeEach - public void setup() { - // Establish a strict mocking session. This means that any - // calls to a mock that have not been stubbed will throw - this.session = Mockito.mockitoSession() - .strictness(Strictness.STRICT_STUBS) - .initMocks(this) - .startMocking(); - - overrideSqsClient(sqsClient); - } - - @AfterEach - public void tearDown() { - session.finishMocking(); - } - - @Test - public void processWholeBatch() { - // Act - AtomicInteger processedCount = new AtomicInteger(); - List results = batchProcessor(sqsBatchEvent, false, (message) -> - { - processedCount.getAndIncrement(); - return true; - }); - - // Assert - assertThat(processedCount.get()).isEqualTo(3); - assertThat(results.size()).isEqualTo(3); - } - - /** - * Check that a failure in the middle of the batch: - * - deletes the successful message explicitly from SQS - * - marks the failed and subsequent message as failed - * - does not delete the failed or subsequent message - */ - @Test - public void singleFailureInMiddleOfBatch() { - // Arrange - Mockito.when(sqsClient.deleteMessageBatch(deleteMessageBatchCaptor.capture())) - .thenReturn(DeleteMessageBatchResponse - .builder().build()); - - // Act - AtomicInteger processedCount = new AtomicInteger(); - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> batchProcessor(sqsBatchEvent, false, (message) -> - { - int value = processedCount.getAndIncrement(); - if (value == 1) { - throw new RuntimeException("Whoops"); - } - return true; - })) - - // Assert - .isInstanceOf(SQSBatchProcessingException.class) - .satisfies(e -> - { - List failures = ((SQSBatchProcessingException) e).getFailures(); - assertThat(failures.size()).isEqualTo(2); - List failureIds = failures.stream() - .map(SQSEvent.SQSMessage::getMessageId) - .collect(Collectors.toList()); - assertThat(failureIds).contains(sqsBatchEvent.getRecords().get(1).getMessageId()); - assertThat(failureIds).contains(sqsBatchEvent.getRecords().get(2).getMessageId()); - }); - - DeleteMessageBatchRequest deleteRequest = deleteMessageBatchCaptor.getValue(); - List messageIds = deleteRequest.entries().stream() - .map(DeleteMessageBatchRequestEntry::id) - .collect(Collectors.toList()); - assertThat(deleteRequest.entries().size()).isEqualTo(1); - assertThat(messageIds.contains(sqsBatchEvent.getRecords().get(0).getMessageId())).isTrue(); - - } - - @Test - public void singleFailureAtEndOfBatch() { - - // Arrange - Mockito.when(sqsClient.deleteMessageBatch(deleteMessageBatchCaptor.capture())) - .thenReturn(DeleteMessageBatchResponse - .builder().build()); - - - // Act - AtomicInteger processedCount = new AtomicInteger(); - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> batchProcessor(sqsBatchEvent, false, (message) -> - { - int value = processedCount.getAndIncrement(); - if (value == 2) { - throw new RuntimeException("Whoops"); - } - return true; - })); - - // Assert - DeleteMessageBatchRequest deleteRequest = deleteMessageBatchCaptor.getValue(); - List messageIds = deleteRequest.entries().stream() - .map(DeleteMessageBatchRequestEntry::id) - .collect(Collectors.toList()); - assertThat(deleteRequest.entries().size()).isEqualTo(2); - assertThat(messageIds.contains(sqsBatchEvent.getRecords().get(0).getMessageId())).isTrue(); - assertThat(messageIds.contains(sqsBatchEvent.getRecords().get(1).getMessageId())).isTrue(); - assertThat(messageIds.contains(sqsBatchEvent.getRecords().get(2).getMessageId())).isFalse(); - } - - @Test - public void messageFailureStopsGroupProcessing() { - String groupToFail = sqsBatchEvent.getRecords().get(0).getAttributes().get("MessageGroupId"); - - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> batchProcessor(sqsBatchEvent, (message) -> - { - String groupId = message.getAttributes().get("MessageGroupId"); - if (groupId.equals(groupToFail)) { - throw new RuntimeException("Failed processing"); - } - return groupId; - })) - .satisfies(e -> - { - assertThat(e.successMessageReturnValues().size()).isEqualTo(0); - assertThat(e.successMessageReturnValues().contains(groupToFail)).isFalse(); - }); - } - -} diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsLargeMessageTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsLargeMessageTest.java deleted file mode 100644 index afc426976..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/SqsUtilsLargeMessageTest.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; - -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; -import java.util.stream.Stream; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import software.amazon.awssdk.core.ResponseInputStream; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.http.AbortableInputStream; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; -import software.amazon.awssdk.services.s3.model.GetObjectRequest; -import software.amazon.awssdk.services.s3.model.GetObjectResponse; -import software.amazon.awssdk.services.s3.model.S3Exception; -import software.amazon.awssdk.utils.StringInputStream; -import software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect; - -class SqsUtilsLargeMessageTest { - - private static final String BUCKET_NAME = "ms-extended-sqs-client"; - private static final String BUCKET_KEY = "c71eb2ae-37e0-4265-8909-32f4153faddf"; - @Mock - private S3Client s3Client; - - private static Stream exception() { - return Stream.of(Arguments.of(S3Exception.builder() - .message("Service Exception") - .build()), - Arguments.of(SdkClientException.builder() - .message("Client Exception") - .build())); - } - - @BeforeEach - void setUp() { - openMocks(this); - SqsUtils.overrideS3Client(s3Client); - } - - @Test - public void testLargeMessage() { - ResponseInputStream s3Response = - new ResponseInputStream<>(GetObjectResponse.builder().build(), - AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes()))); - when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response); - - SQSEvent sqsEvent = messageWithBody( - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + - "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]"); - - Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, sqsMessages -> - { - Map someBusinessLogic = new HashMap<>(); - someBusinessLogic.put("Message", sqsMessages.get(0).getBody()); - return someBusinessLogic; - }); - - assertThat(sqsMessage) - .hasSize(1) - .containsEntry("Message", "A big message"); - - ArgumentCaptor delete = ArgumentCaptor.forClass(DeleteObjectRequest.class); - - verify(s3Client).deleteObject(delete.capture()); - - Assertions.assertThat(delete.getValue()) - .satisfies((Consumer) deleteObjectRequest -> - { - assertThat(deleteObjectRequest.bucket()) - .isEqualTo(BUCKET_NAME); - - assertThat(deleteObjectRequest.key()) - .isEqualTo(BUCKET_KEY); - }); - } - - @ParameterizedTest - @ValueSource(booleans = {true, false}) - public void testLargeMessageDeleteFromS3Toggle(boolean deleteS3Payload) { - ResponseInputStream s3Response = - new ResponseInputStream<>(GetObjectResponse.builder().build(), - AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes()))); - - when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response); - - SQSEvent sqsEvent = messageWithBody( - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + - "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]"); - - Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, deleteS3Payload, sqsMessages -> - { - Map someBusinessLogic = new HashMap<>(); - someBusinessLogic.put("Message", sqsMessages.get(0).getBody()); - return someBusinessLogic; - }); - - assertThat(sqsMessage) - .hasSize(1) - .containsEntry("Message", "A big message"); - if (deleteS3Payload) { - ArgumentCaptor delete = ArgumentCaptor.forClass(DeleteObjectRequest.class); - - verify(s3Client).deleteObject(delete.capture()); - - Assertions.assertThat(delete.getValue()) - .satisfies((Consumer) deleteObjectRequest -> - { - assertThat(deleteObjectRequest.bucket()) - .isEqualTo(BUCKET_NAME); - - assertThat(deleteObjectRequest.key()) - .isEqualTo(BUCKET_KEY); - }); - } else { - verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class)); - } - } - - @Test - public void shouldNotProcessSmallMessageBody() { - ResponseInputStream s3Response = - new ResponseInputStream<>(GetObjectResponse.builder().build(), - AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes()))); - - when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response); - - SQSEvent sqsEvent = messageWithBody("This is small message"); - - Map sqsMessage = SqsUtils.enrichedMessageFromS3(sqsEvent, sqsMessages -> - { - Map someBusinessLogic = new HashMap<>(); - someBusinessLogic.put("Message", sqsMessages.get(0).getBody()); - return someBusinessLogic; - }); - - assertThat(sqsMessage) - .containsEntry("Message", "This is small message"); - - verifyNoInteractions(s3Client); - } - - @ParameterizedTest - @MethodSource("exception") - public void shouldFailEntireBatchIfFailedDownloadingFromS3(RuntimeException exception) { - when(s3Client.getObject(any(GetObjectRequest.class))).thenThrow(exception); - - String messageBody = - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + - "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]"; - SQSEvent sqsEvent = messageWithBody(messageBody); - - assertThatExceptionOfType(SqsLargeMessageAspect.FailedProcessingLargePayloadException.class) - .isThrownBy(() -> SqsUtils.enrichedMessageFromS3(sqsEvent, sqsMessages -> sqsMessages.get(0).getBody())) - .withCause(exception); - - verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class)); - } - - @Test - public void shouldFailEntireBatchIfFailedProcessingDownloadMessageFromS3() { - ResponseInputStream s3Response = - new ResponseInputStream<>(GetObjectResponse.builder().build(), - AbortableInputStream.create(new StringInputStream("test") { - @Override - public void close() throws IOException { - throw new IOException("Failed"); - } - })); - - when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response); - - String messageBody = - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + - "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]"; - SQSEvent sqsEvent = messageWithBody(messageBody); - - assertThatExceptionOfType(SqsLargeMessageAspect.FailedProcessingLargePayloadException.class) - .isThrownBy(() -> SqsUtils.enrichedMessageFromS3(sqsEvent, sqsMessages -> sqsMessages.get(0).getBody())) - .withCauseInstanceOf(IOException.class); - - verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class)); - } - - private SQSEvent messageWithBody(String messageBody) { - SQSMessage sqsMessage = new SQSMessage(); - sqsMessage.setBody(messageBody); - SQSEvent sqsEvent = new SQSEvent(); - sqsEvent.setRecords(singletonList(sqsMessage)); - return sqsEvent; - } -} \ No newline at end of file diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/LambdaHandlerApiGateway.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/LambdaHandlerApiGateway.java deleted file mode 100644 index 3bad9644f..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/LambdaHandlerApiGateway.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.handlers; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import software.amazon.lambda.powertools.sqs.SampleSqsHandler; -import software.amazon.lambda.powertools.sqs.SqsBatch; -import software.amazon.lambda.powertools.sqs.SqsLargeMessage; - -public class LambdaHandlerApiGateway implements RequestHandler { - - @Override - @SqsLargeMessage - @SqsBatch(value = SampleSqsHandler.class) - public String handleRequest(APIGatewayProxyRequestEvent sqsEvent, Context context) { - return sqsEvent.getBody(); - } -} diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchFailureSuppressedHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchFailureSuppressedHandler.java deleted file mode 100644 index 172179057..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchFailureSuppressedHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.handlers; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import software.amazon.lambda.powertools.sqs.SqsBatch; -import software.amazon.lambda.powertools.sqs.SqsMessageHandler; - -public class PartialBatchFailureSuppressedHandler implements RequestHandler { - @Override - @SqsBatch(value = InnerMessageHandler.class, suppressException = true) - public String handleRequest(final SQSEvent sqsEvent, - final Context context) { - return "Success"; - } - - private class InnerMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - if ("2e1424d4-f796-459a-8184-9c92662be6da".equals(message.getMessageId())) { - throw new RuntimeException("2e1424d4-f796-459a-8184-9c92662be6da"); - } - - interactionClient.listQueues(); - return "Success"; - } - } -} diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchPartialFailureHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchPartialFailureHandler.java deleted file mode 100644 index 6e3971269..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchPartialFailureHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.handlers; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import software.amazon.lambda.powertools.sqs.SqsBatch; -import software.amazon.lambda.powertools.sqs.SqsMessageHandler; - -public class PartialBatchPartialFailureHandler implements RequestHandler { - @Override - @SqsBatch(InnerMessageHandler.class) - public String handleRequest(final SQSEvent sqsEvent, - final Context context) { - return "Success"; - } - - private class InnerMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - if ("2e1424d4-f796-459a-8184-9c92662be6da".equals(message.getMessageId())) { - throw new RuntimeException("2e1424d4-f796-459a-8184-9c92662be6da"); - } - - interactionClient.listQueues(); - return "Success"; - } - } -} diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchSuccessHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchSuccessHandler.java deleted file mode 100644 index acfcd7109..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/PartialBatchSuccessHandler.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.handlers; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import software.amazon.lambda.powertools.sqs.SqsBatch; -import software.amazon.lambda.powertools.sqs.SqsMessageHandler; - -public class PartialBatchSuccessHandler implements RequestHandler { - @Override - @SqsBatch(InnerMessageHandler.class) - public String handleRequest(final SQSEvent sqsEvent, - final Context context) { - return "Success"; - } - - private class InnerMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - interactionClient.listQueues(); - return "Success"; - } - } -} diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandler.java deleted file mode 100644 index de096679f..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.handlers; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import software.amazon.lambda.powertools.sqs.SqsLargeMessage; - -public class SqsMessageHandler implements RequestHandler { - - @Override - @SqsLargeMessage - public String handleRequest(SQSEvent sqsEvent, Context context) { - return sqsEvent.getRecords().get(0).getBody(); - } -} diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandler.java deleted file mode 100644 index 74ff02e2c..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.handlers; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import software.amazon.lambda.powertools.sqs.SqsBatch; -import software.amazon.lambda.powertools.sqs.SqsMessageHandler; - -public class SqsMessageHandlerWithNonRetryableHandler implements RequestHandler { - - @Override - @SqsBatch(value = InnerMessageHandler.class, nonRetryableExceptions = {IllegalStateException.class, - IllegalArgumentException.class}) - public String handleRequest(final SQSEvent sqsEvent, - final Context context) { - return "Success"; - } - - private class InnerMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - if (message.getMessageId().isEmpty()) { - throw new IllegalArgumentException("Invalid message and was moved to DLQ"); - } - - if ("2e1424d4-f796-459a-9696-9c92662ba5da".equals(message.getMessageId())) { - throw new RuntimeException("Invalid message and should be reprocessed"); - } - - interactionClient.listQueues(); - return "Success"; - } - } -} diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandlerWithDelete.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandlerWithDelete.java deleted file mode 100644 index 5b341880e..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsMessageHandlerWithNonRetryableHandlerWithDelete.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.handlers; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static software.amazon.lambda.powertools.sqs.internal.SqsMessageBatchProcessorAspectTest.interactionClient; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import software.amazon.lambda.powertools.sqs.SqsBatch; -import software.amazon.lambda.powertools.sqs.SqsMessageHandler; - -public class SqsMessageHandlerWithNonRetryableHandlerWithDelete implements RequestHandler { - - @Override - @SqsBatch(value = InnerMessageHandler.class, - nonRetryableExceptions = {IllegalStateException.class, IllegalArgumentException.class}, - deleteNonRetryableMessageFromQueue = true) - public String handleRequest(final SQSEvent sqsEvent, - final Context context) { - return "Success"; - } - - private class InnerMessageHandler implements SqsMessageHandler { - - @Override - public String process(SQSMessage message) { - if (message.getMessageId().isEmpty()) { - throw new IllegalArgumentException("Invalid message and was moved to DLQ"); - } - - if ("2e1424d4-f796-459a-9696-9c92662ba5da".equals(message.getMessageId())) { - throw new RuntimeException("Invalid message and should be reprocessed"); - } - - interactionClient.listQueues(); - return "Success"; - } - } -} diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsNoDeleteMessageHandler.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsNoDeleteMessageHandler.java deleted file mode 100644 index e96dc5581..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/handlers/SqsNoDeleteMessageHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.handlers; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import software.amazon.lambda.powertools.sqs.SqsLargeMessage; - -public class SqsNoDeleteMessageHandler implements RequestHandler { - - @Override - @SqsLargeMessage(deletePayloads = false) - public String handleRequest(SQSEvent sqsEvent, Context context) { - return sqsEvent.getRecords().get(0).getBody(); - } -} \ No newline at end of file diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspectTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspectTest.java deleted file mode 100644 index 535da11c7..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsLargeMessageAspectTest.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.internal; - -import static com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; -import static software.amazon.lambda.powertools.sqs.internal.SqsLargeMessageAspect.FailedProcessingLargePayloadException; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.function.Consumer; -import java.util.stream.Stream; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import software.amazon.awssdk.core.ResponseInputStream; -import software.amazon.awssdk.core.exception.SdkClientException; -import software.amazon.awssdk.http.AbortableInputStream; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; -import software.amazon.awssdk.services.s3.model.GetObjectRequest; -import software.amazon.awssdk.services.s3.model.GetObjectResponse; -import software.amazon.awssdk.services.s3.model.S3Exception; -import software.amazon.awssdk.utils.StringInputStream; -import software.amazon.lambda.powertools.sqs.SqsUtils; -import software.amazon.lambda.powertools.sqs.handlers.LambdaHandlerApiGateway; -import software.amazon.lambda.powertools.sqs.handlers.SqsMessageHandler; -import software.amazon.lambda.powertools.sqs.handlers.SqsNoDeleteMessageHandler; - -public class SqsLargeMessageAspectTest { - - private static final String BUCKET_NAME = "bucketname"; - private static final String BUCKET_KEY = "c71eb2ae-37e0-4265-8909-32f4153faddf"; - private RequestHandler requestHandler; - @Mock - private Context context; - @Mock - private S3Client s3Client; - - private static Stream exception() { - return Stream.of(Arguments.of(S3Exception.builder() - .message("Service Exception") - .build()), - Arguments.of(SdkClientException.builder() - .message("Client Exception") - .build())); - } - - @BeforeEach - void setUp() { - openMocks(this); - setupContext(); - SqsUtils.overrideS3Client(s3Client); - requestHandler = new SqsMessageHandler(); - } - - @Test - public void testLargeMessage() { - when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); - SQSEvent sqsEvent = messageWithBody( - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + - "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]"); - - String response = requestHandler.handleRequest(sqsEvent, context); - - assertThat(response) - .isEqualTo("A big message"); - - ArgumentCaptor delete = ArgumentCaptor.forClass(DeleteObjectRequest.class); - - verify(s3Client).deleteObject(delete.capture()); - - Assertions.assertThat(delete.getValue()) - .satisfies((Consumer) deleteObjectRequest -> - { - assertThat(deleteObjectRequest.bucket()) - .isEqualTo(BUCKET_NAME); - - assertThat(deleteObjectRequest.key()) - .isEqualTo(BUCKET_KEY); - }); - } - - @Test - public void shouldNotProcessSmallMessageBody() { - when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); - - SQSEvent sqsEvent = messageWithBody("This is small message"); - - String response = requestHandler.handleRequest(sqsEvent, context); - - assertThat(response) - .isEqualTo("This is small message"); - - verifyNoInteractions(s3Client); - } - - @ParameterizedTest - @MethodSource("exception") - public void shouldFailEntireBatchIfFailedDownloadingFromS3(RuntimeException exception) { - when(s3Client.getObject(any(GetObjectRequest.class))).thenThrow(exception); - - String messageBody = - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + - "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]"; - SQSEvent sqsEvent = messageWithBody(messageBody); - - assertThatExceptionOfType(FailedProcessingLargePayloadException.class) - .isThrownBy(() -> requestHandler.handleRequest(sqsEvent, context)) - .withCause(exception); - - verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class)); - } - - @Test - public void testLargeMessageWithDeletionOff() { - requestHandler = new SqsNoDeleteMessageHandler(); - - when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); - SQSEvent sqsEvent = messageWithBody( - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + - "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]"); - - String response = requestHandler.handleRequest(sqsEvent, context); - - assertThat(response).isEqualTo("A big message"); - - verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class)); - } - - @Test - public void shouldFailEntireBatchIfFailedProcessingDownloadMessageFromS3() { - ResponseInputStream s3Response = - new ResponseInputStream<>(GetObjectResponse.builder().build(), - AbortableInputStream.create(new StringInputStream("test") { - @Override - public void close() throws IOException { - throw new IOException("Failed"); - } - })); - - when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response); - - String messageBody = - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + - "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]"; - SQSEvent sqsEvent = messageWithBody(messageBody); - - assertThatExceptionOfType(FailedProcessingLargePayloadException.class) - .isThrownBy(() -> requestHandler.handleRequest(sqsEvent, context)) - .withCauseInstanceOf(IOException.class); - - verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class)); - } - - @Test - public void shouldNotDoAnyProcessingWhenNotSqsEvent() { - LambdaHandlerApiGateway handler = new LambdaHandlerApiGateway(); - - String messageBody = - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + - "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]"; - - APIGatewayProxyRequestEvent event = new APIGatewayProxyRequestEvent(); - event.setBody(messageBody); - String response = handler.handleRequest(event, context); - - assertThat(response) - .isEqualTo(messageBody); - - verifyNoInteractions(s3Client); - } - - private ResponseInputStream s3ObjectWithLargeMessage() { - return new ResponseInputStream<>(GetObjectResponse.builder().build(), - AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes()))); - } - - private SQSEvent messageWithBody(String messageBody) { - SQSMessage sqsMessage = new SQSMessage(); - sqsMessage.setBody(messageBody); - SQSEvent sqsEvent = new SQSEvent(); - sqsEvent.setRecords(singletonList(sqsMessage)); - return sqsEvent; - } - - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - } -} \ No newline at end of file diff --git a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java b/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java deleted file mode 100644 index c0211cb83..000000000 --- a/powertools-sqs/src/test/java/software/amazon/lambda/powertools/sqs/internal/SqsMessageBatchProcessorAspectTest.java +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.sqs.internal; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; -import static software.amazon.lambda.powertools.sqs.SqsUtils.overrideSqsClient; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.util.HashMap; -import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import software.amazon.awssdk.services.sqs.SqsClient; -import software.amazon.awssdk.services.sqs.model.BatchResultErrorEntry; -import software.amazon.awssdk.services.sqs.model.DeleteMessageBatchRequest; -import software.amazon.awssdk.services.sqs.model.GetQueueAttributesRequest; -import software.amazon.awssdk.services.sqs.model.GetQueueAttributesResponse; -import software.amazon.awssdk.services.sqs.model.QueueAttributeName; -import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; -import software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse; -import software.amazon.lambda.powertools.sqs.SQSBatchProcessingException; -import software.amazon.lambda.powertools.sqs.handlers.LambdaHandlerApiGateway; -import software.amazon.lambda.powertools.sqs.handlers.PartialBatchFailureSuppressedHandler; -import software.amazon.lambda.powertools.sqs.handlers.PartialBatchPartialFailureHandler; -import software.amazon.lambda.powertools.sqs.handlers.PartialBatchSuccessHandler; -import software.amazon.lambda.powertools.sqs.handlers.SqsMessageHandlerWithNonRetryableHandler; -import software.amazon.lambda.powertools.sqs.handlers.SqsMessageHandlerWithNonRetryableHandlerWithDelete; - -public class SqsMessageBatchProcessorAspectTest { - public static final SqsClient interactionClient = mock(SqsClient.class); - private static final SqsClient sqsClient = mock(SqsClient.class); - private static final ObjectMapper MAPPER = new ObjectMapper(); - private final Context context = mock(Context.class); - private SQSEvent event; - private RequestHandler requestHandler; - - @BeforeEach - void setUp() throws IOException { - overrideSqsClient(sqsClient); - reset(interactionClient); - reset(sqsClient); - setupContext(); - event = MAPPER.readValue(this.getClass().getResource("/sampleSqsBatchEvent.json"), SQSEvent.class); - requestHandler = new PartialBatchSuccessHandler(); - } - - @Test - void shouldBatchProcessAllMessageSuccessfullyAndNotDeleteFromSQS() { - requestHandler.handleRequest(event, context); - - verify(interactionClient, times(2)).listQueues(); - verify(sqsClient, times(0)).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - } - - @Test - void shouldBatchProcessMessageWithSuccessDeletedOnFailureInBatchFromSQS() { - requestHandler = new PartialBatchPartialFailureHandler(); - - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> requestHandler.handleRequest(event, context)) - .satisfies(e -> - { - assertThat(e.getExceptions()) - .hasSize(1) - .extracting("message") - .containsExactly("2e1424d4-f796-459a-8184-9c92662be6da"); - - assertThat(e.getFailures()) - .hasSize(1) - .extracting("messageId") - .containsExactly("2e1424d4-f796-459a-8184-9c92662be6da"); - - assertThat(e.successMessageReturnValues()) - .hasSize(1) - .contains("Success"); - }); - - verify(interactionClient).listQueues(); - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - } - - @Test - void shouldBatchProcessMessageWithSuccessDeletedOnFailureWithSuppressionInBatchFromSQS() { - requestHandler = new PartialBatchFailureSuppressedHandler(); - - requestHandler.handleRequest(event, context); - - verify(interactionClient).listQueues(); - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - } - - @Test - void shouldNotTakeEffectOnNonSqsEventHandler() { - LambdaHandlerApiGateway handlerApiGateway = new LambdaHandlerApiGateway(); - - handlerApiGateway.handleRequest(mock(APIGatewayProxyRequestEvent.class), context); - - verifyNoInteractions(sqsClient); - } - - @Test - void shouldBatchProcessAndMoveNonRetryableExceptionToDlq() { - requestHandler = new SqsMessageHandlerWithNonRetryableHandler(); - event.getRecords().get(0).setMessageId(""); - - HashMap attributes = new HashMap<>(); - - attributes.put(QueueAttributeName.REDRIVE_POLICY, "{\n" + - " \"deadLetterTargetArn\": \"arn:aws:sqs:us-east-2:123456789012:retry-queue\",\n" + - " \"maxReceiveCount\": 2\n" + - "}"); - - when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn( - GetQueueAttributesResponse.builder() - .attributes(attributes) - .build()); - - requestHandler.handleRequest(event, context); - - verify(interactionClient).listQueues(); - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - verify(sqsClient).sendMessageBatch(any(SendMessageBatchRequest.class)); - } - - @Test - void shouldBatchProcessAndThrowExceptionForNonRetryableExceptionWhenMoveToDlqReturnFailedResponse() { - requestHandler = new SqsMessageHandlerWithNonRetryableHandler(); - event.getRecords().get(0).setMessageId(""); - - when(sqsClient.sendMessageBatch(any(SendMessageBatchRequest.class))).thenReturn( - SendMessageBatchResponse.builder() - .failed(BatchResultErrorEntry.builder() - .message("Permission Error") - .code("KMS.AccessDeniedException") - .senderFault(true) - .build()) - .build()); - - HashMap attributes = new HashMap<>(); - - attributes.put(QueueAttributeName.REDRIVE_POLICY, "{\n" + - " \"deadLetterTargetArn\": \"arn:aws:sqs:us-east-2:123456789012:retry-queue\",\n" + - " \"maxReceiveCount\": 2\n" + - "}"); - - when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn( - GetQueueAttributesResponse.builder() - .attributes(attributes) - .build()); - - Assertions.assertThatExceptionOfType(SQSBatchProcessingException.class). - isThrownBy(() -> requestHandler.handleRequest(event, context)); - - verify(interactionClient).listQueues(); - verify(sqsClient).sendMessageBatch(any(SendMessageBatchRequest.class)); - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - } - - @Test - void shouldBatchProcessAndDeleteNonRetryableExceptionMessage() { - requestHandler = new SqsMessageHandlerWithNonRetryableHandlerWithDelete(); - event.getRecords().get(0).setMessageId(""); - - requestHandler.handleRequest(event, context); - - verify(interactionClient).listQueues(); - ArgumentCaptor captor = ArgumentCaptor.forClass(DeleteMessageBatchRequest.class); - verify(sqsClient).deleteMessageBatch(captor.capture()); - verify(sqsClient, never()).sendMessageBatch(any(SendMessageBatchRequest.class)); - verify(sqsClient, never()).getQueueAttributes(any(GetQueueAttributesRequest.class)); - - assertThat(captor.getValue()) - .satisfies(deleteMessageBatchRequest -> assertThat(deleteMessageBatchRequest.entries()) - .hasSize(2) - .extracting("id") - .contains("", "2e1424d4-f796-459a-8184-9c92662be6da")); - } - - @Test - void shouldBatchProcessAndFailWithExceptionForNonRetryableExceptionAndNoDlq() { - requestHandler = new SqsMessageHandlerWithNonRetryableHandler(); - - event.getRecords().get(0).setMessageId(""); - event.getRecords() - .forEach(sqsMessage -> sqsMessage.setEventSourceArn(sqsMessage.getEventSourceArn() + "-temp")); - - when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn( - GetQueueAttributesResponse.builder() - .build()); - - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> requestHandler.handleRequest(event, context)) - .satisfies(e -> - { - assertThat(e.getExceptions()) - .hasSize(1) - .extracting("message") - .containsExactly("Invalid message and was moved to DLQ"); - - assertThat(e.getFailures()) - .hasSize(1) - .extracting("messageId") - .containsExactly(""); - - assertThat(e.successMessageReturnValues()) - .hasSize(1) - .contains("Success"); - }); - - verify(interactionClient).listQueues(); - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - verify(sqsClient, never()).sendMessageBatch(any(SendMessageBatchRequest.class)); - } - - @Test - void shouldBatchProcessAndFailWithExceptionForNonRetryableExceptionWhenFailedParsingPolicy() { - requestHandler = new SqsMessageHandlerWithNonRetryableHandler(); - event.getRecords().get(0).setMessageId(""); - event.getRecords() - .forEach(sqsMessage -> sqsMessage.setEventSourceArn(sqsMessage.getEventSourceArn() + "-temp-queue")); - - HashMap attributes = new HashMap<>(); - - attributes.put(QueueAttributeName.REDRIVE_POLICY, "MalFormedRedrivePolicy"); - - when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn( - GetQueueAttributesResponse.builder() - .attributes(attributes) - .build()); - - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> requestHandler.handleRequest(event, context)) - .satisfies(e -> - { - assertThat(e.getExceptions()) - .hasSize(1) - .extracting("message") - .containsExactly("Invalid message and was moved to DLQ"); - - assertThat(e.getFailures()) - .hasSize(1) - .extracting("messageId") - .containsExactly(""); - - assertThat(e.successMessageReturnValues()) - .hasSize(1) - .contains("Success"); - }); - - verify(interactionClient).listQueues(); - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - verify(sqsClient, never()).sendMessageBatch(any(SendMessageBatchRequest.class)); - } - - @Test - void shouldBatchProcessAndMoveNonRetryableExceptionToDlqAndThrowException() throws IOException { - requestHandler = new SqsMessageHandlerWithNonRetryableHandler(); - event = MAPPER.readValue(this.getClass().getResource("/threeMessageSqsBatchEvent.json"), SQSEvent.class); - - event.getRecords().get(1).setMessageId(""); - - HashMap attributes = new HashMap<>(); - - attributes.put(QueueAttributeName.REDRIVE_POLICY, "{\n" + - " \"deadLetterTargetArn\": \"arn:aws:sqs:us-east-2:123456789012:retry-queue\",\n" + - " \"maxReceiveCount\": 2\n" + - "}"); - - when(sqsClient.getQueueAttributes(any(GetQueueAttributesRequest.class))).thenReturn( - GetQueueAttributesResponse.builder() - .attributes(attributes) - .build()); - - assertThatExceptionOfType(SQSBatchProcessingException.class) - .isThrownBy(() -> requestHandler.handleRequest(event, context)) - .satisfies(e -> - { - assertThat(e.getExceptions()) - .hasSize(1) - .extracting("message") - .containsExactly("Invalid message and should be reprocessed"); - - assertThat(e.getFailures()) - .hasSize(1) - .extracting("messageId") - .containsExactly("2e1424d4-f796-459a-9696-9c92662ba5da"); - - assertThat(e.successMessageReturnValues()) - .hasSize(1) - .contains("Success"); - }); - - verify(interactionClient).listQueues(); - verify(sqsClient).deleteMessageBatch(any(DeleteMessageBatchRequest.class)); - verify(sqsClient).sendMessageBatch(any(SendMessageBatchRequest.class)); - } - - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - } -} \ No newline at end of file diff --git a/powertools-sqs/src/test/resources/SqsFifoBatchEvent.json b/powertools-sqs/src/test/resources/SqsFifoBatchEvent.json deleted file mode 100644 index 726e45ea1..000000000 --- a/powertools-sqs/src/test/resources/SqsFifoBatchEvent.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "Records": [ - { - "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d", - "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082649183", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082649185", - "MessageGroupId": "Group1" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceARN": "arn:aws:sqs:us-east-1:906126917321:sqs-lambda-MySqsQueue-4DYWWJIE97N5", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6da", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649", - "MessageGroupId": "Group2" - }, - "messageAttributes": { - "Attribute3" : { - "binaryValue" : "MTEwMA==", - "dataType" : "Binary" - }, - "Attribute2" : { - "stringValue" : "123", - "dataType" : "Number" - }, - "Attribute1" : { - "stringValue" : "AttributeValue1", - "dataType" : "String" - } - }, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceARN": "arn:aws:sqs:us-east-1:906126917321:sqs-lambda-MySqsQueue-4DYWWJIE97N5", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-9696-9c92662ba5da", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649", - "MessageGroupId": "Group1" - }, - "messageAttributes": { - "Attribute2" : { - "stringValue" : "123", - "dataType" : "Number" - } - }, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceARN": "arn:aws:sqs:us-east-1:906126917321:sqs-lambda-MySqsQueue-4DYWWJIE97N5", - "awsRegion": "us-east-2" - } - ] -} \ No newline at end of file diff --git a/powertools-sqs/src/test/resources/sampleSqsBatchEvent.json b/powertools-sqs/src/test/resources/sampleSqsBatchEvent.json deleted file mode 100644 index 8a5fbf309..000000000 --- a/powertools-sqs/src/test/resources/sampleSqsBatchEvent.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "records": [ - { - "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d", - "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082649183", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082649185" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6da", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - } - ] -} \ No newline at end of file diff --git a/powertools-sqs/src/test/resources/sampleSqsBatchEventBatchSize25.json b/powertools-sqs/src/test/resources/sampleSqsBatchEventBatchSize25.json deleted file mode 100644 index 31b8862ad..000000000 --- a/powertools-sqs/src/test/resources/sampleSqsBatchEventBatchSize25.json +++ /dev/null @@ -1,404 +0,0 @@ -{ - "records": [ - { - "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d", - "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082649183", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082649185" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6da", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d3", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d4", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b5", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d6", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b7", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d8", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d9", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d10", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d11", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d12", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d13", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d14", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d15", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d16", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d17", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d18", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d19", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d20", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d21", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d22", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d23", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d24", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d25", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d26", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6d27", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-2:123456789012:my-queue", - "awsRegion": "us-east-2" - } - ] -} \ No newline at end of file diff --git a/powertools-sqs/src/test/resources/threeMessageSqsBatchEvent.json b/powertools-sqs/src/test/resources/threeMessageSqsBatchEvent.json deleted file mode 100644 index b3b61da3b..000000000 --- a/powertools-sqs/src/test/resources/threeMessageSqsBatchEvent.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "records": [ - { - "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d", - "receiptHandle": "AQEBwJnKyrHigUMZj6rYigCgxlaS3SLy0a...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082649183", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082649185" - }, - "messageAttributes": {}, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-1:906126917321:sqs-lambda-MySqsQueue-4DYWWJIE97N5", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-8184-9c92662be6da", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": { - "Attribute3" : { - "binaryValue" : "MTEwMA==", - "dataType" : "Binary" - }, - "Attribute2" : { - "stringValue" : "123", - "dataType" : "Number" - }, - "Attribute1" : { - "stringValue" : "AttributeValue1", - "dataType" : "String" - } - }, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-1:906126917321:sqs-lambda-MySqsQueue-4DYWWJIE97N5", - "awsRegion": "us-east-2" - }, - { - "messageId": "2e1424d4-f796-459a-9696-9c92662ba5da", - "receiptHandle": "AQEBzWwaftRI0KuVm4tP+/7q1rGgNqicHq...", - "body": "Test message.", - "attributes": { - "ApproximateReceiveCount": "1", - "SentTimestamp": "1545082650636", - "SenderId": "AIDAIENQZJOLO23YVJ4VO", - "ApproximateFirstReceiveTimestamp": "1545082650649" - }, - "messageAttributes": { - "Attribute2" : { - "stringValue" : "123", - "dataType" : "Number" - } - }, - "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3", - "eventSource": "aws:sqs", - "eventSourceArn": "arn:aws:sqs:us-east-1:906126917321:sqs-lambda-MySqsQueue-4DYWWJIE97N5", - "awsRegion": "us-east-2" - } - ] -} \ No newline at end of file diff --git a/powertools-test-suite/pom.xml b/powertools-test-suite/pom.xml deleted file mode 100644 index 4a79d2987..000000000 --- a/powertools-test-suite/pom.xml +++ /dev/null @@ -1,164 +0,0 @@ - - - - - 4.0.0 - - powertools-test-suite - jar - - - powertools-parent - software.amazon.lambda - 1.17.0-SNAPSHOT - - - Powertools for AWS Lambda (Java) library Test Suite - - A suite of tests for interactions between the various Powertools for AWS Lambda (Java) modules. - - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - true - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - - - - - software.amazon.lambda - powertools-core - - - org.apache.logging.log4j - log4j-jcl - - - com.amazonaws - aws-lambda-java-core - - - com.amazonaws - aws-lambda-java-events - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-sqs - - - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - org.apache.commons - commons-lang3 - test - - - org.mockito - mockito-core - test - - - org.aspectj - aspectjweaver - test - - - org.assertj - assertj-core - test - - - org.skyscreamer - jsonassert - test - - - - - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-sqs - - - - - - - compile - - - - - - - \ No newline at end of file diff --git a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/LoggingOrderTest.java b/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/LoggingOrderTest.java deleted file mode 100644 index 9e9c464a6..000000000 --- a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/LoggingOrderTest.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.testsuite; - - -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonList; -import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification; -import com.amazonaws.xray.AWSXRay; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.channels.FileChannel; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.Map; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.ThreadContext; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import software.amazon.awssdk.core.ResponseInputStream; -import software.amazon.awssdk.http.AbortableInputStream; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.GetObjectRequest; -import software.amazon.awssdk.services.s3.model.GetObjectResponse; -import software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor; -import software.amazon.lambda.powertools.logging.internal.LambdaLoggingAspect; -import software.amazon.lambda.powertools.sqs.SqsUtils; -import software.amazon.lambda.powertools.testsuite.handler.LoggingOrderMessageHandler; -import software.amazon.lambda.powertools.testsuite.handler.TracingLoggingStreamMessageHandler; - -public class LoggingOrderTest { - - private static final String BUCKET_NAME = "ms-extended-sqs-client"; - private static final String BUCKET_KEY = "c71eb2ae-37e0-4265-8909-32f4153faddf"; - - @Mock - private Context context; - - @Mock - private S3Client s3Client; - - @BeforeEach - void setUp() throws IllegalAccessException, IOException, NoSuchMethodException, InvocationTargetException { - openMocks(this); - SqsUtils.overrideS3Client(s3Client); - ThreadContext.clearAll(); - writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); - //Make sure file is cleaned up before running full stack logging regression - FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); - resetLogLevel(Level.INFO); - AWSXRay.beginSegment(LoggingOrderTest.class.getName()); - } - - @AfterEach - void tearDown() { - AWSXRay.endSegment(); - } - - /** - * The SQSEvent payload will be altered by the @SqsLargeMessage annotation. Logging of the event should happen - * after the event has been altered - */ - @Test - public void testThatLoggingAnnotationActsLast() throws IOException { - ResponseInputStream s3Response = - new ResponseInputStream<>(GetObjectResponse.builder().build(), - AbortableInputStream.create(new ByteArrayInputStream("A big message".getBytes()))); - - when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3Response); - SQSEvent sqsEvent = messageWithBody( - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"" + BUCKET_NAME + - "\",\"s3Key\":\"" + BUCKET_KEY + "\"}]"); - - LoggingOrderMessageHandler requestHandler = new LoggingOrderMessageHandler(); - requestHandler.handleRequest(sqsEvent, context); - - assertThat(Files.lines(Paths.get("target/logfile.json"))) - .hasSize(2) - .satisfies(line -> - { - Map actual = parseToMap(line.get(0)); - - String message = actual.get("message").toString(); - - assertThat(message) - .contains("A big message"); - }); - } - - @Test - public void testLoggingAnnotationActsAfterTracingForStreamingHandler() throws IOException { - - ByteArrayOutputStream output = new ByteArrayOutputStream(); - S3EventNotification s3EventNotification = s3EventNotification(); - - TracingLoggingStreamMessageHandler handler = new TracingLoggingStreamMessageHandler(); - handler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(s3EventNotification)), - output, context); - - assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) - .isNotEmpty(); - } - - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } - - private void resetLogLevel(Level level) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - Method resetLogLevels = LambdaLoggingAspect.class.getDeclaredMethod("resetLogLevels", Level.class); - resetLogLevels.setAccessible(true); - resetLogLevels.invoke(null, level); - writeStaticField(LambdaLoggingAspect.class, "LEVEL_AT_INITIALISATION", level, true); - } - - private Map parseToMap(String stringAsJson) { - try { - return new ObjectMapper().readValue(stringAsJson, Map.class); - } catch (JsonProcessingException e) { - fail("Failed parsing logger line " + stringAsJson); - return emptyMap(); - } - } - - private S3EventNotification s3EventNotification() { - S3EventNotification.S3EventNotificationRecord record = - new S3EventNotification.S3EventNotificationRecord("us-west-2", - "ObjectCreated:Put", - "aws:s3", - null, - "2.1", - new S3EventNotification.RequestParametersEntity("127.0.0.1"), - new S3EventNotification.ResponseElementsEntity("C3D13FE58DE4C810", - "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"), - new S3EventNotification.S3Entity("testConfigRule", - new S3EventNotification.S3BucketEntity("mybucket", - new S3EventNotification.UserIdentityEntity("A3NL1KOZZKExample"), - "arn:aws:s3:::mybucket"), - new S3EventNotification.S3ObjectEntity("HappyFace.jpg", - 1024L, - "d41d8cd98f00b204e9800998ecf8427e", - "096fKKXTRTtl3on89fVO.nfljtsv6qko", - "0055AED6DCD90281E5"), - "1.0"), - new S3EventNotification.UserIdentityEntity("AIDAJDPLRKLG7UEXAMPLE") - ); - - return new S3EventNotification(singletonList(record)); - } - - private SQSEvent messageWithBody(String messageBody) { - SQSEvent.SQSMessage sqsMessage = new SQSEvent.SQSMessage(); - sqsMessage.setBody(messageBody); - SQSEvent sqsEvent = new SQSEvent(); - sqsEvent.setRecords(singletonList(sqsMessage)); - return sqsEvent; - } -} \ No newline at end of file diff --git a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/LoggingOrderMessageHandler.java b/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/LoggingOrderMessageHandler.java deleted file mode 100644 index 5592b1fd3..000000000 --- a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/LoggingOrderMessageHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.testsuite.handler; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.sqs.SqsLargeMessage; - -public class LoggingOrderMessageHandler implements RequestHandler { - - @Override - @SqsLargeMessage - @Logging(logEvent = true) - public String handleRequest(SQSEvent sqsEvent, Context context) { - return sqsEvent.getRecords().get(0).getBody(); - } -} diff --git a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/TracingLoggingStreamMessageHandler.java b/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/TracingLoggingStreamMessageHandler.java deleted file mode 100644 index 4a60d0949..000000000 --- a/powertools-test-suite/src/test/java/software/amazon/lambda/powertools/testsuite/handler/TracingLoggingStreamMessageHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.testsuite.handler; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Map; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.tracing.Tracing; - -public class TracingLoggingStreamMessageHandler implements RequestStreamHandler { - - @Logging(logEvent = true) - @Tracing - @Override - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - ObjectMapper mapper = new ObjectMapper(); - mapper.writeValue(output, mapper.readValue(input, Map.class)); - } -} diff --git a/powertools-test-suite/src/test/resources/log4j2.xml b/powertools-test-suite/src/test/resources/log4j2.xml deleted file mode 100644 index 8ac9b34ce..000000000 --- a/powertools-test-suite/src/test/resources/log4j2.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 23261c7cf82c57778317b57142e89ef4cb08c737 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 7 Aug 2023 18:39:26 +0100 Subject: [PATCH 002/577] v2: fix version (#1348) --- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-core/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 0cd62e326..aca250dae 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-examples - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT pom Powertools for AWS Lambda (Java) library Examples diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index d3c4bc49b..10e15d532 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-examples-batch jar Powertools for AWS Lambda (Java) library Examples - Batch diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 35d5e340c..c9fe249b3 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-examples-cloudformation jar diff --git a/examples/powertools-examples-core/pom.xml b/examples/powertools-examples-core/pom.xml index a5d854d6b..d402ce09c 100644 --- a/examples/powertools-examples-core/pom.xml +++ b/examples/powertools-examples-core/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-examples-core jar diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index f24b2ffc4..38682e164 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-examples-idempotency jar Powertools for AWS Lambda (Java) library Examples - Idempotency diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index c4631fd05..1c7d177f4 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-examples-parameters jar Powertools for AWS Lambda (Java) library Examples - Parameters diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 4974842dd..0ec05cd82 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-examples-serialization jar Powertools for AWS Lambda (Java) library Examples - Serialization diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 1c7e33de0..b3947513f 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-examples-validation jar Powertools for AWS Lambda (Java) library Examples - Validation diff --git a/pom.xml b/pom.xml index bebb2493f..7cdf8a71f 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-parent - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT pom Powertools for AWS Lambda (Java) library Parent diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 9e25dabd8..593b22444 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index a122e7ac8..336a3f94c 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT Powertools for AWS Lambda (Java)library Cloudformation diff --git a/powertools-core/pom.xml b/powertools-core/pom.xml index 78cd735b9..c244f70fc 100644 --- a/powertools-core/pom.xml +++ b/powertools-core/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT Powertools for AWS Lambda (Java) library Core diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 6e82c7aec..49b4b5a20 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -10,7 +10,7 @@ Fake handlers that use Powertools for AWS Lambda (Java). - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT UTF-8 1.8 1.8 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index f3194c163..e8a3273b1 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-e2e-tests diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 2e68ea563..6b9e46a4a 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-parent - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-idempotency diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index a9ded60c5..19793d616 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ software.amazon.lambda powertools-parent - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-large-messages diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 83650fcde..e13a88e57 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT Powertools for AWS Lambda (Java) library Logging diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 7b2e99045..0681ed000 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT Powertools for AWS Lambda (Java) library Metrics diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index fab72a9b7..367996e9c 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-parameters diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 2a57f21e3..c34cddef1 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-serialization diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index b5de90f7b..5f397aa9f 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT Powertools for AWS Lambda (Java) library Tracing diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index daec3aa99..1b939f46f 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT Powertools for AWS Lambda (Java) validation library From be284e24a2c1ca9a35e079a8f2728400119d5040 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Aug 2023 13:57:03 +0200 Subject: [PATCH 003/577] build(deps): bump aws.sdk.version from 2.20.126 to 2.20.127 (#1372) Bumps `aws.sdk.version` from 2.20.126 to 2.20.127. Updates `software.amazon.awssdk:bom` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:http-client-spi` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.127 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.127 Updates `software.amazon.awssdk:s3` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:dynamodb` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:lambda` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.127 Updates `software.amazon.awssdk:cloudwatch` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:xray` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:cloudformation` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:sts` from 2.20.126 to 2.20.127 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index ad1c2eb51..8ce21299d 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -16,7 +16,7 @@ true 1.2.2 3.11.2 - 2.20.126 + 2.20.127 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index e5156adee..e50ab2f3f 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -28,7 +28,7 @@ software.amazon.awssdk url-connection-client - 2.20.126 + 2.20.127 com.amazonaws diff --git a/pom.xml b/pom.xml index d75a731b1..ec0b5ae21 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.126 + 2.20.127 2.14.0 2.1.3 UTF-8 From 424f8883cf01decb0b6ae4ac13ab31a5bb448c77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 13:22:12 +0200 Subject: [PATCH 004/577] build(deps): bump aws.sdk.version from 2.20.109 to 2.20.128 (#1377) Bumps `aws.sdk.version` from 2.20.109 to 2.20.128. Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.128 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.128 Updates `software.amazon.awssdk:sdk-core` from 2.20.109 to 2.20.128 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.128 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.20.109 to 2.20.128 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index d3c4bc49b..2096774b5 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -15,7 +15,7 @@ 1.8 1.8 true - 2.20.109 + 2.20.128 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index e50ab2f3f..bcbab5472 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -28,7 +28,7 @@ software.amazon.awssdk url-connection-client - 2.20.127 + 2.20.128 com.amazonaws From 29f71ddb4373e24549916b1f06a715cfe8d674e2 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Fri, 18 Aug 2023 10:32:45 +0100 Subject: [PATCH 005/577] fix: Roll log4j shade transformer forwards (#1376) * Roll log4j shade transformer forwards * missed one --- examples/powertools-examples-batch/pom.xml | 10 ++++------ .../powertools-examples-cloudformation/pom.xml | 10 ++++------ examples/powertools-examples-core/cdk/app/pom.xml | 10 ++++------ examples/powertools-examples-core/sam/pom.xml | 10 ++++------ examples/powertools-examples-idempotency/pom.xml | 10 ++++------ examples/powertools-examples-sqs/pom.xml | 10 ++++------ powertools-e2e-tests/handlers/pom.xml | 14 ++++++-------- 7 files changed, 30 insertions(+), 44 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 2096774b5..cb7b8242c 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -107,18 +107,16 @@ - - + - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 8ce21299d..c6c12e4d9 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -132,18 +132,16 @@ - - + - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml index a4359e223..7b57bd55d 100644 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ b/examples/powertools-examples-core/cdk/app/pom.xml @@ -107,18 +107,16 @@ - - + - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index bc3667b4f..f1bffb896 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -106,18 +106,16 @@ - - + - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index f24b2ffc4..533f6acfd 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -169,18 +169,16 @@ - - + - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index bcbab5472..b8b6c2578 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -105,18 +105,16 @@ - - + - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 6e82c7aec..dcf8908e7 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -120,19 +120,17 @@ - - + - - io.github.edwgiz - log4j-maven-shade-plugin-extensions - 2.17.2 - + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + From a0ea4c3d9d7b324d9f95a74a593e975869ff1ded Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Aug 2023 14:14:52 +0200 Subject: [PATCH 006/577] build(deps): bump com.amazonaws:aws-lambda-java-core from 1.2.2 to 1.2.3 (#1379) Bumps [com.amazonaws:aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs) from 1.2.2 to 1.2.3. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core/cdk/app/pom.xml | 2 +- examples/powertools-examples-core/sam/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- pom.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index cb7b8242c..418da8fe7 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -37,7 +37,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 software.amazon.awssdk diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index c6c12e4d9..f3b14648f 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 1.8 1.8 true - 1.2.2 + 1.2.3 3.11.2 2.20.127 diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml index 7b57bd55d..a1aba1b8d 100644 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ b/examples/powertools-examples-core/cdk/app/pom.xml @@ -35,7 +35,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 com.amazonaws diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index f1bffb896..4d90bff94 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -35,7 +35,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 com.amazonaws diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 533f6acfd..c6afdcbe2 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -48,7 +48,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 com.amazonaws diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index c4631fd05..dc3395069 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -27,7 +27,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 com.amazonaws diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 4974842dd..459d7a7b2 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -27,7 +27,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 com.amazonaws diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index b8b6c2578..99815d5c0 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -33,7 +33,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 com.amazonaws diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 1c7e33de0..f916930d5 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -41,7 +41,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 diff --git a/pom.xml b/pom.xml index ec0b5ae21..0704c9057 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ 2.14.0 2.1.3 UTF-8 - 1.2.2 + 1.2.3 3.11.2 1.1.2 3.11.0 From e7fb00c4727ae0d26fcca71238ce76d4f87da034 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Aug 2023 14:15:10 +0200 Subject: [PATCH 007/577] build(deps): bump aws.sdk.version from 2.20.127 to 2.20.129 (#1380) Bumps `aws.sdk.version` from 2.20.127 to 2.20.129. Updates `software.amazon.awssdk:bom` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:http-client-spi` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:url-connection-client` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:sqs` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:s3` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:dynamodb` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:lambda` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:kinesis` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:cloudwatch` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:xray` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:cloudformation` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:sts` from 2.20.127 to 2.20.129 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index f3b14648f..d8b2d022d 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -16,7 +16,7 @@ true 1.2.3 3.11.2 - 2.20.127 + 2.20.129 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 99815d5c0..84cbefb2a 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -28,7 +28,7 @@ software.amazon.awssdk url-connection-client - 2.20.128 + 2.20.129 com.amazonaws diff --git a/pom.xml b/pom.xml index 0704c9057..5c6d94795 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.127 + 2.20.129 2.14.0 2.1.3 UTF-8 From cfd45bd04474bc50db08076100b0721171d39696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Mon, 21 Aug 2023 10:22:34 +0200 Subject: [PATCH 008/577] chore:Prep release 1.17.0 (#1381) * chore:prep release 1.17.0 * Update changelog --------- Co-authored-by: scottgerring Co-authored-by: Scott Gerring --- CHANGELOG.md | 22 +++++++++++++++++++ examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- .../pom.xml | 2 +- .../cdk/infra/pom.xml | 2 +- examples/powertools-examples-core/sam/pom.xml | 2 +- .../powertools-examples-idempotency/pom.xml | 2 +- .../powertools-examples-parameters/pom.xml | 2 +- .../powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- .../powertools-examples-validation/pom.xml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-core/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-sqs/pom.xml | 2 +- powertools-test-suite/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 27 files changed, 48 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5619f0bbb..dbb90ce3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,28 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo ## [Unreleased] +## [1.17.0] - 2023-08-21 + +### Added +* Feat: Add Batch Processor module in (#1317) by @scottgerring +* Feat: Add SNS+SQS large messages module (#1310) by @jeromevdl + +### Maintenance +* fix: use default credentials provider for all provided SDK clients in (#1303) by @roamingthings +* Chore: Make request for Logger explicitly for current class in (#1307) by @jreijn +* Chore: checkstyle formater & linter in (#1316) by @jeromevdl +* Chore: Add powertools specific user-agent-suffix to the AWS SDK v2 clients by @eldimi in (#1306) +* Chore: Add 'v2' branch to build workflows to prepare for v2 work in (#1341) by @scottgerring +* Deps: Bump third party dependencies to the latest versions. + +### Documentation +* Docs: Add maintainers guide in (#1326) by @scottgerring +* Docs: improve contributing guide in (#1334) by @jeromevdl +* Docs: Improve example documentation in (#1291) by @scottgerring +* Docs: Add discord + sec disclosure links to readme in (#1311) by @scottgerring +* Docs: Add external examples from AWS SAM CLI App Templates in (#1318) by @AlexeySoshin +* Docs: Add CDK example in (#1321) by @AlexeySoshin + ## [1.16.1] - 2023-07-19 * Fix: idempotency timeout bug (#1285) by @scottgerring diff --git a/examples/pom.xml b/examples/pom.xml index 9689e8d71..652a845a5 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-examples - 1.17.0-SNAPSHOT + 1.17.0 pom Powertools for AWS Lambda (Java) library Examples diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 418da8fe7..aea59e873 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 1.17.0 powertools-examples-batch jar Powertools for AWS Lambda (Java) library Examples - Batch diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index d8b2d022d..8a4834cdf 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 1.17.0 powertools-examples-cloudformation jar diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index 3dc7adb6a..6a244a68d 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -4,7 +4,7 @@ 4.0.0 software.amazon.lambda.examples cdk - 1.17.0-SNAPSHOT + 1.17.0 UTF-8 2.91.0 diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index 4d90bff94..a21d64910 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 1.17.0 powertools-examples-core-sam jar diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index c6afdcbe2..1f194eeb2 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 1.17.0 powertools-examples-idempotency jar Powertools for AWS Lambda (Java) library Examples - Idempotency diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index dc3395069..11d5de24a 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 1.17.0 powertools-examples-parameters jar Powertools for AWS Lambda (Java) library Examples - Parameters diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 459d7a7b2..3674c8b10 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 1.17.0 powertools-examples-serialization jar Powertools for AWS Lambda (Java) library Examples - Serialization diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 84cbefb2a..277c282a4 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 1.17.0 powertools-examples-sqs jar Powertools for AWS Lambda (Java) library Examples - SQS diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index f916930d5..3fdb55412 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 1.17.0 powertools-examples-validation jar Powertools for AWS Lambda (Java) library Examples - Validation diff --git a/pom.xml b/pom.xml index 5c6d94795..3b05583a6 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-parent - 1.17.0-SNAPSHOT + 1.17.0 pom Powertools for AWS Lambda (Java) library Parent diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 9e25dabd8..2243c3097 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 1.17.0-SNAPSHOT + 1.17.0 diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index a122e7ac8..99b4a6fdc 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 Powertools for AWS Lambda (Java)library Cloudformation diff --git a/powertools-core/pom.xml b/powertools-core/pom.xml index 78cd735b9..830405376 100644 --- a/powertools-core/pom.xml +++ b/powertools-core/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 Powertools for AWS Lambda (Java) library Core diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index dcf8908e7..9b3636dbd 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -10,7 +10,7 @@ Fake handlers that use Powertools for AWS Lambda (Java). - 1.17.0-SNAPSHOT + 1.17.0 UTF-8 1.8 1.8 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 534b65d3b..848f7768a 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 powertools-e2e-tests diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 2e68ea563..3f205b321 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-parent - 1.17.0-SNAPSHOT + 1.17.0 powertools-idempotency diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index a9ded60c5..88ace5b4e 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ software.amazon.lambda powertools-parent - 1.17.0-SNAPSHOT + 1.17.0 powertools-large-messages diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 83650fcde..5e1ee339c 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 Powertools for AWS Lambda (Java) library Logging diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 7b2e99045..253b2596f 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 Powertools for AWS Lambda (Java) library Metrics diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index fab72a9b7..74055614a 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 powertools-parameters diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 2a57f21e3..3dd59ba32 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 powertools-serialization diff --git a/powertools-sqs/pom.xml b/powertools-sqs/pom.xml index c21943fba..1e274011d 100644 --- a/powertools-sqs/pom.xml +++ b/powertools-sqs/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 Powertools for AWS Lambda (Java) library SQS diff --git a/powertools-test-suite/pom.xml b/powertools-test-suite/pom.xml index 4a79d2987..4969f171a 100644 --- a/powertools-test-suite/pom.xml +++ b/powertools-test-suite/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 Powertools for AWS Lambda (Java) library Test Suite diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index b5de90f7b..afe4cb570 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 Powertools for AWS Lambda (Java) library Tracing diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index daec3aa99..ad8e192fd 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0-SNAPSHOT + 1.17.0 Powertools for AWS Lambda (Java) validation library From 7b0af2c433e49876e9f18f4c42f08dfddcf603fc Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 21 Aug 2023 09:48:22 +0100 Subject: [PATCH 009/577] chore: Fix missing version change pieces (#1382) * Add missing bits * And fixed the fix --- README.md | 6 +++--- mkdocs.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 70cfab314..e120bfb00 100644 --- a/README.md +++ b/README.md @@ -20,17 +20,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your software.amazon.lambda powertools-tracing - 1.16.1 + 1.17.0 software.amazon.lambda powertools-logging - 1.16.1 + 1.17.0 software.amazon.lambda powertools-metrics - 1.16.1 + 1.17.0 ... diff --git a/mkdocs.yml b/mkdocs.yml index d54ece508..0f9c065a7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -88,7 +88,7 @@ extra_javascript: extra: powertools: - version: 1.16.1 # to update after each release (we do not want snapshot version here) + version: 1.17.0 # to update after each release (we do not want snapshot version here) repo_url: https://github.com/aws-powertools/powertools-lambda-java edit_uri: edit/main/docs From 018e3196c60a0b3fd1522c2f1229ab5129ffc000 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 21 Aug 2023 10:59:38 +0100 Subject: [PATCH 010/577] We shouldn't deploy CDK (#1383) --- examples/powertools-examples-core/cdk/infra/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index 6a244a68d..9a7850b93 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -10,6 +10,7 @@ 2.91.0 [10.0.0,11.0.0) 5.10.0 + true From 1c847957911a2c3a6bd9cdac9c00a1e2552e8915 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 14:04:08 +0200 Subject: [PATCH 011/577] build(deps): bump aws.sdk.version from 2.20.129 to 2.20.130 (#1386) Bumps `aws.sdk.version` from 2.20.129 to 2.20.130. Updates `software.amazon.awssdk:bom` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:http-client-spi` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:url-connection-client` from 2.20.128 to 2.20.130 Updates `software.amazon.awssdk:sqs` from 2.20.128 to 2.20.130 Updates `software.amazon.awssdk:s3` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:dynamodb` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:lambda` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:kinesis` from 2.20.128 to 2.20.130 Updates `software.amazon.awssdk:cloudwatch` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:xray` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:cloudformation` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:sts` from 2.20.129 to 2.20.130 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 8a4834cdf..86bd29f93 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -16,7 +16,7 @@ true 1.2.3 3.11.2 - 2.20.129 + 2.20.130 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 277c282a4..f676e1a73 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -28,7 +28,7 @@ software.amazon.awssdk url-connection-client - 2.20.129 + 2.20.130 com.amazonaws diff --git a/pom.xml b/pom.xml index 3b05583a6..2bd2f9ad2 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.129 + 2.20.130 2.14.0 2.1.3 UTF-8 From 99982d6cd54cf44b9603f31a0548e292a60a5630 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 21 Aug 2023 13:39:10 +0100 Subject: [PATCH 012/577] Fix batch pom (#1385) --- powertools-batch/pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 2243c3097..82d1d57b2 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -9,6 +9,9 @@ 1.17.0 + A suite of utilities that makes batch message processing using AWS Lambda easier. + Powertools for AWS Lambda (Java) batch messages + From b01e3dfa4f23f5a58bc154208fa473f224e8999e Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 21 Aug 2023 13:55:37 +0100 Subject: [PATCH 013/577] Update to snapshot (#1384) --- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core/cdk/infra/pom.xml | 2 +- examples/powertools-examples-core/sam/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-core/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-sqs/pom.xml | 2 +- powertools-test-suite/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 652a845a5..948005546 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-examples - 1.17.0 + 1.18.0-SNAPSHOT pom Powertools for AWS Lambda (Java) library Examples diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index aea59e873..dd75b597b 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0 + 1.18.0-SNAPSHOT powertools-examples-batch jar Powertools for AWS Lambda (Java) library Examples - Batch diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 86bd29f93..93cf4acc1 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0 + 1.18.0-SNAPSHOT powertools-examples-cloudformation jar diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index 9a7850b93..d81118cde 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -4,7 +4,7 @@ 4.0.0 software.amazon.lambda.examples cdk - 1.17.0 + 1.18.0-SNAPSHOT UTF-8 2.91.0 diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index a21d64910..7350542cd 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0 + 1.18.0-SNAPSHOT powertools-examples-core-sam jar diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 1f194eeb2..e9337aafc 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0 + 1.18.0-SNAPSHOT powertools-examples-idempotency jar Powertools for AWS Lambda (Java) library Examples - Idempotency diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 11d5de24a..301247136 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0 + 1.18.0-SNAPSHOT powertools-examples-parameters jar Powertools for AWS Lambda (Java) library Examples - Parameters diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 3674c8b10..18318ff76 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0 + 1.18.0-SNAPSHOT powertools-examples-serialization jar Powertools for AWS Lambda (Java) library Examples - Serialization diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index f676e1a73..5eee08b22 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0 + 1.18.0-SNAPSHOT powertools-examples-sqs jar Powertools for AWS Lambda (Java) library Examples - SQS diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 3fdb55412..3aa8dad2b 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.17.0 + 1.18.0-SNAPSHOT powertools-examples-validation jar Powertools for AWS Lambda (Java) library Examples - Validation diff --git a/pom.xml b/pom.xml index 2bd2f9ad2..d806dcb43 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-parent - 1.17.0 + 1.18.0-SNAPSHOT pom Powertools for AWS Lambda (Java) library Parent diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 82d1d57b2..27bb33a42 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 1.17.0 + 1.18.0-SNAPSHOT A suite of utilities that makes batch message processing using AWS Lambda easier. diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 99b4a6fdc..1347d95a3 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT Powertools for AWS Lambda (Java)library Cloudformation diff --git a/powertools-core/pom.xml b/powertools-core/pom.xml index 830405376..a5460031d 100644 --- a/powertools-core/pom.xml +++ b/powertools-core/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT Powertools for AWS Lambda (Java) library Core diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 9b3636dbd..6507e3104 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -10,7 +10,7 @@ Fake handlers that use Powertools for AWS Lambda (Java). - 1.17.0 + 1.18.0-SNAPSHOT UTF-8 1.8 1.8 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 848f7768a..e13cb65fc 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT powertools-e2e-tests diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 3f205b321..e89df47f7 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-parent - 1.17.0 + 1.18.0-SNAPSHOT powertools-idempotency diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 88ace5b4e..aed8cc2e4 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ software.amazon.lambda powertools-parent - 1.17.0 + 1.18.0-SNAPSHOT powertools-large-messages diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 5e1ee339c..26ad8c243 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT Powertools for AWS Lambda (Java) library Logging diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 253b2596f..cb3acf110 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT Powertools for AWS Lambda (Java) library Metrics diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 74055614a..f99a3d3cd 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT powertools-parameters diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 3dd59ba32..b1f228df7 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT powertools-serialization diff --git a/powertools-sqs/pom.xml b/powertools-sqs/pom.xml index 1e274011d..f824f409d 100644 --- a/powertools-sqs/pom.xml +++ b/powertools-sqs/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT Powertools for AWS Lambda (Java) library SQS diff --git a/powertools-test-suite/pom.xml b/powertools-test-suite/pom.xml index 4969f171a..80b8635f5 100644 --- a/powertools-test-suite/pom.xml +++ b/powertools-test-suite/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT Powertools for AWS Lambda (Java) library Test Suite diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index afe4cb570..d2f14c3e0 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT Powertools for AWS Lambda (Java) library Tracing diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index ad8e192fd..23841777e 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.17.0 + 1.18.0-SNAPSHOT Powertools for AWS Lambda (Java) validation library From 07c31d3e337d2585a08e9d569654440df8149a92 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 21 Aug 2023 16:39:44 +0100 Subject: [PATCH 014/577] Fix batch logging (#1387) --- .../main/java/org/demo/batch/kinesis/KinesisBatchHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java index d9339549b..b188df501 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java @@ -12,7 +12,7 @@ public class KinesisBatchHandler implements RequestHandler { - private final static Logger LOGGER = LogManager.getLogger(org.demo.batch.sqs.SqsBatchHandler.class); + private final static Logger LOGGER = LogManager.getLogger(KinesisBatchHandler.class); private final BatchMessageHandler handler; public KinesisBatchHandler() { From 869192a5756f9a0e54d4c840fd2e79a2bda4a0be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 13:31:35 +0200 Subject: [PATCH 015/577] build(deps): bump aws.sdk.version from 2.20.130 to 2.20.131 (#1389) Bumps `aws.sdk.version` from 2.20.130 to 2.20.131. Updates `software.amazon.awssdk:bom` from 2.20.130 to 2.20.131 Updates `software.amazon.awssdk:http-client-spi` from 2.20.130 to 2.20.131 Updates `software.amazon.awssdk:url-connection-client` from 2.20.128 to 2.20.131 Updates `software.amazon.awssdk:sqs` from 2.20.128 to 2.20.131 Updates `software.amazon.awssdk:s3` from 2.20.130 to 2.20.131 Updates `software.amazon.awssdk:dynamodb` from 2.20.130 to 2.20.131 Updates `software.amazon.awssdk:lambda` from 2.20.130 to 2.20.131 Updates `software.amazon.awssdk:kinesis` from 2.20.128 to 2.20.131 Updates `software.amazon.awssdk:cloudwatch` from 2.20.130 to 2.20.131 Updates `software.amazon.awssdk:xray` from 2.20.130 to 2.20.131 Updates `software.amazon.awssdk:cloudformation` from 2.20.130 to 2.20.131 Updates `software.amazon.awssdk:sts` from 2.20.130 to 2.20.131 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 93cf4acc1..4c4a53039 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -16,7 +16,7 @@ true 1.2.3 3.11.2 - 2.20.130 + 2.20.131 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 5eee08b22..8969662a8 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -28,7 +28,7 @@ software.amazon.awssdk url-connection-client - 2.20.130 + 2.20.131 com.amazonaws diff --git a/pom.xml b/pom.xml index d806dcb43..76cdee1f8 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.130 + 2.20.131 2.14.0 2.1.3 UTF-8 From 69eafe6279135d96091281eea6a605246b151037 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Tue, 22 Aug 2023 13:19:22 +0100 Subject: [PATCH 016/577] chore: V2 update from main (#1365) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build(deps): bump aws.sdk.version from 2.20.119 to 2.20.120 (#1349) Bumps `aws.sdk.version` from 2.20.119 to 2.20.120. Updates `software.amazon.awssdk:bom` from 2.20.119 to 2.20.120 Updates `software.amazon.awssdk:http-client-spi` from 2.20.119 to 2.20.120 Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.120 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.120 Updates `software.amazon.awssdk:s3` from 2.20.119 to 2.20.120 Updates `software.amazon.awssdk:dynamodb` from 2.20.119 to 2.20.120 Updates `software.amazon.awssdk:lambda` from 2.20.119 to 2.20.120 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.120 Updates `software.amazon.awssdk:cloudwatch` from 2.20.119 to 2.20.120 Updates `software.amazon.awssdk:xray` from 2.20.119 to 2.20.120 Updates `software.amazon.awssdk:cloudformation` from 2.20.119 to 2.20.120 Updates `software.amazon.awssdk:sts` from 2.20.119 to 2.20.120 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1350) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.89.0 to 2.90.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.89.0...v2.90.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump aws.sdk.version from 2.20.120 to 2.20.121 (#1351) Bumps `aws.sdk.version` from 2.20.120 to 2.20.121. Updates `software.amazon.awssdk:bom` from 2.20.120 to 2.20.121 Updates `software.amazon.awssdk:http-client-spi` from 2.20.120 to 2.20.121 Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.121 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.121 Updates `software.amazon.awssdk:s3` from 2.20.120 to 2.20.121 Updates `software.amazon.awssdk:dynamodb` from 2.20.120 to 2.20.121 Updates `software.amazon.awssdk:lambda` from 2.20.120 to 2.20.121 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.121 Updates `software.amazon.awssdk:cloudwatch` from 2.20.120 to 2.20.121 Updates `software.amazon.awssdk:xray` from 2.20.120 to 2.20.121 Updates `software.amazon.awssdk:cloudformation` from 2.20.120 to 2.20.121 Updates `software.amazon.awssdk:sts` from 2.20.120 to 2.20.121 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump aws.sdk.version from 2.20.121 to 2.20.122 (#1354) Bumps `aws.sdk.version` from 2.20.121 to 2.20.122. Updates `software.amazon.awssdk:bom` from 2.20.121 to 2.20.122 Updates `software.amazon.awssdk:http-client-spi` from 2.20.121 to 2.20.122 Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.122 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.122 Updates `software.amazon.awssdk:s3` from 2.20.121 to 2.20.122 Updates `software.amazon.awssdk:dynamodb` from 2.20.121 to 2.20.122 Updates `software.amazon.awssdk:lambda` from 2.20.121 to 2.20.122 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.122 Updates `software.amazon.awssdk:cloudwatch` from 2.20.121 to 2.20.122 Updates `software.amazon.awssdk:xray` from 2.20.121 to 2.20.122 Updates `software.amazon.awssdk:cloudformation` from 2.20.121 to 2.20.122 Updates `software.amazon.awssdk:sts` from 2.20.121 to 2.20.122 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump aws.sdk.version from 2.20.122 to 2.20.123 (#1355) Bumps `aws.sdk.version` from 2.20.122 to 2.20.123. Updates `software.amazon.awssdk:bom` from 2.20.122 to 2.20.123 Updates `software.amazon.awssdk:http-client-spi` from 2.20.122 to 2.20.123 Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.123 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.123 Updates `software.amazon.awssdk:s3` from 2.20.122 to 2.20.123 Updates `software.amazon.awssdk:dynamodb` from 2.20.122 to 2.20.123 Updates `software.amazon.awssdk:lambda` from 2.20.122 to 2.20.123 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.123 Updates `software.amazon.awssdk:cloudwatch` from 2.20.122 to 2.20.123 Updates `software.amazon.awssdk:xray` from 2.20.122 to 2.20.123 Updates `software.amazon.awssdk:cloudformation` from 2.20.122 to 2.20.123 Updates `software.amazon.awssdk:sts` from 2.20.122 to 2.20.123 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump aws.sdk.version from 2.20.123 to 2.20.124 (#1356) Bumps `aws.sdk.version` from 2.20.123 to 2.20.124. Updates `software.amazon.awssdk:bom` from 2.20.123 to 2.20.124 Updates `software.amazon.awssdk:http-client-spi` from 2.20.123 to 2.20.124 Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.124 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.124 Updates `software.amazon.awssdk:s3` from 2.20.123 to 2.20.124 Updates `software.amazon.awssdk:dynamodb` from 2.20.123 to 2.20.124 Updates `software.amazon.awssdk:lambda` from 2.20.123 to 2.20.124 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.124 Updates `software.amazon.awssdk:cloudwatch` from 2.20.123 to 2.20.124 Updates `software.amazon.awssdk:xray` from 2.20.123 to 2.20.124 Updates `software.amazon.awssdk:cloudformation` from 2.20.123 to 2.20.124 Updates `software.amazon.awssdk:sts` from 2.20.123 to 2.20.124 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1357) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.90.0 to 2.91.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.90.0...v2.91.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Scott Gerring * docs: Adding CDK example (#1321) * Move the current example, which is for SAM, under /sam directory * Create a new directory for CDK * Add CDK Example as a Maven module * CDK Stack stub * Restructure CDK application info Infra and App projects * Define the build of the project inside the CDK stack * Use default account and region * Add example of setting environment variables in CDK * Remove threads from the examples, as this should be covered by documentation * Add general README for the project * Add specific README for SAM * Add specific README for CDK * Use Java11 syntax for CDK * Refactor the code for clarity * Fix imports * Add outputs example * Add test for the stack * Update examples/powertools-examples-core/README.md Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Update examples/powertools-examples-core/cdk/README.md Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Remove unnecessary .gitignore * Mixed log level and sample rate * Combine .gitignore files * Remove `cdk ls`, since there's just a single stack * Remove SAM mentions from the CDK readme * Replace "architecture" with "tool" while talking about SAM/CDK * Update examples/powertools-examples-core/README.md Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Update examples/powertools-examples-core/README.md Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Reformat imports * Don't include version number in the HelloWorld jar * Update examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Add Streaming example as well * Update examples/powertools-examples-core/README.md Co-authored-by: Scott Gerring * Update examples/.gitignore Co-authored-by: Scott Gerring * Update examples/.gitignore Co-authored-by: Scott Gerring * Update examples/powertools-examples-core/README.md Co-authored-by: Scott Gerring * Update examples/powertools-examples-core/cdk/README.md Co-authored-by: Scott Gerring * Update examples/powertools-examples-core/sam/README.md Co-authored-by: Scott Gerring * Exclude examples from duplicate code scan https://github.com/aws-powertools/powertools-lambda-java/pull/1317/files * Fix broken link to the events file * Trim cdk.json * Trim cdk.json * Downgrade code to Java 8 * Correct README to point to powertools-core-idempotency for a quick start * Add the missing license to the new Java files * Reformat code --------- Co-authored-by: Scott Gerring Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * build(deps-dev): bump org.yaml:snakeyaml from 2.0 to 2.1 (#1344) Bumps [org.yaml:snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) from 2.0 to 2.1. - [Commits](https://bitbucket.org/snakeyaml/snakeyaml/branches/compare/snakeyaml-2.1..snakeyaml-2.0) --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Scott Gerring * build(deps): bump org.apache.maven.plugins:maven-compiler-plugin (#1360) Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.8.1 to 3.11.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.8.1...maven-compiler-plugin-3.11.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps-dev): bump org.junit.jupiter:junit-jupiter (#1362) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.7.1 to 5.10.0. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.7.1...r5.10.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump aws.sdk.version from 2.20.124 to 2.20.125 (#1361) Bumps `aws.sdk.version` from 2.20.124 to 2.20.125. Updates `software.amazon.awssdk:bom` from 2.20.124 to 2.20.125 Updates `software.amazon.awssdk:http-client-spi` from 2.20.124 to 2.20.125 Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.125 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.125 Updates `software.amazon.awssdk:s3` from 2.20.124 to 2.20.125 Updates `software.amazon.awssdk:dynamodb` from 2.20.124 to 2.20.125 Updates `software.amazon.awssdk:lambda` from 2.20.124 to 2.20.125 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.125 Updates `software.amazon.awssdk:cloudwatch` from 2.20.124 to 2.20.125 Updates `software.amazon.awssdk:xray` from 2.20.124 to 2.20.125 Updates `software.amazon.awssdk:cloudformation` from 2.20.124 to 2.20.125 Updates `software.amazon.awssdk:sts` from 2.20.124 to 2.20.125 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump org.codehaus.mojo:exec-maven-plugin (#1366) Bumps [org.codehaus.mojo:exec-maven-plugin](https://github.com/mojohaus/exec-maven-plugin) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/mojohaus/exec-maven-plugin/releases) - [Commits](https://github.com/mojohaus/exec-maven-plugin/compare/exec-maven-plugin-3.0.0...exec-maven-plugin-3.1.0) --- updated-dependencies: - dependency-name: org.codehaus.mojo:exec-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1368) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.88.0 to 2.91.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.88.0...v2.91.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump aws.sdk.version from 2.20.125 to 2.20.126 (#1367) Bumps `aws.sdk.version` from 2.20.125 to 2.20.126. Updates `software.amazon.awssdk:bom` from 2.20.125 to 2.20.126 Updates `software.amazon.awssdk:http-client-spi` from 2.20.125 to 2.20.126 Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.126 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.126 Updates `software.amazon.awssdk:s3` from 2.20.125 to 2.20.126 Updates `software.amazon.awssdk:dynamodb` from 2.20.125 to 2.20.126 Updates `software.amazon.awssdk:lambda` from 2.20.125 to 2.20.126 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.126 Updates `software.amazon.awssdk:cloudwatch` from 2.20.125 to 2.20.126 Updates `software.amazon.awssdk:xray` from 2.20.125 to 2.20.126 Updates `software.amazon.awssdk:cloudformation` from 2.20.125 to 2.20.126 Updates `software.amazon.awssdk:sts` from 2.20.125 to 2.20.126 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump aws.sdk.version from 2.20.126 to 2.20.127 (#1372) Bumps `aws.sdk.version` from 2.20.126 to 2.20.127. Updates `software.amazon.awssdk:bom` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:http-client-spi` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.127 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.127 Updates `software.amazon.awssdk:s3` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:dynamodb` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:lambda` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.127 Updates `software.amazon.awssdk:cloudwatch` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:xray` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:cloudformation` from 2.20.126 to 2.20.127 Updates `software.amazon.awssdk:sts` from 2.20.126 to 2.20.127 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump aws.sdk.version from 2.20.109 to 2.20.128 (#1377) Bumps `aws.sdk.version` from 2.20.109 to 2.20.128. Updates `software.amazon.awssdk:url-connection-client` from 2.20.109 to 2.20.128 Updates `software.amazon.awssdk:sqs` from 2.20.109 to 2.20.128 Updates `software.amazon.awssdk:sdk-core` from 2.20.109 to 2.20.128 Updates `software.amazon.awssdk:kinesis` from 2.20.109 to 2.20.128 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.20.109 to 2.20.128 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix: Roll log4j shade transformer forwards (#1376) * Roll log4j shade transformer forwards * missed one * build(deps): bump com.amazonaws:aws-lambda-java-core from 1.2.2 to 1.2.3 (#1379) Bumps [com.amazonaws:aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs) from 1.2.2 to 1.2.3. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * build(deps): bump aws.sdk.version from 2.20.127 to 2.20.129 (#1380) Bumps `aws.sdk.version` from 2.20.127 to 2.20.129. Updates `software.amazon.awssdk:bom` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:http-client-spi` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:url-connection-client` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:sqs` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:s3` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:dynamodb` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:lambda` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:kinesis` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:cloudwatch` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:xray` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:cloudformation` from 2.20.127 to 2.20.129 Updates `software.amazon.awssdk:sts` from 2.20.127 to 2.20.129 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore:Prep release 1.17.0 (#1381) * chore:prep release 1.17.0 * Update changelog --------- Co-authored-by: scottgerring Co-authored-by: Scott Gerring * chore: Fix missing version change pieces (#1382) * Add missing bits * And fixed the fix * We shouldn't deploy CDK (#1383) * build(deps): bump aws.sdk.version from 2.20.129 to 2.20.130 (#1386) Bumps `aws.sdk.version` from 2.20.129 to 2.20.130. Updates `software.amazon.awssdk:bom` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:http-client-spi` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:url-connection-client` from 2.20.128 to 2.20.130 Updates `software.amazon.awssdk:sqs` from 2.20.128 to 2.20.130 Updates `software.amazon.awssdk:s3` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:dynamodb` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:lambda` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:kinesis` from 2.20.128 to 2.20.130 Updates `software.amazon.awssdk:cloudwatch` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:xray` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:cloudformation` from 2.20.129 to 2.20.130 Updates `software.amazon.awssdk:sts` from 2.20.129 to 2.20.130 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix batch pom (#1385) * Update to snapshot (#1384) * Fix batch logging (#1387) --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alexey Soshin Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> --- CHANGELOG.md | 22 ++ README.md | 6 +- examples/.gitignore | 2 + examples/README.md | 10 +- examples/pom.xml | 4 +- examples/powertools-examples-batch/pom.xml | 14 +- .../batch/kinesis/KinesisBatchHandler.java | 2 +- .../pom.xml | 14 +- examples/powertools-examples-core/.gitignore | 0 examples/powertools-examples-core/README.md | 27 +-- .../powertools-examples-core/cdk/README.md | 36 ++++ .../{ => cdk/app}/events/event.json | 0 .../powertools-examples-core/cdk/app/pom.xml | 200 ++++++++++++++++++ .../app}/src/main/java/helloworld/App.java | 26 +-- .../src/main/java/helloworld/AppStream.java | 0 .../app}/src/main/resources/log4j2.xml | 0 .../src/test/java/helloworld/AppTest.java | 0 .../cdk/infra/cdk.json | 36 ++++ .../cdk/infra/pom.xml | 56 +++++ .../cdk/infra/src/main/java/cdk/CdkApp.java | 53 +++++ .../cdk/infra/src/main/java/cdk/CdkStack.java | 144 +++++++++++++ .../infra/src/test/java/cdk/CdkStackTest.java | 48 +++++ .../powertools-examples-core/sam/README.md | 24 +++ .../sam/events/event.json | 63 ++++++ .../{ => sam}/pom.xml | 12 +- .../sam/src/main/java/helloworld/App.java | 107 ++++++++++ .../src/main/java/helloworld/AppStream.java | 38 ++++ .../sam/src/main/resources/log4j2.xml | 16 ++ .../sam/src/test/java/helloworld/AppTest.java | 59 ++++++ .../{ => sam}/template.yaml | 0 .../powertools-examples-idempotency/pom.xml | 12 +- .../src/main/java/helloworld/App.java | 3 +- .../powertools-examples-parameters/pom.xml | 2 +- .../powertools-examples-serialization/pom.xml | 2 +- .../powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 4 +- powertools-batch/pom.xml | 3 + powertools-e2e-tests/handlers/pom.xml | 14 +- powertools-e2e-tests/pom.xml | 4 +- 40 files changed, 969 insertions(+), 98 deletions(-) delete mode 100644 examples/powertools-examples-core/.gitignore create mode 100644 examples/powertools-examples-core/cdk/README.md rename examples/powertools-examples-core/{ => cdk/app}/events/event.json (100%) create mode 100644 examples/powertools-examples-core/cdk/app/pom.xml rename examples/powertools-examples-core/{ => cdk/app}/src/main/java/helloworld/App.java (82%) rename examples/powertools-examples-core/{ => cdk/app}/src/main/java/helloworld/AppStream.java (100%) rename examples/powertools-examples-core/{ => cdk/app}/src/main/resources/log4j2.xml (100%) rename examples/powertools-examples-core/{ => cdk/app}/src/test/java/helloworld/AppTest.java (100%) create mode 100644 examples/powertools-examples-core/cdk/infra/cdk.json create mode 100644 examples/powertools-examples-core/cdk/infra/pom.xml create mode 100644 examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkApp.java create mode 100644 examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java create mode 100644 examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java create mode 100644 examples/powertools-examples-core/sam/README.md create mode 100644 examples/powertools-examples-core/sam/events/event.json rename examples/powertools-examples-core/{ => sam}/pom.xml (94%) create mode 100644 examples/powertools-examples-core/sam/src/main/java/helloworld/App.java create mode 100644 examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java create mode 100644 examples/powertools-examples-core/sam/src/main/resources/log4j2.xml create mode 100644 examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java rename examples/powertools-examples-core/{ => sam}/template.yaml (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5619f0bbb..dbb90ce3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,28 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo ## [Unreleased] +## [1.17.0] - 2023-08-21 + +### Added +* Feat: Add Batch Processor module in (#1317) by @scottgerring +* Feat: Add SNS+SQS large messages module (#1310) by @jeromevdl + +### Maintenance +* fix: use default credentials provider for all provided SDK clients in (#1303) by @roamingthings +* Chore: Make request for Logger explicitly for current class in (#1307) by @jreijn +* Chore: checkstyle formater & linter in (#1316) by @jeromevdl +* Chore: Add powertools specific user-agent-suffix to the AWS SDK v2 clients by @eldimi in (#1306) +* Chore: Add 'v2' branch to build workflows to prepare for v2 work in (#1341) by @scottgerring +* Deps: Bump third party dependencies to the latest versions. + +### Documentation +* Docs: Add maintainers guide in (#1326) by @scottgerring +* Docs: improve contributing guide in (#1334) by @jeromevdl +* Docs: Improve example documentation in (#1291) by @scottgerring +* Docs: Add discord + sec disclosure links to readme in (#1311) by @scottgerring +* Docs: Add external examples from AWS SAM CLI App Templates in (#1318) by @AlexeySoshin +* Docs: Add CDK example in (#1321) by @AlexeySoshin + ## [1.16.1] - 2023-07-19 * Fix: idempotency timeout bug (#1285) by @scottgerring diff --git a/README.md b/README.md index 47fb59bd7..76f8b2e4b 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your software.amazon.lambda powertools-tracing - 1.16.1 + 1.17.0 software.amazon.lambda powertools-logging - 1.16.1 + 1.17.0 software.amazon.lambda powertools-metrics - 1.16.1 + 1.17.0 ... diff --git a/examples/.gitignore b/examples/.gitignore index 79e044a40..892320d3b 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,2 +1,4 @@ dependency-reduced-pom.xml .aws-sam +cdk.out +.m2 diff --git a/examples/README.md b/examples/README.md index 9b76faa82..0744c2bb1 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,7 +5,9 @@ Each example can be copied from its subdirectory and used independently of the r ## Examples -* [powertools-examples-core](powertools-examples-core) - Demonstrates the core logging, tracing, and metrics modules +* [powertools-examples-core](powertools-examples-core) - Demonstrates the core logging, tracing, and metrics modules with different build tools + * [SAM](./powertools-examples-core/sam) + * [CDK](./powertools-examples-core/cdk) * [powertools-examples-idempotency](powertools-examples-idempotency) - An idempotent HTTP API * [powertools-examples-parameters](powertools-examples-parameters) - Uses the parameters module to provide runtime parameters to a function * [powertools-examples-serialization](powertools-examples-serialization) - Uses the serialization module to serialize and deserialize API Gateway & SQS payloads @@ -34,8 +36,8 @@ amongst other things. To build and deploy an example application for the first time, run the following in your shell: ```bash -# Switch to the directory containing an example for the powertools-core module -$ cd powertools-examples-core +# Switch to the directory containing an example for the powertools-idempotency module +$ cd powertools-examples-idempotency # Build and deploy the example $ sam build @@ -52,6 +54,8 @@ The first command will build the source of your application. The second command You can find your API Gateway Endpoint URL in the output values displayed after deployment. +If you're not using SAM, you can look for examples for other tools under [powertools-examples-core](./powertools-examples-core) + ### External examples You can find more examples in the https://github.com/aws/aws-sam-cli-app-templates project: diff --git a/examples/pom.xml b/examples/pom.xml index aca250dae..f290b3951 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -29,7 +29,9 @@ - powertools-examples-core + powertools-examples-core/sam + powertools-examples-core/cdk/app + powertools-examples-core/cdk/infra powertools-examples-idempotency powertools-examples-parameters powertools-examples-serialization diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 10e15d532..9efa7fa63 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -15,7 +15,7 @@ 1.8 1.8 true - 2.20.109 + 2.20.128 @@ -37,7 +37,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 software.amazon.awssdk @@ -107,18 +107,16 @@ - - + - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java index d9339549b..b188df501 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java @@ -12,7 +12,7 @@ public class KinesisBatchHandler implements RequestHandler { - private final static Logger LOGGER = LogManager.getLogger(org.demo.batch.sqs.SqsBatchHandler.class); + private final static Logger LOGGER = LogManager.getLogger(KinesisBatchHandler.class); private final BatchMessageHandler handler; public KinesisBatchHandler() { diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index c9fe249b3..50cfff85d 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,9 +14,9 @@ 1.8 1.8 true - 1.2.2 + 1.2.3 3.11.2 - 2.20.119 + 2.20.130 @@ -132,18 +132,16 @@ - - + - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 diff --git a/examples/powertools-examples-core/.gitignore b/examples/powertools-examples-core/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/examples/powertools-examples-core/README.md b/examples/powertools-examples-core/README.md index a47d0d26c..f11982477 100644 --- a/examples/powertools-examples-core/README.md +++ b/examples/powertools-examples-core/README.md @@ -5,17 +5,17 @@ This project demonstrates the Lambda for Powertools Java module - including [tracing](https://docs.powertools.aws.dev/lambda/java/core/tracing/), and [metrics](https://docs.powertools.aws.dev/lambda/java/core/metrics/). -It is made up of the following: +We provide examples for the following infrastructure-as-code tools: +* [AWS SAM](sam/) +* [AWS CDK](cdk/) -- [App.java](src/main/java/helloworld/App.java) - Code for the application's Lambda function. -- [events](events) - Invocation events that you can use to invoke the function. -- [AppTests.java](src/test/java/helloworld/AppTest.java) - Unit tests for the application code. -- [template.yaml](template.yaml) - A template that defines the application's AWS resources. +For each of the tools, the example application is the same, and consists of the following files: -## Deploy the sample application +- [App.java](sam/src/main/java/helloworld/App.java) - Code for the application's Lambda function. +- [AppTests.java](sam/src/test/java/helloworld/AppTest.java) - Unit tests for the application code. +- [events](sam/events/event.json) - Invocation events that you can use to invoke the function. -This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting -started with SAM in [the examples directory](../README.md) +Configuration files and deployment process for each tool are described in corresponding README files. ## Test the application @@ -35,13 +35,4 @@ different function calls within the example Likewise, from the CloudWatch dashboard, under **Metrics**, **all metrics**, you will find the namespaces `Another` and `ServerlessAirline`. The values in each of these are published by the code in -[App.java](src/main/java/helloworld/App.java). - -You can also watch the trace information or log information using the SAM CLI: -```bash -# Tail the logs -sam logs --tail $MY_STACK - -# Tail the traces -sam traces --tail -``` \ No newline at end of file +[App.java](sam/src/main/java/helloworld/App.java). diff --git a/examples/powertools-examples-core/cdk/README.md b/examples/powertools-examples-core/cdk/README.md new file mode 100644 index 000000000..f15a24168 --- /dev/null +++ b/examples/powertools-examples-core/cdk/README.md @@ -0,0 +1,36 @@ +# Powertools for AWS Lambda (Java) - Core Utilities Example with CDK + +This project demonstrates the Lambda for Powertools Java module deployed using [Cloud Development Kit](https://aws.amazon.com/cdk/). + +For general information on the deployed example itself, you can refer to the parent [README](../README.md) + +## Configuration +CDK uses the following project structure: +- [app](./app) - stores the source code of your application, which is similar between all examples +- [infra](./infra) - stores the definition of your infrastructure + - [cdk.json](./infra/cdk.json) - tells the CDK Toolkit how to execute your app + - [CdkApp](./infra/src/main/java/cdk/CdkApp.java) - bootstraps your stack, taking AWS `account` and `region` as input + - [CdkStack](./infra/src/main/java/cdk/CdkStack.java) - defines the Lambda function to be deployed as well as API Gateway for it. + +It is a [Maven](https://maven.apache.org/) based project, so you can open this project with any Maven compatible Java IDE to build and run tests. + + +## Deploy the sample application + +The minimum to deploy the app should be +```bash +cdk deploy +``` + +If you're running CDK for the first time, you'll need to first run the bootstrap command: +```bash +cdk bootstrap +``` + +## Useful commands + +* `mvn package` compile and run tests +* `cdk synth` emits the synthesized CloudFormation template +* `cdk deploy` deploy this stack to your default AWS account/region +* `cdk diff` compare deployed stack with current state +* `cdk docs` open CDK documentation \ No newline at end of file diff --git a/examples/powertools-examples-core/events/event.json b/examples/powertools-examples-core/cdk/app/events/event.json similarity index 100% rename from examples/powertools-examples-core/events/event.json rename to examples/powertools-examples-core/cdk/app/events/event.json diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml new file mode 100644 index 000000000..a1aba1b8d --- /dev/null +++ b/examples/powertools-examples-core/cdk/app/pom.xml @@ -0,0 +1,200 @@ + + 4.0.0 + + software.amazon.lambda.examples + 1.16.1 + powertools-examples-core-cdk + jar + + Powertools for AWS Lambda (Java) library Examples - Core + + + 2.20.0 + 1.8 + 1.8 + true + + + + + software.amazon.lambda + powertools-tracing + ${project.version} + + + software.amazon.lambda + powertools-logging + ${project.version} + + + software.amazon.lambda + powertools-metrics + ${project.version} + + + com.amazonaws + aws-lambda-java-core + 1.2.3 + + + com.amazonaws + aws-lambda-java-events + 3.11.2 + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + + junit + junit + 4.13.2 + test + + + + + helloworld-lambda + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + + + + + + jdk8 + + (,11) + + + 1.9.7 + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + + + dev.aspectj + aspectj-maven-plugin + ${aspectj.plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + test-compile + + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + + + + diff --git a/examples/powertools-examples-core/src/main/java/helloworld/App.java b/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/App.java similarity index 82% rename from examples/powertools-examples-core/src/main/java/helloworld/App.java rename to examples/powertools-examples-core/cdk/app/src/main/java/helloworld/App.java index a1ea9a9e3..988da2a73 100644 --- a/examples/powertools-examples-core/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/App.java @@ -17,14 +17,11 @@ import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; -import static software.amazon.lambda.powertools.tracing.TracingUtils.withEntitySubsegment; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.amazonaws.xray.AWSXRay; -import com.amazonaws.xray.entities.Entity; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -83,38 +80,17 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv log.info(output); }); - threadOption1(); - - threadOption2(); - log.info("After output"); return response .withStatusCode(200) .withBody(output); - } catch (IOException | InterruptedException e) { + } catch (IOException e) { return response .withBody("{}") .withStatusCode(500); } } - private void threadOption1() throws InterruptedException { - final Entity traceEntity = AWSXRay.getTraceEntity(); - assert traceEntity != null; - traceEntity.run(new Thread(this::log)); - } - - private void threadOption2() throws InterruptedException { - Entity traceEntity = AWSXRay.getTraceEntity(); - Thread anotherThread = new Thread(() -> withEntitySubsegment("inlineLog", traceEntity, subsegment -> - { - String var = "somethingToProcess"; - log.info("inside threaded logging inline {}", var); - })); - anotherThread.start(); - anotherThread.join(); - } - @Tracing private void log() { log.info("inside threaded logging for function"); diff --git a/examples/powertools-examples-core/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/AppStream.java similarity index 100% rename from examples/powertools-examples-core/src/main/java/helloworld/AppStream.java rename to examples/powertools-examples-core/cdk/app/src/main/java/helloworld/AppStream.java diff --git a/examples/powertools-examples-core/src/main/resources/log4j2.xml b/examples/powertools-examples-core/cdk/app/src/main/resources/log4j2.xml similarity index 100% rename from examples/powertools-examples-core/src/main/resources/log4j2.xml rename to examples/powertools-examples-core/cdk/app/src/main/resources/log4j2.xml diff --git a/examples/powertools-examples-core/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java similarity index 100% rename from examples/powertools-examples-core/src/test/java/helloworld/AppTest.java rename to examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java diff --git a/examples/powertools-examples-core/cdk/infra/cdk.json b/examples/powertools-examples-core/cdk/infra/cdk.json new file mode 100644 index 000000000..e24ee7b04 --- /dev/null +++ b/examples/powertools-examples-core/cdk/infra/cdk.json @@ -0,0 +1,36 @@ +{ + "app": "mvn -e -q compile exec:java", + "watch": { + "include": [ + "**" + ], + "exclude": [ + "README.md", + "cdk*.json", + "target", + "pom.xml", + "src/test" + ] + }, + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-iam:standardizedServicePrincipals": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, + "@aws-cdk/aws-kms:aliasNameRef": true, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": true + } +} diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml new file mode 100644 index 000000000..d81118cde --- /dev/null +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + software.amazon.lambda.examples + cdk + 1.18.0-SNAPSHOT + + UTF-8 + 2.91.0 + [10.0.0,11.0.0) + 5.10.0 + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + 1.8 + 1.8 + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + cdk.CdkApp + + + + + + + + software.amazon.awscdk + aws-cdk-lib + ${cdk.version} + + + software.constructs + constructs + ${constructs.version} + + + + org.junit.jupiter + junit-jupiter + ${junit.version} + test + + + diff --git a/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkApp.java b/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkApp.java new file mode 100644 index 000000000..d564eb9a0 --- /dev/null +++ b/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkApp.java @@ -0,0 +1,53 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package cdk; + +import software.amazon.awscdk.App; +import software.amazon.awscdk.StackProps; + +public class CdkApp { + public static void main(final String[] args) { + App app = new App(); + + new CdkStack(app, "CdkStack", StackProps.builder() + // If you don't specify 'env', this stack will be environment-agnostic. + // Account/Region-dependent features and context lookups will not work, + // but a single synthesized template can be deployed anywhere. + + // Uncomment the next block to specialize this stack for the AWS Account + // and Region that are implied by the current CLI configuration. + /* + .env(Environment.builder() + .account(System.getenv("CDK_DEFAULT_ACCOUNT")) + .region(System.getenv("CDK_DEFAULT_REGION")) + .build()) + */ + + + // Uncomment the next block if you know exactly what Account and Region you + // want to deploy the stack to. + /* + .env(Environment.builder() + .account("1234567890") + .region("region") + .build()) + */ + + // For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html + .build()); + + app.synth(); + } +} diff --git a/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java b/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java new file mode 100644 index 000000000..8e6b44112 --- /dev/null +++ b/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java @@ -0,0 +1,144 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package cdk; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import software.amazon.awscdk.BundlingOptions; +import software.amazon.awscdk.CfnOutput; +import software.amazon.awscdk.Duration; +import software.amazon.awscdk.Stack; +import software.amazon.awscdk.StackProps; +import software.amazon.awscdk.services.apigateway.LambdaIntegration; +import software.amazon.awscdk.services.apigateway.RestApi; +import software.amazon.awscdk.services.lambda.Code; +import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.lambda.Runtime; +import software.amazon.awscdk.services.lambda.Tracing; +import software.amazon.awscdk.services.s3.assets.AssetOptions; +import software.constructs.Construct; + +/** + * Defines a stack that consists of a single Java Lambda function and an API Gateway + */ +public class CdkStack extends Stack { + private static final String SHELL_COMMAND = "/bin/sh"; + private static final String MAVEN_PACKAGE = "mvn package"; + private static final String COPY_OUTPUT = "cp /asset-input/target/helloworld-lambda.jar /asset-output/"; + + public CdkStack(final Construct scope, final String id) { + this(scope, id, null); + } + + public CdkStack(final Construct scope, final String id, final StackProps props) { + super(scope, id, props); + + Function helloWorldFunction = createHelloWorldFunction(); + Function helloWorldStreamFunction = createHelloWorldStreamFunction(); + RestApi restApi = createHelloWorldApi(); + + restApi.getRoot().resourceForPath("/hello") + .addMethod("GET", LambdaIntegration.Builder.create(helloWorldFunction) + .build()); + + restApi.getRoot().resourceForPath("/hellostream") + .addMethod("GET", LambdaIntegration.Builder.create(helloWorldStreamFunction) + .build()); + + outputApiUrl(restApi); + } + + private static List createFunctionPackageInstructions() { + // CDK will use this command to package your Java Lambda + return Arrays.asList( + SHELL_COMMAND, + "-c", + MAVEN_PACKAGE + " && " + + COPY_OUTPUT + ); + } + + /** + * Adds API URL to the outputs + * + * @param restApi + */ + private void outputApiUrl(RestApi restApi) { + CfnOutput.Builder.create(this, "HelloWorldApiUrl") + .description("API Gateway endpoint URL for Prod stage for Hello World function") + .value(restApi.getUrl() + "hello").build(); + } + + // Method to create the Lambda function + private Function createHelloWorldFunction() { + List functionPackageInstructions = createFunctionPackageInstructions(); + + Map environment = new HashMap<>(); + environment.put("POWERTOOLS_LOG_LEVEL", "INFO"); + environment.put("POWERTOOLS_LOGGER_SAMPLE_RATE", "0.1"); + environment.put("POWERTOOLS_LOGGER_LOG_EVENT", "true"); + environment.put("POWERTOOLS_METRICS_NAMESPACE", "Coreutilities"); + + return Function.Builder.create(this, "HelloWorldFunction") + .runtime(Runtime.JAVA_11) + .memorySize(512) + .timeout(Duration.seconds(20)) + .tracing(Tracing.ACTIVE) + .code(Code.fromAsset("../app/", AssetOptions.builder() + .bundling(BundlingOptions.builder() + .image(Runtime.JAVA_11.getBundlingImage()) + .command(functionPackageInstructions) + .build()) + .build())) + .handler("helloworld.App") + .environment(environment) + .build(); + } + + private Function createHelloWorldStreamFunction() { + List functionPackageInstructions = createFunctionPackageInstructions(); + + Map environment = new HashMap<>(); + environment.put("POWERTOOLS_LOG_LEVEL", "INFO"); + environment.put("POWERTOOLS_LOGGER_SAMPLE_RATE", "0.7"); + environment.put("POWERTOOLS_LOGGER_LOG_EVENT", "true"); + environment.put("POWERTOOLS_METRICS_NAMESPACE", "Coreutilities"); + environment.put("POWERTOOLS_SERVICE_NAME", "hello"); + + return Function.Builder.create(this, "HelloWorldStreamFunction") + .runtime(Runtime.JAVA_11) + .memorySize(512) + .timeout(Duration.seconds(20)) + .tracing(Tracing.ACTIVE) + .code(Code.fromAsset("../app/", AssetOptions.builder() + .bundling(BundlingOptions.builder() + .image(Runtime.JAVA_11.getBundlingImage()) + .command(functionPackageInstructions) + .build()) + .build())) + .handler("helloworld.AppStream") + .environment(environment) + .build(); + } + + // Method to create the REST API + private RestApi createHelloWorldApi() { + return RestApi.Builder.create(this, "HelloWorldApi") + .description("API Gateway endpoint URL for Prod stage for Hello World function") + .build(); + } +} diff --git a/examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java b/examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java new file mode 100644 index 000000000..29cb15545 --- /dev/null +++ b/examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package cdk; + +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; +import software.amazon.awscdk.App; +import software.amazon.awscdk.assertions.Template; + +public class CdkStackTest { + + @Test + public void testStack() { + App app = new App(); + CdkStack stack = new CdkStack(app, "test"); + + Template template = Template.fromStack(stack); + + // There should be 2 lambda functions, one to handle regular input, and another for streaming + template.resourceCountIs("AWS::Lambda::Function", 2); + + // API Gateway should exist + template.resourceCountIs("AWS::ApiGateway::RestApi", 1); + + // API Gateway should have a path pointing to the regular Lambda + Map resourceProperties = new HashMap<>(); + resourceProperties.put("PathPart", "hello"); + template.hasResourceProperties("AWS::ApiGateway::Resource", resourceProperties); + + // API Gateway should have a path pointing to the streaming Lambda + resourceProperties = new HashMap<>(); + resourceProperties.put("PathPart", "hellostream"); + template.hasResourceProperties("AWS::ApiGateway::Resource", resourceProperties); + } +} diff --git a/examples/powertools-examples-core/sam/README.md b/examples/powertools-examples-core/sam/README.md new file mode 100644 index 000000000..7a4279ae3 --- /dev/null +++ b/examples/powertools-examples-core/sam/README.md @@ -0,0 +1,24 @@ +# Powertools for AWS Lambda (Java) - Core Utilities Example with SAM + +This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/). + +For general information on the deployed example itself, you can refer to the parent [README](../README.md) + +## Configuration +SAM uses [template.yaml](template.yaml) to define the application's AWS resources. +This file defines the Lambda function to be deployed as well as API Gateway for it. + +## Deploy the sample application +To deploy the example, check out the instructions for getting +started with SAM in [the examples directory](../../README.md) + +## Additional notes + +You can watch the trace information or log information using the SAM CLI: +```bash +# Tail the logs +sam logs --tail $MY_STACK + +# Tail the traces +sam traces --tail +``` \ No newline at end of file diff --git a/examples/powertools-examples-core/sam/events/event.json b/examples/powertools-examples-core/sam/events/event.json new file mode 100644 index 000000000..3822fadaa --- /dev/null +++ b/examples/powertools-examples-core/sam/events/event.json @@ -0,0 +1,63 @@ +{ + "body": "{\"message\": \"hello world\"}", + "resource": "/{proxy+}", + "path": "/path/to/resource", + "httpMethod": "POST", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/path/to/resource", + "resourcePath": "/{proxy+}", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } + } + \ No newline at end of file diff --git a/examples/powertools-examples-core/pom.xml b/examples/powertools-examples-core/sam/pom.xml similarity index 94% rename from examples/powertools-examples-core/pom.xml rename to examples/powertools-examples-core/sam/pom.xml index d402ce09c..bb2e01097 100644 --- a/examples/powertools-examples-core/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -35,7 +35,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 com.amazonaws @@ -106,18 +106,16 @@ - - + - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 diff --git a/examples/powertools-examples-core/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-core/sam/src/main/java/helloworld/App.java new file mode 100644 index 000000000..fccc63b9a --- /dev/null +++ b/examples/powertools-examples-core/sam/src/main/java/helloworld/App.java @@ -0,0 +1,107 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; +import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; +import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.tracing.CaptureMode; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.tracing.TracingUtils; + +/** + * Handler for requests to Lambda function. + */ +public class App implements RequestHandler { + private final static Logger log = LogManager.getLogger(App.class); + + @Logging(logEvent = true, samplingRate = 0.7) + @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + Map headers = new HashMap<>(); + + headers.put("Content-Type", "application/json"); + headers.put("X-Custom-Header", "application/json"); + + metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + + withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> + { + metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); + metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); + }); + + LoggingUtils.appendKey("test", "willBeLogged"); + + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() + .withHeaders(headers); + try { + final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); + log.info(pageContents); + TracingUtils.putAnnotation("Test", "New"); + String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); + + TracingUtils.withSubsegment("loggingResponse", subsegment -> + { + String sampled = "log something out"; + log.info(sampled); + log.info(output); + }); + + log.info("After output"); + return response + .withStatusCode(200) + .withBody(output); + } catch (RuntimeException | IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + @Tracing + private void log() { + log.info("inside threaded logging for function"); + } + + @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + putMetadata("getPageContents", address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java new file mode 100644 index 000000000..401ef8c48 --- /dev/null +++ b/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.Metrics; + +public class AppStream implements RequestStreamHandler { + private static final ObjectMapper mapper = new ObjectMapper(); + + @Override + @Logging(logEvent = true) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { + Map map = mapper.readValue(input, Map.class); + + System.out.println(map.size()); + } +} diff --git a/examples/powertools-examples-core/sam/src/main/resources/log4j2.xml b/examples/powertools-examples-core/sam/src/main/resources/log4j2.xml new file mode 100644 index 000000000..e1fd14cea --- /dev/null +++ b/examples/powertools-examples-core/sam/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java new file mode 100644 index 000000000..70dad8d71 --- /dev/null +++ b/examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import com.amazonaws.xray.AWSXRay; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class AppTest { + + @Before + public void setup() { + if (null == System.getenv("LAMBDA_TASK_ROOT")) { + AWSXRay.beginSegment("test"); + } + } + + @After + public void tearDown() { + if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) { + AWSXRay.endSubsegment(); + } + + if (null == System.getenv("LAMBDA_TASK_ROOT")) { + AWSXRay.endSegment(); + } + } + + @Test + public void successfulResponse() { + App app = new App(); + APIGatewayProxyResponseEvent result = app.handleRequest(null, null); + assertEquals(result.getStatusCode().intValue(), 200); + assertEquals(result.getHeaders().get("Content-Type"), "application/json"); + String content = result.getBody(); + assertNotNull(content); + assertTrue(content.contains("\"message\"")); + assertTrue(content.contains("\"hello world\"")); + assertTrue(content.contains("\"location\"")); + } +} diff --git a/examples/powertools-examples-core/template.yaml b/examples/powertools-examples-core/sam/template.yaml similarity index 100% rename from examples/powertools-examples-core/template.yaml rename to examples/powertools-examples-core/sam/template.yaml diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 38682e164..d0e98ec28 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -48,7 +48,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 com.amazonaws @@ -169,18 +169,16 @@ - - + - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 diff --git a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java index ac2c7ef1b..72fa621ad 100644 --- a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @@ -113,7 +114,7 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv */ private String getPageContents(String address) throws IOException { URL url = new URL(address); - try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"))) { + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) { return br.lines().collect(Collectors.joining(System.lineSeparator())); } } diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 1c7d177f4..19be585a5 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -27,7 +27,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 com.amazonaws diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 0ec05cd82..d084df983 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -27,7 +27,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 com.amazonaws diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index b3947513f..d4b26d166 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -41,7 +41,7 @@ com.amazonaws aws-lambda-java-core - 1.2.2 + 1.2.3 diff --git a/mkdocs.yml b/mkdocs.yml index 62d8d75ce..cde47c815 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -85,7 +85,7 @@ extra_javascript: extra: powertools: - version: 1.16.1 # to update after each release (we do not want snapshot version here) + version: 1.17.0 # to update after each release (we do not want snapshot version here) repo_url: https://github.com/aws-powertools/powertools-lambda-java edit_uri: edit/main/docs diff --git a/pom.xml b/pom.xml index 7cdf8a71f..24f71c6bd 100644 --- a/pom.xml +++ b/pom.xml @@ -74,11 +74,11 @@ 2.20.0 2.15.2 1.9.7 - 2.20.119 + 2.20.130 2.14.0 2.1.3 UTF-8 - 1.2.2 + 1.2.3 3.11.2 1.1.2 3.11.0 diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 593b22444..2c878416a 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -9,6 +9,9 @@ 2.0.0-SNAPSHOT + A suite of utilities that makes batch message processing using AWS Lambda easier. + Powertools for AWS Lambda (Java) batch messages + diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 49b4b5a20..7abaec9d0 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -120,19 +120,17 @@ - - + - - io.github.edwgiz - log4j-maven-shade-plugin-extensions - 2.17.2 - + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index e8a3273b1..8f3997dbd 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ 1.8 1.8 10.2.69 - 2.89.0 + 2.91.0 true @@ -162,7 +162,7 @@ org.yaml snakeyaml - 2.0 + 2.1 test From 52a1f48ec7baddb6fc2a756b4e0c74d8cb2913ab Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Tue, 22 Aug 2023 16:24:31 +0100 Subject: [PATCH 017/577] docs: Change link to absolute versioned path for examples (#1374) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change link to absolute versioned path for examples * Update README.md --------- Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e120bfb00..e351b5c0e 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam ## Examples -See the **[examples](examples)** directory for example projects showcasing usage of different utilities. +See the latest release of the **[examples](https://github.com/aws-powertools/powertools-lambda-java/tree/v1.17.0/examples)** for example projects showcasing usage of different utilities. Have a demo project to contribute which showcase usage of different utilities from powertools? We are happy to accept it [here](CONTRIBUTING.md#security-issue-notifications). From 7c3e45b81e607c98d64034bc36492795d4eb446e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Aug 2023 13:52:22 +0200 Subject: [PATCH 018/577] build(deps): bump aws.sdk.version from 2.20.131 to 2.20.132 (#1390) Bumps `aws.sdk.version` from 2.20.131 to 2.20.132. Updates `software.amazon.awssdk:bom` from 2.20.131 to 2.20.132 Updates `software.amazon.awssdk:http-client-spi` from 2.20.131 to 2.20.132 Updates `software.amazon.awssdk:url-connection-client` from 2.20.128 to 2.20.132 Updates `software.amazon.awssdk:sqs` from 2.20.128 to 2.20.132 Updates `software.amazon.awssdk:s3` from 2.20.131 to 2.20.132 Updates `software.amazon.awssdk:dynamodb` from 2.20.131 to 2.20.132 Updates `software.amazon.awssdk:lambda` from 2.20.131 to 2.20.132 Updates `software.amazon.awssdk:kinesis` from 2.20.128 to 2.20.132 Updates `software.amazon.awssdk:cloudwatch` from 2.20.131 to 2.20.132 Updates `software.amazon.awssdk:xray` from 2.20.131 to 2.20.132 Updates `software.amazon.awssdk:cloudformation` from 2.20.131 to 2.20.132 Updates `software.amazon.awssdk:sts` from 2.20.131 to 2.20.132 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 4c4a53039..bfa183290 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -16,7 +16,7 @@ true 1.2.3 3.11.2 - 2.20.131 + 2.20.132 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 8969662a8..60387f2d3 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -28,7 +28,7 @@ software.amazon.awssdk url-connection-client - 2.20.131 + 2.20.132 com.amazonaws diff --git a/pom.xml b/pom.xml index 76cdee1f8..dd12c2ae7 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.131 + 2.20.132 2.14.0 2.1.3 UTF-8 From 9f67d215865821a288ee8e4c2a9327c5fa3691f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 13:50:29 +0200 Subject: [PATCH 019/577] build(deps): bump aws.sdk.version from 2.20.132 to 2.20.133 (#1392) Bumps `aws.sdk.version` from 2.20.132 to 2.20.133. Updates `software.amazon.awssdk:bom` from 2.20.132 to 2.20.133 Updates `software.amazon.awssdk:http-client-spi` from 2.20.132 to 2.20.133 Updates `software.amazon.awssdk:url-connection-client` from 2.20.128 to 2.20.133 Updates `software.amazon.awssdk:sqs` from 2.20.128 to 2.20.133 Updates `software.amazon.awssdk:s3` from 2.20.132 to 2.20.133 Updates `software.amazon.awssdk:dynamodb` from 2.20.132 to 2.20.133 Updates `software.amazon.awssdk:lambda` from 2.20.132 to 2.20.133 Updates `software.amazon.awssdk:kinesis` from 2.20.128 to 2.20.133 Updates `software.amazon.awssdk:cloudwatch` from 2.20.132 to 2.20.133 Updates `software.amazon.awssdk:xray` from 2.20.132 to 2.20.133 Updates `software.amazon.awssdk:cloudformation` from 2.20.132 to 2.20.133 Updates `software.amazon.awssdk:sts` from 2.20.132 to 2.20.133 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index bfa183290..20aa5aeaf 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -16,7 +16,7 @@ true 1.2.3 3.11.2 - 2.20.132 + 2.20.133 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 60387f2d3..b030d22fd 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -28,7 +28,7 @@ software.amazon.awssdk url-connection-client - 2.20.132 + 2.20.133 com.amazonaws diff --git a/pom.xml b/pom.xml index dd12c2ae7..8226fa878 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.132 + 2.20.133 2.14.0 2.1.3 UTF-8 From 46124b4fb9d2a53efdff784345ac07d29678a5a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 13:55:56 +0200 Subject: [PATCH 020/577] build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1373) --- examples/powertools-examples-core/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index d81118cde..5131e22af 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -7,7 +7,7 @@ 1.18.0-SNAPSHOT UTF-8 - 2.91.0 + 2.92.0 [10.0.0,11.0.0) 5.10.0 true diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index e13cb65fc..8fd96030b 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ 1.8 1.8 10.2.69 - 2.91.0 + 2.92.0 true From 1fb444abcd6f51142377dc6f8831151a4f288dd6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Aug 2023 14:06:23 +0200 Subject: [PATCH 021/577] build(deps): bump aws.sdk.version from 2.20.128 to 2.20.133 (#1393) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `aws.sdk.version` from 2.20.128 to 2.20.133. Updates `software.amazon.awssdk:url-connection-client` from 2.20.128 to 2.20.133 Updates `software.amazon.awssdk:sqs` from 2.20.128 to 2.20.133 Updates `software.amazon.awssdk:sdk-core` from 2.20.128 to 2.20.133 Updates `software.amazon.awssdk:kinesis` from 2.20.128 to 2.20.133 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.20.128 to 2.20.133 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index dd75b597b..9faa4dc24 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -15,7 +15,7 @@ 1.8 1.8 true - 2.20.128 + 2.20.133 From 787aa9d0a811dbf79bef400e718e7171694fb35b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Thu, 24 Aug 2023 14:19:52 +0200 Subject: [PATCH 022/577] chore: secure github actions using hash instead of versions (#1232) * secure github actions using hash instead of versions * delete docs.yaml * fix hash for dcos --------- Co-authored-by: Scott Gerring --- .github/workflows/auto-merge.yml | 8 +++--- .github/workflows/build-docs.yml | 4 +-- .github/workflows/build.yml | 8 +++--- .github/workflows/dispatch_analytics.yml | 2 +- .github/workflows/docs.yml | 4 +-- .github/workflows/publish.yml | 9 ++++--- .github/workflows/release-drafter.yml | 2 +- .github/workflows/release-prep.yml | 16 ++++++------ .github/workflows/run-e2e-tests.yml | 6 ++--- .github/workflows/secure_workflows.yml | 32 ++++++++++++++++++++++++ .github/workflows/spotbugs.yml | 6 ++--- 11 files changed, 65 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/secure_workflows.yml diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 21b5e20e5..5401eedc9 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -17,12 +17,12 @@ jobs: runs-on: ubuntu-latest if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' && github.actor == 'dependabot[bot]' steps: - - uses: actions/checkout@v3 - - uses: ahmadnassri/action-workflow-run-wait@v1 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: ahmadnassri/action-workflow-run-wait@2aa3d9e1a12ecaaa9908e368eaf2123bb084323e # v1.4.4 with: timeout: 300000 - name: 'Download artifact' - uses: actions/github-script@v3.1.0 + uses: actions/github-script@47f7cf65b5ced0830a325f705cad64f2f58dddf7 # v3.1.0 with: script: | var artifacts = await github.actions.listWorkflowRunArtifacts({ @@ -43,7 +43,7 @@ jobs: fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data)); - run: unzip pr.zip - name: Create review - uses: actions/github-script@v3 + uses: actions/github-script@47f7cf65b5ced0830a325f705cad64f2f58dddf7 # v3.1.0 with: script: | var fs = require('fs'); diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index f4a9c4d3f..a4ab6e7de 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -22,9 +22,9 @@ jobs: docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 with: python-version: "3.8" - name: Capture branch and tag diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9ed871a6c..f9a985fb9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,9 +54,9 @@ jobs: JAVA: ${{ matrix.java }} AWS_REGION: eu-west-1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java - uses: actions/setup-java@v3 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'corretto' java-version: ${{ matrix.java }} @@ -64,7 +64,7 @@ jobs: - name: Build with Maven run: mvn -B install --file pom.xml - name: Upload coverage to Codecov - uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # 3.1.1 + uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 if: ${{ matrix.java == '11' }} # publish results once with: files: ./powertools-cloudformation/target/site/jacoco/jacoco.xml,./powertools-core/target/site/jacoco/jacoco.xml,./powertools-idempotency/target/site/jacoco/jacoco.xml,./powertools-logging/target/site/jacoco/jacoco.xml,./powertools-metrics/target/site/jacoco/jacoco.xml,./powertools-parameters/target/site/jacoco/jacoco.xml,./powertools-serialization/target/site/jacoco/jacoco.xml,./powertools-sqs/target/site/jacoco/jacoco.xml,./powertools-tracing/target/site/jacoco/jacoco.xml,./powertools-validation/target/site/jacoco/jacoco.xml @@ -78,7 +78,7 @@ jobs: mkdir -p ./pr echo ${{ github.event.number }} echo ${{ github.event.number }} > ./pr/NR - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 name: Upload artifact with: name: pr diff --git a/.github/workflows/dispatch_analytics.yml b/.github/workflows/dispatch_analytics.yml index 49a276f6f..c93cb5b36 100644 --- a/.github/workflows/dispatch_analytics.yml +++ b/.github/workflows/dispatch_analytics.yml @@ -29,7 +29,7 @@ jobs: environment: analytics steps: - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef + uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 with: aws-region: eu-central-1 role-to-assume: ${{ secrets.AWS_ANALYTICS_ROLE_ARN }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9c09e294d..5e37c5f45 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -16,9 +16,9 @@ jobs: runs-on: ubuntu-latest environment: Docs steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 with: python-version: "3.8" - name: Capture branch and tag diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2068c09c5..03f04e0f4 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,15 +8,16 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Set up Maven Central Repository - uses: actions/setup-java@v2 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: - distribution: 'zulu' + distribution: 'corretto' java-version: 8 server-id: ossrh server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD + # TODO: use environments https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }} # Value of the GPG private key to import gpg-passphrase: GPG_PASSPHRASE # env variable for GPG private key passphrase - name: Set release notes tag @@ -30,7 +31,7 @@ jobs: MAVEN_PASSWORD: ${{ secrets.OSSRH_JIRA_PASSWORD }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - name: Close issues related to this release - uses: actions/github-script@v5 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: script: | const post_release = require('.github/workflows/post_release.js') diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 5b27fd671..72bd5c24f 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -10,6 +10,6 @@ jobs: update_release_draft: runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v5 + - uses: release-drafter/release-drafter@569eb7ee3a85817ab916c8f8ff03a5bd96c9c83e # v5.23.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-prep.yml b/.github/workflows/release-prep.yml index 345bd2a10..f7a3c74c0 100644 --- a/.github/workflows/release-prep.yml +++ b/.github/workflows/release-prep.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Get current date id: date run: echo "::set-output name=date::$(date +'%Y-%m-%d')" @@ -18,42 +18,42 @@ jobs: run: | echo "CURRENT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in mkdocs.yml - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: 'version: ${{ env.CURRENT_VERSION }}' replace: 'version: ${{ github.event.inputs.targetRelease }}' regex: false include: "mkdocs.yml" - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in main pom.xml - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: ${{ env.CURRENT_VERSION }} replace: ${{ github.event.inputs.targetRelease }} regex: false include: "pom.xml" - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in modules pom.xml - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: ${{ env.CURRENT_VERSION }} replace: ${{ github.event.inputs.targetRelease }} regex: false include: "**/*pom.xml" - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in build.gradle - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: ${{ env.CURRENT_VERSION }} replace: ${{ github.event.inputs.targetRelease }} regex: false include: "**/*build.gradle" - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in README.md - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: ${{ env.CURRENT_VERSION }} replace: ${{ github.event.inputs.targetRelease }} regex: false include: "README.md" - name: Create changelog placeholder for ${{ github.event.inputs.targetRelease }} - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: '## [Unreleased]' replace: | @@ -66,7 +66,7 @@ jobs: regex: false include: CHANGELOG.md - name: Create Release Pull Request - uses: peter-evans/create-pull-request@v3 + uses: peter-evans/create-pull-request@18f7dc018cc2cd597073088f7c7591b9d1c02672 # v3.14.0 with: commit-message: chore:prep release ${{ github.event.inputs.targetRelease }} token: ${{ secrets.RELEASE }} diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 36c9dd97a..c4a8c6fb2 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -41,15 +41,15 @@ jobs: id-token: write # needed to interact with GitHub's OIDC Token endpoint. contents: read steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java - uses: actions/setup-java@v3 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'corretto' java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@v1.6.1 + uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} aws-region: ${{ env.AWS_DEFAULT_REGION }} diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml new file mode 100644 index 000000000..1430e91d6 --- /dev/null +++ b/.github/workflows/secure_workflows.yml @@ -0,0 +1,32 @@ +name: Lockdown untrusted workflows + +# PROCESS +# +# 1. Scans for any external GitHub Action being used without version pinning (@ vs @v3) +# 2. Scans for insecure practices for inline bash scripts (shellcheck) +# 3. Fail CI and prevent PRs to be merged if any malpractice is found + +# USAGE +# +# Always triggered on new PR, PR changes and PR merge. + + +on: + push: + paths: + - ".github/workflows/**" + pull_request: + paths: + - ".github/workflows/**" + +jobs: + enforce_pinned_workflows: + name: Harden Security + runs-on: ubuntu-latest + permissions: + contents: read # checkout code and subsequently GitHub action workflows + steps: + - name: Checkout code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Ensure 3rd party workflows have SHA pinned + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@555a30da2656b4a7cf47b107800bef097723363e # v2.1.3 diff --git a/.github/workflows/spotbugs.yml b/.github/workflows/spotbugs.yml index 0b07bcd81..d314107fa 100644 --- a/.github/workflows/spotbugs.yml +++ b/.github/workflows/spotbugs.yml @@ -23,11 +23,11 @@ jobs: codecheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java JDK 1.8 - uses: actions/setup-java@v2 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: - distribution: 'zulu' + distribution: 'corretto' java-version: 8 # https://github.com/jwgmeligmeyling/spotbugs-github-action/issues/6 # https://github.blog/2020-08-03-github-actions-improvements-for-fork-and-pull-request-workflows/ From 50e7b56feed62e1c964a0384a0b1968c2affe7b6 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Thu, 24 Aug 2023 14:26:16 +0100 Subject: [PATCH 023/577] chore: [V2] rename 'core' module to 'common' (#1364) * First rename * POM updates * Rename namespace * Fix * Fix? * More namespace changes * Rename core examples to core utilities * Finish renaming core utilities * Clean up name/description of module * More change * Fix readme --- examples/README.md | 8 ++++---- examples/pom.xml | 6 +++--- .../.gitignore | 0 .../README.md | 0 .../cdk/README.md | 10 +++++----- .../cdk/app/events/event.json | 0 .../cdk/app/pom.xml | 2 +- .../cdk/app/src/main/java/helloworld/App.java | 0 .../src/main/java/helloworld/AppStream.java | 0 .../cdk/app/src/main/resources/log4j2.xml | 0 .../app/src/test/java/helloworld/AppTest.java | 0 .../cdk/infra/cdk.json | 0 .../cdk/infra/pom.xml | 0 .../cdk/infra/src/main/java/cdk/CdkApp.java | 0 .../cdk/infra/src/main/java/cdk/CdkStack.java | 0 .../infra/src/test/java/cdk/CdkStackTest.java | 0 .../sam/README.md | 0 .../sam/events/event.json | 0 .../sam/pom.xml | 4 ++-- .../sam/src/main/java/helloworld/App.java | 0 .../src/main/java/helloworld/AppStream.java | 0 .../sam/src/main/resources/log4j2.xml | 0 .../sam/src/test/java/helloworld/AppTest.java | 0 .../sam/template.yaml | 0 pom.xml | 4 ++-- {powertools-core => powertools-common}/pom.xml | 10 ++++------ .../common}/internal/LambdaConstants.java | 2 +- .../internal/LambdaHandlerProcessor.java | 4 ++-- .../common}/internal/SystemWrapper.java | 2 +- .../internal/UserAgentConfigurator.java | 4 ++-- .../main/resources-filtered/version.properties | 0 .../internal/LambdaHandlerProcessorTest.java | 7 +++++-- .../internal/UserAgentConfiguratorTest.java | 13 +++++++------ .../src/test/resources/test.properties | 0 .../src/test/resources/unreadable.properties | 0 powertools-idempotency/pom.xml | 2 +- .../idempotency/internal/IdempotentAspect.java | 2 +- .../persistence/BasePersistenceStore.java | 2 +- .../persistence/DynamoDBPersistenceStore.java | 6 +++--- powertools-large-messages/pom.xml | 2 +- .../largemessages/LargeMessageConfig.java | 2 +- powertools-logging/pom.xml | 2 +- .../logging/internal/LambdaLoggingAspect.java | 16 ++++++++-------- .../internal/LambdaLoggingAspectTest.java | 6 +++--- powertools-metrics/pom.xml | 2 +- .../powertools/metrics/MetricsUtils.java | 2 +- .../metrics/internal/LambdaMetricsAspect.java | 12 ++++++------ .../powertools/metrics/MetricsLoggerTest.java | 18 +++++++++--------- .../internal/LambdaMetricsAspectTest.java | 16 ++++++++-------- powertools-parameters/pom.xml | 2 +- .../parameters/AppConfigProvider.java | 2 +- .../parameters/DynamoDbProvider.java | 2 +- .../powertools/parameters/SSMProvider.java | 2 +- .../powertools/parameters/SecretsProvider.java | 2 +- powertools-tracing/pom.xml | 2 +- .../powertools/tracing/TracingUtils.java | 2 +- .../tracing/internal/LambdaTracingAspect.java | 10 +++++----- .../internal/LambdaTracingAspectTest.java | 2 +- powertools-validation/pom.xml | 2 +- .../validation/internal/ValidationAspect.java | 2 +- 60 files changed, 99 insertions(+), 97 deletions(-) create mode 100644 examples/powertools-examples-core-utilities/.gitignore rename examples/{powertools-examples-core => powertools-examples-core-utilities}/README.md (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/README.md (67%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/app/events/event.json (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/app/pom.xml (99%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/app/src/main/java/helloworld/App.java (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/app/src/main/java/helloworld/AppStream.java (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/app/src/main/resources/log4j2.xml (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/app/src/test/java/helloworld/AppTest.java (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/infra/cdk.json (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/infra/pom.xml (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/infra/src/main/java/cdk/CdkApp.java (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/infra/src/main/java/cdk/CdkStack.java (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/cdk/infra/src/test/java/cdk/CdkStackTest.java (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/sam/README.md (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/sam/events/event.json (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/sam/pom.xml (98%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/sam/src/main/java/helloworld/App.java (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/sam/src/main/java/helloworld/AppStream.java (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/sam/src/main/resources/log4j2.xml (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/sam/src/test/java/helloworld/AppTest.java (100%) rename examples/{powertools-examples-core => powertools-examples-core-utilities}/sam/template.yaml (100%) rename {powertools-core => powertools-common}/pom.xml (92%) rename {powertools-core/src/main/java/software/amazon/lambda/powertools/core => powertools-common/src/main/java/software/amazon/lambda/powertools/common}/internal/LambdaConstants.java (96%) rename {powertools-core/src/main/java/software/amazon/lambda/powertools/core => powertools-common/src/main/java/software/amazon/lambda/powertools/common}/internal/LambdaHandlerProcessor.java (96%) rename {powertools-core/src/main/java/software/amazon/lambda/powertools/core => powertools-common/src/main/java/software/amazon/lambda/powertools/common}/internal/SystemWrapper.java (92%) rename {powertools-core/src/main/java/software/amazon/lambda/powertools/core => powertools-common/src/main/java/software/amazon/lambda/powertools/common}/internal/UserAgentConfigurator.java (96%) rename {powertools-core => powertools-common}/src/main/resources-filtered/version.properties (100%) rename {powertools-core/src/test/java/software/amazon/lambda/powertools/core => powertools-common/src/test/java/software/amazon/lambda/powertools/common}/internal/LambdaHandlerProcessorTest.java (96%) rename {powertools-core/src/test/java/software/amazon/lambda/powertools/core => powertools-common/src/test/java/software/amazon/lambda/powertools/common}/internal/UserAgentConfiguratorTest.java (86%) rename {powertools-core => powertools-common}/src/test/resources/test.properties (100%) rename {powertools-core => powertools-common}/src/test/resources/unreadable.properties (100%) diff --git a/examples/README.md b/examples/README.md index 0744c2bb1..79e2133ad 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,9 +5,9 @@ Each example can be copied from its subdirectory and used independently of the r ## Examples -* [powertools-examples-core](powertools-examples-core) - Demonstrates the core logging, tracing, and metrics modules with different build tools - * [SAM](./powertools-examples-core/sam) - * [CDK](./powertools-examples-core/cdk) +* [powertools-examples-core-utilities](powertools-examples-core-utilities) - Demonstrates the core logging, tracing, and metrics modules with different build tools + * [SAM](powertools-examples-core-utilities/sam) + * [CDK](powertools-examples-core-utilities/cdk) * [powertools-examples-idempotency](powertools-examples-idempotency) - An idempotent HTTP API * [powertools-examples-parameters](powertools-examples-parameters) - Uses the parameters module to provide runtime parameters to a function * [powertools-examples-serialization](powertools-examples-serialization) - Uses the serialization module to serialize and deserialize API Gateway & SQS payloads @@ -54,7 +54,7 @@ The first command will build the source of your application. The second command You can find your API Gateway Endpoint URL in the output values displayed after deployment. -If you're not using SAM, you can look for examples for other tools under [powertools-examples-core](./powertools-examples-core) +If you're not using SAM, you can look for examples for other tools under [powertools-examples-core-utilities](./powertools-examples-core-utilities) ### External examples diff --git a/examples/pom.xml b/examples/pom.xml index f290b3951..b790cb12e 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -29,9 +29,9 @@ - powertools-examples-core/sam - powertools-examples-core/cdk/app - powertools-examples-core/cdk/infra + powertools-examples-core-utilities/sam + powertools-examples-core-utilities/cdk/app + powertools-examples-core-utilities/cdk/infra powertools-examples-idempotency powertools-examples-parameters powertools-examples-serialization diff --git a/examples/powertools-examples-core-utilities/.gitignore b/examples/powertools-examples-core-utilities/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/examples/powertools-examples-core/README.md b/examples/powertools-examples-core-utilities/README.md similarity index 100% rename from examples/powertools-examples-core/README.md rename to examples/powertools-examples-core-utilities/README.md diff --git a/examples/powertools-examples-core/cdk/README.md b/examples/powertools-examples-core-utilities/cdk/README.md similarity index 67% rename from examples/powertools-examples-core/cdk/README.md rename to examples/powertools-examples-core-utilities/cdk/README.md index f15a24168..acd857ed7 100644 --- a/examples/powertools-examples-core/cdk/README.md +++ b/examples/powertools-examples-core-utilities/cdk/README.md @@ -6,11 +6,11 @@ For general information on the deployed example itself, you can refer to the par ## Configuration CDK uses the following project structure: -- [app](./app) - stores the source code of your application, which is similar between all examples -- [infra](./infra) - stores the definition of your infrastructure - - [cdk.json](./infra/cdk.json) - tells the CDK Toolkit how to execute your app - - [CdkApp](./infra/src/main/java/cdk/CdkApp.java) - bootstraps your stack, taking AWS `account` and `region` as input - - [CdkStack](./infra/src/main/java/cdk/CdkStack.java) - defines the Lambda function to be deployed as well as API Gateway for it. +- [app](app) - stores the source code of your application, which is similar between all examples +- [infra](infra) - stores the definition of your infrastructure + - [cdk.json](infra/cdk.json) - tells the CDK Toolkit how to execute your app + - [CdkApp](infra/src/main/java/cdk/CdkApp.java) - bootstraps your stack, taking AWS `account` and `region` as input + - [CdkStack](infra/src/main/java/cdk/CdkStack.java) - defines the Lambda function to be deployed as well as API Gateway for it. It is a [Maven](https://maven.apache.org/) based project, so you can open this project with any Maven compatible Java IDE to build and run tests. diff --git a/examples/powertools-examples-core/cdk/app/events/event.json b/examples/powertools-examples-core-utilities/cdk/app/events/event.json similarity index 100% rename from examples/powertools-examples-core/cdk/app/events/event.json rename to examples/powertools-examples-core-utilities/cdk/app/events/event.json diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml similarity index 99% rename from examples/powertools-examples-core/cdk/app/pom.xml rename to examples/powertools-examples-core-utilities/cdk/app/pom.xml index a1aba1b8d..6895f4117 100644 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -4,7 +4,7 @@ software.amazon.lambda.examples 1.16.1 - powertools-examples-core-cdk + powertools-examples-core-utilities-cdk jar Powertools for AWS Lambda (Java) library Examples - Core diff --git a/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java similarity index 100% rename from examples/powertools-examples-core/cdk/app/src/main/java/helloworld/App.java rename to examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java diff --git a/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/AppStream.java similarity index 100% rename from examples/powertools-examples-core/cdk/app/src/main/java/helloworld/AppStream.java rename to examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/AppStream.java diff --git a/examples/powertools-examples-core/cdk/app/src/main/resources/log4j2.xml b/examples/powertools-examples-core-utilities/cdk/app/src/main/resources/log4j2.xml similarity index 100% rename from examples/powertools-examples-core/cdk/app/src/main/resources/log4j2.xml rename to examples/powertools-examples-core-utilities/cdk/app/src/main/resources/log4j2.xml diff --git a/examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core-utilities/cdk/app/src/test/java/helloworld/AppTest.java similarity index 100% rename from examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java rename to examples/powertools-examples-core-utilities/cdk/app/src/test/java/helloworld/AppTest.java diff --git a/examples/powertools-examples-core/cdk/infra/cdk.json b/examples/powertools-examples-core-utilities/cdk/infra/cdk.json similarity index 100% rename from examples/powertools-examples-core/cdk/infra/cdk.json rename to examples/powertools-examples-core-utilities/cdk/infra/cdk.json diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml similarity index 100% rename from examples/powertools-examples-core/cdk/infra/pom.xml rename to examples/powertools-examples-core-utilities/cdk/infra/pom.xml diff --git a/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkApp.java b/examples/powertools-examples-core-utilities/cdk/infra/src/main/java/cdk/CdkApp.java similarity index 100% rename from examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkApp.java rename to examples/powertools-examples-core-utilities/cdk/infra/src/main/java/cdk/CdkApp.java diff --git a/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java b/examples/powertools-examples-core-utilities/cdk/infra/src/main/java/cdk/CdkStack.java similarity index 100% rename from examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java rename to examples/powertools-examples-core-utilities/cdk/infra/src/main/java/cdk/CdkStack.java diff --git a/examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java b/examples/powertools-examples-core-utilities/cdk/infra/src/test/java/cdk/CdkStackTest.java similarity index 100% rename from examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java rename to examples/powertools-examples-core-utilities/cdk/infra/src/test/java/cdk/CdkStackTest.java diff --git a/examples/powertools-examples-core/sam/README.md b/examples/powertools-examples-core-utilities/sam/README.md similarity index 100% rename from examples/powertools-examples-core/sam/README.md rename to examples/powertools-examples-core-utilities/sam/README.md diff --git a/examples/powertools-examples-core/sam/events/event.json b/examples/powertools-examples-core-utilities/sam/events/event.json similarity index 100% rename from examples/powertools-examples-core/sam/events/event.json rename to examples/powertools-examples-core-utilities/sam/events/event.json diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml similarity index 98% rename from examples/powertools-examples-core/sam/pom.xml rename to examples/powertools-examples-core-utilities/sam/pom.xml index bb2e01097..204a828c0 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,10 +4,10 @@ software.amazon.lambda.examples 2.0.0-SNAPSHOT - powertools-examples-core + powertools-examples-core-utilities jar - Powertools for AWS Lambda (Java) library Examples - Core + Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) 2.20.0 diff --git a/examples/powertools-examples-core/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java similarity index 100% rename from examples/powertools-examples-core/sam/src/main/java/helloworld/App.java rename to examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java diff --git a/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/AppStream.java similarity index 100% rename from examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java rename to examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/AppStream.java diff --git a/examples/powertools-examples-core/sam/src/main/resources/log4j2.xml b/examples/powertools-examples-core-utilities/sam/src/main/resources/log4j2.xml similarity index 100% rename from examples/powertools-examples-core/sam/src/main/resources/log4j2.xml rename to examples/powertools-examples-core-utilities/sam/src/main/resources/log4j2.xml diff --git a/examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core-utilities/sam/src/test/java/helloworld/AppTest.java similarity index 100% rename from examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java rename to examples/powertools-examples-core-utilities/sam/src/test/java/helloworld/AppTest.java diff --git a/examples/powertools-examples-core/sam/template.yaml b/examples/powertools-examples-core-utilities/sam/template.yaml similarity index 100% rename from examples/powertools-examples-core/sam/template.yaml rename to examples/powertools-examples-core-utilities/sam/template.yaml diff --git a/pom.xml b/pom.xml index 24f71c6bd..17fb1a712 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ - powertools-core + powertools-common powertools-serialization powertools-logging powertools-tracing @@ -105,7 +105,7 @@ software.amazon.lambda - powertools-core + powertools-common ${project.version} diff --git a/powertools-core/pom.xml b/powertools-common/pom.xml similarity index 92% rename from powertools-core/pom.xml rename to powertools-common/pom.xml index c244f70fc..721f264e0 100644 --- a/powertools-core/pom.xml +++ b/powertools-common/pom.xml @@ -18,7 +18,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - powertools-core + powertools-common jar @@ -27,10 +27,8 @@ 2.0.0-SNAPSHOT - Powertools for AWS Lambda (Java) library Core - - A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. - + Powertools for AWS Lambda (Java) library Common Internal Utilities + Internal utilities shared by the Powertools for AWS Lambda (Java) modules. Do not use directly in your project. https://aws.amazon.com/lambda/ GitHub Issues @@ -123,4 +121,4 @@ - \ No newline at end of file + diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java similarity index 96% rename from powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java rename to powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java index d0f94260b..f43cd52a3 100644 --- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java @@ -12,7 +12,7 @@ * */ -package software.amazon.lambda.powertools.core.internal; +package software.amazon.lambda.powertools.common.internal; public class LambdaConstants { public static final String LAMBDA_FUNCTION_NAME_ENV = "AWS_LAMBDA_FUNCTION_NAME"; diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java similarity index 96% rename from powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java rename to powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java index e9e220e41..1a2b29c2c 100644 --- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java @@ -12,11 +12,11 @@ * */ -package software.amazon.lambda.powertools.core.internal; +package software.amazon.lambda.powertools.common.internal; import static java.util.Optional.empty; import static java.util.Optional.of; -import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; +import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/SystemWrapper.java similarity index 92% rename from powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java rename to powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/SystemWrapper.java index 30f72232f..c537283b5 100644 --- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/SystemWrapper.java @@ -12,7 +12,7 @@ * */ -package software.amazon.lambda.powertools.core.internal; +package software.amazon.lambda.powertools.common.internal; public class SystemWrapper { private SystemWrapper() { diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/UserAgentConfigurator.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java similarity index 96% rename from powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/UserAgentConfigurator.java rename to powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java index 354305d33..585c38c59 100644 --- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/UserAgentConfigurator.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java @@ -12,9 +12,9 @@ * */ -package software.amazon.lambda.powertools.core.internal; +package software.amazon.lambda.powertools.common.internal; -import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; +import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; import java.io.FileInputStream; import java.io.IOException; diff --git a/powertools-core/src/main/resources-filtered/version.properties b/powertools-common/src/main/resources-filtered/version.properties similarity index 100% rename from powertools-core/src/main/resources-filtered/version.properties rename to powertools-common/src/main/resources-filtered/version.properties diff --git a/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java similarity index 96% rename from powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessorTest.java rename to powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index dc8f49580..589aab703 100644 --- a/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -12,14 +12,14 @@ * */ -package software.amazon.lambda.powertools.core.internal; +package software.amazon.lambda.powertools.common.internal; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; -import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; +import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; @@ -31,6 +31,9 @@ import org.aspectj.lang.Signature; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; +import software.amazon.lambda.powertools.common.internal.LambdaConstants; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.internal.SystemWrapper; class LambdaHandlerProcessorTest { diff --git a/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/UserAgentConfiguratorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java similarity index 86% rename from powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/UserAgentConfiguratorTest.java rename to powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java index 2d75bdb3a..9e4d26504 100644 --- a/powertools-core/src/test/java/software/amazon/lambda/powertools/core/internal/UserAgentConfiguratorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java @@ -12,15 +12,16 @@ * */ -package software.amazon.lambda.powertools.core.internal; +package software.amazon.lambda.powertools.common.internal; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mockStatic; -import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; -import static software.amazon.lambda.powertools.core.internal.UserAgentConfigurator.AWS_EXECUTION_ENV; -import static software.amazon.lambda.powertools.core.internal.UserAgentConfigurator.VERSION_KEY; -import static software.amazon.lambda.powertools.core.internal.UserAgentConfigurator.VERSION_PROPERTIES_FILENAME; -import static software.amazon.lambda.powertools.core.internal.UserAgentConfigurator.getVersionFromProperties; +import static software.amazon.lambda.powertools.common.internal.UserAgentConfigurator.AWS_EXECUTION_ENV; +import static software.amazon.lambda.powertools.common.internal.UserAgentConfigurator.VERSION_KEY; +import static software.amazon.lambda.powertools.common.internal.UserAgentConfigurator.VERSION_PROPERTIES_FILENAME; +import static software.amazon.lambda.powertools.common.internal.UserAgentConfigurator.getVersionFromProperties; +import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; + import java.io.File; import java.util.Objects; diff --git a/powertools-core/src/test/resources/test.properties b/powertools-common/src/test/resources/test.properties similarity index 100% rename from powertools-core/src/test/resources/test.properties rename to powertools-common/src/test/resources/test.properties diff --git a/powertools-core/src/test/resources/unreadable.properties b/powertools-common/src/test/resources/unreadable.properties similarity index 100% rename from powertools-core/src/test/resources/unreadable.properties rename to powertools-common/src/test/resources/unreadable.properties diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 6b9e46a4a..6a39ae6e0 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -57,7 +57,7 @@ software.amazon.lambda - powertools-core + powertools-common software.amazon.lambda diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java index 989e88eb7..0b9d729f4 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java +++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java @@ -14,7 +14,7 @@ package software.amazon.lambda.powertools.idempotency.internal; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnRequestHandler; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnRequestHandler; import com.amazonaws.services.lambda.runtime.Context; import com.fasterxml.jackson.databind.JsonNode; diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java index f58b276fd..8ae3598b9 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java +++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java @@ -14,7 +14,7 @@ package software.amazon.lambda.powertools.idempotency.persistence; -import static software.amazon.lambda.powertools.core.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; +import static software.amazon.lambda.powertools.common.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java index 82e7b9ead..054f61ef3 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java +++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java @@ -14,8 +14,8 @@ package software.amazon.lambda.powertools.idempotency.persistence; -import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_REGION_ENV; -import static software.amazon.lambda.powertools.core.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; +import static software.amazon.lambda.powertools.common.internal.LambdaConstants.AWS_REGION_ENV; +import static software.amazon.lambda.powertools.common.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS; import java.time.Instant; @@ -40,7 +40,7 @@ import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; import software.amazon.awssdk.utils.StringUtils; -import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.idempotency.Constants; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 19793d616..6cffecb73 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -56,7 +56,7 @@ software.amazon.lambda - powertools-core + powertools-common org.aspectj diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfig.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfig.java index fb8ea9b15..6ad529496 100644 --- a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfig.java +++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessageConfig.java @@ -14,7 +14,7 @@ package software.amazon.lambda.powertools.largemessages; -import static software.amazon.lambda.powertools.core.internal.LambdaConstants.AWS_REGION_ENV; +import static software.amazon.lambda.powertools.common.internal.LambdaConstants.AWS_REGION_ENV; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.regions.Region; diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index e13a88e57..e16dd0a8b 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -57,7 +57,7 @@ software.amazon.lambda - powertools-core + powertools-common com.amazonaws diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java index 4a98735af..0a36723f6 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java @@ -17,14 +17,14 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Optional.empty; import static java.util.Optional.ofNullable; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.coldStartDone; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.extractContext; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.getXrayTraceId; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isColdStart; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnRequestHandler; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnStreamHandler; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.coldStartDone; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.extractContext; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isColdStart; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isHandlerMethod; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnRequestHandler; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnStreamHandler; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.serviceName; import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKey; import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKeys; import static software.amazon.lambda.powertools.logging.LoggingUtils.objectMapper; diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index b78710586..942f79d32 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -24,7 +24,7 @@ import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.openMocks; import static org.skyscreamer.jsonassert.JSONAssert.assertEquals; -import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; +import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; @@ -59,8 +59,8 @@ import org.junit.jupiter.params.ParameterizedTest; import org.mockito.Mock; import org.mockito.MockedStatic; -import software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor; -import software.amazon.lambda.powertools.core.internal.SystemWrapper; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.internal.SystemWrapper; import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayHttpApiCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayRestApiCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabled; diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 0681ed000..e67aca7e2 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -58,7 +58,7 @@ software.amazon.lambda - powertools-core + powertools-common com.amazonaws diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java index 09517d46e..8ab2a2f29 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java @@ -16,7 +16,7 @@ import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.getXrayTraceId; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; import static software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect.REQUEST_ID_PROPERTY; import static software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect.TRACE_ID_PROPERTY; diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java index 8ca069b01..56a35f67f 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java @@ -16,11 +16,11 @@ import static software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper.dimensionsCount; import static software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper.hasNoMetrics; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.coldStartDone; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.extractContext; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isColdStart; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.coldStartDone; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.extractContext; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isColdStart; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isHandlerMethod; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.serviceName; import static software.amazon.lambda.powertools.metrics.MetricsUtils.hasDefaultDimension; import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; @@ -34,7 +34,7 @@ import software.amazon.cloudwatchlogs.emf.model.DimensionSet; import software.amazon.cloudwatchlogs.emf.model.MetricsContext; import software.amazon.cloudwatchlogs.emf.model.Unit; -import software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.metrics.Metrics; import software.amazon.lambda.powertools.metrics.MetricsUtils; import software.amazon.lambda.powertools.metrics.ValidationException; diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java index 7f234a4d6..89cba6bc4 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNullPointerException; import static org.mockito.Mockito.mockStatic; -import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; +import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -62,8 +62,8 @@ void tearDown() { @Test void singleMetricsCaptureUtilityWithDefaultDimension() { try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { + MockedStatic internalWrapper = mockStatic( + software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); @@ -92,8 +92,8 @@ void singleMetricsCaptureUtilityWithDefaultDimension() { @Test void singleMetricsCaptureUtility() { try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { + MockedStatic internalWrapper = mockStatic( + software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); @@ -118,8 +118,8 @@ void singleMetricsCaptureUtility() { @Test void singleMetricsCaptureUtilityWithDefaultNameSpace() { try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { + MockedStatic internalWrapper = mockStatic( + software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) @@ -167,8 +167,8 @@ void shouldThrowExceptionWhenDefaultDimensionIsNull() { private void testLogger(Consumer> methodToTest) { try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { + MockedStatic internalWrapper = mockStatic( + software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java index eaddfa75d..d24cd5bb3 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java @@ -21,7 +21,7 @@ import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.openMocks; -import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; +import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; @@ -40,7 +40,7 @@ import org.mockito.Mock; import org.mockito.MockedStatic; import software.amazon.cloudwatchlogs.emf.config.SystemWrapper; -import software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.metrics.MetricsUtils; import software.amazon.lambda.powertools.metrics.ValidationException; import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsColdStartEnabledHandler; @@ -86,8 +86,8 @@ void tearDown() { @Test public void metricsWithoutColdStart() { try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { + MockedStatic internalWrapper = mockStatic( + software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) @@ -130,8 +130,8 @@ public void metricsWithoutColdStart() { @Test public void metricsWithDefaultDimensionSpecified() { try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { + MockedStatic internalWrapper = mockStatic( + software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) @@ -174,8 +174,8 @@ public void metricsWithDefaultDimensionSpecified() { @Test public void metricsWithDefaultNoDimensionSpecified() { try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { + MockedStatic internalWrapper = mockStatic( + software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 367996e9c..a703bf36b 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -57,7 +57,7 @@ software.amazon.lambda - powertools-core + powertools-common software.amazon.awssdk diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java index f2e4faebb..5a1e575dd 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java @@ -25,7 +25,7 @@ import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationRequest; import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationResponse; import software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionRequest; -import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java index 3a8732e18..363f39d7c 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java @@ -28,7 +28,7 @@ import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; import software.amazon.awssdk.services.dynamodb.model.QueryRequest; import software.amazon.awssdk.services.dynamodb.model.QueryResponse; -import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java index 549cdfbab..10bb70c15 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java @@ -27,7 +27,7 @@ import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest; import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse; import software.amazon.awssdk.utils.StringUtils; -import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; import software.amazon.lambda.powertools.parameters.transform.Transformer; diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java index 2612f6c7f..b77f501f2 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java @@ -26,7 +26,7 @@ import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; -import software.amazon.lambda.powertools.core.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; import software.amazon.lambda.powertools.parameters.transform.Transformer; diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 5f397aa9f..0c9ed8f71 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -58,7 +58,7 @@ software.amazon.lambda - powertools-core + powertools-common software.amazon.awssdk diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java index 9fb021548..98aaf9c57 100644 --- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java +++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java @@ -14,7 +14,7 @@ package software.amazon.lambda.powertools.tracing; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.serviceName; import com.amazonaws.xray.AWSXRay; import com.amazonaws.xray.entities.Entity; diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java index 62416fce6..198cb7f34 100644 --- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java +++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java @@ -14,11 +14,11 @@ package software.amazon.lambda.powertools.tracing.internal; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.coldStartDone; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isColdStart; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isHandlerMethod; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.isSamLocal; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.serviceName; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.coldStartDone; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isColdStart; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isHandlerMethod; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isSamLocal; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.serviceName; import static software.amazon.lambda.powertools.tracing.TracingUtils.objectMapper; import com.amazonaws.xray.AWSXRay; diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java index d61206886..a676bf683 100644 --- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java +++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java @@ -35,7 +35,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockedStatic; -import software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.tracing.handlers.PowerToolDisabled; import software.amazon.lambda.powertools.tracing.handlers.PowerToolDisabledForStream; import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabled; diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 1b939f46f..5868629de 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -58,7 +58,7 @@ software.amazon.lambda - powertools-core + powertools-common software.amazon.lambda diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java index 6055f8d58..0d71104f3 100644 --- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java @@ -16,7 +16,7 @@ import static com.networknt.schema.SpecVersion.VersionFlag.V201909; import static java.nio.charset.StandardCharsets.UTF_8; -import static software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor.placedOnRequestHandler; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnRequestHandler; import static software.amazon.lambda.powertools.utilities.jmespath.Base64Function.decode; import static software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunction.decompress; import static software.amazon.lambda.powertools.validation.ValidationUtils.getJsonSchema; From 8d032490a3da5cd891fc80b163a5f9f010c10734 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Thu, 24 Aug 2023 15:09:18 +0100 Subject: [PATCH 024/577] docs: Update gradle configuration readme (#1359) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update gradle configuration readme * Move into configuration * Starting gradle example * Remove * Start again * Update documentation for gradle * Clarify gradle versions a bit better * Starting gradle example * Cleanup gradle example * Build gradle example * Fix build hopefully * Add gradle wrapper * Formatting * Update docs/index.md Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Updated README with sam instructions --------- Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> --- .github/workflows/build.yml | 5 + .gitignore | 2 + README.md | 16 +- docs/index.md | 17 +- examples/powertools-examples-core/README.md | 5 + .../powertools-examples-core/gradle/README.md | 38 +++ .../gradle/build.gradle | 35 +++ .../gradle/events/event.json | 62 +++++ .../gradle/gradle/wrapper/.gitignore | 2 + .../gradle/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63375 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../powertools-examples-core/gradle/gradlew | 248 ++++++++++++++++++ .../gradle/gradlew.bat | 92 +++++++ .../gradle/src/main/java/helloworld/App.java | 107 ++++++++ .../src/main/java/helloworld/AppStream.java | 38 +++ .../src/test/java/helloworld/AppTest.java | 24 ++ .../gradle/template.yaml | 71 +++++ 17 files changed, 767 insertions(+), 2 deletions(-) create mode 100644 examples/powertools-examples-core/gradle/README.md create mode 100644 examples/powertools-examples-core/gradle/build.gradle create mode 100644 examples/powertools-examples-core/gradle/events/event.json create mode 100644 examples/powertools-examples-core/gradle/gradle/wrapper/.gitignore create mode 100644 examples/powertools-examples-core/gradle/gradle/wrapper/gradle-wrapper.jar create mode 100644 examples/powertools-examples-core/gradle/gradle/wrapper/gradle-wrapper.properties create mode 100755 examples/powertools-examples-core/gradle/gradlew create mode 100644 examples/powertools-examples-core/gradle/gradlew.bat create mode 100644 examples/powertools-examples-core/gradle/src/main/java/helloworld/App.java create mode 100644 examples/powertools-examples-core/gradle/src/main/java/helloworld/AppStream.java create mode 100644 examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java create mode 100644 examples/powertools-examples-core/gradle/template.yaml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f9a985fb9..73ae67553 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -63,6 +63,11 @@ jobs: cache: 'maven' - name: Build with Maven run: mvn -B install --file pom.xml + - name: Build Gradle Example + if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 + run: | + cd examples/powertools-examples-core/gradle + ./gradlew build - name: Upload coverage to Codecov uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 if: ${{ matrix.java == '11' }} # publish results once diff --git a/.gitignore b/.gitignore index 04e85211d..b404d2cb2 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,5 @@ example/HelloWorldFunction/.gradle example/HelloWorldFunction/build /example/.gradle/ /example/.java-version +.gradle +build/ \ No newline at end of file diff --git a/README.md b/README.md index e351b5c0e..2afb40e5d 100644 --- a/README.md +++ b/README.md @@ -130,11 +130,18 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam Gradle - Java 11+ ```groovy + plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.2.2' } + // the freefair aspect plugins targets gradle 8.2.1 + // https://docs.freefair.io/gradle-plugins/8.2.2/reference/ + wrapper { + gradleVersion = "8.2.1" + } + repositories { mavenCentral() } @@ -143,6 +150,7 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' aspect 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' + implementation "org.aspectj:aspectjrt:1.9.8.RC3" } sourceCompatibility = 11 @@ -159,6 +167,12 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' } + // the freefair aspect plugins targets gradle 7.6.1 + // https://docs.freefair.io/gradle-plugins/6.6.3/reference/ + wrapper { + gradleVersion = "7.6.1" + } + repositories { mavenCentral() } diff --git a/docs/index.md b/docs/index.md index d3e487174..6af4c5e8d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -211,10 +211,17 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl === "Gradle Java 11+" ```groovy + plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.2.2' } + + // the freefair aspect plugins targets gradle 8.2.1 + // https://docs.freefair.io/gradle-plugins/8.2.2/reference/ + wrapper { + gradleVersion = "8.2.1" + } repositories { mavenCentral() @@ -233,10 +240,18 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl === "Gradle Java 1.8" ```groovy + plugins { id 'java' id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' } + + // the freefair aspect plugins targets gradle 7.6.1 + // https://docs.freefair.io/gradle-plugins/6.6.3/reference/ + wrapper { + gradleVersion = "7.6.1" + } + repositories { mavenCentral() diff --git a/examples/powertools-examples-core/README.md b/examples/powertools-examples-core/README.md index f11982477..d690b01c5 100644 --- a/examples/powertools-examples-core/README.md +++ b/examples/powertools-examples-core/README.md @@ -6,9 +6,14 @@ This project demonstrates the Lambda for Powertools Java module - including [metrics](https://docs.powertools.aws.dev/lambda/java/core/metrics/). We provide examples for the following infrastructure-as-code tools: + * [AWS SAM](sam/) * [AWS CDK](cdk/) +We also provide an example showing the integration of SAM, Powertools, and Gradle: + +* [AWS SAM with a Gradle build](gradle/) + For each of the tools, the example application is the same, and consists of the following files: - [App.java](sam/src/main/java/helloworld/App.java) - Code for the application's Lambda function. diff --git a/examples/powertools-examples-core/gradle/README.md b/examples/powertools-examples-core/gradle/README.md new file mode 100644 index 000000000..c7c798d5d --- /dev/null +++ b/examples/powertools-examples-core/gradle/README.md @@ -0,0 +1,38 @@ +# Powertools for AWS Lambda (Java) - Core Utilities Example with Gradle + +This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) with +[Gradle](https://gradle.org/) running the build. This example is configured for Java 1.8 only; in order to use a newer version, check out the Gradle +configuration guide [in the main project README](../../../README.md). + +You can also use `sam init` to create a new Gradle-powered Powertools application - choose to use the **AWS Quick Start Templates**, +and then **Hello World Example with Powertools for AWS Lambda**, **Java 17** runtime, and finally **gradle**. + + +For general information on the deployed example itself, you can refer to the parent [README](../README.md) + +## Configuration +SAM uses [template.yaml](template.yaml) to define the application's AWS resources. +This file defines the Lambda function to be deployed as well as API Gateway for it. + +The build of the project is managed by Gradle, and configured in [build.gradle](build.gradle). + +## Deploy the sample application +To get started, you can use the Gradle wrapper to bootstrap Gradle and run the build: + +```bash +./gradlew build +``` + +Once this is done to deploy the example, check out the instructions for getting started with SAM in +[the examples directory](../../README.md) + +## Additional notes + +You can watch the trace information or log information using the SAM CLI: +```bash +# Tail the logs +sam logs --tail $MY_STACK + +# Tail the traces +sam traces --tail +``` \ No newline at end of file diff --git a/examples/powertools-examples-core/gradle/build.gradle b/examples/powertools-examples-core/gradle/build.gradle new file mode 100644 index 000000000..e7367c246 --- /dev/null +++ b/examples/powertools-examples-core/gradle/build.gradle @@ -0,0 +1,35 @@ + +plugins { + id 'java' + id "io.freefair.aspectj.post-compile-weaving" version "6.6.3" +} + +wrapper { + gradleVersion = "7.6.1" +} + +compileJava { + sourceCompatibility = "1.8" + targetCompatibility = "1.8" + + ajc { + enabled = true + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'com.amazonaws:aws-lambda-java-core:1.2.2' + implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.2' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' + implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' + aspect 'software.amazon.lambda:powertools-tracing:1.17.0' + aspect 'software.amazon.lambda:powertools-logging:1.17.0' + aspect 'software.amazon.lambda:powertools-metrics:1.17.0' + testImplementation 'junit:junit:4.13.2' +} + diff --git a/examples/powertools-examples-core/gradle/events/event.json b/examples/powertools-examples-core/gradle/events/event.json new file mode 100644 index 000000000..070ad8e01 --- /dev/null +++ b/examples/powertools-examples-core/gradle/events/event.json @@ -0,0 +1,62 @@ +{ + "body": "{\"message\": \"hello world\"}", + "resource": "/{proxy+}", + "path": "/path/to/resource", + "httpMethod": "POST", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/path/to/resource", + "resourcePath": "/{proxy+}", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } +} diff --git a/examples/powertools-examples-core/gradle/gradle/wrapper/.gitignore b/examples/powertools-examples-core/gradle/gradle/wrapper/.gitignore new file mode 100644 index 000000000..59c09e205 --- /dev/null +++ b/examples/powertools-examples-core/gradle/gradle/wrapper/.gitignore @@ -0,0 +1,2 @@ +!gradle-wrapper.jar + diff --git a/examples/powertools-examples-core/gradle/gradle/wrapper/gradle-wrapper.jar b/examples/powertools-examples-core/gradle/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..033e24c4cdf41af1ab109bc7f253b2b887023340 GIT binary patch literal 63375 zcmb5VV{~QRw)Y#`wrv{~+qP{x72B%VwzFc}c2cp;N~)5ZbDrJayPv(!dGEd-##*zr z)#n-$y^sH|_dchh3@8{H5D*j;5D<{i*8l5IFJ|DjL!e)upfGNX(kojugZ3I`oH1PvW`wFW_ske0j@lB9bX zO;2)`y+|!@X(fZ1<2n!Qx*)_^Ai@Cv-dF&(vnudG?0CsddG_&Wtae(n|K59ew)6St z#dj7_(Cfwzh$H$5M!$UDd8=4>IQsD3xV=lXUq($;(h*$0^yd+b{qq63f0r_de#!o_ zXDngc>zy`uor)4A^2M#U*DC~i+dc<)Tb1Tv&~Ev@oM)5iJ4Sn#8iRw16XXuV50BS7 zdBL5Mefch(&^{luE{*5qtCZk$oFr3RH=H!c3wGR=HJ(yKc_re_X9pD` zJ;uxPzUfVpgU>DSq?J;I@a+10l0ONXPcDkiYcihREt5~T5Gb}sT0+6Q;AWHl`S5dV>lv%-p9l#xNNy7ZCr%cyqHY%TZ8Q4 zbp&#ov1*$#grNG#1vgfFOLJCaNG@K|2!W&HSh@3@Y%T?3YI75bJp!VP*$*!< z;(ffNS_;@RJ`=c7yX04!u3JP*<8jeqLHVJu#WV&v6wA!OYJS4h<_}^QI&97-;=ojW zQ-1t)7wnxG*5I%U4)9$wlv5Fr;cIizft@&N+32O%B{R1POm$oap@&f| zh+5J{>U6ftv|vAeKGc|zC=kO(+l7_cLpV}-D#oUltScw})N>~JOZLU_0{Ka2e1evz z{^a*ZrLr+JUj;)K&u2CoCAXLC2=fVScI(m_p~0FmF>>&3DHziouln?;sxW`NB}cSX z8?IsJB)Z=aYRz!X=yJn$kyOWK%rCYf-YarNqKzmWu$ZvkP12b4qH zhS9Q>j<}(*frr?z<%9hl*i^#@*O2q(Z^CN)c2c z>1B~D;@YpG?G!Yk+*yn4vM4sO-_!&m6+`k|3zd;8DJnxsBYtI;W3We+FN@|tQ5EW= z!VU>jtim0Mw#iaT8t_<+qKIEB-WwE04lBd%Letbml9N!?SLrEG$nmn7&W(W`VB@5S zaY=sEw2}i@F_1P4OtEw?xj4@D6>_e=m=797#hg}f*l^`AB|Y0# z9=)o|%TZFCY$SzgSjS|8AI-%J4x}J)!IMxY3_KYze`_I=c1nmrk@E8c9?MVRu)7+Ue79|)rBX7tVB7U|w4*h(;Gi3D9le49B38`wuv zp7{4X^p+K4*$@gU(Tq3K1a#3SmYhvI42)GzG4f|u zwQFT1n_=n|jpi=70-yE9LA+d*T8u z`=VmmXJ_f6WmZveZPct$Cgu^~gFiyL>Lnpj*6ee>*0pz=t$IJ}+rE zsf@>jlcG%Wx;Cp5x)YSVvB1$yyY1l&o zvwX=D7k)Dn;ciX?Z)Pn8$flC8#m`nB&(8?RSdBvr?>T9?E$U3uIX7T?$v4dWCa46 z+&`ot8ZTEgp7G+c52oHJ8nw5}a^dwb_l%MOh(ebVj9>_koQP^$2B~eUfSbw9RY$_< z&DDWf2LW;b0ZDOaZ&2^i^g+5uTd;GwO(-bbo|P^;CNL-%?9mRmxEw~5&z=X^Rvbo^WJW=n_%*7974RY}JhFv46> zd}`2|qkd;89l}R;i~9T)V-Q%K)O=yfVKNM4Gbacc7AOd>#^&W&)Xx!Uy5!BHnp9kh z`a(7MO6+Ren#>R^D0K)1sE{Bv>}s6Rb9MT14u!(NpZOe-?4V=>qZ>}uS)!y~;jEUK z&!U7Fj&{WdgU#L0%bM}SYXRtM5z!6M+kgaMKt%3FkjWYh=#QUpt$XX1!*XkpSq-pl zhMe{muh#knk{9_V3%qdDcWDv}v)m4t9 zQhv{;} zc{}#V^N3H>9mFM8`i`0p+fN@GqX+kl|M94$BK3J-X`Hyj8r!#x6Vt(PXjn?N)qedP z=o1T^#?1^a{;bZ&x`U{f?}TMo8ToN zkHj5v|}r}wDEi7I@)Gj+S1aE-GdnLN+$hw!=DzglMaj#{qjXi_dwpr|HL(gcCXwGLEmi|{4&4#OZ4ChceA zKVd4K!D>_N=_X;{poT~4Q+!Le+ZV>=H7v1*l%w`|`Dx8{)McN@NDlQyln&N3@bFpV z_1w~O4EH3fF@IzJ9kDk@7@QctFq8FbkbaH7K$iX=bV~o#gfh?2JD6lZf(XP>~DACF)fGFt)X%-h1yY~MJU{nA5 ze2zxWMs{YdX3q5XU*9hOH0!_S24DOBA5usB+Ws$6{|AMe*joJ?RxfV}*7AKN9V*~J zK+OMcE@bTD>TG1*yc?*qGqjBN8mgg@h1cJLDv)0!WRPIkC` zZrWXrceVw;fB%3`6kq=a!pq|hFIsQ%ZSlo~)D z|64!aCnw-?>}AG|*iOl44KVf8@|joXi&|)1rB;EQWgm+iHfVbgllP$f!$Wf42%NO5b(j9Bw6L z;0dpUUK$5GX4QbMlTmLM_jJt!ur`_0~$b#BB7FL*%XFf<b__1o)Ao3rlobbN8-(T!1d-bR8D3S0@d zLI!*GMb5s~Q<&sjd}lBb8Nr0>PqE6_!3!2d(KAWFxa{hm`@u|a(%#i(#f8{BP2wbs zt+N_slWF4IF_O|{w`c~)Xvh&R{Au~CFmW#0+}MBd2~X}t9lz6*E7uAD`@EBDe$>7W zzPUkJx<`f$0VA$=>R57^(K^h86>09?>_@M(R4q($!Ck6GG@pnu-x*exAx1jOv|>KH zjNfG5pwm`E-=ydcb+3BJwuU;V&OS=6yM^4Jq{%AVqnTTLwV`AorIDD}T&jWr8pB&j28fVtk_y*JRP^t@l*($UZ z6(B^-PBNZ+z!p?+e8@$&jCv^EWLb$WO=}Scr$6SM*&~B95El~;W_0(Bvoha|uQ1T< zO$%_oLAwf1bW*rKWmlD+@CP&$ObiDy=nh1b2ejz%LO9937N{LDe7gle4i!{}I$;&Y zkexJ9Ybr+lrCmKWg&}p=`2&Gf10orS?4$VrzWidT=*6{KzOGMo?KI0>GL0{iFWc;C z+LPq%VH5g}6V@-tg2m{C!-$fapJ9y}c$U}aUmS{9#0CM*8pC|sfer!)nG7Ji>mfRh z+~6CxNb>6eWKMHBz-w2{mLLwdA7dA-qfTu^A2yG1+9s5k zcF=le_UPYG&q!t5Zd_*E_P3Cf5T6821bO`daa`;DODm8Ih8k89=RN;-asHIigj`n=ux>*f!OC5#;X5i;Q z+V!GUy0|&Y_*8k_QRUA8$lHP;GJ3UUD08P|ALknng|YY13)}!!HW@0z$q+kCH%xet zlWf@BXQ=b=4}QO5eNnN~CzWBbHGUivG=`&eWK}beuV*;?zt=P#pM*eTuy3 zP}c#}AXJ0OIaqXji78l;YrP4sQe#^pOqwZUiiN6^0RCd#D271XCbEKpk`HI0IsN^s zES7YtU#7=8gTn#lkrc~6)R9u&SX6*Jk4GFX7){E)WE?pT8a-%6P+zS6o&A#ml{$WX zABFz#i7`DDlo{34)oo?bOa4Z_lNH>n;f0nbt$JfAl~;4QY@}NH!X|A$KgMmEsd^&Y zt;pi=>AID7ROQfr;MsMtClr5b0)xo|fwhc=qk33wQ|}$@?{}qXcmECh>#kUQ-If0$ zseb{Wf4VFGLNc*Rax#P8ko*=`MwaR-DQ8L8V8r=2N{Gaips2_^cS|oC$+yScRo*uF zUO|5=?Q?{p$inDpx*t#Xyo6=s?bbN}y>NNVxj9NZCdtwRI70jxvm3!5R7yiWjREEd zDUjrsZhS|P&|Ng5r+f^kA6BNN#|Se}_GF>P6sy^e8kBrgMv3#vk%m}9PCwUWJg-AD zFnZ=}lbi*mN-AOm zCs)r=*YQAA!`e#1N>aHF=bb*z*hXH#Wl$z^o}x##ZrUc=kh%OHWhp=7;?8%Xj||@V?1c ziWoaC$^&04;A|T)!Zd9sUzE&$ODyJaBpvqsw19Uiuq{i#VK1!htkdRWBnb z`{rat=nHArT%^R>u#CjjCkw-7%g53|&7z-;X+ewb?OLWiV|#nuc8mp*LuGSi3IP<<*Wyo9GKV7l0Noa4Jr0g3p_$ z*R9{qn=?IXC#WU>48-k5V2Oc_>P;4_)J@bo1|pf=%Rcbgk=5m)CJZ`caHBTm3%!Z9 z_?7LHr_BXbKKr=JD!%?KhwdYSdu8XxPoA{n8^%_lh5cjRHuCY9Zlpz8g+$f@bw@0V z+6DRMT9c|>1^3D|$Vzc(C?M~iZurGH2pXPT%F!JSaAMdO%!5o0uc&iqHx?ImcX6fI zCApkzc~OOnfzAd_+-DcMp&AOQxE_EsMqKM{%dRMI5`5CT&%mQO?-@F6tE*xL?aEGZ z8^wH@wRl`Izx4sDmU>}Ym{ybUm@F83qqZPD6nFm?t?(7>h*?`fw)L3t*l%*iw0Qu#?$5eq!Qc zpQvqgSxrd83NsdO@lL6#{%lsYXWen~d3p4fGBb7&5xqNYJ)yn84!e1PmPo7ChVd%4 zHUsV0Mh?VpzZD=A6%)Qrd~i7 z96*RPbid;BN{Wh?adeD_p8YU``kOrGkNox3D9~!K?w>#kFz!4lzOWR}puS(DmfjJD z`x0z|qB33*^0mZdM&6$|+T>fq>M%yoy(BEjuh9L0>{P&XJ3enGpoQRx`v6$txXt#c z0#N?b5%srj(4xmPvJxrlF3H%OMB!jvfy z;wx8RzU~lb?h_}@V=bh6p8PSb-dG|-T#A?`c&H2`_!u+uenIZe`6f~A7r)`9m8atC zt(b|6Eg#!Q*DfRU=Ix`#B_dK)nnJ_+>Q<1d7W)eynaVn`FNuN~%B;uO2}vXr5^zi2 z!ifIF5@Zlo0^h~8+ixFBGqtweFc`C~JkSq}&*a3C}L?b5Mh-bW=e)({F_g4O3 zb@SFTK3VD9QuFgFnK4Ve_pXc3{S$=+Z;;4+;*{H}Rc;845rP?DLK6G5Y-xdUKkA6E3Dz&5f{F^FjJQ(NSpZ8q-_!L3LL@H* zxbDF{gd^U3uD;)a)sJwAVi}7@%pRM&?5IaUH%+m{E)DlA_$IA1=&jr{KrhD5q&lTC zAa3c)A(K!{#nOvenH6XrR-y>*4M#DpTTOGQEO5Jr6kni9pDW`rvY*fs|ItV;CVITh z=`rxcH2nEJpkQ^(;1c^hfb8vGN;{{oR=qNyKtR1;J>CByul*+=`NydWnSWJR#I2lN zTvgnR|MBx*XFsfdA&;tr^dYaqRZp*2NwkAZE6kV@1f{76e56eUmGrZ>MDId)oqSWw z7d&r3qfazg+W2?bT}F)4jD6sWaw`_fXZGY&wnGm$FRPFL$HzVTH^MYBHWGCOk-89y zA+n+Q6EVSSCpgC~%uHfvyg@ufE^#u?JH?<73A}jj5iILz4Qqk5$+^U(SX(-qv5agK znUkfpke(KDn~dU0>gdKqjTkVk`0`9^0n_wzXO7R!0Thd@S;U`y)VVP&mOd-2 z(hT(|$=>4FY;CBY9#_lB$;|Wd$aOMT5O_3}DYXEHn&Jrc3`2JiB`b6X@EUOD zVl0S{ijm65@n^19T3l%>*;F(?3r3s?zY{thc4%AD30CeL_4{8x6&cN}zN3fE+x<9; zt2j1RRVy5j22-8U8a6$pyT+<`f+x2l$fd_{qEp_bfxfzu>ORJsXaJn4>U6oNJ#|~p z`*ZC&NPXl&=vq2{Ne79AkQncuxvbOG+28*2wU$R=GOmns3W@HE%^r)Fu%Utj=r9t` zd;SVOnA(=MXgnOzI2@3SGKHz8HN~Vpx&!Ea+Df~`*n@8O=0!b4m?7cE^K*~@fqv9q zF*uk#1@6Re_<^9eElgJD!nTA@K9C732tV~;B`hzZ321Ph=^BH?zXddiu{Du5*IPg} zqDM=QxjT!Rp|#Bkp$(mL)aar)f(dOAXUiw81pX0DC|Y4;>Vz>>DMshoips^8Frdv} zlTD=cKa48M>dR<>(YlLPOW%rokJZNF2gp8fwc8b2sN+i6&-pHr?$rj|uFgktK@jg~ zIFS(%=r|QJ=$kvm_~@n=ai1lA{7Z}i+zj&yzY+!t$iGUy|9jH#&oTNJ;JW-3n>DF+ z3aCOzqn|$X-Olu_p7brzn`uk1F*N4@=b=m;S_C?#hy{&NE#3HkATrg?enaVGT^$qIjvgc61y!T$9<1B@?_ibtDZ{G zeXInVr5?OD_nS_O|CK3|RzzMmu+8!#Zb8Ik;rkIAR%6?$pN@d<0dKD2c@k2quB%s( zQL^<_EM6ow8F6^wJN1QcPOm|ehA+dP(!>IX=Euz5qqIq}Y3;ibQtJnkDmZ8c8=Cf3 zu`mJ!Q6wI7EblC5RvP*@)j?}W=WxwCvF3*5Up_`3*a~z$`wHwCy)2risye=1mSp%p zu+tD6NAK3o@)4VBsM!@);qgsjgB$kkCZhaimHg&+k69~drbvRTacWKH;YCK(!rC?8 zP#cK5JPHSw;V;{Yji=55X~S+)%(8fuz}O>*F3)hR;STU`z6T1aM#Wd+FP(M5*@T1P z^06O;I20Sk!bxW<-O;E081KRdHZrtsGJflFRRFS zdi5w9OVDGSL3 zNrC7GVsGN=b;YH9jp8Z2$^!K@h=r-xV(aEH@#JicPy;A0k1>g1g^XeR`YV2HfmqXY zYbRwaxHvf}OlCAwHoVI&QBLr5R|THf?nAevV-=~V8;gCsX>jndvNOcFA+DI+zbh~# zZ7`qNk&w+_+Yp!}j;OYxIfx_{f0-ONc?mHCiCUak=>j>~>YR4#w# zuKz~UhT!L~GfW^CPqG8Lg)&Rc6y^{%3H7iLa%^l}cw_8UuG;8nn9)kbPGXS}p3!L_ zd#9~5CrH8xtUd?{d2y^PJg+z(xIfRU;`}^=OlehGN2=?}9yH$4Rag}*+AWotyxfCJ zHx=r7ZH>j2kV?%7WTtp+-HMa0)_*DBBmC{sd$)np&GEJ__kEd`xB5a2A z*J+yx>4o#ZxwA{;NjhU*1KT~=ZK~GAA;KZHDyBNTaWQ1+;tOFFthnD)DrCn`DjBZ% zk$N5B4^$`n^jNSOr=t(zi8TN4fpaccsb`zOPD~iY=UEK$0Y70bG{idLx@IL)7^(pL z{??Bnu=lDeguDrd%qW1)H)H`9otsOL-f4bSu};o9OXybo6J!Lek`a4ff>*O)BDT_g z<6@SrI|C9klY(>_PfA^qai7A_)VNE4c^ZjFcE$Isp>`e5fLc)rg@8Q_d^Uk24$2bn z9#}6kZ2ZxS9sI(RqT7?El2@B+($>eBQrNi_k#CDJ8D9}8$mmm z4oSKO^F$i+NG)-HE$O6s1--6EzJa?C{x=QgK&c=)b(Q9OVoAXYEEH20G|q$}Hue%~ zO3B^bF=t7t48sN zWh_zA`w~|){-!^g?6Mqf6ieV zFx~aPUOJGR=4{KsW7I?<=J2|lY`NTU=lt=%JE9H1vBpkcn=uq(q~=?iBt_-r(PLBM zP-0dxljJO>4Wq-;stY)CLB4q`-r*T$!K2o}?E-w_i>3_aEbA^MB7P5piwt1dI-6o!qWCy0 ztYy!x9arGTS?kabkkyv*yxvsPQ7Vx)twkS6z2T@kZ|kb8yjm+^$|sEBmvACeqbz)RmxkkDQX-A*K!YFziuhwb|ym>C$}U|J)4y z$(z#)GH%uV6{ec%Zy~AhK|+GtG8u@c884Nq%w`O^wv2#A(&xH@c5M`Vjk*SR_tJnq z0trB#aY)!EKW_}{#L3lph5ow=@|D5LzJYUFD6 z7XnUeo_V0DVSIKMFD_T0AqAO|#VFDc7c?c-Q%#u00F%!_TW1@JVnsfvm@_9HKWflBOUD~)RL``-!P;(bCON_4eVdduMO>?IrQ__*zE@7(OX zUtfH@AX*53&xJW*Pu9zcqxGiM>xol0I~QL5B%Toog3Jlenc^WbVgeBvV8C8AX^Vj& z^I}H})B=VboO%q1;aU5ACMh{yK4J;xlMc`jCnZR^!~LDs_MP&8;dd@4LDWw~*>#OT zeZHwdQWS!tt5MJQI~cw|Ka^b4c|qyd_ly(+Ql2m&AAw^ zQeSXDOOH!!mAgzAp0z)DD>6Xo``b6QwzUV@w%h}Yo>)a|xRi$jGuHQhJVA%>)PUvK zBQ!l0hq<3VZ*RnrDODP)>&iS^wf64C;MGqDvx>|p;35%6(u+IHoNbK z;Gb;TneFo*`zUKS6kwF*&b!U8e5m4YAo03a_e^!5BP42+r)LFhEy?_7U1IR<; z^0v|DhCYMSj<-;MtY%R@Fg;9Kky^pz_t2nJfKWfh5Eu@_l{^ph%1z{jkg5jQrkvD< z#vdK!nku*RrH~TdN~`wDs;d>XY1PH?O<4^U4lmA|wUW{Crrv#r%N>7k#{Gc44Fr|t z@UZP}Y-TrAmnEZ39A*@6;ccsR>)$A)S>$-Cj!=x$rz7IvjHIPM(TB+JFf{ehuIvY$ zsDAwREg*%|=>Hw$`us~RP&3{QJg%}RjJKS^mC_!U;E5u>`X`jW$}P`Mf}?7G7FX#{ zE(9u1SO;3q@ZhDL9O({-RD+SqqPX)`0l5IQu4q)49TUTkxR(czeT}4`WV~pV*KY&i zAl3~X%D2cPVD^B43*~&f%+Op)wl<&|D{;=SZwImydWL6@_RJjxP2g)s=dH)u9Npki zs~z9A+3fj0l?yu4N0^4aC5x)Osnm0qrhz@?nwG_`h(71P znbIewljU%T*cC=~NJy|)#hT+lx#^5MuDDnkaMb*Efw9eThXo|*WOQzJ*#3dmRWm@! zfuSc@#kY{Um^gBc^_Xdxnl!n&y&}R4yAbK&RMc+P^Ti;YIUh|C+K1|=Z^{nZ}}rxH*v{xR!i%qO~o zTr`WDE@k$M9o0r4YUFFeQO7xCu_Zgy)==;fCJ94M_rLAv&~NhfvcLWCoaGg2ao~3e zBG?Ms9B+efMkp}7BhmISGWmJsKI@a8b}4lLI48oWKY|8?zuuNc$lt5Npr+p7a#sWu zh!@2nnLBVJK!$S~>r2-pN||^w|fY`CT{TFnJy`B|e5;=+_v4l8O-fkN&UQbA4NKTyntd zqK{xEKh}U{NHoQUf!M=2(&w+eef77VtYr;xs%^cPfKLObyOV_9q<(%76-J%vR>w9!us-0c-~Y?_EVS%v!* z15s2s3eTs$Osz$JayyH|5nPAIPEX=U;r&p;K14G<1)bvn@?bM5kC{am|C5%hyxv}a z(DeSKI5ZfZ1*%dl8frIX2?);R^^~LuDOpNpk-2R8U1w92HmG1m&|j&J{EK=|p$;f9 z7Rs5|jr4r8k5El&qcuM+YRlKny%t+1CgqEWO>3;BSRZi(LA3U%Jm{@{y+A+w(gzA< z7dBq6a1sEWa4cD0W7=Ld9z0H7RI^Z7vl(bfA;72j?SWCo`#5mVC$l1Q2--%V)-uN* z9ha*s-AdfbDZ8R8*fpwjzx=WvOtmSzGFjC#X)hD%Caeo^OWjS(3h|d9_*U)l%{Ab8 zfv$yoP{OuUl@$(-sEVNt{*=qi5P=lpxWVuz2?I7Dc%BRc+NGNw+323^ z5BXGfS71oP^%apUo(Y#xkxE)y?>BFzEBZ}UBbr~R4$%b7h3iZu3S(|A;&HqBR{nK& z$;GApNnz=kNO^FL&nYcfpB7Qg;hGJPsCW44CbkG1@l9pn0`~oKy5S777uH)l{irK!ru|X+;4&0D;VE*Ii|<3P zUx#xUqvZT5kVQxsF#~MwKnv7;1pR^0;PW@$@T7I?s`_rD1EGUdSA5Q(C<>5SzE!vw z;{L&kKFM-MO>hy#-8z`sdVx})^(Dc-dw;k-h*9O2_YZw}|9^y-|8RQ`BWJUJL(Cer zP5Z@fNc>pTXABbTRY-B5*MphpZv6#i802giwV&SkFCR zGMETyUm(KJbh+&$8X*RB#+{surjr;8^REEt`2&Dubw3$mx>|~B5IKZJ`s_6fw zKAZx9&PwBqW1Oz0r0A4GtnZd7XTKViX2%kPfv+^X3|_}RrQ2e3l=KG_VyY`H?I5&CS+lAX5HbA%TD9u6&s#v!G> zzW9n4J%d5ye7x0y`*{KZvqyXUfMEE^ZIffzI=Hh|3J}^yx7eL=s+TPH(Q2GT-sJ~3 zI463C{(ag7-hS1ETtU;_&+49ABt5!A7CwLwe z=SoA8mYZIQeU;9txI=zcQVbuO%q@E)JI+6Q!3lMc=Gbj(ASg-{V27u>z2e8n;Nc*pf}AqKz1D>p9G#QA+7mqqrEjGfw+85Uyh!=tTFTv3|O z+)-kFe_8FF_EkTw!YzwK^Hi^_dV5x-Ob*UWmD-})qKj9@aE8g240nUh=g|j28^?v7 zHRTBo{0KGaWBbyX2+lx$wgXW{3aUab6Bhm1G1{jTC7ota*JM6t+qy)c5<@ zpc&(jVdTJf(q3xB=JotgF$X>cxh7k*(T`-V~AR+`%e?YOeALQ2Qud( zz35YizXt(aW3qndR}fTw1p()Ol4t!D1pitGNL95{SX4ywzh0SF;=!wf=?Q?_h6!f* zh7<+GFi)q|XBsvXZ^qVCY$LUa{5?!CgwY?EG;*)0ceFe&=A;!~o`ae}Z+6me#^sv- z1F6=WNd6>M(~ z+092z>?Clrcp)lYNQl9jN-JF6n&Y0mp7|I0dpPx+4*RRK+VQI~>en0Dc;Zfl+x z_e_b7s`t1_A`RP3$H}y7F9_na%D7EM+**G_Z0l_nwE+&d_kc35n$Fxkd4r=ltRZhh zr9zER8>j(EdV&Jgh(+i}ltESBK62m0nGH6tCBr90!4)-`HeBmz54p~QP#dsu%nb~W z7sS|(Iydi>C@6ZM(Us!jyIiszMkd)^u<1D+R@~O>HqZIW&kearPWmT>63%_t2B{_G zX{&a(gOYJx!Hq=!T$RZ&<8LDnxsmx9+TBL0gTk$|vz9O5GkK_Yx+55^R=2g!K}NJ3 zW?C;XQCHZl7H`K5^BF!Q5X2^Mj93&0l_O3Ea3!Ave|ixx+~bS@Iv18v2ctpSt4zO{ zp#7pj!AtDmti$T`e9{s^jf(ku&E|83JIJO5Qo9weT6g?@vX!{7)cNwymo1+u(YQ94 zopuz-L@|5=h8A!(g-MXgLJC0MA|CgQF8qlonnu#j z;uCeq9ny9QSD|p)9sp3ebgY3rk#y0DA(SHdh$DUm^?GI<>%e1?&}w(b zdip1;P2Z=1wM+$q=TgLP$}svd!vk+BZ@h<^4R=GS2+sri7Z*2f`9 z5_?i)xj?m#pSVchk-SR!2&uNhzEi+#5t1Z$o0PoLGz*pT64%+|Wa+rd5Z}60(j?X= z{NLjtgRb|W?CUADqOS@(*MA-l|E342NxRaxLTDqsOyfWWe%N(jjBh}G zm7WPel6jXijaTiNita+z(5GCO0NM=Melxud57PP^d_U## zbA;9iVi<@wr0DGB8=T9Ab#2K_#zi=$igyK48@;V|W`fg~7;+!q8)aCOo{HA@vpSy-4`^!ze6-~8|QE||hC{ICKllG9fbg_Y7v z$jn{00!ob3!@~-Z%!rSZ0JO#@>|3k10mLK0JRKP-Cc8UYFu>z93=Ab-r^oL2 zl`-&VBh#=-?{l1TatC;VweM^=M7-DUE>m+xO7Xi6vTEsReyLs8KJ+2GZ&rxw$d4IT zPXy6pu^4#e;;ZTsgmG+ZPx>piodegkx2n0}SM77+Y*j^~ICvp#2wj^BuqRY*&cjmL zcKp78aZt>e{3YBb4!J_2|K~A`lN=u&5j!byw`1itV(+Q_?RvV7&Z5XS1HF)L2v6ji z&kOEPmv+k_lSXb{$)of~(BkO^py&7oOzpjdG>vI1kcm_oPFHy38%D4&A4h_CSo#lX z2#oqMCTEP7UvUR3mwkPxbl8AMW(e{ARi@HCYLPSHE^L<1I}OgZD{I#YH#GKnpRmW3 z2jkz~Sa(D)f?V?$gNi?6)Y;Sm{&?~2p=0&BUl_(@hYeX8YjaRO=IqO7neK0RsSNdYjD zaw$g2sG(>JR=8Iz1SK4`*kqd_3-?;_BIcaaMd^}<@MYbYisWZm2C2|Np_l|8r9yM|JkUngSo@?wci(7&O9a z%|V(4C1c9pps0xxzPbXH=}QTxc2rr7fXk$9`a6TbWKPCz&p=VsB8^W96W=BsB|7bc zf(QR8&Ktj*iz)wK&mW`#V%4XTM&jWNnDF56O+2bo<3|NyUhQ%#OZE8$Uv2a@J>D%t zMVMiHh?es!Ex19q&6eC&L=XDU_BA&uR^^w>fpz2_`U87q_?N2y;!Z!bjoeKrzfC)} z?m^PM=(z{%n9K`p|7Bz$LuC7!>tFOuN74MFELm}OD9?%jpT>38J;=1Y-VWtZAscaI z_8jUZ#GwWz{JqvGEUmL?G#l5E=*m>`cY?m*XOc*yOCNtpuIGD+Z|kn4Xww=BLrNYS zGO=wQh}Gtr|7DGXLF%|`G>J~l{k^*{;S-Zhq|&HO7rC_r;o`gTB7)uMZ|WWIn@e0( zX$MccUMv3ABg^$%_lNrgU{EVi8O^UyGHPNRt%R!1#MQJn41aD|_93NsBQhP80yP<9 zG4(&0u7AtJJXLPcqzjv`S~5;Q|5TVGccN=Uzm}K{v)?f7W!230C<``9(64}D2raRU zAW5bp%}VEo{4Rko`bD%Ehf=0voW?-4Mk#d3_pXTF!-TyIt6U+({6OXWVAa;s-`Ta5 zTqx&8msH3+DLrVmQOTBOAj=uoxKYT3DS1^zBXM?1W+7gI!aQNPYfUl{3;PzS9*F7g zWJN8x?KjBDx^V&6iCY8o_gslO16=kh(|Gp)kz8qlQ`dzxQv;)V&t+B}wwdi~uBs4? zu~G|}y!`3;8#vIMUdyC7YEx6bb^1o}G!Jky4cN?BV9ejBfN<&!4M)L&lRKiuMS#3} z_B}Nkv+zzxhy{dYCW$oGC&J(Ty&7%=5B$sD0bkuPmj7g>|962`(Q{ZZMDv%YMuT^KweiRDvYTEop3IgFv#)(w>1 zSzH>J`q!LK)c(AK>&Ib)A{g`Fdykxqd`Yq@yB}E{gnQV$K!}RsgMGWqC3DKE(=!{}ekB3+(1?g}xF>^icEJbc z5bdxAPkW90atZT+&*7qoLqL#p=>t-(-lsnl2XMpZcYeW|o|a322&)yO_8p(&Sw{|b zn(tY$xn5yS$DD)UYS%sP?c|z>1dp!QUD)l;aW#`%qMtQJjE!s2z`+bTSZmLK7SvCR z=@I4|U^sCwZLQSfd*ACw9B@`1c1|&i^W_OD(570SDLK`MD0wTiR8|$7+%{cF&){$G zU~|$^Ed?TIxyw{1$e|D$050n8AjJvvOWhLtLHbSB|HIfhMpqVf>AF&}ZQHhOJ14Bz zww+XL+qP}nww+W`F>b!by|=&a(cM4JIDhsTXY8@|ntQG}-}jm0&Bcj|LV(#sc=BNS zRjh;k9l>EdAFdd)=H!U`~$WP*}~^3HZ_?H>gKw>NBa;tA8M1{>St|)yDF_=~{KEPAGkg3VB`QCHol!AQ0|?e^W?81f{@()Wy!vQ$bY; z0ctx)l7VK83d6;dp!s{Nu=SwXZ8lHQHC*J2g@P0a={B8qHdv(+O3wV=4-t4HK1+smO#=S; z3cSI#Nh+N@AqM#6wPqjDmQM|x95JG|l1#sAU|>I6NdF*G@bD?1t|ytHlkKD+z9}#j zbU+x_cR-j9yX4s{_y>@zk*ElG1yS({BInGJcIT>l4N-DUs6fufF#GlF2lVUNOAhJT zGZThq54GhwCG(h4?yWR&Ax8hU<*U)?g+HY5-@{#ls5CVV(Wc>Bavs|l<}U|hZn z_%m+5i_gaakS*Pk7!v&w3&?R5Xb|AkCdytTY;r+Z7f#Id=q+W8cn)*9tEet=OG+Y} z58U&!%t9gYMx2N=8F?gZhIjtkH!`E*XrVJ?$2rRxLhV1z82QX~PZi8^N5z6~f-MUE zLKxnNoPc-SGl7{|Oh?ZM$jq67sSa)Wr&3)0YxlJt(vKf!-^L)a|HaPv*IYXb;QmWx zsqM>qY;tpK3RH-omtta+Xf2Qeu^$VKRq7`e$N-UCe1_2|1F{L3&}M0XbJ@^xRe&>P zRdKTgD6601x#fkDWkoYzRkxbn#*>${dX+UQ;FbGnTE-+kBJ9KPn)501#_L4O_k`P3 zm+$jI{|EC?8BXJY{P~^f-{**E53k%kVO$%p+=H5DiIdwMmUo>2euq0UzU90FWL!>; z{5@sd0ecqo5j!6AH@g6Mf3keTP$PFztq}@)^ZjK;H6Go$#SV2|2bAFI0%?aXgVH$t zb4Kl`$Xh8qLrMbZUS<2*7^F0^?lrOE=$DHW+O zvLdczsu0^TlA6RhDy3=@s!k^1D~Awulk!Iyo#}W$xq8{yTAK!CLl={H0@YGhg-g~+ z(u>pss4k#%8{J%~%8=H5!T`rqK6w^es-cNVE}=*lP^`i&K4R=peg1tdmT~UAbDKc& zg%Y*1E{hBf<)xO>HDWV7BaMWX6FW4ou1T2m^6{Jb!Su1UaCCYY8RR8hAV$7ho|FyEyP~ zEgK`@%a$-C2`p zV*~G>GOAs*3KN;~IY_UR$ISJxB(N~K>=2C2V6>xTmuX4klRXdrJd&UPAw7&|KEwF8Zcy2j-*({gSNR1^p02Oj88GN9a_Hq;Skdp}kO0;FLbje%2ZvPiltDZgv^ z#pb4&m^!79;O8F+Wr9X71laPY!CdNXG?J6C9KvdAE2xWW1>U~3;0v≫L+crb^Bz zc+Nw%zgpZ6>!A3%lau!Pw6`Y#WPVBtAfKSsqwYDWQK-~ zz(mx=nJ6-8t`YXB{6gaZ%G}Dmn&o500Y}2Rd?e&@=hBEmB1C=$OMBfxX__2c2O4K2#(0ksclP$SHp*8jq-1&(<6(#=6&H`Nlc2RVC4->r6U}sTY<1? zn@tv7XwUs-c>Lcmrm5AE0jHI5={WgHIow6cX=UK)>602(=arbuAPZ37;{HTJSIO%9EL`Et5%J7$u_NaC(55x zH^qX^H}*RPDx)^c46x>js=%&?y?=iFs^#_rUl@*MgLD92E5y4B7#EDe9yyn*f-|pQ zi>(!bIg6zY5fLSn@;$*sN|D2A{}we*7+2(4&EhUV%Qqo5=uuN^xt_hll7=`*mJq6s zCWUB|s$)AuS&=)T&_$w>QXHqCWB&ndQ$y4-9fezybZb0bYD^zeuZ>WZF{rc>c4s`` zgKdppTB|o>L1I1hAbnW%H%EkFt%yWC|0~+o7mIyFCTyb?@*Ho)eu(x`PuO8pLikN> z6YeI`V?AUWD(~3=8>}a6nZTu~#QCK(H0+4!ql3yS`>JX;j4+YkeG$ZTm33~PLa3L} zksw7@%e-mBM*cGfz$tS4LC^SYVdBLsR}nAprwg8h2~+Cv*W0%izK+WPVK}^SsL5R_ zpA}~G?VNhJhqx2he2;2$>7>DUB$wN9_-adL@TqVLe=*F8Vsw-yho@#mTD6*2WAr6B zjtLUh`E(;#p0-&$FVw(r$hn+5^Z~9J0}k;j$jL1;?2GN9s?}LASm?*Rvo@?E+(}F& z+=&M-n`5EIz%%F^e)nnWjkQUdG|W^~O|YeY4Fz}>qH2juEere}vN$oJN~9_Th^&b{ z%IBbET*E8%C@jLTxV~h#mxoRrJCF{!CJOghjuKOyl_!Jr?@4Upo7u>fTGtfm|CH2v z&9F+>;6aFbYXLj3{yZ~Yn1J2%!)A3~j2$`jOy{XavW@t)g}}KUVjCWG0OUc7aBc=2 zR3^u=dT47=5SmT{K1aGaVZkOx|24T-J0O$b9dfB25J|7yb6frwS6wZ1^y%EWOm}S< zc1SdYhfsdLG*FB-;!QLV3D!d~hnXTGVQVck9x%=B(Kk8c3y%f0nR95_TbY;l=obSl zEE@fp0|8Q$b3(+DXh?d0FEloGhO0#11CLQT5qtEckBLe-VN-I>9ys}PVK0r;0!jIG zH_q$;a`3Xv9P_V2ekV1SMzd#SKo<1~Dq2?M{(V;AwhH_2x@mN$=|=cG0<3o^j_0OF z7|WJ-f2G=7sA4NVGU2X5`o*D2T7(MbmZ2(oipooE{R?9!{WxX!%ofhsrPAxoIk!Kr z>I$a{Zq=%KaLrDCIL^gmA3z{2z%Wkr)b$QHcNUA^QwydWMJmxymO0QS22?mo%4(Md zgME(zE}ub--3*wGjV`3eBMCQG-@Gel1NKZDGuqobN|mAt0{@ZC9goI|BSmGBTUZ(`Xt z^e2LiMg?6E?G*yw(~K8lO(c4)RY7UWxrXzW^iCg-P41dUiE(i+gDmmAoB?XOB}+Ln z_}rApiR$sqNaT4frw69Wh4W?v(27IlK$Toy<1o)GeF+sGzYVeJ`F)3`&2WDi^_v67 zg;@ehwl3=t+}(DJtOYO!s`jHyo-}t@X|U*9^sIfaZfh;YLqEFmZ^E;$_XK}%eq;>0 zl?+}*kh)5jGA}3daJ*v1knbW0GusR1+_xD`MFPZc3qqYMXd>6*5?%O5pC7UVs!E-` zuMHc6igdeFQ`plm+3HhP)+3I&?5bt|V8;#1epCsKnz0%7m9AyBmz06r90n~9o;K30 z=fo|*`Qq%dG#23bVV9Jar*zRcV~6fat9_w;x-quAwv@BkX0{9e@y0NB(>l3#>82H6 z^US2<`=M@6zX=Pz>kb8Yt4wmeEo%TZ=?h+KP2e3U9?^Nm+OTx5+mVGDvgFee%}~~M zK+uHmj44TVs}!A}0W-A92LWE%2=wIma(>jYx;eVB*%a>^WqC7IVN9{o?iw{e4c=CG zC#i=cRJZ#v3 zF^9V+7u?W=xCY%2dvV_0dCP%5)SH*Xm|c#rXhwEl*^{Ar{NVoK*H6f5qCSy`+|85e zjGaKqB)p7zKNKI)iWe6A9qkl=rTjs@W1Crh(3G57qdT0w2ig^{*xerzm&U>YY{+fZbkQ#;^<$JniUifmAuEd^_M(&?sTrd(a*cD! zF*;`m80MrZ^> zaF{}rDhEFLeH#`~rM`o903FLO?qw#_Wyb5}13|0agjSTVkSI6Uls)xAFZifu@N~PM zQ%o?$k)jbY0u|45WTLAirUg3Zi1E&=G#LnSa89F3t3>R?RPcmkF}EL-R!OF_r1ZN` z?x-uHH+4FEy>KrOD-$KHg3$-Xl{Cf0;UD4*@eb~G{CK-DXe3xpEEls?SCj^p z$Uix(-j|9f^{z0iUKXcZQen}*`Vhqq$T?^)Ab2i|joV;V-qw5reCqbh(8N)c%!aB< zVs+l#_)*qH_iSZ_32E~}>=wUO$G_~k0h@ch`a6Wa zsk;<)^y=)cPpHt@%~bwLBy;>TNrTf50BAHUOtt#9JRq1ro{w80^sm-~fT>a$QC;<| zZIN%&Uq>8`Js_E((_1sewXz3VlX|-n8XCfScO`eL|H&2|BPZhDn}UAf_6s}|!XpmUr90v|nCutzMjb9|&}#Y7fj_)$alC zM~~D6!dYxhQof{R;-Vp>XCh1AL@d-+)KOI&5uKupy8PryjMhTpCZnSIQ9^Aq+7=Mb zCYCRvm4;H=Q8nZWkiWdGspC_Wvggg|7N`iED~Eap)Th$~wsxc(>(KI>{i#-~Dd8iQ zzonqc9DW1w4a*}k`;rxykUk+~N)|*I?@0901R`xy zN{20p@Ls<%`1G1Bx87Vm6Z#CA`QR(x@t8Wc?tpaunyV^A*-9K9@P>hAWW9Ev)E$gb z<(t?Te6GcJX2&0% z403pe>e)>m-^qlJU^kYIH)AutgOnq!J>FoMXhA-aEx-((7|(*snUyxa+5$wx8FNxS zKuVAVWArlK#kDzEM zqR?&aXIdyvxq~wF?iYPho*(h?k zD(SBpRDZ}z$A})*Qh!9&pZZRyNixD!8)B5{SK$PkVET(yd<8kImQ3ILe%jhx8Ga-1 zE}^k+Eo^?c4Y-t2_qXiVwW6i9o2qosBDj%DRPNT*UXI0=D9q{jB*22t4HHcd$T&Xi zT=Vte*Gz2E^qg%b7ev04Z&(;=I4IUtVJkg<`N6i7tjUn-lPE(Y4HPyJKcSjFnEzCH zPO(w%LmJ_=D~}PyfA91H4gCaf-qur3_KK}}>#9A}c5w@N;-#cHph=x}^mQ3`oo`Y$ope#)H9(kQK zGyt<7eNPuSAs$S%O>2ElZ{qtDIHJ!_THqTwcc-xfv<@1>IJ;YTv@!g-zDKBKAH<

Zet1e^8c}8fE97XH}+lF{qbF<`Y%dU|I!~Y`ZrVfKX82i z)(%!Tcf~eE^%2_`{WBPGPU@1NB5SCXe1sAI<4&n1IwO{&S$ThWn37heGOSW%nW7*L zxh0WK!E7zh%6yF-7%~l@I~b`2=*$;RYbi(I#zp$gL_d39U4A)KuB( zcS0bt48&%G_I~( zL(}w&2NA6#$=|g)J+-?ehHflD^lr77ngdz=dszFI;?~ZxeJv=gsm?4$$6#V==H{fa zqO!EkT>1-OQSJoX)cN}XsB;shvrHRwTH(I2^Ah4|rizn!V7T7fLh~Z<`Q+?zEMVxh z$=-x^RR*PlhkV_8mshTvs+zmZWY&Jk{9LX0Nx|+NAEq-^+Rh|ZlinVZ=e8=`WQt;e@= zPU}^1cG*O;G7l{Y#nl znp`y%CO_SC7gk0i0gY&phM04Y)~vU0!3$V$2T+h(1ZS+cCgc zaC?3M;B48^faGo>h~--#FNFauH?0BJJ6_nG5qOlr>k~%DCSJaOfl%KWHusw>tGrTxAhlEVDxc8R2C-)LCt&$Rt9IKor=ml7jirX@?WW+M z^I{b}MD5r$s>^^sN@&g`cXD~S_u09xo;{;noKZatIuzqd zW1e7oTl9>g8opPBT(p+&fo0F#!c{NFYYpIZ6u8hOB{F#{nP)@})X20$3iJtG$cO zJ$Oxl_qH{sL5d?=D$2M4C3Ajc;GN0(B-HVT;@pJ-LvIrN%|SY?t}g!J>ufQrR%hoY z!nr$tq~N%)9}^tEip93XW=MQ1@XovSvn`PTqXeT9@_7hGv4%LK1M**Q%UKi|(v@1_ zKGe*@+1%Y4v&`;5vUL`C&{tc+_7HFs7*OtjY8@Gg`C4O&#An{0xOvgNSehTHS~_1V z=daxCMzI5b_ydM5$z zZl`a{mM}i@x;=QyaqJY&{Q^R*^1Yzq!dHH~UwCCga+Us~2wk59ArIYtSw9}tEmjbo z5!JA=`=HP*Ae~Z4Pf7sC^A3@Wfa0Ax!8@H_&?WVe*)9B2y!8#nBrP!t1fqhI9jNMd zM_5I)M5z6Ss5t*f$Eh{aH&HBeh310Q~tRl3wCEcZ>WCEq%3tnoHE)eD=)XFQ7NVG5kM zaUtbnq2LQomJSWK)>Zz1GBCIHL#2E>T8INWuN4O$fFOKe$L|msB3yTUlXES68nXRX zP6n*zB+kXqqkpQ3OaMc9GqepmV?Ny!T)R@DLd`|p5ToEvBn(~aZ%+0q&vK1)w4v0* zgW44F2ixZj0!oB~^3k|vni)wBh$F|xQN>~jNf-wFstgiAgB!=lWzM&7&&OYS=C{ce zRJw|)PDQ@3koZfm`RQ$^_hEN$GuTIwoTQIDb?W&wEo@c75$dW(ER6q)qhF`{#7UTuPH&)w`F!w z0EKs}=33m}_(cIkA2rBWvApydi0HSOgc>6tu&+hmRSB%)s`v_NujJNhKLS3r6hv~- z)Hm@?PU{zd0Tga)cJWb2_!!9p3sP%Z zAFT|jy;k>4X)E>4fh^6=SxV5w6oo`mus&nWo*gJL zZH{SR!x)V)y=Qc7WEv-xLR zhD4OcBwjW5r+}pays`o)i$rcJb2MHLGPmeOmt5XJDg@(O3PCbxdDn{6qqb09X44T zh6I|s=lM6Nr#cGaA5-eq*T=LQ6SlRq*`~`b+dVi5^>el1p;#si6}kK}>w;1 z6B1dz{q_;PY{>DBQ+v@1pfXTd5a*^H9U*;qdj@XBF}MoSSQxVXeUpEM5Z0909&8$pRfR|B(t0ox&xl8{8mUNd#(zWONW{oycv$VjP1>q;jU@ z@+8E~fjz*I54OFFaQ{A5jn1w>r;l!NRlI(8q3*%&+tM?lov_G3wB`<}bQ>1=&xUht zmti5VZzV1Cx006Yzt|%Vwid>QPX8Nfa8|sue7^un@C+!3h!?-YK>lSfNIHh|0kL8v zbv_BklQ4HOqje|@Fyxn%IvL$N&?m(KN;%`I$N|muStjSsgG;gP4Smgz$2u(mG;DXP zf~uQ z212x^l6!MW>V@ORUGSFLAAjz3i5zO$=UmD_zhIk2OXUz^LkDLWjla*PW?l;`LLos> z7FBvCr)#)XBByDm(=n%{D>BcUq>0GOV9`i-(ZSI;RH1rdrAJ--f0uuAQ4odl z_^$^U_)0BBJwl@6R#&ZtJN+@a(4~@oYF)yG+G#3=)ll8O#Zv3SjV#zSXTW3h9kqn* z@AHL=vf~KMas}6{+u=}QFumr-!c=(BFP_dwvrdehzTyqco)m@xRc=6b#Dy+KD*-Bq zK=y*1VAPJ;d(b?$2cz{CUeG(0`k9_BIuUki@iRS5lp3=1#g)A5??1@|p=LOE|FNd; z-?5MLKd-5>yQ7n__5W^3C!_`hP(o%_E3BKEmo1h=H(7;{6$XRRW6{u+=oQX<((xAJ zNRY`Egtn#B1EBGHLy^eM5y}Jy0h!GAGhb7gZJoZI-9WuSRw)GVQAAcKd4Qm)pH`^3 zq6EIM}Q zxZGx%aLnNP1an=;o8p9+U^>_Bi`e23E^X|}MB&IkS+R``plrRzTE%ncmfvEW#AHJ~ znmJ`x&ez6eT21aLnoI`%pYYj zzQ?f^ob&Il;>6Fe>HPhAtTZa*B*!;;foxS%NGYmg!#X%)RBFe-acahHs3nkV61(E= zhekiPp1d@ACtA=cntbjuv+r-Zd`+lwKFdqZuYba_ey`&H<Psu;Tzwt;-LQxvv<_D5;ik7 zwETZe`+voUhk%$s2-7Rqfl`Ti_{(fydI(DAHKr<66;rYa6p8AD+NEc@Fd@%m`tiK% z=Mebzrtp=*Q%a}2UdK4J&5#tCN5PX>W=(9rUEXZ8yjRu+7)mFpKh{6;n%!bI(qA9kfyOtstGtOl zX!@*O0fly*L4k##fsm&V0j9Lj<_vu1)i?!#xTB7@2H&)$Kzt@r(GH=xRZlIimTDd_o(%9xO388LwC#;vQ?7OvRU_s< zDS@6@g}VnvQ+tn(C#sx0`J^T4WvFxYI17;uPs-Ub{R`J-NTdtBGl+Q>e81Z3#tDUr ztnVc*p{o|RNnMYts4pdw=P!uJkF@8~h)oV4dXu5F7-j0AW|=mt!QhP&ZV!!82*c7t zuOm>B*2gFtq;A8ynZ~Ms?!gEi5<{R_8tRN%aGM!saR4LJQ|?9w>Ff_61(+|ol_vL4 z-+N>fushRbkB4(e{{SQ}>6@m}s1L!-#20N&h%srA=L50?W9skMF9NGfQ5wU*+0<@> zLww8%f+E0Rc81H3e_5^DB@Dn~TWYk}3tqhO{7GDY;K7b*WIJ-tXnYM@z4rn(LGi?z z8%$wivs)fC#FiJh?(SbH-1bgdmHw&--rn7zBWe1xAhDdv#IRB@DGy}}zS%M0(F_3_ zLb-pWsdJ@xXE;=tpRAw?yj(Gz=i$;bsh&o2XN%24b6+?_gJDBeY zws3PE2u!#Cec>aFMk#ECxDlAs;|M7@LT8)Y4(`M}N6IQ{0YtcA*8e42!n^>`0$LFU zUCq2IR2(L`f++=85M;}~*E($nE&j;p{l%xchiTau*tB9bI= zn~Ygd@<+9DrXxoGPq}@vI1Q3iEfKRleuy*)_$+hg?+GOgf1r?d@Or42|s|D>XMa;ebr1uiTNUq@heusd6%WwJqyCCv!L*qou9l!B22H$bQ z)<)IA>Yo77S;|`fqBk!_PhLJEQb0wd1Z|`pCF;hol!34iQYtqu3K=$QxLW7(HFx~v>`vVRr zyqk^B4~!3F8t8Q_D|GLRrAbbQDf??D&Jd|mgw*t1YCd)CM2$76#Cqj1bD*vADwavp zS<`n@gLU4pwCqNPsIfHKl{5}gu9t-o+O< z??!fMqMrt$s}02pdBbOScUrc1T*{*-ideR6(1q4@oC6mxg8v8Y^h^^hfx6| z|Mld6Ax1CuSlmSJmHwdOix?$8emihK#&8&}u8m!#T1+c5u!H)>QW<7&R$eih)xkov zHvvEIJHbkt+2KQ<-bMR;2SYX?8SI=_<-J!GD5@P2FJ}K z5u82YFotCJF(dUeJFRX_3u8%iIYbRS??A?;iVO?84c}4Du9&jG<#urlZ_Unrcg8dR z!5I3%9F*`qwk#joKG_Q%5_xpU7|jm4h0+l$p;g%Tr>i74#3QnMXdz|1l2MQN$yw|5 zThMw15BxjWf2{KM)XtZ+e#N)ihlkxPe=5ymT9>@Ym%_LF}o z1XhCP`3E1A{iVoHA#|O|&5=w;=j*Qf`;{mBAK3={y-YS$`!0UmtrvzHBfR*s{z<0m zW>4C=%N98hZlUhwAl1X`rR)oL0&A`gv5X79??p_==g*n4$$8o5g9V<)F^u7v0Vv^n z1sp8{W@g6eWv2;A31Rhf5j?KJhITYfXWZsl^`7z`CFtnFrHUWiD?$pwU6|PQjs|7RA0o9ARk^9$f`u3&C|#Z3iYdh<0R`l2`)6+ z6tiDj@xO;Q5PDTYSxsx6n>bj+$JK8IPJ=U5#dIOS-zwyK?+t^V`zChdW|jpZuReE_ z)e~ywgFe!0q|jzsBn&(H*N`%AKpR@qM^|@qFai0};6mG_TvXjJ`;qZ{lGDZHScZk( z>pO+%icp)SaPJUwtIPo1BvGyP8E@~w2y}=^PnFJ$iHod^JH%j1>nXl<3f!nY9K$e` zq-?XYl)K`u*cVXM=`ym{N?z=dHQNR23M8uA-(vsA$6(xn+#B-yY!CB2@`Uz({}}w+ z0sni*39>rMC!Ay|1B@;al%T&xE(wCf+`3w>N)*LxZZZYi{5sqiVWgbNd>W*X?V}C- zjQ4F7e_uCUOHbtewQkq?m$*#@ZvWbu{4i$`aeKM8tc^ zL5!GL8gX}c+qNUtUIcps1S)%Gsx*MQLlQeoZz2y2OQb(A73Jc3`LmlQf0N{RTt;wa`6h|ljX1V7UugML=W5-STDbeWTiEMjPQ$({hn_s&NDXzs6?PLySp$?L`0ilH3vCUO{JS0Dp`z;Ry$6}R@1NdY7rxccbm$+;ApSe=2q!0 z()3$vYN0S$Cs)#-OBs{_2uFf}L4h$;7^2w20=l%5r9ui&pTEgg4U!FoCqyA6r2 zC5s72l}i*9y|KTjDE5gVlYe4I2gGZD)e`Py2gq7cK4at{bT~DSbQQ4Z4sl)kqXbbr zqvXtSqMrDdT2qt-%-HMoqeFEMsv~u)-NJ%Z*ipSJUm$)EJ+we|4*-Mi900K{K|e0; z1_j{X5)a%$+vM7;3j>skgrji92K1*Ip{SfM)=ob^E374JaF!C(cZ$R_E>Wv+?Iy9M z?@`#XDy#=z%3d9&)M=F8Xq5Zif%ldIT#wrlw(D_qOKo4wD(fyDHM5(wm1%7hy6euJ z%Edg!>Egs;ZC6%ktLFtyN0VvxN?*4C=*tOEw`{KQvS7;c514!FP98Nf#d#)+Y-wsl zP3N^-Pnk*{o(3~m=3DX$b76Clu=jMf9E?c^cbUk_h;zMF&EiVz*4I(rFoaHK7#5h0 zW7CQx+xhp}Ev+jw;SQ6P$QHINCxeF8_VX=F3&BWUd(|PVViKJl@-sYiUp@xLS2NuF z8W3JgUSQ&lUp@2E(7MG`sh4X!LQFa6;lInWqx}f#Q z4xhgK1%}b(Z*rZn=W{wBOe7YQ@1l|jQ|9ELiXx+}aZ(>{c7Ltv4d>PJf7f+qjRU8i%XZZFJkj&6D^s;!>`u%OwLa*V5Js9Y$b-mc!t@{C415$K38iVu zP7!{3Ff%i_e!^LzJWhBgQo=j5k<<($$b&%%Xm_f8RFC_(97&nk83KOy@I4k?(k<(6 zthO$3yl&0x!Pz#!79bv^?^85K5e7uS$ zJ33yka2VzOGUhQXeD{;?%?NTYmN3{b0|AMtr(@bCx+c=F)&_>PXgAG}4gwi>g82n> zL3DlhdL|*^WTmn;XPo62HhH-e*XIPSTF_h{#u=NY8$BUW=5@PD{P5n~g5XDg?Fzvb_u ziK&CJqod4srfY2T?+4x@)g9%3%*(Q2%YdCA3yM{s=+QD0&IM`8k8N&-6%iIL3kon> z0>p3BUe!lrz&_ZX2FiP%MeuQY-xVV%K?=bGPOM&XM0XRd7or< zy}jn_eEzuQ>t2fM9ict#ZNxD7HUycsq76IavfoNl$G1|t*qpUSX;YgpmJrr_8yOJ2 z(AwL;Ugi{gJ29@!G-mD82Z)46T`E+s86Qw|YSPO*OoooraA!8x_jQXYq5vUw!5f_x zubF$}lHjIWxFar8)tTg8z-FEz)a=xa`xL~^)jIdezZsg4%ePL$^`VN#c!c6`NHQ9QU zkC^<0f|Ksp45+YoX!Sv>+57q}Rwk*2)f{j8`d8Ctz^S~me>RSakEvxUa^Pd~qe#fb zN7rnAQc4u$*Y9p~li!Itp#iU=*D4>dvJ{Z~}kqAOBcL8ln3YjR{Sp!O`s=5yM zWRNP#;2K#+?I&?ZSLu)^z-|*$C}=0yi7&~vZE$s``IE^PY|dj^HcWI$9ZRm>3w(u` z-1%;;MJbzHFNd^!Ob!^PLO-xhhj@XrI81Y)x4@FdsI( za`o4Gy(`T$P?PB?s>o+eIOtuirMykbuAi65Y_UN1(?jTCy@J8Px`%;bcNmPm#Fr!= z5V!YViFJ!FBfEq>nJFk0^RAV1(7w+X`HRgP;nJHJdMa!}&vvduCMoslwHTes_I76|h>;(-9lbfGnt zoZomakOt759AuTX4b$)G8TzJ&m*BV8!vMs9#=e0tWa z%)84R=3?tfh72~=Rc;fXwj+x z+25xapYK@2@;}6)@8IL+F6iuJ_B{&A-0=U=U6WMbY>~ykVFp$XkH)f**b>TE5)shN z39E2L@JPCSl!?pkvFeh@6dCv9oE}|{GbbVM!XIgByN#md&tXy@>QscU0#z!I&X4;d z&B&ZA4lbrHJ!x4lCN4KC-)u#gT^cE{Xnhu`0RXVKn|j$vz8m}v^%*cQ{(h%FW8_8a zFM{$PirSI8@#*xg2T){A+EKX(eTC66Fb})w{vg%Vw)hvV-$tttI^V5wvU?a{(G}{G z@ob7Urk1@hDN&C$N!Nio9YrkiUC{5qA`KH*7CriaB;2~2Od>2l=WytBRl#~j`EYsj}jqK2xD*3 ztEUiPZzEJC??#Tj^?f)=sRXOJ_>5aO(|V#Yqro05p6)F$j5*wYr1zz|T4qz$0K(5! zr`6Pqd+)%a9Xq3aNKrY9843)O56F%=j_Yy_;|w8l&RU1+B4;pP*O_}X8!qD?IMiyT zLXBOOPg<*BZtT4LJ7DfyghK|_*mMP7a1>zS{8>?}#_XXaLoUBAz(Wi>$Q!L;oQ&cL z6O|T6%Dxq3E35$0g5areq9$2+R(911!Z9=wRPq-pju7DnN9LAfOu3%&onnfx^Px5( zT2^sU>Y)88F5#ATiVoS$jzC-M`vY8!{8#9O#3c&{7J1lo-rcNK7rlF0Zt*AKE(WN* z*o?Tv?Sdz<1v6gfCok8MG6Pzecx9?C zrQG5j^2{V556Hj=xTiU-seOCr2ni@b<&!j>GyHbv!&uBbHjH-U5Ai-UuXx0lcz$D7%=! z&zXD#Jqzro@R=hy8bv>D_CaOdqo6)vFjZldma5D+R;-)y1NGOFYqEr?h zd_mTwQ@K2veZTxh1aaV4F;YnaWA~|<8$p}-eFHashbWW6Dzj=3L=j-C5Ta`w-=QTw zA*k9!Ua~-?eC{Jc)xa;PzkUJ#$NfGJOfbiV^1au;`_Y8|{eJ(~W9pP9q?gLl5E6|e{xkT@s|Ac;yk01+twk_3nuk|lRu{7-zOjLAGe!)j?g+@-;wC_=NPIhk(W zfEpQrdRy z^Q$YBs%>$=So>PAMkrm%yc28YPi%&%=c!<}a=)sVCM51j+x#<2wz?2l&UGHhOv-iu z64x*^E1$55$wZou`E=qjP1MYz0xErcpMiNYM4+Qnb+V4MbM;*7vM_Yp^uXUuf`}-* z_2CnbQ);j5;Rz?7q)@cGmwE^P>4_u9;K|BFlOz_|c^1n~%>!uO#nA?5o4A>XLO{X2 z=8M%*n=IdnXQ}^+`DXRKM;3juVrXdgv79;E=ovQa^?d7wuw~nbu%%lsjUugE8HJ9zvZIM^nWvjLc-HKc2 zbj{paA}ub~4N4Vw5oY{wyop9SqPbWRq=i@Tbce`r?6e`?`iOoOF;~pRyJlKcIJf~G z)=BF$B>YF9>qV#dK^Ie#{0X(QPnOuu((_-u?(mxB7c9;LSS-DYJ8Wm4gz1&DPQ8;0 z=Wao(zb1RHXjwbu_Zv<=9njK28sS}WssjOL!3-E5>d17Lfnq0V$+IU84N z-4i$~!$V-%Ik;`Z3MOqYZdiZ^3nqqzIjLE+zpfQC+LlomQu-uNCStj%MsH(hsimN# z%l4vpJBs_2t7C)x@6*-k_2v0FOk<1nIRO3F{E?2DnS}w> z#%9Oa{`RB5FL5pKLkg59#x~)&I7GzfhiVC@LVFSmxZuiRUPVW*&2ToCGST0K`kRK) z02#c8W{o)w1|*YmjGSUO?`}ukX*rHIqGtFH#!5d1Jd}&%4Kc~Vz`S7_M;wtM|6PgI zNb-Dy-GI%dr3G3J?_yBX#NevuYzZgzZ!vN>$-aWOGXqX!3qzCIOzvA5PLC6GLIo|8 zQP^c)?NS29hPmk5WEP>cHV!6>u-2rR!tit#F6`_;%4{q^6){_CHGhvAs=1X8Fok+l zt&mk>{4ARXVvE-{^tCO?inl{)o}8(48az1o=+Y^r*AIe%0|{D_5_e>nUu`S%zR6|1 zu0$ov7c`pQEKr0sIIdm7hm{4K_s0V%M-_Mh;^A0*=$V9G1&lzvN9(98PEo=Zh$`Vj zXh?fZ;9$d!6sJRSjTkOhb7@jgSV^2MOgU^s2Z|w*e*@;4h?A8?;v8JaLPCoKP_1l- z=Jp0PYDf(d2Z`;O7mb6(_X_~z0O2yq?H`^c=h|8%gfywg#}wIyv&_uW{-e8e)YmGR zI0NNSDoJWa%0ztGzkwl>IYW*DesPRY?oH+ow^(>(47XUm^F`fAa0B~ja-ae$e>4-A z64lb_;|W0ppKI+ zxu2VLZzv4?Mr~mi?WlS-1L4a^5k+qb5#C)ktAYGUE1H?Vbg9qsRDHAvwJUN=w~AuT zUXYioFg2Dx-W)}w9VdFK#vpjoSc!WcvRZ_;TgHu;LSY*i7K_>Px{%C4-IL?6q?Qa_ zL7l=EEo|@X&$gX;fYP02qJF~LN9?E-OL2G(Fo4hW)G{`qnW zTIuc+-1VJvKgph0jAc(LzM);Pg$MPln?U|ek{_5nNJHfm-Y#ec+n#Yf_e>XfbLbN)eqHEDr0#?<;TskL5-0JGv|Ut{=$Xk8hlwbaMXdcI3GL zY-hykR{zX9liy$Z2F3!z346uu%9@-y6Gda`X2*ixlD_P@<}K?AoV?(%lM%* z(xNk=|A()443aGj)-~IDf3J+UA2p2lh6ei^pG*HL#SiThnIr5WZDXebI)F7X zGmP-3bH$i$+(IwqgbM7h%G5oJ@4{Z~qZ#Zs*k7eXJIqg;@0kAGV|b=F#hZs)2BYu1 zr8sj#Zd+Iu^G}|@-dR5S*U-;DqzkX3V0@q-k8&VHW?h0b0?tJ-Atqmg^J8iF7DP6k z)W{g?5~F*$5x?6W)3YKcrNu8%%(DglnzMx5rsU{#AD+WPpRBf``*<8F-x75D$$13U zcaNXYC0|;r&(F@!+E=%+;bFKwKAB$?6R%E_QG5Yn5xX#h+zeI-=mdXD5+D+lEuM`M ze+*G!zX^xbnA?~LnPI=D2`825Ax8rM()i*{G0gcV5MATV?<7mh+HDA7-f6nc@95st zzC_si${|&=$MUj@nLxl_HwEXb2PDH+V?vg zA^DJ%dn069O9TNK-jV}cQKh|$L4&Uh`?(z$}#d+{X zm&=KTJ$+KvLZv-1GaHJm{>v=zXW%NSDr8$0kSQx(DQ)6S?%sWSHUazXSEg_g3agt2@0nyD?A?B%9NYr(~CYX^&U#B4XwCg{%YMYo%e68HVJ7`9KR`mE*Wl7&5t71*R3F>*&hVIaZXaI;2a$?;{Ew{e3Hr1* zbf$&Fyhnrq7^hNC+0#%}n^U2{ma&eS)7cWH$bA@)m59rXlh96piJu@lcKl<>+!1#s zW#6L5Ov%lS(?d66-(n`A%UuiIqs|J|Ulq0RYq-m&RR0>wfA1?<34tI?MBI#a8lY{m z{F2m|A@=`DpZpwdIH#4)9$#H3zr4kn2OX!UE=r8FEUFAwq6VB?DJ8h59z$GXud$#+ zjneIq8uSi&rnG0IR8}UEn5OcZC?@-;$&Ry9hG{-1ta`8aAcOe1|82R7EH`$Qd3sf* zbrOk@G%H7R`j;hOosRVIP_2_-TuyB@rdj?(+k-qQwnhV3niH+CMl>ELX(;X3VzZVJ ztRais0C^L*lmaE(nmhvep+peCqr!#|F?iVagZcL>NKvMS_=*Yl%*OASDl3(mMOY9! z=_J$@nWpA-@><43m4olSQV8(PwhsO@+7#qs@0*1fDj70^UfQ(ORV0N?H{ceLX4<43 zEn)3CGoF&b{t2hbIz;Og+$+WiGf+x5mdWASEWIA*HQ9K9a?-Pf9f1gO6LanVTls)t z^f6_SD|>2Kx8mdQuiJwc_SmZOZP|wD7(_ti#0u=io|w~gq*Odv>@8JBblRCzMKK_4 zM-uO0Ud9>VD>J;zZzueo#+jbS7k#?W%`AF1@ZPI&q%}beZ|ThISf-ly)}HsCS~b^g zktgqOZ@~}1h&x50UQD~!xsW-$K~whDQNntLW=$oZDClUJeSr2$r3}94Wk1>co3beS zoY-7t{rGv|6T?5PNkY zj*XjF()ybvnVz5=BFnLO=+1*jG>E7F%&vm6up*QgyNcJJPD|pHoZ!H6?o3Eig0>-! zt^i-H@bJ;^!$6ZSH}@quF#RO)j>7A5kq4e+7gK=@g;POXcGV28Zv$jybL1J`g@wC# z_DW1ck}3+n@h2LFQhwVfaV@D+-kff4celZC0;0ef?pA#*PPd8Kk8sO1wza&BHQFblVU8P1=-qScHff^^fR zycH!hlHQs7iejITpc4UaBxzqTJ}Z#^lk{W(cr`qtW~Ap;HvuUf#MxgEG?tEU+B?G% znub0I(s@XvI(lva}$Z7<}Qg=rWd5n)}rX{nb+Aw;}?l9LZI-`N-*hts=c6XgjfJs ztp>-686v6ug{glEZ}K=jVG|N1WSWrU*&ue|4Q|O@;s0#L5P*U%Vx;)w7S0ZmLuvwA z@zs2Kut)n1K7qaywO#TbBR`Q~%mdr`V)D`|gN0!07C1!r3{+!PYf9*;h?;dE@#z(k z;o`g~<>P|Sy$ldHTUR3v=_X0Iw6F>3GllrFXVW?gU0q6|ocjd!glA)#f0G7i20ly>qxRljgfO2)RVpvmg#BSrN)GbGsrIb}9 z1t+r;Q>?MGLk#LI5*vR*C8?McB|=AoAjuDk&Pn`KQo z`!|mi{Cz@BGJ!TwMUUTkKXKNtS#OVNxfFI_Gfq3Kpw0`2AsJv9PZPq9x?~kNNR9BR zw#2jp%;FJNoOzW>tE#zskPICp>XSs?|B0E%DaJH)rtLA}$Y>?P+vEOvr#8=pylh zch;H3J`RE1{97O+1(1msdshZx$it^VfM$`-Gw>%NN`K|Tr$0}U`J?EBgR%bg=;et0 z_en)!x`~3so^V9-jffh3G*8Iy6sUq=uFq%=OkYvHaL~#3jHtr4sGM?&uY&U8N1G}QTMdqBM)#oLTLdKYOdOY%{5#Tgy$7QA! zWQmP!Wny$3YEm#Lt8TA^CUlTa{Cpp=x<{9W$A9fyKD0ApHfl__Dz4!HVVt(kseNzV z5Fb`|7Mo>YDTJ>g;7_MOpRi?kl>n(ydAf7~`Y6wBVEaxqK;l;}6x8(SD7}Tdhe2SR zncsdn&`eI}u}@^~_9(0^r!^wuKTKbs-MYjXy#-_#?F=@T*vUG@p4X+l^SgwF>TM}d zr2Ree{TP5x@ZtVcWd3++o|1`BCFK(ja-QP?zj6=ZOq)xf$CfSv{v;jCcNt4{r8f+m zz#dP|-~weHla%rsyYhB_&LHkwuj83RuCO0p;wyXsxW5o6{)zFAC~2%&NL? z=mA}szjHKsVSSnH#hM|C%;r0D$7)T`HQ1K5vZGOyUbgXjxD%4xbs$DAEz)-;iO?3& zXcyU*Z8zm?pP}w&9ot_5I;x#jIn^Joi5jBDOBP1)+p@G1U)pL6;SIO>Nhw?9St2UN zMedM(m(T6bNcPPD`%|9dvXAB&IS=W4?*7-tqldqALH=*UapL!4`2TM_{`W&pm*{?| z0DcsaTdGA%RN={Ikvaa&6p=Ux5ycM){F1OgOh(^Yk-T}a5zHH|=%Jk)S^vv9dY~`x zG+!=lsDjp!D}7o94RSQ-o_g#^CnBJlJ@?saH&+j0P+o=eKqrIApyR7ttQu*0 z1f;xPyH2--)F9uP2#Mw}OQhOFqXF#)W#BAxGP8?an<=JBiokg;21gKG_G8X!&Hv;7 zP9Vpzm#@;^-lf=6POs>UrGm-F>-! zm;3qp!Uw?VuXW~*Fw@LC)M%cvbe9!F(Oa^Y6~mb=8%$lg=?a0KcGtC$5y?`L5}*-j z7KcU8WT>2PpKx<58`m((l9^aYa3uP{PMb)nvu zgt;ia9=ZofxkrW7TfSrQf4(2juZRBgcE1m;WF{v1Fbm}zqsK^>sj=yN(x}v9#_{+C zR4r7abT2cS%Wz$RVt!wp;9U7FEW&>T>YAjpIm6ZSM4Q<{Gy+aN`Vb2_#Q5g@62uR_>II@eiHaay+JU$J=#>DY9jX*2A=&y8G%b zIY6gcJ@q)uWU^mSK$Q}?#Arq;HfChnkAOZ6^002J>fjPyPGz^D5p}o;h2VLNTI{HGg!obo3K!*I~a7)p-2Z3hCV_hnY?|6i`29b zoszLpkmch$mJeupLbt4_u-<3k;VivU+ww)a^ekoIRj4IW4S z{z%4_dfc&HAtm(o`d{CZ^AAIE5XCMvwQSlkzx3cLi?`4q8;iFTzuBAddTSWjfcZp* zn{@Am!pl&fv#k|kj86e$2%NK1G4kU=E~z9L^`@%2<%Dx%1TKk_hb-K>tq8A9bCDfW z@;Dc3KqLafkhN6414^46Hl8Tcv1+$q_sYjj%oHz)bsoGLEY1)ia5p=#eii(5AM|TW zA8=;pt?+U~>`|J(B85BKE0cB4n> zWrgZ)Rbu}^A=_oz65LfebZ(1xMjcj_g~eeoj74-Ex@v-q9`Q{J;M!mITVEfk6cn!u zn;Mj8C&3^8Kn%<`Di^~Y%Z$0pb`Q3TA}$TiOnRd`P1XM=>5)JN9tyf4O_z}-cN|i> zwpp9g`n%~CEa!;)nW@WUkF&<|wcWqfL35A}<`YRxV~$IpHnPQs2?+Fg3)wOHqqAA* zPv<6F6s)c^o%@YqS%P{tB%(Lxm`hsKv-Hb}MM3=U|HFgh8R-|-K(3m(eU$L@sg=uW zB$vAK`@>E`iM_rSo;Cr*?&wss@UXi19B9*0m3t3q^<)>L%4j(F85Ql$i^;{3UIP0c z*BFId*_mb>SC)d#(WM1%I}YiKoleKqQswkdhRt9%_dAnDaKM4IEJ|QK&BnQ@D;i-ame%MR5XbAfE0K1pcxt z{B5_&OhL2cx9@Sso@u2T56tE0KC`f4IXd_R3ymMZ%-!e^d}v`J?XC{nv1mAbaNJX| zXau+s`-`vAuf+&yi2bsd5%xdqyi&9o;h&fcO+W|XsKRFOD+pQw-p^pnwwYGu=hF7& z{cZj$O5I)4B1-dEuG*tU7wgYxNEhqAxH?p4Y1Naiu8Lt>FD%AxJ811`W5bveUp%*e z9H+S}!nLI;j$<*Dn~I*_H`zM^j;!rYf!Xf#X;UJW<0gic?y>NoFw}lBB6f#rl%t?k zm~}eCw{NR_%aosL*t$bmlf$u|U2hJ*_rTcTwgoi_N=wDhpimYnf5j!bj0lQ*Go`F& z6Wg+xRv55a(|?sCjOIshTEgM}2`dN-yV>)Wf$J58>lNVhjRagGZw?U9#2p!B5C3~Nc%S>p`H4PK z7vX@|Uo^*F4GXiFnMf4gwHB;Uk8X4TaLX4A>B&L?mw4&`XBnLCBrK2FYJLrA{*))0 z$*~X?2^Q0KS?Yp##T#ohH1B)y4P+rR7Ut^7(kCwS8QqgjP!aJ89dbv^XBbLhTO|=A z|3FNkH1{2Nh*j{p-58N=KA#6ZS}Ir&QWV0CU)a~{P%yhd-!ehF&~gkMh&Slo9gAT+ zM_&3ms;1Um8Uy0S|0r{{8xCB&Tg{@xotF!nU=YOpug~QlZRKR{DHGDuk(l{)d$1VD zj)3zgPeP%wb@6%$zYbD;Uhvy4(D|u{Q_R=fC+9z#sJ|I<$&j$|kkJiY?AY$ik9_|% z?Z;gOQG5I%{2{-*)Bk|Tia8n>TbrmjnK+8u*_cS%*;%>R|K|?urtIdgTM{&}Yn1;| zk`xq*Bn5HP5a`ANv`B$IKaqA4e-XC`sRn3Z{h!hN0=?x(kTP+fE1}-<3eL+QDFXN- z1JmcDt0|7lZN8sh^=$e;P*8;^33pN>?S7C0BqS)ow4{6ODm~%3018M6P^b~(Gos!k z2AYScAdQf36C)D`w&p}V89Lh1s88Dw@zd27Rv0iE7k#|U4jWDqoUP;-He5cd4V7Ql)4S+t>u9W;R-8#aee-Ct1{fPD+jv&zV(L&k z)!65@R->DB?K6Aml57?psj5r;%w9Vc3?zzGs&kTA>J9CmtMp^Wm#1a@cCG!L46h-j z8ZUL4#HSfW;2DHyGD|cXHNARk*{ql-J2W`9DMxzI0V*($9{tr|O3c;^)V4jwp^RvW z2wzIi`B8cYISb;V5lK}@xtm3NB;88)Kn}2fCH(WRH1l@3XaO7{R*Lc7{ZN1m+#&diI7_qzE z?BS+v<)xVMwt{IJ4yS2Q4(77II<>kqm$Jc3yWL42^gG6^Idg+y3)q$-(m2>E49-fV zyvsCzJ5EM4hyz1r#cOh5vgrzNGCBS}(Bupe`v6z{e z)cP*a8VCbRuhPp%BUwIRvj-$`3vrbp;V3wmAUt{?F z0OO?Mw`AS?y@>w%(pBO=0lohnxFWx`>Hs}V$j{XI2?}BtlvIl7!ZMZukDF7 z^6Rq2H*36KHxJ1xWm5uTy@%7;N0+|<>Up>MmxKhb;WbH1+=S94nOS-qN(IKDIw-yr zi`Ll^h%+%k`Yw?o3Z|ObJWtfO|AvPOc96m5AIw;4;USG|6jQKr#QP}+BLy*5%pnG2 zyN@VMHkD`(66oJ!GvsiA`UP;0kTmUST4|P>jTRfbf&Wii8~a`wMwVZoJ@waA{(t(V zwoc9l*4F>YUM8!aE1{?%{P4IM=;NUF|8YkmG0^Y_jTJtKClDV3D3~P7NSm7BO^r7& zWn!YrNc-ryEvhN$$!P%l$Y_P$s8E>cdAe3=@!Igo^0diL6`y}enr`+mQD;RC?w zb8}gXT!aC`%rdxx2_!`Qps&&w4i0F95>;6;NQ-ys;?j#Gt~HXzG^6j=Pv{3l1x{0( z4~&GNUEbH=9_^f@%o&BADqxb54EAq=8rKA~4~A!iDp9%eFHeA1L!Bb8Lz#kF(p#)X zn`CglEJ(+tr=h4bIIHlLkxP>exGw~{Oe3@L^zA)|Vx~2yNuPKtF^cV6X^5lw8hU*b zK-w6x4l&YWVB%0SmN{O|!`Sh6H45!7}oYPOc+a#a|n3f%G@eO)N>W!C|!FNXV3taFdpEK*A1TFGcRK zV$>xN%??ii7jx5D69O>W6O`$M)iQU7o!TPG*+>v6{TWI@p)Yg$;8+WyE9DVBMB=vnONSQ6k1v z;u&C4wZ_C`J-M0MV&MpOHuVWbq)2LZGR0&@A!4fZwTM^i;GaN?xA%0)q*g(F0PIB( zwGrCC#}vtILC_irDXI5{vuVO-(`&lf2Q4MvmXuU8G0+oVvzZp0Y)zf}Co0D+mUEZz zgwR+5y!d(V>s1} zji+mrd_6KG;$@Le2Ic&am6O+Rk1+QS?urB4$FQNyg2%9t%!*S5Ts{8j*&(H1+W;0~ z$frd%jJjlV;>bXD7!a-&!n52H^6Yp}2h3&v=}xyi>EXXZDtOIq@@&ljEJG{D`7Bjr zaibxip6B6Mf3t#-*Tn7p z96yx1Qv-&r3)4vg`)V~f8>>1_?E4&$bR~uR;$Nz=@U(-vyap|Jx zZ;6Ed+b#GXN+gN@ICTHx{=c@J|97TIPWs(_kjEIwZFHfc!rl8Ep-ZALBEZEr3^R-( z7ER1YXOgZ)&_=`WeHfWsWyzzF&a;AwTqzg~m1lOEJ0Su=C2<{pjK;{d#;E zr2~LgXN?ol2ua5Y*1)`(be0tpiFpKbRG+IK(`N?mIgdd9&e6vxzqxzaa`e7zKa3D_ zHi+c1`|720|dn(z4Qos^e7sn(PU%NYLv$&!|4kEse%DK;YAD06@XO3!EpKpz!^*?(?-Ip zC_Zlb(-_as+-D?0Ag9`|4?)bN)5o(J=&udAY|YgV(YuK9k=E>0z`$dSaL(wmxd!1f zME&3wwv@#{dgeMlZ4}GL!I`VZxtdQY$lmauCN_|mGXqEEj@i~du$|>5UvLjsbq!{; z@jEf;21iC1jFEmIPE^4gykHQzCMLj=2Ek4&FvlpqTlS(0YT%*W<>XgH$4ww`D`aihBGkPM(&EG};Cl&wzg8!jL z`rkqPzvH(0Kd{2n=?Bt8aAU&0IyiA+V-qnXVId^qG!SWZ7%_f&i!D{R#7Jo$%tICxY%j)ebORE>3H_c|to}c#HX;HAC?~B;2mmQrMp2;8T zmzde!k7BYg^Z1r|DUvSD3@{6S<1kndb%Qt%GA# z+sB2&F5L`R&fLRdAlpU_pVsJsYDEz{^ zKGaAz#%W+MPGT+D$+xowMY0=ipM)0p?zym&Aoi)qL(pO_weO(k?s|ELHl^W zviJiFUXRL&?`;3_;mvc02A@sbsW9}#{anvGafZ#ST;}za?XS3}ZG3B4m(SW{>w}Fh z)T5Yi*``Tstmi9SHXmuWSND@cj}qtY!`tuD29Dpu+-D3$h<5FY>jE>YJvqBmhw?oll`x7Ono(}R~P zle_eBwYy0Rr7kmf_SEt_gn4)AO-r`}^Z5Y%Rm8)K-?X>rvDL+QT?#)QwDsQ2c$tc* z&#hbgkL6}GnBDH;+lREM6MGIskRa@r>5Iq(ll2IepuhW86w@14=E{6$cz*cBDQ)CT>}v-DLM-v8)xaPBnmGBKM63RgDGqh!<*j90tSE4|G^+r@#-7g2 zs8KE8eZPZhQuN>wBU%8CmkE9LH1%O;-*ty0&K~01>F3XB>6sAm*m3535)9T&Fz}A4 zwGjZYVea@Fesd=Rv?ROE#q=}yfvQEP8*4zoEw4@^Qvw54utUfaR1T6gLmq?c9sON> z>Np6|0hdP_VURy81;`8{ZYS)EpU9-3;huFq)N3r{yP1ZBCHH7=b?Ig6OFK~%!GwtQ z3`RLKe8O&%^V`x=J4%^Oqg4ZN9rW`UQN^rslcr_Utzd-@u-Sm{rphS-y}{k41)Y4E zfzu}IC=J0JmRCV6a3E38nWl1G495grsDDc^H0Fn%^E0FZ=CSHB4iG<6jW1dY`2gUr zF>nB!y@2%rouAUe9m0VQIg$KtA~k^(f{C*Af_tOl=>vz>$>7qh+fPrSD0YVUnTt)? z;@1E0a*#AT{?oUs#bol@SPm0U5g<`AEF^=b-~&4Er)MsNnPsLb^;fL2kwp|$dwiE3 zNc5VDOQ%Q8j*d5vY##)PGXx51s8`0}2_X9u&r(k?s7|AgtW0LYbtlh!KJ;C9QZuz< zq>??uxAI1YP|JpN$+{X=97Cdu^mkwlB={`aUp+Uyu1P139=t%pSVKo7ZGi_v(0z>l zHLGxV%0w&#xvev)KCQ{7GC$nc3H?1VOsYGgjTK;Px(;o0`lerxB<+EJX9G9f8b+)VJdm(Ia)xjD&5ZL45Np?9 zB%oU;z05XN7zt{Q!#R~gcV^5~Y^gn+Lbad7C{UDX2Nznj8e{)TLH|zEc|{a#idm@z z6(zon+{a>FopmQsCXIs*4-dLGgTc)iOhO3r=l?imNUR-pWl!ktO0r_a0Nqo@bu8MzyjSq9zkqPe*`Sxz75rZ zr9X%(=PVqCRB=zfX+_u&*k4#s1k4OV11YgkCrlr6V;vz<{99HKC@qQ+H8xv5)sc63 z69;U4O&{fb5(fN``jJH#3=GHsV56@{d@7`VhA$K^;GU+R-V%%cnmjYs?>c5^6Ugv} zn<}L&i;2`zzW@(kxf$$gVH@7nh}2%G%ciQ_B?r{13?Q@=Q+6msQGtnyY%Gkjeor?g z7F*tMqLdhcq+LCCo^D;CtOACCBhXgK-M&w{*dcUdmtv@XFTofmmpcWKtCn^`#?oZC zUOm52 z7sK$hR|Vh6y&pfIUK&!`8HH*>12$nWA)Ynp+XwOj=jNLD z{QA4gezbe>wiP?`jJO;c&EId;=2u80s_r97;TX!6@*(<%WL+^bmxheMB3pKx0OpH^ zPs}knV+jpJ4TaD@r^V`mTsjf`7!z^H}eHQ#Rp z72(>Dm#QO!ZYR*O@yHic`3*T^t7jc=d`Jz6Lk@Y-bL%cOp_~=#xzIJl?`{Qu;$uC~NkePE+7wSW_FM`&V{gFN zl;lq@;FtAsl!h;tnOvj z#gYx!q$5MdZ0Jxjy=t*q)HFeeyI-vgaGdh1QNhqGRy8qS)|6S0QK7Gj9R?Co{Knh> za>xkQZ0}bBx!9@EUxRBYGm25^G}&j-`0VWX04E|J!kJ8^WoZ(jbhU_twFwWIH32fv zi=pg~(b#ajW=`)Vikwwe39lpML?|sY$?*6*kYBxku_<=#$gfTqQ_F!9F0=OkHnzBo zEwR!H_h|MNjuG$Tj6zaaouO}HYWCF8vN4C%EX-%Iu%ho;q$G#ErnafhXR*4J2Rp5* zhsi0;wlSwE*inVFO>{(8?N~82zijpt+9Y_-^>xnE%T*zk9gi|j7b@s<5{|qEquUD( zS;-%RySZOCOEh*>!kvbsQ265* z>X8*_Wy&~FB@aDHz%glyiAujXq-|2kDUjFTn9Rafsl+XNyFP%PG|l&ZGWBcEXxy=9 zeDn2PIoVuL$gX0RgVK1O$x3%pOzS7x^U5Pi;mtT)%cY;&e&M7GLM}zP+IPbqLt=^5 z7qLfri8myf;~2psc@^cA6mG&{C%e_(M$$!wC^5p^T1QzrS%I?(U{qcd+oJJkQxe10 zON{Q*?iz%F4MbEsoEc+x3E?&2wVR^v3|Q0lDaMvgS7mNjI{2w! z9|~=!83T%GW*iaChSS!`Xd^beFp9N4%K+k*j#jFumk}U?=WKL_kJAltxnxp~+lZzT zp@&&kSPTg3oSGos`rVBhK0|4NdHM_hnKuw1#0JV{gi_dKDJLB+ix~~HpU9%jD)@YY zOK)L7kgbLyN2%Dx#fuY}8swh4ACk7%BpP-n5(RhDq{gEHP*Fo4IviX{C49|B5h~SC zFr`=0)=h2^F5UpCAgt?R5u{6VvpUf#*nC zCQ`$!|C;L2lpjlG?(>T$(_$O3_YNNbPT~(?!j3aD8k=yu^ogw4bkjvgF|3BOq(hB& zG;^cPXmcUP$ox8zElCJ-zMbK9q^8{rri#8Cek5Ydr0YT-KTh@J z6^AcB9ejew8BY5kzZUZX(7Po==eW<(;uV~E7(BY5c0^xr`cuRwn)47bN?zOb!0?cw z#v}R$z66&m#+AHfo@(^V2#S~bhoUkkTArg+6w>JzZ52r96^({1W!?>4$h0l|-jDfj z>7(<+%67#(A|4hZ3>Y;hd&S?}F;`Vtqz|pK&B>NJ=Faci;gkf-+GmfQR8^zo_vul2 zB!)kfu4Dq_g)8TBBo52*sB6F`qa&JCR=_A$QWgX_K}fZm{Cb2#1q`^S3+WaS>sS#@ z-4k*G=#?z6d_e7JJ+Z8^(t0tNdL{K5F;2nfQbXgld}a(X)Gr;WojOy`^?es~AClT$ z5^lD{WJek0!p-QEH5E7n6DKQ0%_ZBZ=|jfV_MM{VmL8y-Wd|>OmeemP=C@xI@@M~1 zW2S*im@Rc=O>V886_UJ@oh1!2H$Ku&U*Hh_oxd{32)vf1$cRiepv28ricM;}#p!+k zaK{z1I=9Y%3m4|Pj*BD*Fn5Vh?O@oD^1UcjyeNh0fbhh~V6xb#4njlGW8OehUe!MnoR(wn#nsoyL1m!Rov)Nv4~&JEVl7L z#^qYdTpNI#u`N0UbVMiDmD>g2VQcG3>4D6gErgddZnSQTs){BExxRJRB?bIxTdZa z;!S8FHJPPiIDQ*FAUiWSYnjILFjDvxvSC zk z=j4Kx@Pg~&2Z?cmMDa;)#xVeorJrxDBqy{+`kG+ZPQqC@#ku-c3ucU+69$#q_*se` z-H#PFW^>-C0>++|6r=<$Z8)ZFaK=ZjwsNYXqRpl9G|yme@Eld5B-*I69Nx_TResHi z!5nm+>6zaJYQO#%D{~o-oOJ;q`fa5}l!8G*U-E$OM&7@dqciBCWtd}|SrDXz$TB($&m*=Epuolu2k`KUwO7maP3P0ok zmF57lSh0Ba@&sO1iZ5^+3s8{B8t|M;Pg&O+{tZJCiLWd6H@{b~9{CLF9s3Kn zt5)Rs9ejne?o{%f>B$Dl%X7fd~KY)I|(pxUeHj;gNsK6;ZR>`ciu;GxvhDUt!+31Knss2U(%ts8K z18)8;<2ax9RG?!|Lwdt^i5L^&O788roKmVAB)=EdK~HqR2Q=)H_VW}xY=95MP_Ov< zPEz3%DRK}+(aUBwsr83H8>`H^v~|A_t}0vPmRwKPt1{|qOY|PZu}j9+{ZhF&-H_TB zU9xWLpNTc`enI|)h9jQeqf5RfGLFk_vfX`40iMpd%KZF!lKbZTdBw$<^G6nuS+$fT zrbK)xo&;buPJcpOZ=x>n+bRXVFDs(23Xr=rDE&!)pVXZ;;A07NXGl_0m`{Z)DQIu$ zFDvY4xu-ifTe_$|n2B83eI;KUg6pVbw+N!nyLj~wnRi{4mNy{WDV)G1!6$y=+x6U{ z%4_9=Q^L!x_gAYp?J3+u5hA5cO8aHeI=6AC8^S{mzhqCBvBLYEutUC(X0>hKg|AvN zvkmJCQNA45_KjW{aEcyrBppcO6G0zTy%v1&@~+2!n?kA9?>0>AjFN|JdCnHQ8$hEU zw#mwGifHppLP?89LMb(Y3Li9iCPx7W%ek}2FgD2YSzjsR4Xj<=zN{Yo@7s7(k%mP4 znT2p&4EQ@q_chd-E z78uvD*C@oba`U3W2Iw`M#`5C8jOHv8^Li<|j^SI>>>`77Dp71Vtz=J?4Zck4SdRbd zfF}C_>Y(#)r@y!Q0`tMlG#b9>5`fAI$B&tWJfbGlYW$J4V+-s=HH!`+;1XeL@USdx zR0$G&&XBf9lQtkH5)p=U!8J!1{oc4E!N-~Abxl6E;;=3-hMYZ+44?u}zabmCE)yB?*_w91m$n1Yskp&@ z;kxeJX-#ioX^{elyLu~gzx|_KxLpX62MF%Axq3$!Z_P`pBWR?zP8OI`PV~6Aa0Oi0 zv_Ot1m&plf-ZF{e(z(Ms3*S5q$e|j;gOwGrmWsCHfLi(h8y?gc$(2H{884C1FvHQQ12tX=qFUsK~zM!W=K>;zaRsu4Xmcc@8nSs!vK+{ z?}bq}-m&p5jRSam67n>yG9ez=I^|J1O;Np8s=P~9MXYLxD+cFQK7PhG=bkjo{Naae zjp3NWWrlFWDb3Z5D07Q|WjZ=wOQ=aKA%en=O@hL$QCKpIXNZE=InFk|Fhq-&H!6&X z*MVy8=hL7Aw&pQjHrFf27C%3B<>FX{@fOLNhUoxL4*@nY}&M3G*T-p67a zo}~_&yGOB)#vbU|Q3FA8S^X)c-yBlmN(_%}`7Ha3uWFe?>9f=3hlO{^gv~$p`v?vk z_P*r43|(S{%ihs;)YH|jAMpP=-Ms7Ne75_YZZiL3CHVjSU`X1|?Ehh&gA=Xn7W7d@ zf8bM9Y>lG!`PWFDDA9G;x*{1Eh^55u66*9D+-4^dYZ{xXP@?sQLVrY%(azM;C^4FuN7CQ%$!3sr1JL=!Be& zuOZL^bLp$Qo2rL=WDzQIls%s!Go z{s}Q0b#+#8bKga|01t%^9Z=wEsevvXM_{$dCR97ed3@1kX)mtSS!JN^rtqKOj}p~> zfpCI@DX*DqcB6ZnBcl~}sGO~1s$AtfkX6fy3N8*ebvZc*KBW;dA=)?#BE&}-or74i zZUt5;{FBPnkZD8YUXDsx&2LvSziAlec3oc>&Lf1Doc3g?H9{OO_$M4B0qTat0UsWP zTlxUeQ3B;oJ%en4n?zQB6*Fb#wH7`$SQN5GI|=DnJKiYm{?-?#-H;#sIjz7kQ4&VW zN9d1(1$_W~S=<%qDD!mwRytas=eqX^iW}YSx3;wJ#)Xp_`Qk1DFiXac$-3;jQbCif zLA-T_s~5yP@Q@W>pXKl^gipQ>gp@HlBB>WDVpW199;V%?N1`U$ovLE;NI2?|_q2~5 zlg>xT9NADWkv5-*FjS~nP^7$k!N2z?dr!)&l0+4xDK7=-6Rkd$+_^`{bVx!5LgC#N z-dv-k@OlYCEvBfcr1*RsNwcV?QT0bm(q-IyJJ$hm2~mq{6zIn!D20k5)fe(+iM6DJ ze-w_*F|c%@)HREgpRrl@W5;_J5vB4c?UW8~%o0)(A4`%-yNk1(H z5CGuzH(uHQ`&j+IRmTOKoJ?#Ct$+1grR|IitpDGt!~ZdqSJ?cOtw-R=EQ+q4UvclH zdX=xlK-fhQKoKCPBoFAZ*(~11O6-tXo>i0w!T$u{lg!#itEUX3V{$S*naW!C@%rll zS{L(1t%xz(*B`{1NL!*aMc<~fE=g;gXi&Gb$HpD!P)8?JzfN;4F&wv(5HH<=c>>)n z({271)xREH89=C(5YKL{mmJJ_d>qHz;;gTvTlgM*vz9@YTTYZ#%_2A zS0G-t9oMQEpvfv(UjfQ8T$vAHi)zOj3>D*{xSRiu3acc=7cvLyD?_ZObdu$5@b*!y zaZ#u?7uF}SrHVQa=sTOhGW{6WUlq#RhPPm^GsRH#qlX8{Kq-i~98l;eq>KdCnWyKl zUu&UWBqu#Tt9jQ97U4}3)&(p2-eCLznXMEm!>i^EMpeVzPg%p;?@O;dJBQQY(vV;d z3v+-3oTPC!2LTUAx^S2t{v;S_h(EZ^0_dS5g^F*m{TEIy^Qal~%mu3h7*o`jWOH}i ztv8M)3X3a*+ry_KkYXYE4dB0?M|t}#Tp+(}6CQ zBbq;xhoHj}b@j-@koDB#XcCY~>_x&Y;i%MH|3tF^X2h{36UCVfQ-;oEA+4ZkJ`^Qi zQf^8}6eFO$Z+Dj-F1wkG##tTx>FjR2oOXFmbKFj6K3+=kePQ<4d7%z5R5cOB;zO6| zm9^m#U4lcA;7t&*=q|a-!`!)}SgYXT#i8hnxtx@kaoBF$QAS-hT7N5kH^l zB^i+})V>L;9_0Qqf-dyF%ky8Mp-dp#%!Nls3vCt}q3QLM3M-(Zs1k}1bqQ9PVU)U` ztE=?;^6=x}_VD%N@${>qhpkU*)AuUBu_cqYiY&@;O$HV*z@~#Tzh?#=CK`=KwBv+o zh%zu%0xPKYtyC)DaQ zpDW}*86g%>BH3IcWMq`g$j()0kWE(qkIL8A&A0mf&+BzxpKF}=`#jG% z&*wa!&pGFLs5_b#QTZE4Bp+})qzyPQ7B4Z7Y*&?0PSX&|FIR;WBP1|coF9ZeP*$9w z!6aJ_3%Sh=HY3FAt8V144|yfu}IAyYHr1OYKIZ51F>_uY^%N#!k~eU53at-_E-Gh?ahmM5y* z+BTIbeH;%v1}Cjo{8d%UeSMWg(nphxEU`sL< zQR~LrTq>Da(FqSP2%&^1ZL#DTo5Sbl9;&57tQ-@U&I#lj)aNSkcfEJwQD!33?anVU z?pw2q7WtMvfji493`rSFnyp7{w87cW`ak=UEYlk5PCB1K6UDVKXyozOChH4yHh~Q< zv>yvKw6WLfi!PZUx60JZcTNM7jo{ww9b8Q+S7C3WA5&llSwdwh$=Q(*(f3ofqcz=nwOmOy z(J!K=*wNoRU*${{Mbwapi9pTB(&VVKefqd-qrUb9*Eyr2E@oZ9Cgf}Mc;QP<0D)R4 zz=!*^VIG4T*7Xl=sJxrWv9hW^eJ%qYp5(d0?E6LZzJ}=7E+1{?GQA;z+!^VBD81}O z0kJ^dKy&WMw+1+aGVYY-v@i28@Gm+sX5=@U%F=Z?W)oar}2~Rc&F|+3A)n-U2GF10+QdxDb^iA@7eL$c7yhBtL z>lABrh^qy9XZ${E1}Ss5!N4;ig0-pUh6@|RPCHOWvgG{|l}2enRgJftsN%D|ck0YO zuAQd2aMPSyGuJ~jm)aY=+p~mGudw4erwE%P^)5f<*$$2C-4^I=e8-}7##ZQ!8!Tep z+Z_!}CAI~sry$|XK$ktXaxP*x<_ijCPp`2=6sNLZU<@9Sz-rz7^BCE9yh0jV4(I!Z zxmA4d;>B-!vD}Xp*&*N%`b^e&R;D97WS}{~{O-EtXeZNfdf51tw!WR6Noo4hjHPv5 z?heYYRSBPjMc}tFEU^|U8a1CxxK%)WTcn9P%`wR^I$QSeMn6=w>Z9OoVvcrl`zYlZ z2y`mAu0bV(Scc>G_EmIo_4 zm*~h`mxYZC&+U>C5G1FZH5L^U>Cq-9UDRQa35jz&NBj*0{uJKfZs5=Fn@&)Xh6aX(H3w9m9BGLePqVotxTeSPh5-mc7$# z-80t6yB0$Nx<54ohdO*QL7m_(&+#*=eoNiYDB4rE4Cag@qfyZS};Fx;Vf1;oync2k z9v#-w?d6R& zOI`CCS_d=tf3|?g3Z}b6-_Rdg3y~enQhmgkni0Cvf9m6%Ft8r;NC5|b%t&?lkl*4{ z8Ui^;Ds^gq6ti(1xB7y_$zA!i-M~#!!tl$ErTR>P~>T=Yky)8(uvPbvLmB=UfoD zrfl}8<1OQrm?8#j1!?s*T>AoectQl&m!o&*^JcIW`_&bk3tN}k^0rjl=HL$z*uIYt z?7l?^Dqr?q1210Sp$xoAy!&{2^{^Anl460 zI&7urrc&|Y{rjv04VOl{y7c82N6xzg5ueYmQ(q(zC3w_C#x*~%yf5j7MI{W`tsoxzA*PrmK)cTskU| zf2C}Bq$>S$-1JgIh0aW@LxI|-8(OGuD#^M01ghh}&#ObO>tZgSw_LW`zdf&IN$YO# z)|X_9m#JwLW5pErZB3ScggKcNzxA9(hyKkK9I#pR&79&*+SV_eu={00{HF=Bb+AEe znaSof+r1jZ!EL5XgqXWkckaFSSyEk}o!%p8XsD}O>borZ6x%X2b&q!s&1-O(>`kZ$ zB2l^5Cx9xQx9)PXN1xPM)@+LxACH_iZ8zGc(>wnFS_O|@hKsxpMjXOzLEa7OvSlM&&G9ioQw9~RsD4F zK7Q+_&|Q6{eZ^8Rx@pKL`le6kH+(fLc{=V&{b%I5=n}VHV4)X_2Y!pYxgC8wU)yP! zPF3t$?(jsC>Ge=&{kmPGUEETpaw(QTAl)m#{qR3_aq9!wK%6XHfV4C>Y^>Z|%ns7j z{Ja?^IA{+@;kR#IjHxkar%3$eJT4?xNBKUVmoO z`A8Zo-{~_;vcikZ(p}EZzU4kO6WPqkMyE{VvS?;44Z@lj zz^fKX9UL!8Wc(9VgI?P4*zpis8dzl};I>yr1>dtXU=FTAlx}Eht4-*7RACL^AflGh zyZb1hTf(~CkMo%#Q%NMgM9tE2D+)joqbtHYA89Ql1nqVTt+MxZ^*FRd&n5YlIi!8m z>$Ysd!l{+C)y;Wa(ZV-=<+NZKV;v4mt}v2m>`v$-$3b;GsLxf= zd~f(rmfpl``{0aVwN7y!>eGyJFP`L+TxHjHTOS{K^$L2`@6(Rli`{EFwpH@R%eZ6g zwf7rc43Yk!=k;{ z-Rn%~B3amGr}}SxfE$vS8FIPL=Qt57$|R#sSoFgdNUT?fYOYjPl%ZBFpi=jq=DWby7Zxm@y;B<89!9= zbgEH*Uy)~iq5kJLX$+ps$kV`#6jW#|9BGz^`ivNeid(wVbk4jl)VBpW&~;eXNi{#` zwx?{DXR~*sqQcFhY0XCfQ4-*2aN1BGX>$_swtKEqnd>j6vcZ!#0)pXRi?<{!P?tGw z2x_`RD$W)qD{?z}VDPt?+)8*rqLWFIPQ(9-VbBdf{7ff?w9CZ{sIi_gnuC$I0(+P8 zms9XB%}VQ>>pve##}jog6+cD?v~n4Pa9Vmc zg#K$|+`adO=B7`uj35Y}6EZ z{dY`x@w8;R-7zrsr1O_~Jvl*|o-x%jF=Rr1C}GXP^|IYN`1sqmG-oI@R#%X66c#5W z$$tQB)sqwiVm;Y^`Dw3mo|firP{*HsOQJre5%Dm^H@we0FN88VWJ0dja?_U38z73f zrCV!b3qNP0kM#%9T!W5`ynGcg%BL28FW1J-J1_S`BJGCaReQ!am(2%qZ3lLgzq|ns z!!fF@`0=*z)J2BwZ*hO|Yu^cI_nF$9l-Pb3jE7=P8gZ#!xiuZ7-cSa`gb`6mxGTgg z-DLdID?M!Z%+hHB#{?&0$GFRpf+_}q<_wbzX6K?w;%6szz1RbySDSr2r^h_qi$khs zXdZ9A0!_Bf)TR2-^-K~q`FQ!#1x(U4VbV%AA@Ei{%cA(EwC{XfjRi?`&9rav5;Q5% zO1`Rn@OA_ZB@N*mC#)?d3P!}Eh;=NgpIKsy{(yr`hv=aouwt@r&P&}Z3DNWo9ro30 zX52~(aTV$*HHlgB66-4GQru!_AZ|)V*I5X=WG)`N@U&D>e@@C#V@JwEL*L`7#$yes z62C^5%Qniaow2$3HrAc7U{qzpb&FA*xLI1JSWR@`RF=JCcvTI)%dH7;sWInt9JLu# z|Ao|Q?K)cDg_JKsym=joo5gR80wtv01N`um1nQ@Ms0Y*bVzxL34} zo?gizp?`=Y{*W>^Hy2%Jl)y?A+&7s1UVHFixuIy~sawXjcDCL`129cK7|ZQS0u;A} zTJC#WNmqkIrnHpAhHVcM(U^vJA~dl@jf_bs*3?i+=&vuC?Aiy_pcB~=1syDni4 zw+FLuz>F773u#$;NUQ9WDtUPY@+rA3WBhQdKFKOyzkA(URa7;4tW>3jQIfi8v0h3g zJC_HVDXS#>DWb|&se7FHnr=q&l#xg9o02}}u=b-R>@sw={Z zHF*?t2FmhqZ=|qa>x=A!*$S+0T zhO*D*M?NTf-eX`eO)9TIQu{7Dm77Acnj4b1jI9@c*ZL8wL%8kLEhd$KM8=Y!fbN@9 zC7B5#y>JM1n5M)!&im==EgHs2j+xCZG~+~QWCi?s!QyFo2kqx{%jE2n3^N*Ayz6Lp zhg5g^3# z+5FoJ@$u@9WJgPKpUWEd4}4AK9TJKU8W%ms!d0p%OIOX+bY+55zl!vIaz$XFI9Ep+ z;bL_}7PDI2Y`Ng*XY(65 zh0%`@Lve%fc;)N4_g12bNrt6gH=N#OHtxO`$lpWlw=Z6MF+E@;>GkZ#lAZTn`aHwf z&I1|aV#b_VHMIgBN*RzU9i@Z@m}0i>o?({&%fpEfaOpFeaJ7V37;m0?kzd}}Lk@9$ zL}8TEo7WZAcRi%zFZxkr6<0k#X-;lTD`Oc~cDb@olwgWCewvk{GJ}hCXbF!AdiLpd z|Cck$ZTKI?Ack{34Lva7+k=H8K2HTZiurox6F+>dy+@R9T^awxj590D$|kXUg+Ygc z(f)jlRwN(4z$#%PnOVc;#Fv{nAi{#UcXPNcmP#5O{zh_*`=q^JCeia{sN4zHjk2*y zqUVh{Ya{j>SPmP^i#Qfcq_MTqo8g52Fi^F zKBc$$HVI!xFx*4Y9l+nt)$AoZORD}%5I10oI3kx`-N30QueiwIw#0VV2E*Fb-nKW% z=+r^hos`Y-7~{cA1FVbK$_=~*z53+Q8KGjg;>ztg((H12%QTf4OYU8y)C}h5yo#$% z&Q$`vMM*g?ZcatAn2j!hFv8KuN(dw)T*}sF#THDHxo8xC^?vJ zc`U6bVo~hOr6I!8*GTZ<^D~;unKjK=!IR|GB4E>Mcvt*2GK);93jIDd<(nNjHO z4Hi@2^%Uyx=^Z~5eZ!5rO5%4H|eFoNjD#+Kcu%_57zZb4Z@Ak#X6txD^{U3wBl^r+W- zLorkK;uc;NgTj7dGxHQS+@T*T>Q*j4^Ll$ejQqWrwcHyG9y%Mk%m8nBVG5hvSaYm5 zJN^#-Q46kZG)@T8n2^QCjxIwxUVi%s>EY`E?#@_(A~njFrTiDq;8v|W-1jT|ROlNI zU$h|YoD4PVTE^&NC6_m{EAFBVqsM`P*`-AcDGWQygURzM32Xeq2xng~XQsYeTZ5v$ zQLaa2M_Iplw}4eL6fLPu`6`PYcVMysO>`{8CB~glD=TX7?JZcHfHNmykBM?QD)#D) zGp>R*<^D?WhFQKRc^}22l6F=D2RPrxaX2ZF!b1X0XF*d4%=!sbNcS1q2WOUE(7e4$ z^L8f;F)__d3>&KQFE8%$I4h^y5FYBfB&fWzn71_OSrPe-DHV{O#Q;GP z+Tw!J?eVjX19RKH?*hKQWQt8r7B#lYX8xoSHFGCW-*DSQ4EM4M3Mw%gkSYNK18@(e zfzMF}WWaCyS@1y%-~Xg0ry~tkQkUmKuI5lGAua{{vn22V!2T()AU5FpKh@Nv)s^Js zv~@VuUG;=CnLmQR{PeUBQf2;lAV!vG>^Z0N zL88rrjL-*J!43;7C=w9xhcw`yjRKq7o4L9=0SmR9PA-nX12@#h(iIu-0N_xm2OV)( zU_raT0y>$wm^oMi2|U3N;OhF9uy}`<-xVka#DV*l{O0yHzi9vUxa1Qtpi$buR*8cU zd4~lS1pT$L^!0=6qUKOpM+XPsy{f7W#1bjrEwaeN!Ik9(zySIT^pEHvHgJUneFN4) zk=k|$55(g8slmS|@+*4fr2urd3LwjIIZA**g+%l(SZNn4HwQ}y6o`vw>2&mR1X+&q zDa1Af0B;4rAMZMOlHbAqK|R_xuwJ7ANARtFE({-P2o{tJJR<>2KVp)ZK-M;)ejx zd*E~Mka<{OL7%CAhk4n|1qg?97-I!l0rOinjVi#arbgg4bi5;nY5oFL`UWtPk5&L#grSxv zE3!}=1px!ZTLT90aYc^s`~{VojjJml&<`@e41dFP+XU6D0AOkbn2rlI3>^LcqauG& zc$m3Z{!u8LvUrm^fT{qX5yD9{?r(CCiUdck%!T`KIZd2oQJz1joB&M(Teg_>;yS<2-5>BWfSPpG`Rt{!j6>kqMAvl^zk0JUEfy$HVJMkxP-GkwZuxL62me2#pj_5*ZIU zP~#C^OZLfl$HO)v;~~c&JHivn|1I9H5y_CDkt0JLLGKm(4*KLVhJ2jh2#vJuM6`b& zE==-lvME^Oj022xF&IV*? '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/examples/powertools-examples-core/gradle/gradlew.bat b/examples/powertools-examples-core/gradle/gradlew.bat new file mode 100644 index 000000000..6689b85be --- /dev/null +++ b/examples/powertools-examples-core/gradle/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/examples/powertools-examples-core/gradle/src/main/java/helloworld/App.java b/examples/powertools-examples-core/gradle/src/main/java/helloworld/App.java new file mode 100644 index 000000000..fccc63b9a --- /dev/null +++ b/examples/powertools-examples-core/gradle/src/main/java/helloworld/App.java @@ -0,0 +1,107 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; +import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; +import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.tracing.CaptureMode; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.tracing.TracingUtils; + +/** + * Handler for requests to Lambda function. + */ +public class App implements RequestHandler { + private final static Logger log = LogManager.getLogger(App.class); + + @Logging(logEvent = true, samplingRate = 0.7) + @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + Map headers = new HashMap<>(); + + headers.put("Content-Type", "application/json"); + headers.put("X-Custom-Header", "application/json"); + + metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + + withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> + { + metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); + metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); + }); + + LoggingUtils.appendKey("test", "willBeLogged"); + + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() + .withHeaders(headers); + try { + final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); + log.info(pageContents); + TracingUtils.putAnnotation("Test", "New"); + String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); + + TracingUtils.withSubsegment("loggingResponse", subsegment -> + { + String sampled = "log something out"; + log.info(sampled); + log.info(output); + }); + + log.info("After output"); + return response + .withStatusCode(200) + .withBody(output); + } catch (RuntimeException | IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + @Tracing + private void log() { + log.info("inside threaded logging for function"); + } + + @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + putMetadata("getPageContents", address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-core/gradle/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/gradle/src/main/java/helloworld/AppStream.java new file mode 100644 index 000000000..401ef8c48 --- /dev/null +++ b/examples/powertools-examples-core/gradle/src/main/java/helloworld/AppStream.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.Metrics; + +public class AppStream implements RequestStreamHandler { + private static final ObjectMapper mapper = new ObjectMapper(); + + @Override + @Logging(logEvent = true) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { + Map map = mapper.readValue(input, Map.class); + + System.out.println(map.size()); + } +} diff --git a/examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java new file mode 100644 index 000000000..af3ec1275 --- /dev/null +++ b/examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java @@ -0,0 +1,24 @@ +package helloworld; + +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class AppTest { + @Test + public void successfulResponse() { + App app = new App(); + APIGatewayProxyResponseEvent result = app.handleRequest(null, null); + assertEquals(200, result.getStatusCode().intValue()); + assertEquals("application/json", result.getHeaders().get("Content-Type")); + String content = result.getBody(); + assertNotNull(content); + assertTrue(content.contains("\"message\"")); + assertTrue(content.contains("\"hello world\"")); + assertTrue(content.contains("\"location\"")); + } +} diff --git a/examples/powertools-examples-core/gradle/template.yaml b/examples/powertools-examples-core/gradle/template.yaml new file mode 100644 index 000000000..a717c2998 --- /dev/null +++ b/examples/powertools-examples-core/gradle/template.yaml @@ -0,0 +1,71 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + gradle + + Sample SAM Template for gradle + +# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst +Globals: + Function: + Timeout: 20 + Runtime: java11 + MemorySize: 512 + Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html + Environment: + Variables: + # Powertools for AWS Lambda (Java) env vars: https://docs.powertools.aws.dev/lambda/java/#environment-variables + POWERTOOLS_LOG_LEVEL: INFO + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 + POWERTOOLS_LOGGER_LOG_EVENT: true + POWERTOOLS_METRICS_NAMESPACE: Coreutilities + +Resources: + HelloWorldFunction: + Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + Properties: + CodeUri: . + Handler: helloworld.App::handleRequest + Runtime: java8 + MemorySize: 512 + Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object + Variables: + POWERTOOLS_SERVICE_NAME: hello + Events: + HelloWorld: + Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api + Properties: + Path: /hello + Method: get + + HelloWorldStreamFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: helloworld.AppStream::handleRequest + Runtime: java8 + MemorySize: 512 + Tracing: Active + Environment: + Variables: + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.7 + Events: + HelloWorld: + Type: Api + Properties: + Path: /hellostream + Method: get + +Outputs: + # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function + # Find out more about other implicit resources you can reference within SAM + # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api + HelloWorldApi: + Description: "API Gateway endpoint URL for Prod stage for Hello World function" + Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" + HelloWorldFunction: + Description: "Hello World Lambda Function ARN" + Value: !GetAtt HelloWorldFunction.Arn + HelloWorldFunctionIamRole: + Description: "Implicit IAM Role created for Hello World function" + Value: !GetAtt HelloWorldFunctionRole.Arn From e35de90f28072814eeb9e6bcb5286c38b8c0338e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Fri, 25 Aug 2023 09:07:00 +0200 Subject: [PATCH 025/577] maven deploy configuration (skip in tests and examples) (#1388) --- examples/pom.xml | 16 +- examples/powertools-examples-batch/pom.xml | 9 +- .../pom.xml | 9 +- .../powertools-examples-core/cdk/app/pom.xml | 9 +- .../cdk/infra/pom.xml | 9 +- examples/powertools-examples-core/sam/pom.xml | 144 +++++++------ .../powertools-examples-idempotency/pom.xml | 202 +++++++++--------- .../powertools-examples-parameters/pom.xml | 75 ++++--- .../powertools-examples-serialization/pom.xml | 9 +- examples/powertools-examples-sqs/pom.xml | 134 ++++++------ .../powertools-examples-validation/pom.xml | 73 ++++--- powertools-e2e-tests/pom.xml | 11 +- powertools-test-suite/pom.xml | 12 +- 13 files changed, 401 insertions(+), 311 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 948005546..eae9e10e5 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -41,9 +41,17 @@ powertools-examples-cloudformation - - - true - + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + \ No newline at end of file diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 9faa4dc24..290fe0cd2 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,6 @@ 2.20.0 1.8 1.8 - true 2.20.133 @@ -120,6 +119,14 @@ + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 20aa5aeaf..030998631 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -13,7 +13,6 @@ 2.20.0 1.8 1.8 - true 1.2.3 3.11.2 2.20.133 @@ -145,6 +144,14 @@ + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml index a1aba1b8d..7831df839 100644 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ b/examples/powertools-examples-core/cdk/app/pom.xml @@ -13,7 +13,6 @@ 2.20.0 1.8 1.8 - true @@ -120,6 +119,14 @@ + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index 5131e22af..cdaccedf4 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -10,7 +10,6 @@ 2.92.0 [10.0.0,11.0.0) 5.10.0 - true @@ -31,6 +30,14 @@ cdk.CdkApp + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index 7350542cd..09cab6cd6 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -1,19 +1,18 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples 1.18.0-SNAPSHOT powertools-examples-core-sam jar - + Powertools for AWS Lambda (Java) library Examples - Core 2.20.0 1.8 1.8 - true @@ -38,9 +37,9 @@ 1.2.3 - com.amazonaws - aws-lambda-java-events - 3.11.2 + com.amazonaws + aws-lambda-java-events + 3.11.2 org.apache.logging.log4j @@ -54,72 +53,81 @@ - junit - junit - 4.13.2 - test + junit + junit + 4.13.2 + test - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - + software.amazon.lambda.examples 1.18.0-SNAPSHOT powertools-examples-idempotency @@ -26,7 +26,6 @@ 2.20.0 1.8 1.8 - true @@ -51,9 +50,9 @@ 1.2.3 - com.amazonaws - aws-lambda-java-events - 3.11.2 + com.amazonaws + aws-lambda-java-events + 3.11.2 org.apache.logging.log4j @@ -92,97 +91,106 @@ - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-idempotency - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy - test-compile - - copy-dependencies - - - test - so,dll,dylib - ${project.build.directory}/native-libs - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.1.2 - - - ${project.build.directory}/native-libs - - - idempotency - eu-central-1 - LOG_ERROR - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-idempotency + + + + + + + compile + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + test-compile + + copy-dependencies + + + test + so,dll,dylib + ${project.build.directory}/native-libs + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + ${project.build.directory}/native-libs + + + idempotency + eu-central-1 + LOG_ERROR + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + - 3.1.2 - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-parameters - - - - - - - compile - - - - - + + + org.apache.maven.plugins + maven-surefire-plugin + + 3.1.2 + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-parameters + + + + + + + compile + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + 3.1.2 + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index b030d22fd..caee0a44d 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples 1.18.0-SNAPSHOT @@ -11,7 +11,6 @@ 2.20.0 1.8 1.8 - true @@ -36,9 +35,9 @@ 1.2.3 - com.amazonaws - aws-lambda-java-events - 3.11.2 + com.amazonaws + aws-lambda-java-events + 3.11.2 org.apache.logging.log4j @@ -57,68 +56,77 @@ - junit - junit - 4.13.2 - test + junit + junit + 4.13.2 + test - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-sqs - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-sqs + + + + + + + compile + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples 1.18.0-SNAPSHOT @@ -24,7 +24,6 @@ 1.8 1.8 - true @@ -66,37 +65,45 @@ - - - org.apache.maven.plugins - maven-surefire-plugin - - 3.1.2 - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-validation - - - - - - - compile - - - - - + + + org.apache.maven.plugins + maven-surefire-plugin + + 3.1.2 + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-validation + + + + + + + compile + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + - true @@ -183,6 +180,14 @@ org.apache.maven.plugins maven-checkstyle-plugin + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + org.apache.maven.plugins maven-compiler-plugin diff --git a/powertools-test-suite/pom.xml b/powertools-test-suite/pom.xml index 80b8635f5..55e713ec0 100644 --- a/powertools-test-suite/pom.xml +++ b/powertools-test-suite/pom.xml @@ -47,10 +47,6 @@ - - true - - ossrh @@ -159,6 +155,14 @@ + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + \ No newline at end of file From 34c6793b5043d09458af88653ba52401c880f92d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Aug 2023 09:17:46 +0200 Subject: [PATCH 026/577] build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1394) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.92.0 to 2.93.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.92.0...v2.93.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index cdaccedf4..6facf8a46 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -7,7 +7,7 @@ 1.18.0-SNAPSHOT UTF-8 - 2.92.0 + 2.93.0 [10.0.0,11.0.0) 5.10.0 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 134b71a06..d3acde3ea 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ 1.8 1.8 10.2.69 - 2.92.0 + 2.93.0 From c21d66d3ba2c2adca4b4a2e90a135e1eac6b763c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Aug 2023 13:31:55 +0200 Subject: [PATCH 027/577] build(deps): bump aws.sdk.version from 2.20.133 to 2.20.134 (#1396) Bumps `aws.sdk.version` from 2.20.133 to 2.20.134. Updates `software.amazon.awssdk:bom` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:http-client-spi` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:url-connection-client` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:sqs` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:s3` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:dynamodb` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:lambda` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:kinesis` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:cloudwatch` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:xray` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:cloudformation` from 2.20.133 to 2.20.134 Updates `software.amazon.awssdk:sts` from 2.20.133 to 2.20.134 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 030998631..ad84d19a1 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.2 - 2.20.133 + 2.20.134 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index caee0a44d..ac0e577ed 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.133 + 2.20.134 com.amazonaws diff --git a/pom.xml b/pom.xml index 8226fa878..9a9b8f05d 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.133 + 2.20.134 2.14.0 2.1.3 UTF-8 From 9f33fed2f62e327f30b38632851ddf891939c9c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Aug 2023 14:18:03 +0200 Subject: [PATCH 028/577] build(deps): bump aws.sdk.version from 2.20.134 to 2.20.135 (#1398) Bumps `aws.sdk.version` from 2.20.134 to 2.20.135. Updates `software.amazon.awssdk:bom` from 2.20.134 to 2.20.135 Updates `software.amazon.awssdk:http-client-spi` from 2.20.134 to 2.20.135 Updates `software.amazon.awssdk:url-connection-client` from 2.20.133 to 2.20.135 Updates `software.amazon.awssdk:sqs` from 2.20.133 to 2.20.135 Updates `software.amazon.awssdk:s3` from 2.20.134 to 2.20.135 Updates `software.amazon.awssdk:dynamodb` from 2.20.134 to 2.20.135 Updates `software.amazon.awssdk:lambda` from 2.20.134 to 2.20.135 Updates `software.amazon.awssdk:kinesis` from 2.20.133 to 2.20.135 Updates `software.amazon.awssdk:cloudwatch` from 2.20.134 to 2.20.135 Updates `software.amazon.awssdk:xray` from 2.20.134 to 2.20.135 Updates `software.amazon.awssdk:cloudformation` from 2.20.134 to 2.20.135 Updates `software.amazon.awssdk:sts` from 2.20.134 to 2.20.135 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index ad84d19a1..127c78e66 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.2 - 2.20.134 + 2.20.135 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index ac0e577ed..9692649ec 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.134 + 2.20.135 com.amazonaws diff --git a/pom.xml b/pom.xml index 9a9b8f05d..273a4b4a4 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.134 + 2.20.135 2.14.0 2.1.3 UTF-8 From c6932aeb0d0d5689f1c8a5d0f3897c8c69850c3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Aug 2023 14:09:54 +0200 Subject: [PATCH 029/577] build(deps): bump aws.sdk.version from 2.20.135 to 2.20.136 (#1404) Bumps `aws.sdk.version` from 2.20.135 to 2.20.136. Updates `software.amazon.awssdk:bom` from 2.20.135 to 2.20.136 Updates `software.amazon.awssdk:http-client-spi` from 2.20.135 to 2.20.136 Updates `software.amazon.awssdk:url-connection-client` from 2.20.133 to 2.20.136 Updates `software.amazon.awssdk:sqs` from 2.20.133 to 2.20.136 Updates `software.amazon.awssdk:s3` from 2.20.135 to 2.20.136 Updates `software.amazon.awssdk:dynamodb` from 2.20.135 to 2.20.136 Updates `software.amazon.awssdk:lambda` from 2.20.135 to 2.20.136 Updates `software.amazon.awssdk:kinesis` from 2.20.133 to 2.20.136 Updates `software.amazon.awssdk:cloudwatch` from 2.20.135 to 2.20.136 Updates `software.amazon.awssdk:xray` from 2.20.135 to 2.20.136 Updates `software.amazon.awssdk:cloudformation` from 2.20.135 to 2.20.136 Updates `software.amazon.awssdk:sts` from 2.20.135 to 2.20.136 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 127c78e66..1273d8d15 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.2 - 2.20.135 + 2.20.136 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 9692649ec..b2ef7145c 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.135 + 2.20.136 com.amazonaws diff --git a/pom.xml b/pom.xml index 273a4b4a4..9066d5880 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.135 + 2.20.136 2.14.0 2.1.3 UTF-8 From b5135c9a3b1557b3aa7e10728fd1fe95ac6605dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:57:43 +0200 Subject: [PATCH 030/577] chore: update v2 (#1409) --- .github/workflows/auto-merge.yml | 8 +- .github/workflows/build-docs.yml | 4 +- .github/workflows/build.yml | 13 +- .github/workflows/dispatch_analytics.yml | 2 +- .github/workflows/docs.yml | 4 +- .github/workflows/publish.yml | 9 +- .github/workflows/release-drafter.yml | 2 +- .github/workflows/release-prep.yml | 16 +- .github/workflows/run-e2e-tests.yml | 6 +- .github/workflows/secure_workflows.yml | 32 +++ .github/workflows/spotbugs.yml | 6 +- .gitignore | 2 + README.md | 18 +- docs/index.md | 17 +- examples/pom.xml | 16 +- examples/powertools-examples-batch/pom.xml | 11 +- .../pom.xml | 11 +- .../README.md | 5 + .../cdk/app/pom.xml | 11 +- .../cdk/infra/pom.xml | 13 +- .../gradle/README.md | 38 +++ .../gradle/build.gradle | 35 +++ .../gradle/events/event.json | 62 +++++ .../gradle/gradle/wrapper/.gitignore | 2 + .../gradle/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63375 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../gradle/gradlew | 248 ++++++++++++++++++ .../gradle/gradlew.bat | 92 +++++++ .../gradle/src/main/java/helloworld/App.java | 107 ++++++++ .../src/main/java/helloworld/AppStream.java | 38 +++ .../src/test/java/helloworld/AppTest.java | 24 ++ .../gradle/template.yaml | 71 +++++ .../sam/pom.xml | 142 +++++----- .../powertools-examples-idempotency/pom.xml | 202 +++++++------- .../powertools-examples-parameters/pom.xml | 75 +++--- .../powertools-examples-serialization/pom.xml | 9 +- .../powertools-examples-validation/pom.xml | 73 +++--- pom.xml | 2 +- powertools-e2e-tests/pom.xml | 13 +- 39 files changed, 1161 insertions(+), 285 deletions(-) create mode 100644 .github/workflows/secure_workflows.yml create mode 100644 examples/powertools-examples-core-utilities/gradle/README.md create mode 100644 examples/powertools-examples-core-utilities/gradle/build.gradle create mode 100644 examples/powertools-examples-core-utilities/gradle/events/event.json create mode 100644 examples/powertools-examples-core-utilities/gradle/gradle/wrapper/.gitignore create mode 100644 examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.jar create mode 100644 examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.properties create mode 100755 examples/powertools-examples-core-utilities/gradle/gradlew create mode 100644 examples/powertools-examples-core-utilities/gradle/gradlew.bat create mode 100644 examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java create mode 100644 examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java create mode 100644 examples/powertools-examples-core-utilities/gradle/src/test/java/helloworld/AppTest.java create mode 100644 examples/powertools-examples-core-utilities/gradle/template.yaml diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 21b5e20e5..5401eedc9 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -17,12 +17,12 @@ jobs: runs-on: ubuntu-latest if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' && github.actor == 'dependabot[bot]' steps: - - uses: actions/checkout@v3 - - uses: ahmadnassri/action-workflow-run-wait@v1 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: ahmadnassri/action-workflow-run-wait@2aa3d9e1a12ecaaa9908e368eaf2123bb084323e # v1.4.4 with: timeout: 300000 - name: 'Download artifact' - uses: actions/github-script@v3.1.0 + uses: actions/github-script@47f7cf65b5ced0830a325f705cad64f2f58dddf7 # v3.1.0 with: script: | var artifacts = await github.actions.listWorkflowRunArtifacts({ @@ -43,7 +43,7 @@ jobs: fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data)); - run: unzip pr.zip - name: Create review - uses: actions/github-script@v3 + uses: actions/github-script@47f7cf65b5ced0830a325f705cad64f2f58dddf7 # v3.1.0 with: script: | var fs = require('fs'); diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index f4a9c4d3f..a4ab6e7de 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -22,9 +22,9 @@ jobs: docs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 with: python-version: "3.8" - name: Capture branch and tag diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9ed871a6c..2ded092ef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,17 +54,22 @@ jobs: JAVA: ${{ matrix.java }} AWS_REGION: eu-west-1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java - uses: actions/setup-java@v3 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'corretto' java-version: ${{ matrix.java }} cache: 'maven' - name: Build with Maven run: mvn -B install --file pom.xml + - name: Build Gradle Example + if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 + run: | + cd examples/powertools-examples-core-utilities/gradle + ./gradlew build - name: Upload coverage to Codecov - uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # 3.1.1 + uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 if: ${{ matrix.java == '11' }} # publish results once with: files: ./powertools-cloudformation/target/site/jacoco/jacoco.xml,./powertools-core/target/site/jacoco/jacoco.xml,./powertools-idempotency/target/site/jacoco/jacoco.xml,./powertools-logging/target/site/jacoco/jacoco.xml,./powertools-metrics/target/site/jacoco/jacoco.xml,./powertools-parameters/target/site/jacoco/jacoco.xml,./powertools-serialization/target/site/jacoco/jacoco.xml,./powertools-sqs/target/site/jacoco/jacoco.xml,./powertools-tracing/target/site/jacoco/jacoco.xml,./powertools-validation/target/site/jacoco/jacoco.xml @@ -78,7 +83,7 @@ jobs: mkdir -p ./pr echo ${{ github.event.number }} echo ${{ github.event.number }} > ./pr/NR - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 name: Upload artifact with: name: pr diff --git a/.github/workflows/dispatch_analytics.yml b/.github/workflows/dispatch_analytics.yml index 49a276f6f..c93cb5b36 100644 --- a/.github/workflows/dispatch_analytics.yml +++ b/.github/workflows/dispatch_analytics.yml @@ -29,7 +29,7 @@ jobs: environment: analytics steps: - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef + uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 with: aws-region: eu-central-1 role-to-assume: ${{ secrets.AWS_ANALYTICS_ROLE_ARN }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9c09e294d..5e37c5f45 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -16,9 +16,9 @@ jobs: runs-on: ubuntu-latest environment: Docs steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 with: python-version: "3.8" - name: Capture branch and tag diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2068c09c5..03f04e0f4 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,15 +8,16 @@ jobs: publish: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Set up Maven Central Repository - uses: actions/setup-java@v2 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: - distribution: 'zulu' + distribution: 'corretto' java-version: 8 server-id: ossrh server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD + # TODO: use environments https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }} # Value of the GPG private key to import gpg-passphrase: GPG_PASSPHRASE # env variable for GPG private key passphrase - name: Set release notes tag @@ -30,7 +31,7 @@ jobs: MAVEN_PASSWORD: ${{ secrets.OSSRH_JIRA_PASSWORD }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - name: Close issues related to this release - uses: actions/github-script@v5 + uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 with: script: | const post_release = require('.github/workflows/post_release.js') diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 5b27fd671..72bd5c24f 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -10,6 +10,6 @@ jobs: update_release_draft: runs-on: ubuntu-latest steps: - - uses: release-drafter/release-drafter@v5 + - uses: release-drafter/release-drafter@569eb7ee3a85817ab916c8f8ff03a5bd96c9c83e # v5.23.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-prep.yml b/.github/workflows/release-prep.yml index 345bd2a10..f7a3c74c0 100644 --- a/.github/workflows/release-prep.yml +++ b/.github/workflows/release-prep.yml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Get current date id: date run: echo "::set-output name=date::$(date +'%Y-%m-%d')" @@ -18,42 +18,42 @@ jobs: run: | echo "CURRENT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in mkdocs.yml - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: 'version: ${{ env.CURRENT_VERSION }}' replace: 'version: ${{ github.event.inputs.targetRelease }}' regex: false include: "mkdocs.yml" - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in main pom.xml - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: ${{ env.CURRENT_VERSION }} replace: ${{ github.event.inputs.targetRelease }} regex: false include: "pom.xml" - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in modules pom.xml - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: ${{ env.CURRENT_VERSION }} replace: ${{ github.event.inputs.targetRelease }} regex: false include: "**/*pom.xml" - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in build.gradle - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: ${{ env.CURRENT_VERSION }} replace: ${{ github.event.inputs.targetRelease }} regex: false include: "**/*build.gradle" - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in README.md - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: ${{ env.CURRENT_VERSION }} replace: ${{ github.event.inputs.targetRelease }} regex: false include: "README.md" - name: Create changelog placeholder for ${{ github.event.inputs.targetRelease }} - uses: jacobtomlinson/gha-find-replace@v2 + uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 with: find: '## [Unreleased]' replace: | @@ -66,7 +66,7 @@ jobs: regex: false include: CHANGELOG.md - name: Create Release Pull Request - uses: peter-evans/create-pull-request@v3 + uses: peter-evans/create-pull-request@18f7dc018cc2cd597073088f7c7591b9d1c02672 # v3.14.0 with: commit-message: chore:prep release ${{ github.event.inputs.targetRelease }} token: ${{ secrets.RELEASE }} diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 36c9dd97a..c4a8c6fb2 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -41,15 +41,15 @@ jobs: id-token: write # needed to interact with GitHub's OIDC Token endpoint. contents: read steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java - uses: actions/setup-java@v3 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'corretto' java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@v1.6.1 + uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} aws-region: ${{ env.AWS_DEFAULT_REGION }} diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml new file mode 100644 index 000000000..1430e91d6 --- /dev/null +++ b/.github/workflows/secure_workflows.yml @@ -0,0 +1,32 @@ +name: Lockdown untrusted workflows + +# PROCESS +# +# 1. Scans for any external GitHub Action being used without version pinning (@ vs @v3) +# 2. Scans for insecure practices for inline bash scripts (shellcheck) +# 3. Fail CI and prevent PRs to be merged if any malpractice is found + +# USAGE +# +# Always triggered on new PR, PR changes and PR merge. + + +on: + push: + paths: + - ".github/workflows/**" + pull_request: + paths: + - ".github/workflows/**" + +jobs: + enforce_pinned_workflows: + name: Harden Security + runs-on: ubuntu-latest + permissions: + contents: read # checkout code and subsequently GitHub action workflows + steps: + - name: Checkout code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Ensure 3rd party workflows have SHA pinned + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@555a30da2656b4a7cf47b107800bef097723363e # v2.1.3 diff --git a/.github/workflows/spotbugs.yml b/.github/workflows/spotbugs.yml index 0b07bcd81..d314107fa 100644 --- a/.github/workflows/spotbugs.yml +++ b/.github/workflows/spotbugs.yml @@ -23,11 +23,11 @@ jobs: codecheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java JDK 1.8 - uses: actions/setup-java@v2 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: - distribution: 'zulu' + distribution: 'corretto' java-version: 8 # https://github.com/jwgmeligmeyling/spotbugs-github-action/issues/6 # https://github.blog/2020-08-03-github-actions-improvements-for-fork-and-pull-request-workflows/ diff --git a/.gitignore b/.gitignore index 04e85211d..b404d2cb2 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,5 @@ example/HelloWorldFunction/.gradle example/HelloWorldFunction/build /example/.gradle/ /example/.java-version +.gradle +build/ \ No newline at end of file diff --git a/README.md b/README.md index 76f8b2e4b..ed3f86e77 100644 --- a/README.md +++ b/README.md @@ -132,11 +132,18 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam

Gradle - Java 11+ ```groovy + plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.2.2' } + // the freefair aspect plugins targets gradle 8.2.1 + // https://docs.freefair.io/gradle-plugins/8.2.2/reference/ + wrapper { + gradleVersion = "8.2.1" + } + repositories { mavenCentral() } @@ -145,6 +152,7 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' aspect 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' + implementation "org.aspectj:aspectjrt:1.9.8.RC3" } sourceCompatibility = 11 @@ -161,6 +169,12 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' } + // the freefair aspect plugins targets gradle 7.6.1 + // https://docs.freefair.io/gradle-plugins/6.6.3/reference/ + wrapper { + gradleVersion = "7.6.1" + } + repositories { mavenCentral() } @@ -178,7 +192,7 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam ## Examples -See the **[examples](examples)** directory for example projects showcasing usage of different utilities. +See the latest release of the **[examples](https://github.com/aws-powertools/powertools-lambda-java/tree/v1.17.0/examples)** for example projects showcasing usage of different utilities. Have a demo project to contribute which showcase usage of different utilities from powertools? We are happy to accept it [here](CONTRIBUTING.md#security-issue-notifications). diff --git a/docs/index.md b/docs/index.md index d3e487174..6af4c5e8d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -211,10 +211,17 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl === "Gradle Java 11+" ```groovy + plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.2.2' } + + // the freefair aspect plugins targets gradle 8.2.1 + // https://docs.freefair.io/gradle-plugins/8.2.2/reference/ + wrapper { + gradleVersion = "8.2.1" + } repositories { mavenCentral() @@ -233,10 +240,18 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl === "Gradle Java 1.8" ```groovy + plugins { id 'java' id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' } + + // the freefair aspect plugins targets gradle 7.6.1 + // https://docs.freefair.io/gradle-plugins/6.6.3/reference/ + wrapper { + gradleVersion = "7.6.1" + } + repositories { mavenCentral() diff --git a/examples/pom.xml b/examples/pom.xml index b790cb12e..da6e272de 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -40,9 +40,17 @@ powertools-examples-cloudformation - - - true - + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + \ No newline at end of file diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 9efa7fa63..cfc035238 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,8 +14,7 @@ 2.20.0 1.8 1.8 - true - 2.20.128 + 2.20.133 @@ -120,6 +119,14 @@
+ + + org.apache.maven.plugins + maven-deploy-plugin + + true + +
diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 50cfff85d..85e330742 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -13,10 +13,9 @@ 2.20.0 1.8 1.8 - true 1.2.3 3.11.2 - 2.20.130 + 2.20.136 @@ -145,6 +144,14 @@ + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + diff --git a/examples/powertools-examples-core-utilities/README.md b/examples/powertools-examples-core-utilities/README.md index f11982477..6960bb1f5 100644 --- a/examples/powertools-examples-core-utilities/README.md +++ b/examples/powertools-examples-core-utilities/README.md @@ -6,9 +6,14 @@ This project demonstrates the Lambda for Powertools Java module - including [metrics](https://docs.powertools.aws.dev/lambda/java/core/metrics/). We provide examples for the following infrastructure-as-code tools: + * [AWS SAM](sam/) * [AWS CDK](cdk/) +We also provide an example showing the integration of SAM, Powertools, and Gradle: + +* [AWS SAM with a Gradle build](../powertools-examples-core-utilities/gradle/) + For each of the tools, the example application is the same, and consists of the following files: - [App.java](sam/src/main/java/helloworld/App.java) - Code for the application's Lambda function. diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 6895f4117..76e02ea48 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.16.1 + 1.17.0 powertools-examples-core-utilities-cdk jar @@ -13,7 +13,6 @@ 2.20.0 1.8 1.8 - true @@ -120,6 +119,14 @@ + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index d81118cde..d67077fae 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,13 +4,12 @@ 4.0.0 software.amazon.lambda.examples cdk - 1.18.0-SNAPSHOT + 2.0.0-SNAPSHOT UTF-8 - 2.91.0 + 2.93.0 [10.0.0,11.0.0) 5.10.0 - true @@ -31,6 +30,14 @@ cdk.CdkApp + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + diff --git a/examples/powertools-examples-core-utilities/gradle/README.md b/examples/powertools-examples-core-utilities/gradle/README.md new file mode 100644 index 000000000..cd6107151 --- /dev/null +++ b/examples/powertools-examples-core-utilities/gradle/README.md @@ -0,0 +1,38 @@ +# Powertools for AWS Lambda (Java) - Core Utilities Example with Gradle + +This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) with +[Gradle](https://gradle.org/) running the build. This example is configured for Java 1.8 only; in order to use a newer version, check out the Gradle +configuration guide [in the main project README](../../../README.md). + +You can also use `sam init` to create a new Gradle-powered Powertools application - choose to use the **AWS Quick Start Templates**, +and then **Hello World Example with Powertools for AWS Lambda**, **Java 17** runtime, and finally **gradle**. + + +For general information on the deployed example itself, you can refer to the parent [README](../../powertools-examples-core/README.md) + +## Configuration +SAM uses [template.yaml](template.yaml) to define the application's AWS resources. +This file defines the Lambda function to be deployed as well as API Gateway for it. + +The build of the project is managed by Gradle, and configured in [build.gradle](build.gradle). + +## Deploy the sample application +To get started, you can use the Gradle wrapper to bootstrap Gradle and run the build: + +```bash +./gradlew build +``` + +Once this is done to deploy the example, check out the instructions for getting started with SAM in +[the examples directory](../../README.md) + +## Additional notes + +You can watch the trace information or log information using the SAM CLI: +```bash +# Tail the logs +sam logs --tail $MY_STACK + +# Tail the traces +sam traces --tail +``` \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle new file mode 100644 index 000000000..e7367c246 --- /dev/null +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -0,0 +1,35 @@ + +plugins { + id 'java' + id "io.freefair.aspectj.post-compile-weaving" version "6.6.3" +} + +wrapper { + gradleVersion = "7.6.1" +} + +compileJava { + sourceCompatibility = "1.8" + targetCompatibility = "1.8" + + ajc { + enabled = true + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'com.amazonaws:aws-lambda-java-core:1.2.2' + implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.2' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' + implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' + aspect 'software.amazon.lambda:powertools-tracing:1.17.0' + aspect 'software.amazon.lambda:powertools-logging:1.17.0' + aspect 'software.amazon.lambda:powertools-metrics:1.17.0' + testImplementation 'junit:junit:4.13.2' +} + diff --git a/examples/powertools-examples-core-utilities/gradle/events/event.json b/examples/powertools-examples-core-utilities/gradle/events/event.json new file mode 100644 index 000000000..070ad8e01 --- /dev/null +++ b/examples/powertools-examples-core-utilities/gradle/events/event.json @@ -0,0 +1,62 @@ +{ + "body": "{\"message\": \"hello world\"}", + "resource": "/{proxy+}", + "path": "/path/to/resource", + "httpMethod": "POST", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/path/to/resource", + "resourcePath": "/{proxy+}", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } +} diff --git a/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/.gitignore b/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/.gitignore new file mode 100644 index 000000000..59c09e205 --- /dev/null +++ b/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/.gitignore @@ -0,0 +1,2 @@ +!gradle-wrapper.jar + diff --git a/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.jar b/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..033e24c4cdf41af1ab109bc7f253b2b887023340 GIT binary patch literal 63375 zcmb5VV{~QRw)Y#`wrv{~+qP{x72B%VwzFc}c2cp;N~)5ZbDrJayPv(!dGEd-##*zr z)#n-$y^sH|_dchh3@8{H5D*j;5D<{i*8l5IFJ|DjL!e)upfGNX(kojugZ3I`oH1PvW`wFW_ske0j@lB9bX zO;2)`y+|!@X(fZ1<2n!Qx*)_^Ai@Cv-dF&(vnudG?0CsddG_&Wtae(n|K59ew)6St z#dj7_(Cfwzh$H$5M!$UDd8=4>IQsD3xV=lXUq($;(h*$0^yd+b{qq63f0r_de#!o_ zXDngc>zy`uor)4A^2M#U*DC~i+dc<)Tb1Tv&~Ev@oM)5iJ4Sn#8iRw16XXuV50BS7 zdBL5Mefch(&^{luE{*5qtCZk$oFr3RH=H!c3wGR=HJ(yKc_re_X9pD` zJ;uxPzUfVpgU>DSq?J;I@a+10l0ONXPcDkiYcihREt5~T5Gb}sT0+6Q;AWHl`S5dV>lv%-p9l#xNNy7ZCr%cyqHY%TZ8Q4 zbp&#ov1*$#grNG#1vgfFOLJCaNG@K|2!W&HSh@3@Y%T?3YI75bJp!VP*$*!< z;(ffNS_;@RJ`=c7yX04!u3JP*<8jeqLHVJu#WV&v6wA!OYJS4h<_}^QI&97-;=ojW zQ-1t)7wnxG*5I%U4)9$wlv5Fr;cIizft@&N+32O%B{R1POm$oap@&f| zh+5J{>U6ftv|vAeKGc|zC=kO(+l7_cLpV}-D#oUltScw})N>~JOZLU_0{Ka2e1evz z{^a*ZrLr+JUj;)K&u2CoCAXLC2=fVScI(m_p~0FmF>>&3DHziouln?;sxW`NB}cSX z8?IsJB)Z=aYRz!X=yJn$kyOWK%rCYf-YarNqKzmWu$ZvkP12b4qH zhS9Q>j<}(*frr?z<%9hl*i^#@*O2q(Z^CN)c2c z>1B~D;@YpG?G!Yk+*yn4vM4sO-_!&m6+`k|3zd;8DJnxsBYtI;W3We+FN@|tQ5EW= z!VU>jtim0Mw#iaT8t_<+qKIEB-WwE04lBd%Letbml9N!?SLrEG$nmn7&W(W`VB@5S zaY=sEw2}i@F_1P4OtEw?xj4@D6>_e=m=797#hg}f*l^`AB|Y0# z9=)o|%TZFCY$SzgSjS|8AI-%J4x}J)!IMxY3_KYze`_I=c1nmrk@E8c9?MVRu)7+Ue79|)rBX7tVB7U|w4*h(;Gi3D9le49B38`wuv zp7{4X^p+K4*$@gU(Tq3K1a#3SmYhvI42)GzG4f|u zwQFT1n_=n|jpi=70-yE9LA+d*T8u z`=VmmXJ_f6WmZveZPct$Cgu^~gFiyL>Lnpj*6ee>*0pz=t$IJ}+rE zsf@>jlcG%Wx;Cp5x)YSVvB1$yyY1l&o zvwX=D7k)Dn;ciX?Z)Pn8$flC8#m`nB&(8?RSdBvr?>T9?E$U3uIX7T?$v4dWCa46 z+&`ot8ZTEgp7G+c52oHJ8nw5}a^dwb_l%MOh(ebVj9>_koQP^$2B~eUfSbw9RY$_< z&DDWf2LW;b0ZDOaZ&2^i^g+5uTd;GwO(-bbo|P^;CNL-%?9mRmxEw~5&z=X^Rvbo^WJW=n_%*7974RY}JhFv46> zd}`2|qkd;89l}R;i~9T)V-Q%K)O=yfVKNM4Gbacc7AOd>#^&W&)Xx!Uy5!BHnp9kh z`a(7MO6+Ren#>R^D0K)1sE{Bv>}s6Rb9MT14u!(NpZOe-?4V=>qZ>}uS)!y~;jEUK z&!U7Fj&{WdgU#L0%bM}SYXRtM5z!6M+kgaMKt%3FkjWYh=#QUpt$XX1!*XkpSq-pl zhMe{muh#knk{9_V3%qdDcWDv}v)m4t9 zQhv{;} zc{}#V^N3H>9mFM8`i`0p+fN@GqX+kl|M94$BK3J-X`Hyj8r!#x6Vt(PXjn?N)qedP z=o1T^#?1^a{;bZ&x`U{f?}TMo8ToN zkHj5v|}r}wDEi7I@)Gj+S1aE-GdnLN+$hw!=DzglMaj#{qjXi_dwpr|HL(gcCXwGLEmi|{4&4#OZ4ChceA zKVd4K!D>_N=_X;{poT~4Q+!Le+ZV>=H7v1*l%w`|`Dx8{)McN@NDlQyln&N3@bFpV z_1w~O4EH3fF@IzJ9kDk@7@QctFq8FbkbaH7K$iX=bV~o#gfh?2JD6lZf(XP>~DACF)fGFt)X%-h1yY~MJU{nA5 ze2zxWMs{YdX3q5XU*9hOH0!_S24DOBA5usB+Ws$6{|AMe*joJ?RxfV}*7AKN9V*~J zK+OMcE@bTD>TG1*yc?*qGqjBN8mgg@h1cJLDv)0!WRPIkC` zZrWXrceVw;fB%3`6kq=a!pq|hFIsQ%ZSlo~)D z|64!aCnw-?>}AG|*iOl44KVf8@|joXi&|)1rB;EQWgm+iHfVbgllP$f!$Wf42%NO5b(j9Bw6L z;0dpUUK$5GX4QbMlTmLM_jJt!ur`_0~$b#BB7FL*%XFf<b__1o)Ao3rlobbN8-(T!1d-bR8D3S0@d zLI!*GMb5s~Q<&sjd}lBb8Nr0>PqE6_!3!2d(KAWFxa{hm`@u|a(%#i(#f8{BP2wbs zt+N_slWF4IF_O|{w`c~)Xvh&R{Au~CFmW#0+}MBd2~X}t9lz6*E7uAD`@EBDe$>7W zzPUkJx<`f$0VA$=>R57^(K^h86>09?>_@M(R4q($!Ck6GG@pnu-x*exAx1jOv|>KH zjNfG5pwm`E-=ydcb+3BJwuU;V&OS=6yM^4Jq{%AVqnTTLwV`AorIDD}T&jWr8pB&j28fVtk_y*JRP^t@l*($UZ z6(B^-PBNZ+z!p?+e8@$&jCv^EWLb$WO=}Scr$6SM*&~B95El~;W_0(Bvoha|uQ1T< zO$%_oLAwf1bW*rKWmlD+@CP&$ObiDy=nh1b2ejz%LO9937N{LDe7gle4i!{}I$;&Y zkexJ9Ybr+lrCmKWg&}p=`2&Gf10orS?4$VrzWidT=*6{KzOGMo?KI0>GL0{iFWc;C z+LPq%VH5g}6V@-tg2m{C!-$fapJ9y}c$U}aUmS{9#0CM*8pC|sfer!)nG7Ji>mfRh z+~6CxNb>6eWKMHBz-w2{mLLwdA7dA-qfTu^A2yG1+9s5k zcF=le_UPYG&q!t5Zd_*E_P3Cf5T6821bO`daa`;DODm8Ih8k89=RN;-asHIigj`n=ux>*f!OC5#;X5i;Q z+V!GUy0|&Y_*8k_QRUA8$lHP;GJ3UUD08P|ALknng|YY13)}!!HW@0z$q+kCH%xet zlWf@BXQ=b=4}QO5eNnN~CzWBbHGUivG=`&eWK}beuV*;?zt=P#pM*eTuy3 zP}c#}AXJ0OIaqXji78l;YrP4sQe#^pOqwZUiiN6^0RCd#D271XCbEKpk`HI0IsN^s zES7YtU#7=8gTn#lkrc~6)R9u&SX6*Jk4GFX7){E)WE?pT8a-%6P+zS6o&A#ml{$WX zABFz#i7`DDlo{34)oo?bOa4Z_lNH>n;f0nbt$JfAl~;4QY@}NH!X|A$KgMmEsd^&Y zt;pi=>AID7ROQfr;MsMtClr5b0)xo|fwhc=qk33wQ|}$@?{}qXcmECh>#kUQ-If0$ zseb{Wf4VFGLNc*Rax#P8ko*=`MwaR-DQ8L8V8r=2N{Gaips2_^cS|oC$+yScRo*uF zUO|5=?Q?{p$inDpx*t#Xyo6=s?bbN}y>NNVxj9NZCdtwRI70jxvm3!5R7yiWjREEd zDUjrsZhS|P&|Ng5r+f^kA6BNN#|Se}_GF>P6sy^e8kBrgMv3#vk%m}9PCwUWJg-AD zFnZ=}lbi*mN-AOm zCs)r=*YQAA!`e#1N>aHF=bb*z*hXH#Wl$z^o}x##ZrUc=kh%OHWhp=7;?8%Xj||@V?1c ziWoaC$^&04;A|T)!Zd9sUzE&$ODyJaBpvqsw19Uiuq{i#VK1!htkdRWBnb z`{rat=nHArT%^R>u#CjjCkw-7%g53|&7z-;X+ewb?OLWiV|#nuc8mp*LuGSi3IP<<*Wyo9GKV7l0Noa4Jr0g3p_$ z*R9{qn=?IXC#WU>48-k5V2Oc_>P;4_)J@bo1|pf=%Rcbgk=5m)CJZ`caHBTm3%!Z9 z_?7LHr_BXbKKr=JD!%?KhwdYSdu8XxPoA{n8^%_lh5cjRHuCY9Zlpz8g+$f@bw@0V z+6DRMT9c|>1^3D|$Vzc(C?M~iZurGH2pXPT%F!JSaAMdO%!5o0uc&iqHx?ImcX6fI zCApkzc~OOnfzAd_+-DcMp&AOQxE_EsMqKM{%dRMI5`5CT&%mQO?-@F6tE*xL?aEGZ z8^wH@wRl`Izx4sDmU>}Ym{ybUm@F83qqZPD6nFm?t?(7>h*?`fw)L3t*l%*iw0Qu#?$5eq!Qc zpQvqgSxrd83NsdO@lL6#{%lsYXWen~d3p4fGBb7&5xqNYJ)yn84!e1PmPo7ChVd%4 zHUsV0Mh?VpzZD=A6%)Qrd~i7 z96*RPbid;BN{Wh?adeD_p8YU``kOrGkNox3D9~!K?w>#kFz!4lzOWR}puS(DmfjJD z`x0z|qB33*^0mZdM&6$|+T>fq>M%yoy(BEjuh9L0>{P&XJ3enGpoQRx`v6$txXt#c z0#N?b5%srj(4xmPvJxrlF3H%OMB!jvfy z;wx8RzU~lb?h_}@V=bh6p8PSb-dG|-T#A?`c&H2`_!u+uenIZe`6f~A7r)`9m8atC zt(b|6Eg#!Q*DfRU=Ix`#B_dK)nnJ_+>Q<1d7W)eynaVn`FNuN~%B;uO2}vXr5^zi2 z!ifIF5@Zlo0^h~8+ixFBGqtweFc`C~JkSq}&*a3C}L?b5Mh-bW=e)({F_g4O3 zb@SFTK3VD9QuFgFnK4Ve_pXc3{S$=+Z;;4+;*{H}Rc;845rP?DLK6G5Y-xdUKkA6E3Dz&5f{F^FjJQ(NSpZ8q-_!L3LL@H* zxbDF{gd^U3uD;)a)sJwAVi}7@%pRM&?5IaUH%+m{E)DlA_$IA1=&jr{KrhD5q&lTC zAa3c)A(K!{#nOvenH6XrR-y>*4M#DpTTOGQEO5Jr6kni9pDW`rvY*fs|ItV;CVITh z=`rxcH2nEJpkQ^(;1c^hfb8vGN;{{oR=qNyKtR1;J>CByul*+=`NydWnSWJR#I2lN zTvgnR|MBx*XFsfdA&;tr^dYaqRZp*2NwkAZE6kV@1f{76e56eUmGrZ>MDId)oqSWw z7d&r3qfazg+W2?bT}F)4jD6sWaw`_fXZGY&wnGm$FRPFL$HzVTH^MYBHWGCOk-89y zA+n+Q6EVSSCpgC~%uHfvyg@ufE^#u?JH?<73A}jj5iILz4Qqk5$+^U(SX(-qv5agK znUkfpke(KDn~dU0>gdKqjTkVk`0`9^0n_wzXO7R!0Thd@S;U`y)VVP&mOd-2 z(hT(|$=>4FY;CBY9#_lB$;|Wd$aOMT5O_3}DYXEHn&Jrc3`2JiB`b6X@EUOD zVl0S{ijm65@n^19T3l%>*;F(?3r3s?zY{thc4%AD30CeL_4{8x6&cN}zN3fE+x<9; zt2j1RRVy5j22-8U8a6$pyT+<`f+x2l$fd_{qEp_bfxfzu>ORJsXaJn4>U6oNJ#|~p z`*ZC&NPXl&=vq2{Ne79AkQncuxvbOG+28*2wU$R=GOmns3W@HE%^r)Fu%Utj=r9t` zd;SVOnA(=MXgnOzI2@3SGKHz8HN~Vpx&!Ea+Df~`*n@8O=0!b4m?7cE^K*~@fqv9q zF*uk#1@6Re_<^9eElgJD!nTA@K9C732tV~;B`hzZ321Ph=^BH?zXddiu{Du5*IPg} zqDM=QxjT!Rp|#Bkp$(mL)aar)f(dOAXUiw81pX0DC|Y4;>Vz>>DMshoips^8Frdv} zlTD=cKa48M>dR<>(YlLPOW%rokJZNF2gp8fwc8b2sN+i6&-pHr?$rj|uFgktK@jg~ zIFS(%=r|QJ=$kvm_~@n=ai1lA{7Z}i+zj&yzY+!t$iGUy|9jH#&oTNJ;JW-3n>DF+ z3aCOzqn|$X-Olu_p7brzn`uk1F*N4@=b=m;S_C?#hy{&NE#3HkATrg?enaVGT^$qIjvgc61y!T$9<1B@?_ibtDZ{G zeXInVr5?OD_nS_O|CK3|RzzMmu+8!#Zb8Ik;rkIAR%6?$pN@d<0dKD2c@k2quB%s( zQL^<_EM6ow8F6^wJN1QcPOm|ehA+dP(!>IX=Euz5qqIq}Y3;ibQtJnkDmZ8c8=Cf3 zu`mJ!Q6wI7EblC5RvP*@)j?}W=WxwCvF3*5Up_`3*a~z$`wHwCy)2risye=1mSp%p zu+tD6NAK3o@)4VBsM!@);qgsjgB$kkCZhaimHg&+k69~drbvRTacWKH;YCK(!rC?8 zP#cK5JPHSw;V;{Yji=55X~S+)%(8fuz}O>*F3)hR;STU`z6T1aM#Wd+FP(M5*@T1P z^06O;I20Sk!bxW<-O;E081KRdHZrtsGJflFRRFS zdi5w9OVDGSL3 zNrC7GVsGN=b;YH9jp8Z2$^!K@h=r-xV(aEH@#JicPy;A0k1>g1g^XeR`YV2HfmqXY zYbRwaxHvf}OlCAwHoVI&QBLr5R|THf?nAevV-=~V8;gCsX>jndvNOcFA+DI+zbh~# zZ7`qNk&w+_+Yp!}j;OYxIfx_{f0-ONc?mHCiCUak=>j>~>YR4#w# zuKz~UhT!L~GfW^CPqG8Lg)&Rc6y^{%3H7iLa%^l}cw_8UuG;8nn9)kbPGXS}p3!L_ zd#9~5CrH8xtUd?{d2y^PJg+z(xIfRU;`}^=OlehGN2=?}9yH$4Rag}*+AWotyxfCJ zHx=r7ZH>j2kV?%7WTtp+-HMa0)_*DBBmC{sd$)np&GEJ__kEd`xB5a2A z*J+yx>4o#ZxwA{;NjhU*1KT~=ZK~GAA;KZHDyBNTaWQ1+;tOFFthnD)DrCn`DjBZ% zk$N5B4^$`n^jNSOr=t(zi8TN4fpaccsb`zOPD~iY=UEK$0Y70bG{idLx@IL)7^(pL z{??Bnu=lDeguDrd%qW1)H)H`9otsOL-f4bSu};o9OXybo6J!Lek`a4ff>*O)BDT_g z<6@SrI|C9klY(>_PfA^qai7A_)VNE4c^ZjFcE$Isp>`e5fLc)rg@8Q_d^Uk24$2bn z9#}6kZ2ZxS9sI(RqT7?El2@B+($>eBQrNi_k#CDJ8D9}8$mmm z4oSKO^F$i+NG)-HE$O6s1--6EzJa?C{x=QgK&c=)b(Q9OVoAXYEEH20G|q$}Hue%~ zO3B^bF=t7t48sN zWh_zA`w~|){-!^g?6Mqf6ieV zFx~aPUOJGR=4{KsW7I?<=J2|lY`NTU=lt=%JE9H1vBpkcn=uq(q~=?iBt_-r(PLBM zP-0dxljJO>4Wq-;stY)CLB4q`-r*T$!K2o}?E-w_i>3_aEbA^MB7P5piwt1dI-6o!qWCy0 ztYy!x9arGTS?kabkkyv*yxvsPQ7Vx)twkS6z2T@kZ|kb8yjm+^$|sEBmvACeqbz)RmxkkDQX-A*K!YFziuhwb|ym>C$}U|J)4y z$(z#)GH%uV6{ec%Zy~AhK|+GtG8u@c884Nq%w`O^wv2#A(&xH@c5M`Vjk*SR_tJnq z0trB#aY)!EKW_}{#L3lph5ow=@|D5LzJYUFD6 z7XnUeo_V0DVSIKMFD_T0AqAO|#VFDc7c?c-Q%#u00F%!_TW1@JVnsfvm@_9HKWflBOUD~)RL``-!P;(bCON_4eVdduMO>?IrQ__*zE@7(OX zUtfH@AX*53&xJW*Pu9zcqxGiM>xol0I~QL5B%Toog3Jlenc^WbVgeBvV8C8AX^Vj& z^I}H})B=VboO%q1;aU5ACMh{yK4J;xlMc`jCnZR^!~LDs_MP&8;dd@4LDWw~*>#OT zeZHwdQWS!tt5MJQI~cw|Ka^b4c|qyd_ly(+Ql2m&AAw^ zQeSXDOOH!!mAgzAp0z)DD>6Xo``b6QwzUV@w%h}Yo>)a|xRi$jGuHQhJVA%>)PUvK zBQ!l0hq<3VZ*RnrDODP)>&iS^wf64C;MGqDvx>|p;35%6(u+IHoNbK z;Gb;TneFo*`zUKS6kwF*&b!U8e5m4YAo03a_e^!5BP42+r)LFhEy?_7U1IR<; z^0v|DhCYMSj<-;MtY%R@Fg;9Kky^pz_t2nJfKWfh5Eu@_l{^ph%1z{jkg5jQrkvD< z#vdK!nku*RrH~TdN~`wDs;d>XY1PH?O<4^U4lmA|wUW{Crrv#r%N>7k#{Gc44Fr|t z@UZP}Y-TrAmnEZ39A*@6;ccsR>)$A)S>$-Cj!=x$rz7IvjHIPM(TB+JFf{ehuIvY$ zsDAwREg*%|=>Hw$`us~RP&3{QJg%}RjJKS^mC_!U;E5u>`X`jW$}P`Mf}?7G7FX#{ zE(9u1SO;3q@ZhDL9O({-RD+SqqPX)`0l5IQu4q)49TUTkxR(czeT}4`WV~pV*KY&i zAl3~X%D2cPVD^B43*~&f%+Op)wl<&|D{;=SZwImydWL6@_RJjxP2g)s=dH)u9Npki zs~z9A+3fj0l?yu4N0^4aC5x)Osnm0qrhz@?nwG_`h(71P znbIewljU%T*cC=~NJy|)#hT+lx#^5MuDDnkaMb*Efw9eThXo|*WOQzJ*#3dmRWm@! zfuSc@#kY{Um^gBc^_Xdxnl!n&y&}R4yAbK&RMc+P^Ti;YIUh|C+K1|=Z^{nZ}}rxH*v{xR!i%qO~o zTr`WDE@k$M9o0r4YUFFeQO7xCu_Zgy)==;fCJ94M_rLAv&~NhfvcLWCoaGg2ao~3e zBG?Ms9B+efMkp}7BhmISGWmJsKI@a8b}4lLI48oWKY|8?zuuNc$lt5Npr+p7a#sWu zh!@2nnLBVJK!$S~>r2-pN||^w|fY`CT{TFnJy`B|e5;=+_v4l8O-fkN&UQbA4NKTyntd zqK{xEKh}U{NHoQUf!M=2(&w+eef77VtYr;xs%^cPfKLObyOV_9q<(%76-J%vR>w9!us-0c-~Y?_EVS%v!* z15s2s3eTs$Osz$JayyH|5nPAIPEX=U;r&p;K14G<1)bvn@?bM5kC{am|C5%hyxv}a z(DeSKI5ZfZ1*%dl8frIX2?);R^^~LuDOpNpk-2R8U1w92HmG1m&|j&J{EK=|p$;f9 z7Rs5|jr4r8k5El&qcuM+YRlKny%t+1CgqEWO>3;BSRZi(LA3U%Jm{@{y+A+w(gzA< z7dBq6a1sEWa4cD0W7=Ld9z0H7RI^Z7vl(bfA;72j?SWCo`#5mVC$l1Q2--%V)-uN* z9ha*s-AdfbDZ8R8*fpwjzx=WvOtmSzGFjC#X)hD%Caeo^OWjS(3h|d9_*U)l%{Ab8 zfv$yoP{OuUl@$(-sEVNt{*=qi5P=lpxWVuz2?I7Dc%BRc+NGNw+323^ z5BXGfS71oP^%apUo(Y#xkxE)y?>BFzEBZ}UBbr~R4$%b7h3iZu3S(|A;&HqBR{nK& z$;GApNnz=kNO^FL&nYcfpB7Qg;hGJPsCW44CbkG1@l9pn0`~oKy5S777uH)l{irK!ru|X+;4&0D;VE*Ii|<3P zUx#xUqvZT5kVQxsF#~MwKnv7;1pR^0;PW@$@T7I?s`_rD1EGUdSA5Q(C<>5SzE!vw z;{L&kKFM-MO>hy#-8z`sdVx})^(Dc-dw;k-h*9O2_YZw}|9^y-|8RQ`BWJUJL(Cer zP5Z@fNc>pTXABbTRY-B5*MphpZv6#i802giwV&SkFCR zGMETyUm(KJbh+&$8X*RB#+{surjr;8^REEt`2&Dubw3$mx>|~B5IKZJ`s_6fw zKAZx9&PwBqW1Oz0r0A4GtnZd7XTKViX2%kPfv+^X3|_}RrQ2e3l=KG_VyY`H?I5&CS+lAX5HbA%TD9u6&s#v!G> zzW9n4J%d5ye7x0y`*{KZvqyXUfMEE^ZIffzI=Hh|3J}^yx7eL=s+TPH(Q2GT-sJ~3 zI463C{(ag7-hS1ETtU;_&+49ABt5!A7CwLwe z=SoA8mYZIQeU;9txI=zcQVbuO%q@E)JI+6Q!3lMc=Gbj(ASg-{V27u>z2e8n;Nc*pf}AqKz1D>p9G#QA+7mqqrEjGfw+85Uyh!=tTFTv3|O z+)-kFe_8FF_EkTw!YzwK^Hi^_dV5x-Ob*UWmD-})qKj9@aE8g240nUh=g|j28^?v7 zHRTBo{0KGaWBbyX2+lx$wgXW{3aUab6Bhm1G1{jTC7ota*JM6t+qy)c5<@ zpc&(jVdTJf(q3xB=JotgF$X>cxh7k*(T`-V~AR+`%e?YOeALQ2Qud( zz35YizXt(aW3qndR}fTw1p()Ol4t!D1pitGNL95{SX4ywzh0SF;=!wf=?Q?_h6!f* zh7<+GFi)q|XBsvXZ^qVCY$LUa{5?!CgwY?EG;*)0ceFe&=A;!~o`ae}Z+6me#^sv- z1F6=WNd6>M(~ z+092z>?Clrcp)lYNQl9jN-JF6n&Y0mp7|I0dpPx+4*RRK+VQI~>en0Dc;Zfl+x z_e_b7s`t1_A`RP3$H}y7F9_na%D7EM+**G_Z0l_nwE+&d_kc35n$Fxkd4r=ltRZhh zr9zER8>j(EdV&Jgh(+i}ltESBK62m0nGH6tCBr90!4)-`HeBmz54p~QP#dsu%nb~W z7sS|(Iydi>C@6ZM(Us!jyIiszMkd)^u<1D+R@~O>HqZIW&kearPWmT>63%_t2B{_G zX{&a(gOYJx!Hq=!T$RZ&<8LDnxsmx9+TBL0gTk$|vz9O5GkK_Yx+55^R=2g!K}NJ3 zW?C;XQCHZl7H`K5^BF!Q5X2^Mj93&0l_O3Ea3!Ave|ixx+~bS@Iv18v2ctpSt4zO{ zp#7pj!AtDmti$T`e9{s^jf(ku&E|83JIJO5Qo9weT6g?@vX!{7)cNwymo1+u(YQ94 zopuz-L@|5=h8A!(g-MXgLJC0MA|CgQF8qlonnu#j z;uCeq9ny9QSD|p)9sp3ebgY3rk#y0DA(SHdh$DUm^?GI<>%e1?&}w(b zdip1;P2Z=1wM+$q=TgLP$}svd!vk+BZ@h<^4R=GS2+sri7Z*2f`9 z5_?i)xj?m#pSVchk-SR!2&uNhzEi+#5t1Z$o0PoLGz*pT64%+|Wa+rd5Z}60(j?X= z{NLjtgRb|W?CUADqOS@(*MA-l|E342NxRaxLTDqsOyfWWe%N(jjBh}G zm7WPel6jXijaTiNita+z(5GCO0NM=Melxud57PP^d_U## zbA;9iVi<@wr0DGB8=T9Ab#2K_#zi=$igyK48@;V|W`fg~7;+!q8)aCOo{HA@vpSy-4`^!ze6-~8|QE||hC{ICKllG9fbg_Y7v z$jn{00!ob3!@~-Z%!rSZ0JO#@>|3k10mLK0JRKP-Cc8UYFu>z93=Ab-r^oL2 zl`-&VBh#=-?{l1TatC;VweM^=M7-DUE>m+xO7Xi6vTEsReyLs8KJ+2GZ&rxw$d4IT zPXy6pu^4#e;;ZTsgmG+ZPx>piodegkx2n0}SM77+Y*j^~ICvp#2wj^BuqRY*&cjmL zcKp78aZt>e{3YBb4!J_2|K~A`lN=u&5j!byw`1itV(+Q_?RvV7&Z5XS1HF)L2v6ji z&kOEPmv+k_lSXb{$)of~(BkO^py&7oOzpjdG>vI1kcm_oPFHy38%D4&A4h_CSo#lX z2#oqMCTEP7UvUR3mwkPxbl8AMW(e{ARi@HCYLPSHE^L<1I}OgZD{I#YH#GKnpRmW3 z2jkz~Sa(D)f?V?$gNi?6)Y;Sm{&?~2p=0&BUl_(@hYeX8YjaRO=IqO7neK0RsSNdYjD zaw$g2sG(>JR=8Iz1SK4`*kqd_3-?;_BIcaaMd^}<@MYbYisWZm2C2|Np_l|8r9yM|JkUngSo@?wci(7&O9a z%|V(4C1c9pps0xxzPbXH=}QTxc2rr7fXk$9`a6TbWKPCz&p=VsB8^W96W=BsB|7bc zf(QR8&Ktj*iz)wK&mW`#V%4XTM&jWNnDF56O+2bo<3|NyUhQ%#OZE8$Uv2a@J>D%t zMVMiHh?es!Ex19q&6eC&L=XDU_BA&uR^^w>fpz2_`U87q_?N2y;!Z!bjoeKrzfC)} z?m^PM=(z{%n9K`p|7Bz$LuC7!>tFOuN74MFELm}OD9?%jpT>38J;=1Y-VWtZAscaI z_8jUZ#GwWz{JqvGEUmL?G#l5E=*m>`cY?m*XOc*yOCNtpuIGD+Z|kn4Xww=BLrNYS zGO=wQh}Gtr|7DGXLF%|`G>J~l{k^*{;S-Zhq|&HO7rC_r;o`gTB7)uMZ|WWIn@e0( zX$MccUMv3ABg^$%_lNrgU{EVi8O^UyGHPNRt%R!1#MQJn41aD|_93NsBQhP80yP<9 zG4(&0u7AtJJXLPcqzjv`S~5;Q|5TVGccN=Uzm}K{v)?f7W!230C<``9(64}D2raRU zAW5bp%}VEo{4Rko`bD%Ehf=0voW?-4Mk#d3_pXTF!-TyIt6U+({6OXWVAa;s-`Ta5 zTqx&8msH3+DLrVmQOTBOAj=uoxKYT3DS1^zBXM?1W+7gI!aQNPYfUl{3;PzS9*F7g zWJN8x?KjBDx^V&6iCY8o_gslO16=kh(|Gp)kz8qlQ`dzxQv;)V&t+B}wwdi~uBs4? zu~G|}y!`3;8#vIMUdyC7YEx6bb^1o}G!Jky4cN?BV9ejBfN<&!4M)L&lRKiuMS#3} z_B}Nkv+zzxhy{dYCW$oGC&J(Ty&7%=5B$sD0bkuPmj7g>|962`(Q{ZZMDv%YMuT^KweiRDvYTEop3IgFv#)(w>1 zSzH>J`q!LK)c(AK>&Ib)A{g`Fdykxqd`Yq@yB}E{gnQV$K!}RsgMGWqC3DKE(=!{}ekB3+(1?g}xF>^icEJbc z5bdxAPkW90atZT+&*7qoLqL#p=>t-(-lsnl2XMpZcYeW|o|a322&)yO_8p(&Sw{|b zn(tY$xn5yS$DD)UYS%sP?c|z>1dp!QUD)l;aW#`%qMtQJjE!s2z`+bTSZmLK7SvCR z=@I4|U^sCwZLQSfd*ACw9B@`1c1|&i^W_OD(570SDLK`MD0wTiR8|$7+%{cF&){$G zU~|$^Ed?TIxyw{1$e|D$050n8AjJvvOWhLtLHbSB|HIfhMpqVf>AF&}ZQHhOJ14Bz zww+XL+qP}nww+W`F>b!by|=&a(cM4JIDhsTXY8@|ntQG}-}jm0&Bcj|LV(#sc=BNS zRjh;k9l>EdAFdd)=H!U`~$WP*}~^3HZ_?H>gKw>NBa;tA8M1{>St|)yDF_=~{KEPAGkg3VB`QCHol!AQ0|?e^W?81f{@()Wy!vQ$bY; z0ctx)l7VK83d6;dp!s{Nu=SwXZ8lHQHC*J2g@P0a={B8qHdv(+O3wV=4-t4HK1+smO#=S; z3cSI#Nh+N@AqM#6wPqjDmQM|x95JG|l1#sAU|>I6NdF*G@bD?1t|ytHlkKD+z9}#j zbU+x_cR-j9yX4s{_y>@zk*ElG1yS({BInGJcIT>l4N-DUs6fufF#GlF2lVUNOAhJT zGZThq54GhwCG(h4?yWR&Ax8hU<*U)?g+HY5-@{#ls5CVV(Wc>Bavs|l<}U|hZn z_%m+5i_gaakS*Pk7!v&w3&?R5Xb|AkCdytTY;r+Z7f#Id=q+W8cn)*9tEet=OG+Y} z58U&!%t9gYMx2N=8F?gZhIjtkH!`E*XrVJ?$2rRxLhV1z82QX~PZi8^N5z6~f-MUE zLKxnNoPc-SGl7{|Oh?ZM$jq67sSa)Wr&3)0YxlJt(vKf!-^L)a|HaPv*IYXb;QmWx zsqM>qY;tpK3RH-omtta+Xf2Qeu^$VKRq7`e$N-UCe1_2|1F{L3&}M0XbJ@^xRe&>P zRdKTgD6601x#fkDWkoYzRkxbn#*>${dX+UQ;FbGnTE-+kBJ9KPn)501#_L4O_k`P3 zm+$jI{|EC?8BXJY{P~^f-{**E53k%kVO$%p+=H5DiIdwMmUo>2euq0UzU90FWL!>; z{5@sd0ecqo5j!6AH@g6Mf3keTP$PFztq}@)^ZjK;H6Go$#SV2|2bAFI0%?aXgVH$t zb4Kl`$Xh8qLrMbZUS<2*7^F0^?lrOE=$DHW+O zvLdczsu0^TlA6RhDy3=@s!k^1D~Awulk!Iyo#}W$xq8{yTAK!CLl={H0@YGhg-g~+ z(u>pss4k#%8{J%~%8=H5!T`rqK6w^es-cNVE}=*lP^`i&K4R=peg1tdmT~UAbDKc& zg%Y*1E{hBf<)xO>HDWV7BaMWX6FW4ou1T2m^6{Jb!Su1UaCCYY8RR8hAV$7ho|FyEyP~ zEgK`@%a$-C2`p zV*~G>GOAs*3KN;~IY_UR$ISJxB(N~K>=2C2V6>xTmuX4klRXdrJd&UPAw7&|KEwF8Zcy2j-*({gSNR1^p02Oj88GN9a_Hq;Skdp}kO0;FLbje%2ZvPiltDZgv^ z#pb4&m^!79;O8F+Wr9X71laPY!CdNXG?J6C9KvdAE2xWW1>U~3;0v≫L+crb^Bz zc+Nw%zgpZ6>!A3%lau!Pw6`Y#WPVBtAfKSsqwYDWQK-~ zz(mx=nJ6-8t`YXB{6gaZ%G}Dmn&o500Y}2Rd?e&@=hBEmB1C=$OMBfxX__2c2O4K2#(0ksclP$SHp*8jq-1&(<6(#=6&H`Nlc2RVC4->r6U}sTY<1? zn@tv7XwUs-c>Lcmrm5AE0jHI5={WgHIow6cX=UK)>602(=arbuAPZ37;{HTJSIO%9EL`Et5%J7$u_NaC(55x zH^qX^H}*RPDx)^c46x>js=%&?y?=iFs^#_rUl@*MgLD92E5y4B7#EDe9yyn*f-|pQ zi>(!bIg6zY5fLSn@;$*sN|D2A{}we*7+2(4&EhUV%Qqo5=uuN^xt_hll7=`*mJq6s zCWUB|s$)AuS&=)T&_$w>QXHqCWB&ndQ$y4-9fezybZb0bYD^zeuZ>WZF{rc>c4s`` zgKdppTB|o>L1I1hAbnW%H%EkFt%yWC|0~+o7mIyFCTyb?@*Ho)eu(x`PuO8pLikN> z6YeI`V?AUWD(~3=8>}a6nZTu~#QCK(H0+4!ql3yS`>JX;j4+YkeG$ZTm33~PLa3L} zksw7@%e-mBM*cGfz$tS4LC^SYVdBLsR}nAprwg8h2~+Cv*W0%izK+WPVK}^SsL5R_ zpA}~G?VNhJhqx2he2;2$>7>DUB$wN9_-adL@TqVLe=*F8Vsw-yho@#mTD6*2WAr6B zjtLUh`E(;#p0-&$FVw(r$hn+5^Z~9J0}k;j$jL1;?2GN9s?}LASm?*Rvo@?E+(}F& z+=&M-n`5EIz%%F^e)nnWjkQUdG|W^~O|YeY4Fz}>qH2juEere}vN$oJN~9_Th^&b{ z%IBbET*E8%C@jLTxV~h#mxoRrJCF{!CJOghjuKOyl_!Jr?@4Upo7u>fTGtfm|CH2v z&9F+>;6aFbYXLj3{yZ~Yn1J2%!)A3~j2$`jOy{XavW@t)g}}KUVjCWG0OUc7aBc=2 zR3^u=dT47=5SmT{K1aGaVZkOx|24T-J0O$b9dfB25J|7yb6frwS6wZ1^y%EWOm}S< zc1SdYhfsdLG*FB-;!QLV3D!d~hnXTGVQVck9x%=B(Kk8c3y%f0nR95_TbY;l=obSl zEE@fp0|8Q$b3(+DXh?d0FEloGhO0#11CLQT5qtEckBLe-VN-I>9ys}PVK0r;0!jIG zH_q$;a`3Xv9P_V2ekV1SMzd#SKo<1~Dq2?M{(V;AwhH_2x@mN$=|=cG0<3o^j_0OF z7|WJ-f2G=7sA4NVGU2X5`o*D2T7(MbmZ2(oipooE{R?9!{WxX!%ofhsrPAxoIk!Kr z>I$a{Zq=%KaLrDCIL^gmA3z{2z%Wkr)b$QHcNUA^QwydWMJmxymO0QS22?mo%4(Md zgME(zE}ub--3*wGjV`3eBMCQG-@Gel1NKZDGuqobN|mAt0{@ZC9goI|BSmGBTUZ(`Xt z^e2LiMg?6E?G*yw(~K8lO(c4)RY7UWxrXzW^iCg-P41dUiE(i+gDmmAoB?XOB}+Ln z_}rApiR$sqNaT4frw69Wh4W?v(27IlK$Toy<1o)GeF+sGzYVeJ`F)3`&2WDi^_v67 zg;@ehwl3=t+}(DJtOYO!s`jHyo-}t@X|U*9^sIfaZfh;YLqEFmZ^E;$_XK}%eq;>0 zl?+}*kh)5jGA}3daJ*v1knbW0GusR1+_xD`MFPZc3qqYMXd>6*5?%O5pC7UVs!E-` zuMHc6igdeFQ`plm+3HhP)+3I&?5bt|V8;#1epCsKnz0%7m9AyBmz06r90n~9o;K30 z=fo|*`Qq%dG#23bVV9Jar*zRcV~6fat9_w;x-quAwv@BkX0{9e@y0NB(>l3#>82H6 z^US2<`=M@6zX=Pz>kb8Yt4wmeEo%TZ=?h+KP2e3U9?^Nm+OTx5+mVGDvgFee%}~~M zK+uHmj44TVs}!A}0W-A92LWE%2=wIma(>jYx;eVB*%a>^WqC7IVN9{o?iw{e4c=CG zC#i=cRJZ#v3 zF^9V+7u?W=xCY%2dvV_0dCP%5)SH*Xm|c#rXhwEl*^{Ar{NVoK*H6f5qCSy`+|85e zjGaKqB)p7zKNKI)iWe6A9qkl=rTjs@W1Crh(3G57qdT0w2ig^{*xerzm&U>YY{+fZbkQ#;^<$JniUifmAuEd^_M(&?sTrd(a*cD! zF*;`m80MrZ^> zaF{}rDhEFLeH#`~rM`o903FLO?qw#_Wyb5}13|0agjSTVkSI6Uls)xAFZifu@N~PM zQ%o?$k)jbY0u|45WTLAirUg3Zi1E&=G#LnSa89F3t3>R?RPcmkF}EL-R!OF_r1ZN` z?x-uHH+4FEy>KrOD-$KHg3$-Xl{Cf0;UD4*@eb~G{CK-DXe3xpEEls?SCj^p z$Uix(-j|9f^{z0iUKXcZQen}*`Vhqq$T?^)Ab2i|joV;V-qw5reCqbh(8N)c%!aB< zVs+l#_)*qH_iSZ_32E~}>=wUO$G_~k0h@ch`a6Wa zsk;<)^y=)cPpHt@%~bwLBy;>TNrTf50BAHUOtt#9JRq1ro{w80^sm-~fT>a$QC;<| zZIN%&Uq>8`Js_E((_1sewXz3VlX|-n8XCfScO`eL|H&2|BPZhDn}UAf_6s}|!XpmUr90v|nCutzMjb9|&}#Y7fj_)$alC zM~~D6!dYxhQof{R;-Vp>XCh1AL@d-+)KOI&5uKupy8PryjMhTpCZnSIQ9^Aq+7=Mb zCYCRvm4;H=Q8nZWkiWdGspC_Wvggg|7N`iED~Eap)Th$~wsxc(>(KI>{i#-~Dd8iQ zzonqc9DW1w4a*}k`;rxykUk+~N)|*I?@0901R`xy zN{20p@Ls<%`1G1Bx87Vm6Z#CA`QR(x@t8Wc?tpaunyV^A*-9K9@P>hAWW9Ev)E$gb z<(t?Te6GcJX2&0% z403pe>e)>m-^qlJU^kYIH)AutgOnq!J>FoMXhA-aEx-((7|(*snUyxa+5$wx8FNxS zKuVAVWArlK#kDzEM zqR?&aXIdyvxq~wF?iYPho*(h?k zD(SBpRDZ}z$A})*Qh!9&pZZRyNixD!8)B5{SK$PkVET(yd<8kImQ3ILe%jhx8Ga-1 zE}^k+Eo^?c4Y-t2_qXiVwW6i9o2qosBDj%DRPNT*UXI0=D9q{jB*22t4HHcd$T&Xi zT=Vte*Gz2E^qg%b7ev04Z&(;=I4IUtVJkg<`N6i7tjUn-lPE(Y4HPyJKcSjFnEzCH zPO(w%LmJ_=D~}PyfA91H4gCaf-qur3_KK}}>#9A}c5w@N;-#cHph=x}^mQ3`oo`Y$ope#)H9(kQK zGyt<7eNPuSAs$S%O>2ElZ{qtDIHJ!_THqTwcc-xfv<@1>IJ;YTv@!g-zDKBKAH<

Zet1e^8c}8fE97XH}+lF{qbF<`Y%dU|I!~Y`ZrVfKX82i z)(%!Tcf~eE^%2_`{WBPGPU@1NB5SCXe1sAI<4&n1IwO{&S$ThWn37heGOSW%nW7*L zxh0WK!E7zh%6yF-7%~l@I~b`2=*$;RYbi(I#zp$gL_d39U4A)KuB( zcS0bt48&%G_I~( zL(}w&2NA6#$=|g)J+-?ehHflD^lr77ngdz=dszFI;?~ZxeJv=gsm?4$$6#V==H{fa zqO!EkT>1-OQSJoX)cN}XsB;shvrHRwTH(I2^Ah4|rizn!V7T7fLh~Z<`Q+?zEMVxh z$=-x^RR*PlhkV_8mshTvs+zmZWY&Jk{9LX0Nx|+NAEq-^+Rh|ZlinVZ=e8=`WQt;e@= zPU}^1cG*O;G7l{Y#nl znp`y%CO_SC7gk0i0gY&phM04Y)~vU0!3$V$2T+h(1ZS+cCgc zaC?3M;B48^faGo>h~--#FNFauH?0BJJ6_nG5qOlr>k~%DCSJaOfl%KWHusw>tGrTxAhlEVDxc8R2C-)LCt&$Rt9IKor=ml7jirX@?WW+M z^I{b}MD5r$s>^^sN@&g`cXD~S_u09xo;{;noKZatIuzqd zW1e7oTl9>g8opPBT(p+&fo0F#!c{NFYYpIZ6u8hOB{F#{nP)@})X20$3iJtG$cO zJ$Oxl_qH{sL5d?=D$2M4C3Ajc;GN0(B-HVT;@pJ-LvIrN%|SY?t}g!J>ufQrR%hoY z!nr$tq~N%)9}^tEip93XW=MQ1@XovSvn`PTqXeT9@_7hGv4%LK1M**Q%UKi|(v@1_ zKGe*@+1%Y4v&`;5vUL`C&{tc+_7HFs7*OtjY8@Gg`C4O&#An{0xOvgNSehTHS~_1V z=daxCMzI5b_ydM5$z zZl`a{mM}i@x;=QyaqJY&{Q^R*^1Yzq!dHH~UwCCga+Us~2wk59ArIYtSw9}tEmjbo z5!JA=`=HP*Ae~Z4Pf7sC^A3@Wfa0Ax!8@H_&?WVe*)9B2y!8#nBrP!t1fqhI9jNMd zM_5I)M5z6Ss5t*f$Eh{aH&HBeh310Q~tRl3wCEcZ>WCEq%3tnoHE)eD=)XFQ7NVG5kM zaUtbnq2LQomJSWK)>Zz1GBCIHL#2E>T8INWuN4O$fFOKe$L|msB3yTUlXES68nXRX zP6n*zB+kXqqkpQ3OaMc9GqepmV?Ny!T)R@DLd`|p5ToEvBn(~aZ%+0q&vK1)w4v0* zgW44F2ixZj0!oB~^3k|vni)wBh$F|xQN>~jNf-wFstgiAgB!=lWzM&7&&OYS=C{ce zRJw|)PDQ@3koZfm`RQ$^_hEN$GuTIwoTQIDb?W&wEo@c75$dW(ER6q)qhF`{#7UTuPH&)w`F!w z0EKs}=33m}_(cIkA2rBWvApydi0HSOgc>6tu&+hmRSB%)s`v_NujJNhKLS3r6hv~- z)Hm@?PU{zd0Tga)cJWb2_!!9p3sP%Z zAFT|jy;k>4X)E>4fh^6=SxV5w6oo`mus&nWo*gJL zZH{SR!x)V)y=Qc7WEv-xLR zhD4OcBwjW5r+}pays`o)i$rcJb2MHLGPmeOmt5XJDg@(O3PCbxdDn{6qqb09X44T zh6I|s=lM6Nr#cGaA5-eq*T=LQ6SlRq*`~`b+dVi5^>el1p;#si6}kK}>w;1 z6B1dz{q_;PY{>DBQ+v@1pfXTd5a*^H9U*;qdj@XBF}MoSSQxVXeUpEM5Z0909&8$pRfR|B(t0ox&xl8{8mUNd#(zWONW{oycv$VjP1>q;jU@ z@+8E~fjz*I54OFFaQ{A5jn1w>r;l!NRlI(8q3*%&+tM?lov_G3wB`<}bQ>1=&xUht zmti5VZzV1Cx006Yzt|%Vwid>QPX8Nfa8|sue7^un@C+!3h!?-YK>lSfNIHh|0kL8v zbv_BklQ4HOqje|@Fyxn%IvL$N&?m(KN;%`I$N|muStjSsgG;gP4Smgz$2u(mG;DXP zf~uQ z212x^l6!MW>V@ORUGSFLAAjz3i5zO$=UmD_zhIk2OXUz^LkDLWjla*PW?l;`LLos> z7FBvCr)#)XBByDm(=n%{D>BcUq>0GOV9`i-(ZSI;RH1rdrAJ--f0uuAQ4odl z_^$^U_)0BBJwl@6R#&ZtJN+@a(4~@oYF)yG+G#3=)ll8O#Zv3SjV#zSXTW3h9kqn* z@AHL=vf~KMas}6{+u=}QFumr-!c=(BFP_dwvrdehzTyqco)m@xRc=6b#Dy+KD*-Bq zK=y*1VAPJ;d(b?$2cz{CUeG(0`k9_BIuUki@iRS5lp3=1#g)A5??1@|p=LOE|FNd; z-?5MLKd-5>yQ7n__5W^3C!_`hP(o%_E3BKEmo1h=H(7;{6$XRRW6{u+=oQX<((xAJ zNRY`Egtn#B1EBGHLy^eM5y}Jy0h!GAGhb7gZJoZI-9WuSRw)GVQAAcKd4Qm)pH`^3 zq6EIM}Q zxZGx%aLnNP1an=;o8p9+U^>_Bi`e23E^X|}MB&IkS+R``plrRzTE%ncmfvEW#AHJ~ znmJ`x&ez6eT21aLnoI`%pYYj zzQ?f^ob&Il;>6Fe>HPhAtTZa*B*!;;foxS%NGYmg!#X%)RBFe-acahHs3nkV61(E= zhekiPp1d@ACtA=cntbjuv+r-Zd`+lwKFdqZuYba_ey`&H<Psu;Tzwt;-LQxvv<_D5;ik7 zwETZe`+voUhk%$s2-7Rqfl`Ti_{(fydI(DAHKr<66;rYa6p8AD+NEc@Fd@%m`tiK% z=Mebzrtp=*Q%a}2UdK4J&5#tCN5PX>W=(9rUEXZ8yjRu+7)mFpKh{6;n%!bI(qA9kfyOtstGtOl zX!@*O0fly*L4k##fsm&V0j9Lj<_vu1)i?!#xTB7@2H&)$Kzt@r(GH=xRZlIimTDd_o(%9xO388LwC#;vQ?7OvRU_s< zDS@6@g}VnvQ+tn(C#sx0`J^T4WvFxYI17;uPs-Ub{R`J-NTdtBGl+Q>e81Z3#tDUr ztnVc*p{o|RNnMYts4pdw=P!uJkF@8~h)oV4dXu5F7-j0AW|=mt!QhP&ZV!!82*c7t zuOm>B*2gFtq;A8ynZ~Ms?!gEi5<{R_8tRN%aGM!saR4LJQ|?9w>Ff_61(+|ol_vL4 z-+N>fushRbkB4(e{{SQ}>6@m}s1L!-#20N&h%srA=L50?W9skMF9NGfQ5wU*+0<@> zLww8%f+E0Rc81H3e_5^DB@Dn~TWYk}3tqhO{7GDY;K7b*WIJ-tXnYM@z4rn(LGi?z z8%$wivs)fC#FiJh?(SbH-1bgdmHw&--rn7zBWe1xAhDdv#IRB@DGy}}zS%M0(F_3_ zLb-pWsdJ@xXE;=tpRAw?yj(Gz=i$;bsh&o2XN%24b6+?_gJDBeY zws3PE2u!#Cec>aFMk#ECxDlAs;|M7@LT8)Y4(`M}N6IQ{0YtcA*8e42!n^>`0$LFU zUCq2IR2(L`f++=85M;}~*E($nE&j;p{l%xchiTau*tB9bI= zn~Ygd@<+9DrXxoGPq}@vI1Q3iEfKRleuy*)_$+hg?+GOgf1r?d@Or42|s|D>XMa;ebr1uiTNUq@heusd6%WwJqyCCv!L*qou9l!B22H$bQ z)<)IA>Yo77S;|`fqBk!_PhLJEQb0wd1Z|`pCF;hol!34iQYtqu3K=$QxLW7(HFx~v>`vVRr zyqk^B4~!3F8t8Q_D|GLRrAbbQDf??D&Jd|mgw*t1YCd)CM2$76#Cqj1bD*vADwavp zS<`n@gLU4pwCqNPsIfHKl{5}gu9t-o+O< z??!fMqMrt$s}02pdBbOScUrc1T*{*-ideR6(1q4@oC6mxg8v8Y^h^^hfx6| z|Mld6Ax1CuSlmSJmHwdOix?$8emihK#&8&}u8m!#T1+c5u!H)>QW<7&R$eih)xkov zHvvEIJHbkt+2KQ<-bMR;2SYX?8SI=_<-J!GD5@P2FJ}K z5u82YFotCJF(dUeJFRX_3u8%iIYbRS??A?;iVO?84c}4Du9&jG<#urlZ_Unrcg8dR z!5I3%9F*`qwk#joKG_Q%5_xpU7|jm4h0+l$p;g%Tr>i74#3QnMXdz|1l2MQN$yw|5 zThMw15BxjWf2{KM)XtZ+e#N)ihlkxPe=5ymT9>@Ym%_LF}o z1XhCP`3E1A{iVoHA#|O|&5=w;=j*Qf`;{mBAK3={y-YS$`!0UmtrvzHBfR*s{z<0m zW>4C=%N98hZlUhwAl1X`rR)oL0&A`gv5X79??p_==g*n4$$8o5g9V<)F^u7v0Vv^n z1sp8{W@g6eWv2;A31Rhf5j?KJhITYfXWZsl^`7z`CFtnFrHUWiD?$pwU6|PQjs|7RA0o9ARk^9$f`u3&C|#Z3iYdh<0R`l2`)6+ z6tiDj@xO;Q5PDTYSxsx6n>bj+$JK8IPJ=U5#dIOS-zwyK?+t^V`zChdW|jpZuReE_ z)e~ywgFe!0q|jzsBn&(H*N`%AKpR@qM^|@qFai0};6mG_TvXjJ`;qZ{lGDZHScZk( z>pO+%icp)SaPJUwtIPo1BvGyP8E@~w2y}=^PnFJ$iHod^JH%j1>nXl<3f!nY9K$e` zq-?XYl)K`u*cVXM=`ym{N?z=dHQNR23M8uA-(vsA$6(xn+#B-yY!CB2@`Uz({}}w+ z0sni*39>rMC!Ay|1B@;al%T&xE(wCf+`3w>N)*LxZZZYi{5sqiVWgbNd>W*X?V}C- zjQ4F7e_uCUOHbtewQkq?m$*#@ZvWbu{4i$`aeKM8tc^ zL5!GL8gX}c+qNUtUIcps1S)%Gsx*MQLlQeoZz2y2OQb(A73Jc3`LmlQf0N{RTt;wa`6h|ljX1V7UugML=W5-STDbeWTiEMjPQ$({hn_s&NDXzs6?PLySp$?L`0ilH3vCUO{JS0Dp`z;Ry$6}R@1NdY7rxccbm$+;ApSe=2q!0 z()3$vYN0S$Cs)#-OBs{_2uFf}L4h$;7^2w20=l%5r9ui&pTEgg4U!FoCqyA6r2 zC5s72l}i*9y|KTjDE5gVlYe4I2gGZD)e`Py2gq7cK4at{bT~DSbQQ4Z4sl)kqXbbr zqvXtSqMrDdT2qt-%-HMoqeFEMsv~u)-NJ%Z*ipSJUm$)EJ+we|4*-Mi900K{K|e0; z1_j{X5)a%$+vM7;3j>skgrji92K1*Ip{SfM)=ob^E374JaF!C(cZ$R_E>Wv+?Iy9M z?@`#XDy#=z%3d9&)M=F8Xq5Zif%ldIT#wrlw(D_qOKo4wD(fyDHM5(wm1%7hy6euJ z%Edg!>Egs;ZC6%ktLFtyN0VvxN?*4C=*tOEw`{KQvS7;c514!FP98Nf#d#)+Y-wsl zP3N^-Pnk*{o(3~m=3DX$b76Clu=jMf9E?c^cbUk_h;zMF&EiVz*4I(rFoaHK7#5h0 zW7CQx+xhp}Ev+jw;SQ6P$QHINCxeF8_VX=F3&BWUd(|PVViKJl@-sYiUp@xLS2NuF z8W3JgUSQ&lUp@2E(7MG`sh4X!LQFa6;lInWqx}f#Q z4xhgK1%}b(Z*rZn=W{wBOe7YQ@1l|jQ|9ELiXx+}aZ(>{c7Ltv4d>PJf7f+qjRU8i%XZZFJkj&6D^s;!>`u%OwLa*V5Js9Y$b-mc!t@{C415$K38iVu zP7!{3Ff%i_e!^LzJWhBgQo=j5k<<($$b&%%Xm_f8RFC_(97&nk83KOy@I4k?(k<(6 zthO$3yl&0x!Pz#!79bv^?^85K5e7uS$ zJ33yka2VzOGUhQXeD{;?%?NTYmN3{b0|AMtr(@bCx+c=F)&_>PXgAG}4gwi>g82n> zL3DlhdL|*^WTmn;XPo62HhH-e*XIPSTF_h{#u=NY8$BUW=5@PD{P5n~g5XDg?Fzvb_u ziK&CJqod4srfY2T?+4x@)g9%3%*(Q2%YdCA3yM{s=+QD0&IM`8k8N&-6%iIL3kon> z0>p3BUe!lrz&_ZX2FiP%MeuQY-xVV%K?=bGPOM&XM0XRd7or< zy}jn_eEzuQ>t2fM9ict#ZNxD7HUycsq76IavfoNl$G1|t*qpUSX;YgpmJrr_8yOJ2 z(AwL;Ugi{gJ29@!G-mD82Z)46T`E+s86Qw|YSPO*OoooraA!8x_jQXYq5vUw!5f_x zubF$}lHjIWxFar8)tTg8z-FEz)a=xa`xL~^)jIdezZsg4%ePL$^`VN#c!c6`NHQ9QU zkC^<0f|Ksp45+YoX!Sv>+57q}Rwk*2)f{j8`d8Ctz^S~me>RSakEvxUa^Pd~qe#fb zN7rnAQc4u$*Y9p~li!Itp#iU=*D4>dvJ{Z~}kqAOBcL8ln3YjR{Sp!O`s=5yM zWRNP#;2K#+?I&?ZSLu)^z-|*$C}=0yi7&~vZE$s``IE^PY|dj^HcWI$9ZRm>3w(u` z-1%;;MJbzHFNd^!Ob!^PLO-xhhj@XrI81Y)x4@FdsI( za`o4Gy(`T$P?PB?s>o+eIOtuirMykbuAi65Y_UN1(?jTCy@J8Px`%;bcNmPm#Fr!= z5V!YViFJ!FBfEq>nJFk0^RAV1(7w+X`HRgP;nJHJdMa!}&vvduCMoslwHTes_I76|h>;(-9lbfGnt zoZomakOt759AuTX4b$)G8TzJ&m*BV8!vMs9#=e0tWa z%)84R=3?tfh72~=Rc;fXwj+x z+25xapYK@2@;}6)@8IL+F6iuJ_B{&A-0=U=U6WMbY>~ykVFp$XkH)f**b>TE5)shN z39E2L@JPCSl!?pkvFeh@6dCv9oE}|{GbbVM!XIgByN#md&tXy@>QscU0#z!I&X4;d z&B&ZA4lbrHJ!x4lCN4KC-)u#gT^cE{Xnhu`0RXVKn|j$vz8m}v^%*cQ{(h%FW8_8a zFM{$PirSI8@#*xg2T){A+EKX(eTC66Fb})w{vg%Vw)hvV-$tttI^V5wvU?a{(G}{G z@ob7Urk1@hDN&C$N!Nio9YrkiUC{5qA`KH*7CriaB;2~2Od>2l=WytBRl#~j`EYsj}jqK2xD*3 ztEUiPZzEJC??#Tj^?f)=sRXOJ_>5aO(|V#Yqro05p6)F$j5*wYr1zz|T4qz$0K(5! zr`6Pqd+)%a9Xq3aNKrY9843)O56F%=j_Yy_;|w8l&RU1+B4;pP*O_}X8!qD?IMiyT zLXBOOPg<*BZtT4LJ7DfyghK|_*mMP7a1>zS{8>?}#_XXaLoUBAz(Wi>$Q!L;oQ&cL z6O|T6%Dxq3E35$0g5areq9$2+R(911!Z9=wRPq-pju7DnN9LAfOu3%&onnfx^Px5( zT2^sU>Y)88F5#ATiVoS$jzC-M`vY8!{8#9O#3c&{7J1lo-rcNK7rlF0Zt*AKE(WN* z*o?Tv?Sdz<1v6gfCok8MG6Pzecx9?C zrQG5j^2{V556Hj=xTiU-seOCr2ni@b<&!j>GyHbv!&uBbHjH-U5Ai-UuXx0lcz$D7%=! z&zXD#Jqzro@R=hy8bv>D_CaOdqo6)vFjZldma5D+R;-)y1NGOFYqEr?h zd_mTwQ@K2veZTxh1aaV4F;YnaWA~|<8$p}-eFHashbWW6Dzj=3L=j-C5Ta`w-=QTw zA*k9!Ua~-?eC{Jc)xa;PzkUJ#$NfGJOfbiV^1au;`_Y8|{eJ(~W9pP9q?gLl5E6|e{xkT@s|Ac;yk01+twk_3nuk|lRu{7-zOjLAGe!)j?g+@-;wC_=NPIhk(W zfEpQrdRy z^Q$YBs%>$=So>PAMkrm%yc28YPi%&%=c!<}a=)sVCM51j+x#<2wz?2l&UGHhOv-iu z64x*^E1$55$wZou`E=qjP1MYz0xErcpMiNYM4+Qnb+V4MbM;*7vM_Yp^uXUuf`}-* z_2CnbQ);j5;Rz?7q)@cGmwE^P>4_u9;K|BFlOz_|c^1n~%>!uO#nA?5o4A>XLO{X2 z=8M%*n=IdnXQ}^+`DXRKM;3juVrXdgv79;E=ovQa^?d7wuw~nbu%%lsjUugE8HJ9zvZIM^nWvjLc-HKc2 zbj{paA}ub~4N4Vw5oY{wyop9SqPbWRq=i@Tbce`r?6e`?`iOoOF;~pRyJlKcIJf~G z)=BF$B>YF9>qV#dK^Ie#{0X(QPnOuu((_-u?(mxB7c9;LSS-DYJ8Wm4gz1&DPQ8;0 z=Wao(zb1RHXjwbu_Zv<=9njK28sS}WssjOL!3-E5>d17Lfnq0V$+IU84N z-4i$~!$V-%Ik;`Z3MOqYZdiZ^3nqqzIjLE+zpfQC+LlomQu-uNCStj%MsH(hsimN# z%l4vpJBs_2t7C)x@6*-k_2v0FOk<1nIRO3F{E?2DnS}w> z#%9Oa{`RB5FL5pKLkg59#x~)&I7GzfhiVC@LVFSmxZuiRUPVW*&2ToCGST0K`kRK) z02#c8W{o)w1|*YmjGSUO?`}ukX*rHIqGtFH#!5d1Jd}&%4Kc~Vz`S7_M;wtM|6PgI zNb-Dy-GI%dr3G3J?_yBX#NevuYzZgzZ!vN>$-aWOGXqX!3qzCIOzvA5PLC6GLIo|8 zQP^c)?NS29hPmk5WEP>cHV!6>u-2rR!tit#F6`_;%4{q^6){_CHGhvAs=1X8Fok+l zt&mk>{4ARXVvE-{^tCO?inl{)o}8(48az1o=+Y^r*AIe%0|{D_5_e>nUu`S%zR6|1 zu0$ov7c`pQEKr0sIIdm7hm{4K_s0V%M-_Mh;^A0*=$V9G1&lzvN9(98PEo=Zh$`Vj zXh?fZ;9$d!6sJRSjTkOhb7@jgSV^2MOgU^s2Z|w*e*@;4h?A8?;v8JaLPCoKP_1l- z=Jp0PYDf(d2Z`;O7mb6(_X_~z0O2yq?H`^c=h|8%gfywg#}wIyv&_uW{-e8e)YmGR zI0NNSDoJWa%0ztGzkwl>IYW*DesPRY?oH+ow^(>(47XUm^F`fAa0B~ja-ae$e>4-A z64lb_;|W0ppKI+ zxu2VLZzv4?Mr~mi?WlS-1L4a^5k+qb5#C)ktAYGUE1H?Vbg9qsRDHAvwJUN=w~AuT zUXYioFg2Dx-W)}w9VdFK#vpjoSc!WcvRZ_;TgHu;LSY*i7K_>Px{%C4-IL?6q?Qa_ zL7l=EEo|@X&$gX;fYP02qJF~LN9?E-OL2G(Fo4hW)G{`qnW zTIuc+-1VJvKgph0jAc(LzM);Pg$MPln?U|ek{_5nNJHfm-Y#ec+n#Yf_e>XfbLbN)eqHEDr0#?<;TskL5-0JGv|Ut{=$Xk8hlwbaMXdcI3GL zY-hykR{zX9liy$Z2F3!z346uu%9@-y6Gda`X2*ixlD_P@<}K?AoV?(%lM%* z(xNk=|A()443aGj)-~IDf3J+UA2p2lh6ei^pG*HL#SiThnIr5WZDXebI)F7X zGmP-3bH$i$+(IwqgbM7h%G5oJ@4{Z~qZ#Zs*k7eXJIqg;@0kAGV|b=F#hZs)2BYu1 zr8sj#Zd+Iu^G}|@-dR5S*U-;DqzkX3V0@q-k8&VHW?h0b0?tJ-Atqmg^J8iF7DP6k z)W{g?5~F*$5x?6W)3YKcrNu8%%(DglnzMx5rsU{#AD+WPpRBf``*<8F-x75D$$13U zcaNXYC0|;r&(F@!+E=%+;bFKwKAB$?6R%E_QG5Yn5xX#h+zeI-=mdXD5+D+lEuM`M ze+*G!zX^xbnA?~LnPI=D2`825Ax8rM()i*{G0gcV5MATV?<7mh+HDA7-f6nc@95st zzC_si${|&=$MUj@nLxl_HwEXb2PDH+V?vg zA^DJ%dn069O9TNK-jV}cQKh|$L4&Uh`?(z$}#d+{X zm&=KTJ$+KvLZv-1GaHJm{>v=zXW%NSDr8$0kSQx(DQ)6S?%sWSHUazXSEg_g3agt2@0nyD?A?B%9NYr(~CYX^&U#B4XwCg{%YMYo%e68HVJ7`9KR`mE*Wl7&5t71*R3F>*&hVIaZXaI;2a$?;{Ew{e3Hr1* zbf$&Fyhnrq7^hNC+0#%}n^U2{ma&eS)7cWH$bA@)m59rXlh96piJu@lcKl<>+!1#s zW#6L5Ov%lS(?d66-(n`A%UuiIqs|J|Ulq0RYq-m&RR0>wfA1?<34tI?MBI#a8lY{m z{F2m|A@=`DpZpwdIH#4)9$#H3zr4kn2OX!UE=r8FEUFAwq6VB?DJ8h59z$GXud$#+ zjneIq8uSi&rnG0IR8}UEn5OcZC?@-;$&Ry9hG{-1ta`8aAcOe1|82R7EH`$Qd3sf* zbrOk@G%H7R`j;hOosRVIP_2_-TuyB@rdj?(+k-qQwnhV3niH+CMl>ELX(;X3VzZVJ ztRais0C^L*lmaE(nmhvep+peCqr!#|F?iVagZcL>NKvMS_=*Yl%*OASDl3(mMOY9! z=_J$@nWpA-@><43m4olSQV8(PwhsO@+7#qs@0*1fDj70^UfQ(ORV0N?H{ceLX4<43 zEn)3CGoF&b{t2hbIz;Og+$+WiGf+x5mdWASEWIA*HQ9K9a?-Pf9f1gO6LanVTls)t z^f6_SD|>2Kx8mdQuiJwc_SmZOZP|wD7(_ti#0u=io|w~gq*Odv>@8JBblRCzMKK_4 zM-uO0Ud9>VD>J;zZzueo#+jbS7k#?W%`AF1@ZPI&q%}beZ|ThISf-ly)}HsCS~b^g zktgqOZ@~}1h&x50UQD~!xsW-$K~whDQNntLW=$oZDClUJeSr2$r3}94Wk1>co3beS zoY-7t{rGv|6T?5PNkY zj*XjF()ybvnVz5=BFnLO=+1*jG>E7F%&vm6up*QgyNcJJPD|pHoZ!H6?o3Eig0>-! zt^i-H@bJ;^!$6ZSH}@quF#RO)j>7A5kq4e+7gK=@g;POXcGV28Zv$jybL1J`g@wC# z_DW1ck}3+n@h2LFQhwVfaV@D+-kff4celZC0;0ef?pA#*PPd8Kk8sO1wza&BHQFblVU8P1=-qScHff^^fR zycH!hlHQs7iejITpc4UaBxzqTJ}Z#^lk{W(cr`qtW~Ap;HvuUf#MxgEG?tEU+B?G% znub0I(s@XvI(lva}$Z7<}Qg=rWd5n)}rX{nb+Aw;}?l9LZI-`N-*hts=c6XgjfJs ztp>-686v6ug{glEZ}K=jVG|N1WSWrU*&ue|4Q|O@;s0#L5P*U%Vx;)w7S0ZmLuvwA z@zs2Kut)n1K7qaywO#TbBR`Q~%mdr`V)D`|gN0!07C1!r3{+!PYf9*;h?;dE@#z(k z;o`g~<>P|Sy$ldHTUR3v=_X0Iw6F>3GllrFXVW?gU0q6|ocjd!glA)#f0G7i20ly>qxRljgfO2)RVpvmg#BSrN)GbGsrIb}9 z1t+r;Q>?MGLk#LI5*vR*C8?McB|=AoAjuDk&Pn`KQo z`!|mi{Cz@BGJ!TwMUUTkKXKNtS#OVNxfFI_Gfq3Kpw0`2AsJv9PZPq9x?~kNNR9BR zw#2jp%;FJNoOzW>tE#zskPICp>XSs?|B0E%DaJH)rtLA}$Y>?P+vEOvr#8=pylh zch;H3J`RE1{97O+1(1msdshZx$it^VfM$`-Gw>%NN`K|Tr$0}U`J?EBgR%bg=;et0 z_en)!x`~3so^V9-jffh3G*8Iy6sUq=uFq%=OkYvHaL~#3jHtr4sGM?&uY&U8N1G}QTMdqBM)#oLTLdKYOdOY%{5#Tgy$7QA! zWQmP!Wny$3YEm#Lt8TA^CUlTa{Cpp=x<{9W$A9fyKD0ApHfl__Dz4!HVVt(kseNzV z5Fb`|7Mo>YDTJ>g;7_MOpRi?kl>n(ydAf7~`Y6wBVEaxqK;l;}6x8(SD7}Tdhe2SR zncsdn&`eI}u}@^~_9(0^r!^wuKTKbs-MYjXy#-_#?F=@T*vUG@p4X+l^SgwF>TM}d zr2Ree{TP5x@ZtVcWd3++o|1`BCFK(ja-QP?zj6=ZOq)xf$CfSv{v;jCcNt4{r8f+m zz#dP|-~weHla%rsyYhB_&LHkwuj83RuCO0p;wyXsxW5o6{)zFAC~2%&NL? z=mA}szjHKsVSSnH#hM|C%;r0D$7)T`HQ1K5vZGOyUbgXjxD%4xbs$DAEz)-;iO?3& zXcyU*Z8zm?pP}w&9ot_5I;x#jIn^Joi5jBDOBP1)+p@G1U)pL6;SIO>Nhw?9St2UN zMedM(m(T6bNcPPD`%|9dvXAB&IS=W4?*7-tqldqALH=*UapL!4`2TM_{`W&pm*{?| z0DcsaTdGA%RN={Ikvaa&6p=Ux5ycM){F1OgOh(^Yk-T}a5zHH|=%Jk)S^vv9dY~`x zG+!=lsDjp!D}7o94RSQ-o_g#^CnBJlJ@?saH&+j0P+o=eKqrIApyR7ttQu*0 z1f;xPyH2--)F9uP2#Mw}OQhOFqXF#)W#BAxGP8?an<=JBiokg;21gKG_G8X!&Hv;7 zP9Vpzm#@;^-lf=6POs>UrGm-F>-! zm;3qp!Uw?VuXW~*Fw@LC)M%cvbe9!F(Oa^Y6~mb=8%$lg=?a0KcGtC$5y?`L5}*-j z7KcU8WT>2PpKx<58`m((l9^aYa3uP{PMb)nvu zgt;ia9=ZofxkrW7TfSrQf4(2juZRBgcE1m;WF{v1Fbm}zqsK^>sj=yN(x}v9#_{+C zR4r7abT2cS%Wz$RVt!wp;9U7FEW&>T>YAjpIm6ZSM4Q<{Gy+aN`Vb2_#Q5g@62uR_>II@eiHaay+JU$J=#>DY9jX*2A=&y8G%b zIY6gcJ@q)uWU^mSK$Q}?#Arq;HfChnkAOZ6^002J>fjPyPGz^D5p}o;h2VLNTI{HGg!obo3K!*I~a7)p-2Z3hCV_hnY?|6i`29b zoszLpkmch$mJeupLbt4_u-<3k;VivU+ww)a^ekoIRj4IW4S z{z%4_dfc&HAtm(o`d{CZ^AAIE5XCMvwQSlkzx3cLi?`4q8;iFTzuBAddTSWjfcZp* zn{@Am!pl&fv#k|kj86e$2%NK1G4kU=E~z9L^`@%2<%Dx%1TKk_hb-K>tq8A9bCDfW z@;Dc3KqLafkhN6414^46Hl8Tcv1+$q_sYjj%oHz)bsoGLEY1)ia5p=#eii(5AM|TW zA8=;pt?+U~>`|J(B85BKE0cB4n> zWrgZ)Rbu}^A=_oz65LfebZ(1xMjcj_g~eeoj74-Ex@v-q9`Q{J;M!mITVEfk6cn!u zn;Mj8C&3^8Kn%<`Di^~Y%Z$0pb`Q3TA}$TiOnRd`P1XM=>5)JN9tyf4O_z}-cN|i> zwpp9g`n%~CEa!;)nW@WUkF&<|wcWqfL35A}<`YRxV~$IpHnPQs2?+Fg3)wOHqqAA* zPv<6F6s)c^o%@YqS%P{tB%(Lxm`hsKv-Hb}MM3=U|HFgh8R-|-K(3m(eU$L@sg=uW zB$vAK`@>E`iM_rSo;Cr*?&wss@UXi19B9*0m3t3q^<)>L%4j(F85Ql$i^;{3UIP0c z*BFId*_mb>SC)d#(WM1%I}YiKoleKqQswkdhRt9%_dAnDaKM4IEJ|QK&BnQ@D;i-ame%MR5XbAfE0K1pcxt z{B5_&OhL2cx9@Sso@u2T56tE0KC`f4IXd_R3ymMZ%-!e^d}v`J?XC{nv1mAbaNJX| zXau+s`-`vAuf+&yi2bsd5%xdqyi&9o;h&fcO+W|XsKRFOD+pQw-p^pnwwYGu=hF7& z{cZj$O5I)4B1-dEuG*tU7wgYxNEhqAxH?p4Y1Naiu8Lt>FD%AxJ811`W5bveUp%*e z9H+S}!nLI;j$<*Dn~I*_H`zM^j;!rYf!Xf#X;UJW<0gic?y>NoFw}lBB6f#rl%t?k zm~}eCw{NR_%aosL*t$bmlf$u|U2hJ*_rTcTwgoi_N=wDhpimYnf5j!bj0lQ*Go`F& z6Wg+xRv55a(|?sCjOIshTEgM}2`dN-yV>)Wf$J58>lNVhjRagGZw?U9#2p!B5C3~Nc%S>p`H4PK z7vX@|Uo^*F4GXiFnMf4gwHB;Uk8X4TaLX4A>B&L?mw4&`XBnLCBrK2FYJLrA{*))0 z$*~X?2^Q0KS?Yp##T#ohH1B)y4P+rR7Ut^7(kCwS8QqgjP!aJ89dbv^XBbLhTO|=A z|3FNkH1{2Nh*j{p-58N=KA#6ZS}Ir&QWV0CU)a~{P%yhd-!ehF&~gkMh&Slo9gAT+ zM_&3ms;1Um8Uy0S|0r{{8xCB&Tg{@xotF!nU=YOpug~QlZRKR{DHGDuk(l{)d$1VD zj)3zgPeP%wb@6%$zYbD;Uhvy4(D|u{Q_R=fC+9z#sJ|I<$&j$|kkJiY?AY$ik9_|% z?Z;gOQG5I%{2{-*)Bk|Tia8n>TbrmjnK+8u*_cS%*;%>R|K|?urtIdgTM{&}Yn1;| zk`xq*Bn5HP5a`ANv`B$IKaqA4e-XC`sRn3Z{h!hN0=?x(kTP+fE1}-<3eL+QDFXN- z1JmcDt0|7lZN8sh^=$e;P*8;^33pN>?S7C0BqS)ow4{6ODm~%3018M6P^b~(Gos!k z2AYScAdQf36C)D`w&p}V89Lh1s88Dw@zd27Rv0iE7k#|U4jWDqoUP;-He5cd4V7Ql)4S+t>u9W;R-8#aee-Ct1{fPD+jv&zV(L&k z)!65@R->DB?K6Aml57?psj5r;%w9Vc3?zzGs&kTA>J9CmtMp^Wm#1a@cCG!L46h-j z8ZUL4#HSfW;2DHyGD|cXHNARk*{ql-J2W`9DMxzI0V*($9{tr|O3c;^)V4jwp^RvW z2wzIi`B8cYISb;V5lK}@xtm3NB;88)Kn}2fCH(WRH1l@3XaO7{R*Lc7{ZN1m+#&diI7_qzE z?BS+v<)xVMwt{IJ4yS2Q4(77II<>kqm$Jc3yWL42^gG6^Idg+y3)q$-(m2>E49-fV zyvsCzJ5EM4hyz1r#cOh5vgrzNGCBS}(Bupe`v6z{e z)cP*a8VCbRuhPp%BUwIRvj-$`3vrbp;V3wmAUt{?F z0OO?Mw`AS?y@>w%(pBO=0lohnxFWx`>Hs}V$j{XI2?}BtlvIl7!ZMZukDF7 z^6Rq2H*36KHxJ1xWm5uTy@%7;N0+|<>Up>MmxKhb;WbH1+=S94nOS-qN(IKDIw-yr zi`Ll^h%+%k`Yw?o3Z|ObJWtfO|AvPOc96m5AIw;4;USG|6jQKr#QP}+BLy*5%pnG2 zyN@VMHkD`(66oJ!GvsiA`UP;0kTmUST4|P>jTRfbf&Wii8~a`wMwVZoJ@waA{(t(V zwoc9l*4F>YUM8!aE1{?%{P4IM=;NUF|8YkmG0^Y_jTJtKClDV3D3~P7NSm7BO^r7& zWn!YrNc-ryEvhN$$!P%l$Y_P$s8E>cdAe3=@!Igo^0diL6`y}enr`+mQD;RC?w zb8}gXT!aC`%rdxx2_!`Qps&&w4i0F95>;6;NQ-ys;?j#Gt~HXzG^6j=Pv{3l1x{0( z4~&GNUEbH=9_^f@%o&BADqxb54EAq=8rKA~4~A!iDp9%eFHeA1L!Bb8Lz#kF(p#)X zn`CglEJ(+tr=h4bIIHlLkxP>exGw~{Oe3@L^zA)|Vx~2yNuPKtF^cV6X^5lw8hU*b zK-w6x4l&YWVB%0SmN{O|!`Sh6H45!7}oYPOc+a#a|n3f%G@eO)N>W!C|!FNXV3taFdpEK*A1TFGcRK zV$>xN%??ii7jx5D69O>W6O`$M)iQU7o!TPG*+>v6{TWI@p)Yg$;8+WyE9DVBMB=vnONSQ6k1v z;u&C4wZ_C`J-M0MV&MpOHuVWbq)2LZGR0&@A!4fZwTM^i;GaN?xA%0)q*g(F0PIB( zwGrCC#}vtILC_irDXI5{vuVO-(`&lf2Q4MvmXuU8G0+oVvzZp0Y)zf}Co0D+mUEZz zgwR+5y!d(V>s1} zji+mrd_6KG;$@Le2Ic&am6O+Rk1+QS?urB4$FQNyg2%9t%!*S5Ts{8j*&(H1+W;0~ z$frd%jJjlV;>bXD7!a-&!n52H^6Yp}2h3&v=}xyi>EXXZDtOIq@@&ljEJG{D`7Bjr zaibxip6B6Mf3t#-*Tn7p z96yx1Qv-&r3)4vg`)V~f8>>1_?E4&$bR~uR;$Nz=@U(-vyap|Jx zZ;6Ed+b#GXN+gN@ICTHx{=c@J|97TIPWs(_kjEIwZFHfc!rl8Ep-ZALBEZEr3^R-( z7ER1YXOgZ)&_=`WeHfWsWyzzF&a;AwTqzg~m1lOEJ0Su=C2<{pjK;{d#;E zr2~LgXN?ol2ua5Y*1)`(be0tpiFpKbRG+IK(`N?mIgdd9&e6vxzqxzaa`e7zKa3D_ zHi+c1`|720|dn(z4Qos^e7sn(PU%NYLv$&!|4kEse%DK;YAD06@XO3!EpKpz!^*?(?-Ip zC_Zlb(-_as+-D?0Ag9`|4?)bN)5o(J=&udAY|YgV(YuK9k=E>0z`$dSaL(wmxd!1f zME&3wwv@#{dgeMlZ4}GL!I`VZxtdQY$lmauCN_|mGXqEEj@i~du$|>5UvLjsbq!{; z@jEf;21iC1jFEmIPE^4gykHQzCMLj=2Ek4&FvlpqTlS(0YT%*W<>XgH$4ww`D`aihBGkPM(&EG};Cl&wzg8!jL z`rkqPzvH(0Kd{2n=?Bt8aAU&0IyiA+V-qnXVId^qG!SWZ7%_f&i!D{R#7Jo$%tICxY%j)ebORE>3H_c|to}c#HX;HAC?~B;2mmQrMp2;8T zmzde!k7BYg^Z1r|DUvSD3@{6S<1kndb%Qt%GA# z+sB2&F5L`R&fLRdAlpU_pVsJsYDEz{^ zKGaAz#%W+MPGT+D$+xowMY0=ipM)0p?zym&Aoi)qL(pO_weO(k?s|ELHl^W zviJiFUXRL&?`;3_;mvc02A@sbsW9}#{anvGafZ#ST;}za?XS3}ZG3B4m(SW{>w}Fh z)T5Yi*``Tstmi9SHXmuWSND@cj}qtY!`tuD29Dpu+-D3$h<5FY>jE>YJvqBmhw?oll`x7Ono(}R~P zle_eBwYy0Rr7kmf_SEt_gn4)AO-r`}^Z5Y%Rm8)K-?X>rvDL+QT?#)QwDsQ2c$tc* z&#hbgkL6}GnBDH;+lREM6MGIskRa@r>5Iq(ll2IepuhW86w@14=E{6$cz*cBDQ)CT>}v-DLM-v8)xaPBnmGBKM63RgDGqh!<*j90tSE4|G^+r@#-7g2 zs8KE8eZPZhQuN>wBU%8CmkE9LH1%O;-*ty0&K~01>F3XB>6sAm*m3535)9T&Fz}A4 zwGjZYVea@Fesd=Rv?ROE#q=}yfvQEP8*4zoEw4@^Qvw54utUfaR1T6gLmq?c9sON> z>Np6|0hdP_VURy81;`8{ZYS)EpU9-3;huFq)N3r{yP1ZBCHH7=b?Ig6OFK~%!GwtQ z3`RLKe8O&%^V`x=J4%^Oqg4ZN9rW`UQN^rslcr_Utzd-@u-Sm{rphS-y}{k41)Y4E zfzu}IC=J0JmRCV6a3E38nWl1G495grsDDc^H0Fn%^E0FZ=CSHB4iG<6jW1dY`2gUr zF>nB!y@2%rouAUe9m0VQIg$KtA~k^(f{C*Af_tOl=>vz>$>7qh+fPrSD0YVUnTt)? z;@1E0a*#AT{?oUs#bol@SPm0U5g<`AEF^=b-~&4Er)MsNnPsLb^;fL2kwp|$dwiE3 zNc5VDOQ%Q8j*d5vY##)PGXx51s8`0}2_X9u&r(k?s7|AgtW0LYbtlh!KJ;C9QZuz< zq>??uxAI1YP|JpN$+{X=97Cdu^mkwlB={`aUp+Uyu1P139=t%pSVKo7ZGi_v(0z>l zHLGxV%0w&#xvev)KCQ{7GC$nc3H?1VOsYGgjTK;Px(;o0`lerxB<+EJX9G9f8b+)VJdm(Ia)xjD&5ZL45Np?9 zB%oU;z05XN7zt{Q!#R~gcV^5~Y^gn+Lbad7C{UDX2Nznj8e{)TLH|zEc|{a#idm@z z6(zon+{a>FopmQsCXIs*4-dLGgTc)iOhO3r=l?imNUR-pWl!ktO0r_a0Nqo@bu8MzyjSq9zkqPe*`Sxz75rZ zr9X%(=PVqCRB=zfX+_u&*k4#s1k4OV11YgkCrlr6V;vz<{99HKC@qQ+H8xv5)sc63 z69;U4O&{fb5(fN``jJH#3=GHsV56@{d@7`VhA$K^;GU+R-V%%cnmjYs?>c5^6Ugv} zn<}L&i;2`zzW@(kxf$$gVH@7nh}2%G%ciQ_B?r{13?Q@=Q+6msQGtnyY%Gkjeor?g z7F*tMqLdhcq+LCCo^D;CtOACCBhXgK-M&w{*dcUdmtv@XFTofmmpcWKtCn^`#?oZC zUOm52 z7sK$hR|Vh6y&pfIUK&!`8HH*>12$nWA)Ynp+XwOj=jNLD z{QA4gezbe>wiP?`jJO;c&EId;=2u80s_r97;TX!6@*(<%WL+^bmxheMB3pKx0OpH^ zPs}knV+jpJ4TaD@r^V`mTsjf`7!z^H}eHQ#Rp z72(>Dm#QO!ZYR*O@yHic`3*T^t7jc=d`Jz6Lk@Y-bL%cOp_~=#xzIJl?`{Qu;$uC~NkePE+7wSW_FM`&V{gFN zl;lq@;FtAsl!h;tnOvj z#gYx!q$5MdZ0Jxjy=t*q)HFeeyI-vgaGdh1QNhqGRy8qS)|6S0QK7Gj9R?Co{Knh> za>xkQZ0}bBx!9@EUxRBYGm25^G}&j-`0VWX04E|J!kJ8^WoZ(jbhU_twFwWIH32fv zi=pg~(b#ajW=`)Vikwwe39lpML?|sY$?*6*kYBxku_<=#$gfTqQ_F!9F0=OkHnzBo zEwR!H_h|MNjuG$Tj6zaaouO}HYWCF8vN4C%EX-%Iu%ho;q$G#ErnafhXR*4J2Rp5* zhsi0;wlSwE*inVFO>{(8?N~82zijpt+9Y_-^>xnE%T*zk9gi|j7b@s<5{|qEquUD( zS;-%RySZOCOEh*>!kvbsQ265* z>X8*_Wy&~FB@aDHz%glyiAujXq-|2kDUjFTn9Rafsl+XNyFP%PG|l&ZGWBcEXxy=9 zeDn2PIoVuL$gX0RgVK1O$x3%pOzS7x^U5Pi;mtT)%cY;&e&M7GLM}zP+IPbqLt=^5 z7qLfri8myf;~2psc@^cA6mG&{C%e_(M$$!wC^5p^T1QzrS%I?(U{qcd+oJJkQxe10 zON{Q*?iz%F4MbEsoEc+x3E?&2wVR^v3|Q0lDaMvgS7mNjI{2w! z9|~=!83T%GW*iaChSS!`Xd^beFp9N4%K+k*j#jFumk}U?=WKL_kJAltxnxp~+lZzT zp@&&kSPTg3oSGos`rVBhK0|4NdHM_hnKuw1#0JV{gi_dKDJLB+ix~~HpU9%jD)@YY zOK)L7kgbLyN2%Dx#fuY}8swh4ACk7%BpP-n5(RhDq{gEHP*Fo4IviX{C49|B5h~SC zFr`=0)=h2^F5UpCAgt?R5u{6VvpUf#*nC zCQ`$!|C;L2lpjlG?(>T$(_$O3_YNNbPT~(?!j3aD8k=yu^ogw4bkjvgF|3BOq(hB& zG;^cPXmcUP$ox8zElCJ-zMbK9q^8{rri#8Cek5Ydr0YT-KTh@J z6^AcB9ejew8BY5kzZUZX(7Po==eW<(;uV~E7(BY5c0^xr`cuRwn)47bN?zOb!0?cw z#v}R$z66&m#+AHfo@(^V2#S~bhoUkkTArg+6w>JzZ52r96^({1W!?>4$h0l|-jDfj z>7(<+%67#(A|4hZ3>Y;hd&S?}F;`Vtqz|pK&B>NJ=Faci;gkf-+GmfQR8^zo_vul2 zB!)kfu4Dq_g)8TBBo52*sB6F`qa&JCR=_A$QWgX_K}fZm{Cb2#1q`^S3+WaS>sS#@ z-4k*G=#?z6d_e7JJ+Z8^(t0tNdL{K5F;2nfQbXgld}a(X)Gr;WojOy`^?es~AClT$ z5^lD{WJek0!p-QEH5E7n6DKQ0%_ZBZ=|jfV_MM{VmL8y-Wd|>OmeemP=C@xI@@M~1 zW2S*im@Rc=O>V886_UJ@oh1!2H$Ku&U*Hh_oxd{32)vf1$cRiepv28ricM;}#p!+k zaK{z1I=9Y%3m4|Pj*BD*Fn5Vh?O@oD^1UcjyeNh0fbhh~V6xb#4njlGW8OehUe!MnoR(wn#nsoyL1m!Rov)Nv4~&JEVl7L z#^qYdTpNI#u`N0UbVMiDmD>g2VQcG3>4D6gErgddZnSQTs){BExxRJRB?bIxTdZa z;!S8FHJPPiIDQ*FAUiWSYnjILFjDvxvSC zk z=j4Kx@Pg~&2Z?cmMDa;)#xVeorJrxDBqy{+`kG+ZPQqC@#ku-c3ucU+69$#q_*se` z-H#PFW^>-C0>++|6r=<$Z8)ZFaK=ZjwsNYXqRpl9G|yme@Eld5B-*I69Nx_TResHi z!5nm+>6zaJYQO#%D{~o-oOJ;q`fa5}l!8G*U-E$OM&7@dqciBCWtd}|SrDXz$TB($&m*=Epuolu2k`KUwO7maP3P0ok zmF57lSh0Ba@&sO1iZ5^+3s8{B8t|M;Pg&O+{tZJCiLWd6H@{b~9{CLF9s3Kn zt5)Rs9ejne?o{%f>B$Dl%X7fd~KY)I|(pxUeHj;gNsK6;ZR>`ciu;GxvhDUt!+31Knss2U(%ts8K z18)8;<2ax9RG?!|Lwdt^i5L^&O788roKmVAB)=EdK~HqR2Q=)H_VW}xY=95MP_Ov< zPEz3%DRK}+(aUBwsr83H8>`H^v~|A_t}0vPmRwKPt1{|qOY|PZu}j9+{ZhF&-H_TB zU9xWLpNTc`enI|)h9jQeqf5RfGLFk_vfX`40iMpd%KZF!lKbZTdBw$<^G6nuS+$fT zrbK)xo&;buPJcpOZ=x>n+bRXVFDs(23Xr=rDE&!)pVXZ;;A07NXGl_0m`{Z)DQIu$ zFDvY4xu-ifTe_$|n2B83eI;KUg6pVbw+N!nyLj~wnRi{4mNy{WDV)G1!6$y=+x6U{ z%4_9=Q^L!x_gAYp?J3+u5hA5cO8aHeI=6AC8^S{mzhqCBvBLYEutUC(X0>hKg|AvN zvkmJCQNA45_KjW{aEcyrBppcO6G0zTy%v1&@~+2!n?kA9?>0>AjFN|JdCnHQ8$hEU zw#mwGifHppLP?89LMb(Y3Li9iCPx7W%ek}2FgD2YSzjsR4Xj<=zN{Yo@7s7(k%mP4 znT2p&4EQ@q_chd-E z78uvD*C@oba`U3W2Iw`M#`5C8jOHv8^Li<|j^SI>>>`77Dp71Vtz=J?4Zck4SdRbd zfF}C_>Y(#)r@y!Q0`tMlG#b9>5`fAI$B&tWJfbGlYW$J4V+-s=HH!`+;1XeL@USdx zR0$G&&XBf9lQtkH5)p=U!8J!1{oc4E!N-~Abxl6E;;=3-hMYZ+44?u}zabmCE)yB?*_w91m$n1Yskp&@ z;kxeJX-#ioX^{elyLu~gzx|_KxLpX62MF%Axq3$!Z_P`pBWR?zP8OI`PV~6Aa0Oi0 zv_Ot1m&plf-ZF{e(z(Ms3*S5q$e|j;gOwGrmWsCHfLi(h8y?gc$(2H{884C1FvHQQ12tX=qFUsK~zM!W=K>;zaRsu4Xmcc@8nSs!vK+{ z?}bq}-m&p5jRSam67n>yG9ez=I^|J1O;Np8s=P~9MXYLxD+cFQK7PhG=bkjo{Naae zjp3NWWrlFWDb3Z5D07Q|WjZ=wOQ=aKA%en=O@hL$QCKpIXNZE=InFk|Fhq-&H!6&X z*MVy8=hL7Aw&pQjHrFf27C%3B<>FX{@fOLNhUoxL4*@nY}&M3G*T-p67a zo}~_&yGOB)#vbU|Q3FA8S^X)c-yBlmN(_%}`7Ha3uWFe?>9f=3hlO{^gv~$p`v?vk z_P*r43|(S{%ihs;)YH|jAMpP=-Ms7Ne75_YZZiL3CHVjSU`X1|?Ehh&gA=Xn7W7d@ zf8bM9Y>lG!`PWFDDA9G;x*{1Eh^55u66*9D+-4^dYZ{xXP@?sQLVrY%(azM;C^4FuN7CQ%$!3sr1JL=!Be& zuOZL^bLp$Qo2rL=WDzQIls%s!Go z{s}Q0b#+#8bKga|01t%^9Z=wEsevvXM_{$dCR97ed3@1kX)mtSS!JN^rtqKOj}p~> zfpCI@DX*DqcB6ZnBcl~}sGO~1s$AtfkX6fy3N8*ebvZc*KBW;dA=)?#BE&}-or74i zZUt5;{FBPnkZD8YUXDsx&2LvSziAlec3oc>&Lf1Doc3g?H9{OO_$M4B0qTat0UsWP zTlxUeQ3B;oJ%en4n?zQB6*Fb#wH7`$SQN5GI|=DnJKiYm{?-?#-H;#sIjz7kQ4&VW zN9d1(1$_W~S=<%qDD!mwRytas=eqX^iW}YSx3;wJ#)Xp_`Qk1DFiXac$-3;jQbCif zLA-T_s~5yP@Q@W>pXKl^gipQ>gp@HlBB>WDVpW199;V%?N1`U$ovLE;NI2?|_q2~5 zlg>xT9NADWkv5-*FjS~nP^7$k!N2z?dr!)&l0+4xDK7=-6Rkd$+_^`{bVx!5LgC#N z-dv-k@OlYCEvBfcr1*RsNwcV?QT0bm(q-IyJJ$hm2~mq{6zIn!D20k5)fe(+iM6DJ ze-w_*F|c%@)HREgpRrl@W5;_J5vB4c?UW8~%o0)(A4`%-yNk1(H z5CGuzH(uHQ`&j+IRmTOKoJ?#Ct$+1grR|IitpDGt!~ZdqSJ?cOtw-R=EQ+q4UvclH zdX=xlK-fhQKoKCPBoFAZ*(~11O6-tXo>i0w!T$u{lg!#itEUX3V{$S*naW!C@%rll zS{L(1t%xz(*B`{1NL!*aMc<~fE=g;gXi&Gb$HpD!P)8?JzfN;4F&wv(5HH<=c>>)n z({271)xREH89=C(5YKL{mmJJ_d>qHz;;gTvTlgM*vz9@YTTYZ#%_2A zS0G-t9oMQEpvfv(UjfQ8T$vAHi)zOj3>D*{xSRiu3acc=7cvLyD?_ZObdu$5@b*!y zaZ#u?7uF}SrHVQa=sTOhGW{6WUlq#RhPPm^GsRH#qlX8{Kq-i~98l;eq>KdCnWyKl zUu&UWBqu#Tt9jQ97U4}3)&(p2-eCLznXMEm!>i^EMpeVzPg%p;?@O;dJBQQY(vV;d z3v+-3oTPC!2LTUAx^S2t{v;S_h(EZ^0_dS5g^F*m{TEIy^Qal~%mu3h7*o`jWOH}i ztv8M)3X3a*+ry_KkYXYE4dB0?M|t}#Tp+(}6CQ zBbq;xhoHj}b@j-@koDB#XcCY~>_x&Y;i%MH|3tF^X2h{36UCVfQ-;oEA+4ZkJ`^Qi zQf^8}6eFO$Z+Dj-F1wkG##tTx>FjR2oOXFmbKFj6K3+=kePQ<4d7%z5R5cOB;zO6| zm9^m#U4lcA;7t&*=q|a-!`!)}SgYXT#i8hnxtx@kaoBF$QAS-hT7N5kH^l zB^i+})V>L;9_0Qqf-dyF%ky8Mp-dp#%!Nls3vCt}q3QLM3M-(Zs1k}1bqQ9PVU)U` ztE=?;^6=x}_VD%N@${>qhpkU*)AuUBu_cqYiY&@;O$HV*z@~#Tzh?#=CK`=KwBv+o zh%zu%0xPKYtyC)DaQ zpDW}*86g%>BH3IcWMq`g$j()0kWE(qkIL8A&A0mf&+BzxpKF}=`#jG% z&*wa!&pGFLs5_b#QTZE4Bp+})qzyPQ7B4Z7Y*&?0PSX&|FIR;WBP1|coF9ZeP*$9w z!6aJ_3%Sh=HY3FAt8V144|yfu}IAyYHr1OYKIZ51F>_uY^%N#!k~eU53at-_E-Gh?ahmM5y* z+BTIbeH;%v1}Cjo{8d%UeSMWg(nphxEU`sL< zQR~LrTq>Da(FqSP2%&^1ZL#DTo5Sbl9;&57tQ-@U&I#lj)aNSkcfEJwQD!33?anVU z?pw2q7WtMvfji493`rSFnyp7{w87cW`ak=UEYlk5PCB1K6UDVKXyozOChH4yHh~Q< zv>yvKw6WLfi!PZUx60JZcTNM7jo{ww9b8Q+S7C3WA5&llSwdwh$=Q(*(f3ofqcz=nwOmOy z(J!K=*wNoRU*${{Mbwapi9pTB(&VVKefqd-qrUb9*Eyr2E@oZ9Cgf}Mc;QP<0D)R4 zz=!*^VIG4T*7Xl=sJxrWv9hW^eJ%qYp5(d0?E6LZzJ}=7E+1{?GQA;z+!^VBD81}O z0kJ^dKy&WMw+1+aGVYY-v@i28@Gm+sX5=@U%F=Z?W)oar}2~Rc&F|+3A)n-U2GF10+QdxDb^iA@7eL$c7yhBtL z>lABrh^qy9XZ${E1}Ss5!N4;ig0-pUh6@|RPCHOWvgG{|l}2enRgJftsN%D|ck0YO zuAQd2aMPSyGuJ~jm)aY=+p~mGudw4erwE%P^)5f<*$$2C-4^I=e8-}7##ZQ!8!Tep z+Z_!}CAI~sry$|XK$ktXaxP*x<_ijCPp`2=6sNLZU<@9Sz-rz7^BCE9yh0jV4(I!Z zxmA4d;>B-!vD}Xp*&*N%`b^e&R;D97WS}{~{O-EtXeZNfdf51tw!WR6Noo4hjHPv5 z?heYYRSBPjMc}tFEU^|U8a1CxxK%)WTcn9P%`wR^I$QSeMn6=w>Z9OoVvcrl`zYlZ z2y`mAu0bV(Scc>G_EmIo_4 zm*~h`mxYZC&+U>C5G1FZH5L^U>Cq-9UDRQa35jz&NBj*0{uJKfZs5=Fn@&)Xh6aX(H3w9m9BGLePqVotxTeSPh5-mc7$# z-80t6yB0$Nx<54ohdO*QL7m_(&+#*=eoNiYDB4rE4Cag@qfyZS};Fx;Vf1;oync2k z9v#-w?d6R& zOI`CCS_d=tf3|?g3Z}b6-_Rdg3y~enQhmgkni0Cvf9m6%Ft8r;NC5|b%t&?lkl*4{ z8Ui^;Ds^gq6ti(1xB7y_$zA!i-M~#!!tl$ErTR>P~>T=Yky)8(uvPbvLmB=UfoD zrfl}8<1OQrm?8#j1!?s*T>AoectQl&m!o&*^JcIW`_&bk3tN}k^0rjl=HL$z*uIYt z?7l?^Dqr?q1210Sp$xoAy!&{2^{^Anl460 zI&7urrc&|Y{rjv04VOl{y7c82N6xzg5ueYmQ(q(zC3w_C#x*~%yf5j7MI{W`tsoxzA*PrmK)cTskU| zf2C}Bq$>S$-1JgIh0aW@LxI|-8(OGuD#^M01ghh}&#ObO>tZgSw_LW`zdf&IN$YO# z)|X_9m#JwLW5pErZB3ScggKcNzxA9(hyKkK9I#pR&79&*+SV_eu={00{HF=Bb+AEe znaSof+r1jZ!EL5XgqXWkckaFSSyEk}o!%p8XsD}O>borZ6x%X2b&q!s&1-O(>`kZ$ zB2l^5Cx9xQx9)PXN1xPM)@+LxACH_iZ8zGc(>wnFS_O|@hKsxpMjXOzLEa7OvSlM&&G9ioQw9~RsD4F zK7Q+_&|Q6{eZ^8Rx@pKL`le6kH+(fLc{=V&{b%I5=n}VHV4)X_2Y!pYxgC8wU)yP! zPF3t$?(jsC>Ge=&{kmPGUEETpaw(QTAl)m#{qR3_aq9!wK%6XHfV4C>Y^>Z|%ns7j z{Ja?^IA{+@;kR#IjHxkar%3$eJT4?xNBKUVmoO z`A8Zo-{~_;vcikZ(p}EZzU4kO6WPqkMyE{VvS?;44Z@lj zz^fKX9UL!8Wc(9VgI?P4*zpis8dzl};I>yr1>dtXU=FTAlx}Eht4-*7RACL^AflGh zyZb1hTf(~CkMo%#Q%NMgM9tE2D+)joqbtHYA89Ql1nqVTt+MxZ^*FRd&n5YlIi!8m z>$Ysd!l{+C)y;Wa(ZV-=<+NZKV;v4mt}v2m>`v$-$3b;GsLxf= zd~f(rmfpl``{0aVwN7y!>eGyJFP`L+TxHjHTOS{K^$L2`@6(Rli`{EFwpH@R%eZ6g zwf7rc43Yk!=k;{ z-Rn%~B3amGr}}SxfE$vS8FIPL=Qt57$|R#sSoFgdNUT?fYOYjPl%ZBFpi=jq=DWby7Zxm@y;B<89!9= zbgEH*Uy)~iq5kJLX$+ps$kV`#6jW#|9BGz^`ivNeid(wVbk4jl)VBpW&~;eXNi{#` zwx?{DXR~*sqQcFhY0XCfQ4-*2aN1BGX>$_swtKEqnd>j6vcZ!#0)pXRi?<{!P?tGw z2x_`RD$W)qD{?z}VDPt?+)8*rqLWFIPQ(9-VbBdf{7ff?w9CZ{sIi_gnuC$I0(+P8 zms9XB%}VQ>>pve##}jog6+cD?v~n4Pa9Vmc zg#K$|+`adO=B7`uj35Y}6EZ z{dY`x@w8;R-7zrsr1O_~Jvl*|o-x%jF=Rr1C}GXP^|IYN`1sqmG-oI@R#%X66c#5W z$$tQB)sqwiVm;Y^`Dw3mo|firP{*HsOQJre5%Dm^H@we0FN88VWJ0dja?_U38z73f zrCV!b3qNP0kM#%9T!W5`ynGcg%BL28FW1J-J1_S`BJGCaReQ!am(2%qZ3lLgzq|ns z!!fF@`0=*z)J2BwZ*hO|Yu^cI_nF$9l-Pb3jE7=P8gZ#!xiuZ7-cSa`gb`6mxGTgg z-DLdID?M!Z%+hHB#{?&0$GFRpf+_}q<_wbzX6K?w;%6szz1RbySDSr2r^h_qi$khs zXdZ9A0!_Bf)TR2-^-K~q`FQ!#1x(U4VbV%AA@Ei{%cA(EwC{XfjRi?`&9rav5;Q5% zO1`Rn@OA_ZB@N*mC#)?d3P!}Eh;=NgpIKsy{(yr`hv=aouwt@r&P&}Z3DNWo9ro30 zX52~(aTV$*HHlgB66-4GQru!_AZ|)V*I5X=WG)`N@U&D>e@@C#V@JwEL*L`7#$yes z62C^5%Qniaow2$3HrAc7U{qzpb&FA*xLI1JSWR@`RF=JCcvTI)%dH7;sWInt9JLu# z|Ao|Q?K)cDg_JKsym=joo5gR80wtv01N`um1nQ@Ms0Y*bVzxL34} zo?gizp?`=Y{*W>^Hy2%Jl)y?A+&7s1UVHFixuIy~sawXjcDCL`129cK7|ZQS0u;A} zTJC#WNmqkIrnHpAhHVcM(U^vJA~dl@jf_bs*3?i+=&vuC?Aiy_pcB~=1syDni4 zw+FLuz>F773u#$;NUQ9WDtUPY@+rA3WBhQdKFKOyzkA(URa7;4tW>3jQIfi8v0h3g zJC_HVDXS#>DWb|&se7FHnr=q&l#xg9o02}}u=b-R>@sw={Z zHF*?t2FmhqZ=|qa>x=A!*$S+0T zhO*D*M?NTf-eX`eO)9TIQu{7Dm77Acnj4b1jI9@c*ZL8wL%8kLEhd$KM8=Y!fbN@9 zC7B5#y>JM1n5M)!&im==EgHs2j+xCZG~+~QWCi?s!QyFo2kqx{%jE2n3^N*Ayz6Lp zhg5g^3# z+5FoJ@$u@9WJgPKpUWEd4}4AK9TJKU8W%ms!d0p%OIOX+bY+55zl!vIaz$XFI9Ep+ z;bL_}7PDI2Y`Ng*XY(65 zh0%`@Lve%fc;)N4_g12bNrt6gH=N#OHtxO`$lpWlw=Z6MF+E@;>GkZ#lAZTn`aHwf z&I1|aV#b_VHMIgBN*RzU9i@Z@m}0i>o?({&%fpEfaOpFeaJ7V37;m0?kzd}}Lk@9$ zL}8TEo7WZAcRi%zFZxkr6<0k#X-;lTD`Oc~cDb@olwgWCewvk{GJ}hCXbF!AdiLpd z|Cck$ZTKI?Ack{34Lva7+k=H8K2HTZiurox6F+>dy+@R9T^awxj590D$|kXUg+Ygc z(f)jlRwN(4z$#%PnOVc;#Fv{nAi{#UcXPNcmP#5O{zh_*`=q^JCeia{sN4zHjk2*y zqUVh{Ya{j>SPmP^i#Qfcq_MTqo8g52Fi^F zKBc$$HVI!xFx*4Y9l+nt)$AoZORD}%5I10oI3kx`-N30QueiwIw#0VV2E*Fb-nKW% z=+r^hos`Y-7~{cA1FVbK$_=~*z53+Q8KGjg;>ztg((H12%QTf4OYU8y)C}h5yo#$% z&Q$`vMM*g?ZcatAn2j!hFv8KuN(dw)T*}sF#THDHxo8xC^?vJ zc`U6bVo~hOr6I!8*GTZ<^D~;unKjK=!IR|GB4E>Mcvt*2GK);93jIDd<(nNjHO z4Hi@2^%Uyx=^Z~5eZ!5rO5%4H|eFoNjD#+Kcu%_57zZb4Z@Ak#X6txD^{U3wBl^r+W- zLorkK;uc;NgTj7dGxHQS+@T*T>Q*j4^Ll$ejQqWrwcHyG9y%Mk%m8nBVG5hvSaYm5 zJN^#-Q46kZG)@T8n2^QCjxIwxUVi%s>EY`E?#@_(A~njFrTiDq;8v|W-1jT|ROlNI zU$h|YoD4PVTE^&NC6_m{EAFBVqsM`P*`-AcDGWQygURzM32Xeq2xng~XQsYeTZ5v$ zQLaa2M_Iplw}4eL6fLPu`6`PYcVMysO>`{8CB~glD=TX7?JZcHfHNmykBM?QD)#D) zGp>R*<^D?WhFQKRc^}22l6F=D2RPrxaX2ZF!b1X0XF*d4%=!sbNcS1q2WOUE(7e4$ z^L8f;F)__d3>&KQFE8%$I4h^y5FYBfB&fWzn71_OSrPe-DHV{O#Q;GP z+Tw!J?eVjX19RKH?*hKQWQt8r7B#lYX8xoSHFGCW-*DSQ4EM4M3Mw%gkSYNK18@(e zfzMF}WWaCyS@1y%-~Xg0ry~tkQkUmKuI5lGAua{{vn22V!2T()AU5FpKh@Nv)s^Js zv~@VuUG;=CnLmQR{PeUBQf2;lAV!vG>^Z0N zL88rrjL-*J!43;7C=w9xhcw`yjRKq7o4L9=0SmR9PA-nX12@#h(iIu-0N_xm2OV)( zU_raT0y>$wm^oMi2|U3N;OhF9uy}`<-xVka#DV*l{O0yHzi9vUxa1Qtpi$buR*8cU zd4~lS1pT$L^!0=6qUKOpM+XPsy{f7W#1bjrEwaeN!Ik9(zySIT^pEHvHgJUneFN4) zk=k|$55(g8slmS|@+*4fr2urd3LwjIIZA**g+%l(SZNn4HwQ}y6o`vw>2&mR1X+&q zDa1Af0B;4rAMZMOlHbAqK|R_xuwJ7ANARtFE({-P2o{tJJR<>2KVp)ZK-M;)ejx zd*E~Mka<{OL7%CAhk4n|1qg?97-I!l0rOinjVi#arbgg4bi5;nY5oFL`UWtPk5&L#grSxv zE3!}=1px!ZTLT90aYc^s`~{VojjJml&<`@e41dFP+XU6D0AOkbn2rlI3>^LcqauG& zc$m3Z{!u8LvUrm^fT{qX5yD9{?r(CCiUdck%!T`KIZd2oQJz1joB&M(Teg_>;yS<2-5>BWfSPpG`Rt{!j6>kqMAvl^zk0JUEfy$HVJMkxP-GkwZuxL62me2#pj_5*ZIU zP~#C^OZLfl$HO)v;~~c&JHivn|1I9H5y_CDkt0JLLGKm(4*KLVhJ2jh2#vJuM6`b& zE==-lvME^Oj022xF&IV*? '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/examples/powertools-examples-core-utilities/gradle/gradlew.bat b/examples/powertools-examples-core-utilities/gradle/gradlew.bat new file mode 100644 index 000000000..93e3f59f1 --- /dev/null +++ b/examples/powertools-examples-core-utilities/gradle/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java new file mode 100644 index 000000000..fccc63b9a --- /dev/null +++ b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java @@ -0,0 +1,107 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; +import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; +import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.tracing.CaptureMode; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.tracing.TracingUtils; + +/** + * Handler for requests to Lambda function. + */ +public class App implements RequestHandler { + private final static Logger log = LogManager.getLogger(App.class); + + @Logging(logEvent = true, samplingRate = 0.7) + @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + Map headers = new HashMap<>(); + + headers.put("Content-Type", "application/json"); + headers.put("X-Custom-Header", "application/json"); + + metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + + withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> + { + metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); + metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); + }); + + LoggingUtils.appendKey("test", "willBeLogged"); + + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() + .withHeaders(headers); + try { + final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); + log.info(pageContents); + TracingUtils.putAnnotation("Test", "New"); + String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); + + TracingUtils.withSubsegment("loggingResponse", subsegment -> + { + String sampled = "log something out"; + log.info(sampled); + log.info(output); + }); + + log.info("After output"); + return response + .withStatusCode(200) + .withBody(output); + } catch (RuntimeException | IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + @Tracing + private void log() { + log.info("inside threaded logging for function"); + } + + @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + putMetadata("getPageContents", address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java new file mode 100644 index 000000000..401ef8c48 --- /dev/null +++ b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.Metrics; + +public class AppStream implements RequestStreamHandler { + private static final ObjectMapper mapper = new ObjectMapper(); + + @Override + @Logging(logEvent = true) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { + Map map = mapper.readValue(input, Map.class); + + System.out.println(map.size()); + } +} diff --git a/examples/powertools-examples-core-utilities/gradle/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core-utilities/gradle/src/test/java/helloworld/AppTest.java new file mode 100644 index 000000000..af3ec1275 --- /dev/null +++ b/examples/powertools-examples-core-utilities/gradle/src/test/java/helloworld/AppTest.java @@ -0,0 +1,24 @@ +package helloworld; + +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class AppTest { + @Test + public void successfulResponse() { + App app = new App(); + APIGatewayProxyResponseEvent result = app.handleRequest(null, null); + assertEquals(200, result.getStatusCode().intValue()); + assertEquals("application/json", result.getHeaders().get("Content-Type")); + String content = result.getBody(); + assertNotNull(content); + assertTrue(content.contains("\"message\"")); + assertTrue(content.contains("\"hello world\"")); + assertTrue(content.contains("\"location\"")); + } +} diff --git a/examples/powertools-examples-core-utilities/gradle/template.yaml b/examples/powertools-examples-core-utilities/gradle/template.yaml new file mode 100644 index 000000000..a717c2998 --- /dev/null +++ b/examples/powertools-examples-core-utilities/gradle/template.yaml @@ -0,0 +1,71 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + gradle + + Sample SAM Template for gradle + +# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst +Globals: + Function: + Timeout: 20 + Runtime: java11 + MemorySize: 512 + Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html + Environment: + Variables: + # Powertools for AWS Lambda (Java) env vars: https://docs.powertools.aws.dev/lambda/java/#environment-variables + POWERTOOLS_LOG_LEVEL: INFO + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 + POWERTOOLS_LOGGER_LOG_EVENT: true + POWERTOOLS_METRICS_NAMESPACE: Coreutilities + +Resources: + HelloWorldFunction: + Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + Properties: + CodeUri: . + Handler: helloworld.App::handleRequest + Runtime: java8 + MemorySize: 512 + Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object + Variables: + POWERTOOLS_SERVICE_NAME: hello + Events: + HelloWorld: + Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api + Properties: + Path: /hello + Method: get + + HelloWorldStreamFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: helloworld.AppStream::handleRequest + Runtime: java8 + MemorySize: 512 + Tracing: Active + Environment: + Variables: + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.7 + Events: + HelloWorld: + Type: Api + Properties: + Path: /hellostream + Method: get + +Outputs: + # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function + # Find out more about other implicit resources you can reference within SAM + # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api + HelloWorldApi: + Description: "API Gateway endpoint URL for Prod stage for Hello World function" + Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" + HelloWorldFunction: + Description: "Hello World Lambda Function ARN" + Value: !GetAtt HelloWorldFunction.Arn + HelloWorldFunctionIamRole: + Description: "Implicit IAM Role created for Hello World function" + Value: !GetAtt HelloWorldFunctionRole.Arn diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 204a828c0..a85bf8941 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ software.amazon.lambda.examples 2.0.0-SNAPSHOT - powertools-examples-core-utilities + powertools-examples-core-utilities-sam jar Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) @@ -13,7 +13,6 @@ 2.20.0 1.8 1.8 - true @@ -38,9 +37,9 @@ 1.2.3 - com.amazonaws - aws-lambda-java-events - 3.11.2 + com.amazonaws + aws-lambda-java-events + 3.11.2 org.apache.logging.log4j @@ -54,72 +53,81 @@ - junit - junit - 4.13.2 - test + junit + junit + 4.13.2 + test - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - + software.amazon.lambda.examples 2.0.0-SNAPSHOT powertools-examples-idempotency @@ -26,7 +26,6 @@ 2.20.0 1.8 1.8 - true @@ -51,9 +50,9 @@ 1.2.3 - com.amazonaws - aws-lambda-java-events - 3.11.2 + com.amazonaws + aws-lambda-java-events + 3.11.2 org.apache.logging.log4j @@ -92,97 +91,106 @@ - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-idempotency - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy - test-compile - - copy-dependencies - - - test - so,dll,dylib - ${project.build.directory}/native-libs - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.1.2 - - - ${project.build.directory}/native-libs - - - idempotency - eu-central-1 - LOG_ERROR - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-idempotency + + + + + + + compile + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + test-compile + + copy-dependencies + + + test + so,dll,dylib + ${project.build.directory}/native-libs + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + ${project.build.directory}/native-libs + + + idempotency + eu-central-1 + LOG_ERROR + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + - 3.1.2 - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-parameters - - - - - - - compile - - - - - + + + org.apache.maven.plugins + maven-surefire-plugin + + 3.1.2 + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-parameters + + + + + + + compile + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + 3.1.2 + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index d4b26d166..296504a32 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -13,7 +13,7 @@ --> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples 2.0.0-SNAPSHOT @@ -24,7 +24,6 @@ 1.8 1.8 - true @@ -66,37 +65,45 @@ - - - org.apache.maven.plugins - maven-surefire-plugin - - 3.1.2 - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-validation - - - - - - - compile - - - - - + + + org.apache.maven.plugins + maven-surefire-plugin + + 3.1.2 + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-validation + + + + + + + compile + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + - true + 2.93.0 @@ -183,6 +180,14 @@ org.apache.maven.plugins maven-checkstyle-plugin + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + org.apache.maven.plugins maven-compiler-plugin From 2d3e865f5ee84986d602c523b1f130b043fef35b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Fri, 1 Sep 2023 08:58:14 +0200 Subject: [PATCH 031/577] chore: remove aspectj-rt from the library (#1408) * remove aspectj-rt from the library * set aspectj.version 1.9.20 --- examples/powertools-examples-batch/pom.xml | 65 +---- .../pom.xml | 65 +---- .../cdk/app/pom.xml | 70 +---- .../sam/pom.xml | 195 +++++-------- .../powertools-examples-idempotency/pom.xml | 259 +++++++----------- .../powertools-examples-parameters/pom.xml | 127 +++------ .../powertools-examples-serialization/pom.xml | 72 +---- .../powertools-examples-validation/pom.xml | 130 +++------ powertools-cloudformation/pom.xml | 14 +- powertools-common/pom.xml | 4 - .../handlers/idempotency/pom.xml | 5 +- .../handlers/largemessage/pom.xml | 4 + .../handlers/largemessage_idempotent/pom.xml | 5 +- powertools-e2e-tests/handlers/logging/pom.xml | 5 +- powertools-e2e-tests/handlers/metrics/pom.xml | 5 +- .../handlers/parameters/pom.xml | 5 +- powertools-e2e-tests/handlers/pom.xml | 111 +++----- powertools-e2e-tests/handlers/tracing/pom.xml | 5 +- powertools-idempotency/pom.xml | 9 +- powertools-large-messages/pom.xml | 9 +- powertools-logging/pom.xml | 4 - powertools-metrics/pom.xml | 5 - powertools-parameters/pom.xml | 5 - powertools-tracing/pom.xml | 4 - powertools-validation/pom.xml | 4 - 25 files changed, 395 insertions(+), 791 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index cfc035238..8d2c6052a 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -15,6 +15,7 @@ 1.8 1.8 2.20.133 + 1.9.20 @@ -63,6 +64,11 @@ kinesis ${sdk.version} + + org.aspectj + aspectjrt + ${aspectj.version} + @@ -93,6 +99,13 @@ + + + org.aspectj + aspectjtools + ${aspectj.version} + + org.apache.maven.plugins @@ -139,6 +152,7 @@ - If you are running on Java 1.8, you should apply the aspectJ version here to the project, and remove the profile. --> + jdk8 @@ -147,57 +161,6 @@ 1.9.7 - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - - - - - compile - test-compile - - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 85e330742..c8eff3211 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -7,7 +7,7 @@ powertools-examples-cloudformation jar - AWS Lambda Powertools for Java library Examples - CloudFormation + Powertools for AWS Lambda (Java) library Examples - CloudFormation 2.20.0 @@ -16,6 +16,7 @@ 1.2.3 3.11.2 2.20.136 + 1.9.20 @@ -60,6 +61,11 @@ log4j-api ${log4j.version} + + org.aspectj + aspectjrt + ${aspectj.version} + software.amazon.awssdk s3 @@ -89,9 +95,6 @@ log4j-jcl ${log4j.version} - - - @@ -118,6 +121,13 @@ + + + org.aspectj + aspectjtools + ${aspectj.version} + + org.apache.maven.plugins @@ -172,53 +182,6 @@ 1.9.7 - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-logging - - - - - - - compile - test-compile - - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 76e02ea48..51c222a07 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -7,12 +7,13 @@ powertools-examples-core-utilities-cdk jar - Powertools for AWS Lambda (Java) library Examples - Core + Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) with CDK 2.20.0 1.8 1.8 + 1.9.20 @@ -51,6 +52,11 @@ log4j-api ${log4j.version} + + org.aspectj + aspectjrt + ${aspectj.version} + junit @@ -93,6 +99,13 @@ + + + org.aspectj + aspectjtools + ${aspectj.version} + + org.apache.maven.plugins @@ -147,61 +160,6 @@ 1.9.7 - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - test-compile - - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index a85bf8941..55b06cbf7 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -7,12 +7,13 @@ powertools-examples-core-utilities-sam jar - Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) + Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) with SAM 2.20.0 1.8 1.8 + 1.9.20 @@ -51,6 +52,11 @@ log4j-api ${log4j.version} + + org.aspectj + aspectjrt + ${aspectj.version} + junit @@ -61,73 +67,71 @@ - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index b7b710ac1..c28594023 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -26,6 +26,7 @@ 2.20.0 1.8 1.8 + 1.9.20 @@ -64,6 +65,11 @@ log4j-api ${log4j.version} + + org.aspectj + aspectjrt + ${aspectj.version} + org.mockito @@ -91,106 +97,104 @@ - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-idempotency - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy - test-compile - - copy-dependencies - - - test - so,dll,dylib - ${project.build.directory}/native-libs - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.1.2 - - - ${project.build.directory}/native-libs - - - idempotency - eu-central-1 - LOG_ERROR - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-idempotency + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + test-compile + + copy-dependencies + + + test + so,dll,dylib + ${project.build.directory}/native-libs + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + ${project.build.directory}/native-libs + + + idempotency + eu-central-1 + LOG_ERROR + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 7bf354ac1..b856de65e 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -10,6 +10,7 @@ 1.8 1.8 + 1.9.20 @@ -33,6 +34,11 @@ aws-lambda-java-events 3.11.2 + + org.aspectj + aspectjrt + ${aspectj.version} + @@ -56,45 +62,44 @@ - - - org.apache.maven.plugins - maven-surefire-plugin - - 3.1.2 - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-parameters - - - - - - - compile - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - + + + org.apache.maven.plugins + maven-surefire-plugin + + 3.1.2 + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-parameters + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 13f01a8d3..0dd626ea0 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -71,71 +71,15 @@ true + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + true + + - - - - jdk8 - - (,11) - - - 1.9.7 - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - ignore - UTF-8 - - - - process-sources - - compile - test-compile - - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 296504a32..08d2eba32 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -24,6 +24,7 @@ 1.8 1.8 + 1.9.20 @@ -42,6 +43,11 @@ aws-lambda-java-core 1.2.3 + + org.aspectj + aspectjrt + ${aspectj.version} + @@ -65,45 +71,44 @@ - - - org.apache.maven.plugins - maven-surefire-plugin - - 3.1.2 - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-validation - - - - - - - compile - - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - + + + org.apache.maven.plugins + maven-surefire-plugin + + 3.1.2 + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-validation + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 336a3f94c..29987fdeb 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -27,7 +27,7 @@ 2.0.0-SNAPSHOT - Powertools for AWS Lambda (Java)library Cloudformation + Powertools for AWS Lambda (Java) library Cloudformation A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. @@ -76,10 +76,6 @@ com.fasterxml.jackson.core jackson-databind - - org.aspectj - aspectjrt - @@ -116,6 +112,14 @@ + + dev.aspectj + aspectj-maven-plugin + ${aspectj-maven-plugin.version} + + true + + org.apache.maven.plugins maven-checkstyle-plugin diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 721f264e0..d85b06486 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -58,10 +58,6 @@ com.amazonaws aws-lambda-java-core - - org.aspectj - aspectjrt - org.apache.logging.log4j log4j-slf4j2-impl diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index 25dfbfabf..22b6a1c53 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -29,7 +29,10 @@ com.amazonaws aws-lambda-java-events - + + org.aspectj + aspectjrt + diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index c626f5f64..8302624ef 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -33,6 +33,10 @@ org.apache.logging.log4j log4j-slf4j2-impl + + org.aspectj + aspectjrt + diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index 9635efd87..1fe9092ef 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -33,7 +33,10 @@ org.apache.logging.log4j log4j-slf4j2-impl - + + org.aspectj + aspectjrt + diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml index 4b613f2bf..0ee014116 100644 --- a/powertools-e2e-tests/handlers/logging/pom.xml +++ b/powertools-e2e-tests/handlers/logging/pom.xml @@ -21,7 +21,10 @@ com.amazonaws aws-lambda-java-events - + + org.aspectj + aspectjrt + diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 35db53899..2f3cabd16 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -21,7 +21,10 @@ com.amazonaws aws-lambda-java-events - + + org.aspectj + aspectjrt + diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index 410cdfb5e..4d5330da0 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -25,7 +25,10 @@ com.amazonaws aws-lambda-java-events - + + org.aspectj + aspectjrt + diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 7abaec9d0..e2f6abb28 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -23,6 +23,7 @@ 3.11.0 2.20.108 2.20.0 + 1.9.20 @@ -98,6 +99,11 @@ log4j-slf4j2-impl ${log4j.version} + + org.aspectj + aspectjrt + ${aspectj.version} + @@ -143,6 +149,34 @@ false + + dev.aspectj + aspectj-maven-plugin + ${aspectj.plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + ignore + ${project.build.sourceEncoding} + + + + process-sources + + compile + test-compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + @@ -156,83 +190,6 @@ 1.9.7 - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - ignore - ${project.build.sourceEncoding} - - - - process-sources - - compile - test-compile - - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - - jdk11plus - - [11,) - - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - ignore - ${project.build.sourceEncoding} - - - - process-sources - - compile - test-compile - - - - - - - diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index 252009aa9..b9240c356 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -21,7 +21,10 @@ com.amazonaws aws-lambda-java-events - + + org.aspectj + aspectjrt + diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 6a39ae6e0..d636d2e75 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -86,10 +86,6 @@ url-connection-client ${aws.sdk.version} - - org.aspectj - aspectjrt - @@ -122,6 +118,11 @@ commons-lang3 test + + org.aspectj + aspectjweaver + test + org.assertj assertj-core diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 6cffecb73..2c58fda4c 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -58,10 +58,6 @@ software.amazon.lambda powertools-common - - org.aspectj - aspectjrt - com.amazonaws aws-lambda-java-events @@ -133,6 +129,11 @@ commons-lang3 test + + org.aspectj + aspectjweaver + test + org.assertj assertj-core diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index e16dd0a8b..c9e6c98df 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -83,10 +83,6 @@ org.apache.logging.log4j log4j-api - - org.aspectj - aspectjrt - diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index e67aca7e2..feecd4bf2 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -83,11 +83,6 @@ jackson-databind - - org.aspectj - aspectjrt - - org.junit.jupiter diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index a703bf36b..18d15ab02 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -104,11 +104,6 @@ com.fasterxml.jackson.core jackson-databind - - org.aspectj - aspectjrt - compile - org.junit.jupiter diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 0c9ed8f71..f55c4f346 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -68,10 +68,6 @@ com.amazonaws aws-lambda-java-core - - org.aspectj - aspectjrt - com.amazonaws aws-xray-recorder-sdk-core diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 5868629de..cbb6159a6 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -80,10 +80,6 @@ com.fasterxml.jackson.core jackson-databind - - org.aspectj - aspectjrt - com.networknt json-schema-validator From 8586bf6a3d4bbce426e530d1e088e29cdc69dbf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:00:51 +0200 Subject: [PATCH 032/577] fix: add aspectj-rt to batch e2e (#1410) * add aspectj-rt * run e2e on v2 updates --- .github/workflows/run-e2e-tests.yml | 1 + powertools-e2e-tests/handlers/batch/pom.xml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index c4a8c6fb2..5c281a037 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -23,6 +23,7 @@ on: pull_request: branches: - main + - v2 paths: - 'powertools-e2e-tests/**' diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index 995121e2a..aee9bf3dd 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -37,6 +37,10 @@ software.amazon.awssdk dynamodb + + org.aspectj + aspectjrt + From 2d7f02449ca2ed863cb4446f14f376ef894c1b1b Mon Sep 17 00:00:00 2001 From: walmsles <2704782+walmsles@users.noreply.github.com> Date: Mon, 4 Sep 2023 14:28:47 +1000 Subject: [PATCH 033/577] docs(logging): align example cloudwatch example to correct output from code: lambda_request_id --> function_request_id (#1411) --- docs/core/logging.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/core/logging.md b/docs/core/logging.md index 09714a512..2df9a4529 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -347,7 +347,7 @@ You can set a Correlation ID using `correlationIdPath` attribute by passing a [J "functionName": "test", "functionMemorySize": 128, "functionArn": "arn:aws:lambda:eu-west-1:12345678910:function:test", - "lambda_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", + "function_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", "correlation_id": "correlation_id_value" } ``` @@ -397,7 +397,7 @@ for known event sources, where either a request ID or X-Ray Trace ID are present "functionName": "test", "functionMemorySize": 128, "functionArn": "arn:aws:lambda:eu-west-1:12345678910:function:test", - "lambda_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", + "function_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", "correlation_id": "correlation_id_value" } ``` @@ -510,7 +510,7 @@ this means that custom keys can be persisted across invocations. If you want all "functionName": "test", "functionMemorySize": 128, "functionArn": "arn:aws:lambda:eu-west-1:12345678910:function:test", - "lambda_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", + "function_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", "specialKey": "value" } ``` @@ -527,7 +527,7 @@ this means that custom keys can be persisted across invocations. If you want all "functionName": "test", "functionMemorySize": 128, "functionArn": "arn:aws:lambda:eu-west-1:12345678910:function:test", - "lambda_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72" + "function_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72" } ``` From ec48401c0cd230560a55d98702580e8c9c1eb21b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 06:29:33 +0200 Subject: [PATCH 034/577] build(deps): bump aws.sdk.version from 2.20.136 to 2.20.137 (#1406) Bumps `aws.sdk.version` from 2.20.136 to 2.20.137. Updates `software.amazon.awssdk:bom` from 2.20.136 to 2.20.137 Updates `software.amazon.awssdk:http-client-spi` from 2.20.136 to 2.20.137 Updates `software.amazon.awssdk:url-connection-client` from 2.20.133 to 2.20.137 Updates `software.amazon.awssdk:sqs` from 2.20.133 to 2.20.137 Updates `software.amazon.awssdk:s3` from 2.20.136 to 2.20.137 Updates `software.amazon.awssdk:dynamodb` from 2.20.136 to 2.20.137 Updates `software.amazon.awssdk:lambda` from 2.20.136 to 2.20.137 Updates `software.amazon.awssdk:kinesis` from 2.20.133 to 2.20.137 Updates `software.amazon.awssdk:cloudwatch` from 2.20.136 to 2.20.137 Updates `software.amazon.awssdk:xray` from 2.20.136 to 2.20.137 Updates `software.amazon.awssdk:cloudformation` from 2.20.136 to 2.20.137 Updates `software.amazon.awssdk:sts` from 2.20.136 to 2.20.137 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 1273d8d15..4e9201aef 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.2 - 2.20.136 + 2.20.137 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index b2ef7145c..7e21bfd28 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.136 + 2.20.137 com.amazonaws diff --git a/pom.xml b/pom.xml index 9066d5880..26e9f1612 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.136 + 2.20.137 2.14.0 2.1.3 UTF-8 From 910b4f2e1cffc53321294524c1fc2a45cc485950 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 06:31:32 +0200 Subject: [PATCH 035/577] build(deps): bump com.puppycrawl.tools:checkstyle (#1399) Bumps [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) from 10.12.2 to 10.12.3. - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.2...checkstyle-10.12.3) --- updated-dependencies: - dependency-name: com.puppycrawl.tools:checkstyle dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 26e9f1612..b8a02d2ed 100644 --- a/pom.xml +++ b/pom.xml @@ -561,7 +561,7 @@ com.puppycrawl.tools checkstyle - 10.12.2 + 10.12.3 From 578fd804754d6585db8faecbb3103f60307cacca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 13:47:24 +0200 Subject: [PATCH 036/577] build(deps): bump aws.sdk.version from 2.20.137 to 2.20.140 (#1412) Bumps `aws.sdk.version` from 2.20.137 to 2.20.140. Updates `software.amazon.awssdk:bom` from 2.20.137 to 2.20.140 Updates `software.amazon.awssdk:http-client-spi` from 2.20.137 to 2.20.140 Updates `software.amazon.awssdk:url-connection-client` from 2.20.133 to 2.20.140 Updates `software.amazon.awssdk:sqs` from 2.20.133 to 2.20.140 Updates `software.amazon.awssdk:s3` from 2.20.137 to 2.20.140 Updates `software.amazon.awssdk:dynamodb` from 2.20.137 to 2.20.140 Updates `software.amazon.awssdk:lambda` from 2.20.137 to 2.20.140 Updates `software.amazon.awssdk:kinesis` from 2.20.133 to 2.20.140 Updates `software.amazon.awssdk:cloudwatch` from 2.20.137 to 2.20.140 Updates `software.amazon.awssdk:xray` from 2.20.137 to 2.20.140 Updates `software.amazon.awssdk:cloudformation` from 2.20.137 to 2.20.140 Updates `software.amazon.awssdk:sts` from 2.20.137 to 2.20.140 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 4e9201aef..142b2e1e9 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.2 - 2.20.137 + 2.20.140 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 7e21bfd28..090905886 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.137 + 2.20.140 com.amazonaws diff --git a/pom.xml b/pom.xml index b8a02d2ed..01f63364b 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.137 + 2.20.140 2.14.0 2.1.3 UTF-8 From 6debe05a56717cb8ff9f7f353dfec69f36ed08e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 13:58:08 +0200 Subject: [PATCH 037/577] build(deps): bump com.amazonaws:aws-lambda-java-events (#1413) Bumps [com.amazonaws:aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs) from 3.11.2 to 3.11.3. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-events dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core/cdk/app/pom.xml | 2 +- examples/powertools-examples-core/sam/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 142b2e1e9..c63bc9dbe 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 1.8 1.8 1.2.3 - 3.11.2 + 3.11.3 2.20.140 diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml index 7831df839..57397f187 100644 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ b/examples/powertools-examples-core/cdk/app/pom.xml @@ -39,7 +39,7 @@ com.amazonaws aws-lambda-java-events - 3.11.2 + 3.11.3 org.apache.logging.log4j diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index 09cab6cd6..93c858556 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -39,7 +39,7 @@ com.amazonaws aws-lambda-java-events - 3.11.2 + 3.11.3 org.apache.logging.log4j diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 1afce1f29..a98645a29 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -52,7 +52,7 @@ com.amazonaws aws-lambda-java-events - 3.11.2 + 3.11.3 org.apache.logging.log4j diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index fe74f859d..deb9c6ba6 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -31,7 +31,7 @@ com.amazonaws aws-lambda-java-events - 3.11.2 + 3.11.3 diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 7b63d266d..eee3e456a 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -31,7 +31,7 @@ com.amazonaws aws-lambda-java-events - 3.11.2 + 3.11.3 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 090905886..65c2e41f3 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -37,7 +37,7 @@ com.amazonaws aws-lambda-java-events - 3.11.2 + 3.11.3 org.apache.logging.log4j diff --git a/pom.xml b/pom.xml index 01f63364b..d66e97397 100644 --- a/pom.xml +++ b/pom.xml @@ -81,7 +81,7 @@ 2.1.3 UTF-8 1.2.3 - 3.11.2 + 3.11.3 1.1.2 3.11.0 1.13.1 From 2e769528a662383ece323ea1ef1e471d1f19e362 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 13:36:41 +0200 Subject: [PATCH 038/577] build(deps): bump aws.sdk.version from 2.20.133 to 2.20.140 (#1415) Bumps `aws.sdk.version` from 2.20.133 to 2.20.140. Updates `software.amazon.awssdk:url-connection-client` from 2.20.133 to 2.20.140 Updates `software.amazon.awssdk:sqs` from 2.20.133 to 2.20.140 Updates `software.amazon.awssdk:sdk-core` from 2.20.133 to 2.20.140 Updates `software.amazon.awssdk:kinesis` from 2.20.133 to 2.20.140 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.20.133 to 2.20.140 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 290fe0cd2..7c0db3174 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 2.20.0 1.8 1.8 - 2.20.133 + 2.20.140 From 9df5830ffdf331e32b743339bd384e2ed7a9c71b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 13:45:20 +0200 Subject: [PATCH 039/577] build(deps): bump aws.sdk.version from 2.20.140 to 2.20.141 (#1421) Bumps `aws.sdk.version` from 2.20.140 to 2.20.141. Updates `software.amazon.awssdk:bom` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:http-client-spi` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:url-connection-client` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:sqs` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:s3` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:dynamodb` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:lambda` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:kinesis` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:cloudwatch` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:xray` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:cloudformation` from 2.20.140 to 2.20.141 Updates `software.amazon.awssdk:sts` from 2.20.140 to 2.20.141 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index c63bc9dbe..336f79b65 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.140 + 2.20.141 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 65c2e41f3..e44f715a7 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.140 + 2.20.141 com.amazonaws diff --git a/pom.xml b/pom.xml index d66e97397..009730a4b 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.140 + 2.20.141 2.14.0 2.1.3 UTF-8 From 5d8e8ba78ea5f2e9620604e3ee719d982a27883a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Sep 2023 13:36:04 +0200 Subject: [PATCH 040/577] build(deps): bump aws.sdk.version from 2.20.140 to 2.20.142 (#1423) Bumps `aws.sdk.version` from 2.20.140 to 2.20.142. Updates `software.amazon.awssdk:url-connection-client` from 2.20.140 to 2.20.142 Updates `software.amazon.awssdk:sqs` from 2.20.140 to 2.20.142 Updates `software.amazon.awssdk:sdk-core` from 2.20.140 to 2.20.142 Updates `software.amazon.awssdk:kinesis` from 2.20.140 to 2.20.142 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.20.140 to 2.20.142 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 7c0db3174..1e87e9754 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 2.20.0 1.8 1.8 - 2.20.140 + 2.20.142 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index e44f715a7..1dcb9ca6e 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.141 + 2.20.142 com.amazonaws From 8935593cf162c3eed93d40098bf5a81fc1b38a21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 14:08:43 +0200 Subject: [PATCH 041/577] build(deps): bump aws.sdk.version from 2.20.141 to 2.20.143 (#1424) Bumps `aws.sdk.version` from 2.20.141 to 2.20.143. Updates `software.amazon.awssdk:url-connection-client` from 2.20.141 to 2.20.143 Updates `software.amazon.awssdk:sqs` from 2.20.141 to 2.20.143 Updates `software.amazon.awssdk:sdk-core` from 2.20.142 to 2.20.143 Updates `software.amazon.awssdk:kinesis` from 2.20.141 to 2.20.143 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.20.142 to 2.20.143 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 1e87e9754..7ab895c07 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 2.20.0 1.8 1.8 - 2.20.142 + 2.20.143 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 1dcb9ca6e..12a07a1ce 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.142 + 2.20.143 com.amazonaws From f66b46bc953ca2ba46d4d7ddc2fb232d5a2045e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 14:35:16 +0200 Subject: [PATCH 042/577] build(deps): bump com.github.tomakehurst:wiremock-jre8 (#1426) Bumps [com.github.tomakehurst:wiremock-jre8](https://github.com/wiremock/wiremock) from 2.35.0 to 2.35.1. - [Release notes](https://github.com/wiremock/wiremock/releases) - [Commits](https://github.com/wiremock/wiremock/compare/2.35.0...2.35.1) --- updated-dependencies: - dependency-name: com.github.tomakehurst:wiremock-jre8 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 009730a4b..0bb1de3c6 100644 --- a/pom.xml +++ b/pom.xml @@ -307,7 +307,7 @@ com.github.tomakehurst wiremock-jre8 - 2.35.0 + 2.35.1 test From 6b5b1a4a497e1b9621503f3c539b877508cdf48e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 14:16:01 +0200 Subject: [PATCH 043/577] build(deps): bump aws.sdk.version from 2.20.141 to 2.20.144 (#1427) Bumps `aws.sdk.version` from 2.20.141 to 2.20.144. Updates `software.amazon.awssdk:bom` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:http-client-spi` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:url-connection-client` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:sqs` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:s3` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:dynamodb` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:lambda` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:kinesis` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:cloudwatch` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:xray` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:cloudformation` from 2.20.141 to 2.20.144 Updates `software.amazon.awssdk:sts` from 2.20.141 to 2.20.144 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 336f79b65..7d49819e4 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.141 + 2.20.144 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 12a07a1ce..2ec7a0071 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.143 + 2.20.144 com.amazonaws diff --git a/pom.xml b/pom.xml index 0bb1de3c6..e688c5890 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.141 + 2.20.144 2.14.0 2.1.3 UTF-8 From 18294afd40e7200df90e8e256e18d050f1e26957 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 11 Sep 2023 16:48:26 +0200 Subject: [PATCH 044/577] docs: Fix link to SQS large message migration guide (#1422) * Fix link to SQS large message migration guide * Better --- docs/utilities/sqs_large_message_handling.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/utilities/sqs_large_message_handling.md b/docs/utilities/sqs_large_message_handling.md index 0924d01cf..9d721f544 100644 --- a/docs/utilities/sqs_large_message_handling.md +++ b/docs/utilities/sqs_large_message_handling.md @@ -6,7 +6,7 @@ description: Utility !!! warning This module is now deprecated and will be removed in version 2. See [Large Message Handling](large_messages.md) and - [the migration guide](http://localhost:8000/lambda-java/utilities/large_messages/#migration-from-the-sqs-large-message-utility) + [the migration guide](large_messages.md#migration-from-the-sqs-large-message-utility) for the new module (`powertools-large-messages`) documentation The large message handling utility handles SQS messages which have had their payloads From 3dfebee220549d4d19a7500bcd483ae01a8f0dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Mon, 11 Sep 2023 17:46:29 +0200 Subject: [PATCH 045/577] fix #1419 (#1420) --- .../persistence/BasePersistenceStore.java | 37 +++++++++---------- .../internal/IdempotencyAspectTest.java | 22 +++++++++++ 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java index f58b276fd..a3b1b0ff4 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java +++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java @@ -26,7 +26,6 @@ import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.time.temporal.ChronoUnit; -import java.util.Map; import java.util.Optional; import java.util.OptionalInt; import java.util.OptionalLong; @@ -122,7 +121,7 @@ public void saveSuccess(JsonNode data, Object result, Instant now) { // missing idempotency key => non-idempotent transaction, we do not store the data, simply return return; } - DataRecord record = new DataRecord( + DataRecord dataRecord = new DataRecord( hashedIdempotencyKey.get(), DataRecord.Status.COMPLETED, getExpiryEpochSecond(now), @@ -130,9 +129,9 @@ public void saveSuccess(JsonNode data, Object result, Instant now) { getHashedPayload(data) ); LOG.debug("Function successfully executed. Saving record to persistence store with idempotency key: {}", - record.getIdempotencyKey()); - updateRecord(record); - saveToCache(record); + dataRecord.getIdempotencyKey()); + updateRecord(dataRecord); + saveToCache(dataRecord); } catch (JsonProcessingException e) { // TODO : throw ? throw new RuntimeException("Error while serializing the response", e); @@ -164,7 +163,7 @@ public void saveInProgress(JsonNode data, Instant now, OptionalInt remainingTime OptionalLong.of(now.plus(remainingTimeInMs.getAsInt(), ChronoUnit.MILLIS).toEpochMilli()); } - DataRecord record = new DataRecord( + DataRecord dataRecord = new DataRecord( idempotencyKey, DataRecord.Status.INPROGRESS, getExpiryEpochSecond(now), @@ -172,8 +171,8 @@ public void saveInProgress(JsonNode data, Instant now, OptionalInt remainingTime getHashedPayload(data), inProgressExpirationMsTimestamp ); - LOG.debug("saving in progress record for idempotency key: {}", record.getIdempotencyKey()); - putRecord(record, now); + LOG.debug("saving in progress record for idempotency key: {}", dataRecord.getIdempotencyKey()); + putRecord(dataRecord, now); } /** @@ -223,10 +222,10 @@ public DataRecord getRecord(JsonNode data, Instant now) return cachedRecord; } - DataRecord record = getRecord(idemPotencyKey); - saveToCache(record); - validatePayload(data, record); - return record; + DataRecord dataRecord = getRecord(idemPotencyKey); + saveToCache(dataRecord); + validatePayload(data, dataRecord); + return dataRecord; } /** @@ -258,10 +257,10 @@ private Optional getHashedIdempotencyKey(JsonNode data) { private boolean isMissingIdemPotencyKey(JsonNode data) { if (data.isContainerNode()) { - Stream> stream = - StreamSupport.stream(Spliterators.spliteratorUnknownSize(data.fields(), Spliterator.ORDERED), + Stream stream = + StreamSupport.stream(Spliterators.spliteratorUnknownSize(data.elements(), Spliterator.ORDERED), false); - return stream.allMatch(e -> e.getValue().isNull()); + return stream.allMatch(JsonNode::isNull); } return data.isNull(); } @@ -378,10 +377,10 @@ private DataRecord retrieveFromCache(String idempotencyKey, Instant now) { return null; } - DataRecord record = cache.get(idempotencyKey); - if (record != null) { - if (!record.isExpired(now)) { - return record; + DataRecord dataRecord = cache.get(idempotencyKey); + if (dataRecord != null) { + if (!dataRecord.isExpired(now)) { + return dataRecord; } LOG.debug("Removing expired local cache record for idempotency key: {}", idempotencyKey); deleteFromCache(idempotencyKey); diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java index 9a30472a8..c72593b66 100644 --- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java +++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java @@ -378,6 +378,28 @@ public void idempotencyOnSubMethodAnnotated_keyJMESPath_shouldPutInStoreWithKey( "testFunction.createBasket#a1d0c6e83f027327d8461063f4ac58a6"); } + @Test + public void idempotencyOnSubMethodAnnotated_keyJMESPathArray_shouldPutInStoreWithKey() { + BasePersistenceStore persistenceStore = spy(BasePersistenceStore.class); + + Idempotency.config() + .withPersistenceStore(persistenceStore) + .withConfig(IdempotencyConfig.builder().withEventKeyJMESPath("[id,name]").build()) + .configure(); + + // WHEN + IdempotencyInternalFunctionInternalKey function = new IdempotencyInternalFunctionInternalKey(); + Product p = new Product(42, "fake product", 12); + function.handleRequest(p, context); + + // THEN + ArgumentCaptor recordCaptor = ArgumentCaptor.forClass(DataRecord.class); + verify(persistenceStore).putRecord(recordCaptor.capture(), any()); + // eec7cd392d9e3bb20deb2c9676697c3c = MD5([42,"fake product"]) + assertThat(recordCaptor.getValue().getIdempotencyKey()).isEqualTo( + "testFunction.createBasket#eec7cd392d9e3bb20deb2c9676697c3c"); + } + @Test public void idempotencyOnSubMethodNotAnnotated_shouldThrowException() { Idempotency.config() From aa56890302ea9270f0fd559b7804637fba749ac0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 13:37:54 +0200 Subject: [PATCH 046/577] build(deps): bump aws.sdk.version from 2.20.143 to 2.20.145 (#1429) Bumps `aws.sdk.version` from 2.20.143 to 2.20.145. Updates `software.amazon.awssdk:url-connection-client` from 2.20.143 to 2.20.145 Updates `software.amazon.awssdk:sqs` from 2.20.143 to 2.20.145 Updates `software.amazon.awssdk:sdk-core` from 2.20.143 to 2.20.145 Updates `software.amazon.awssdk:kinesis` from 2.20.143 to 2.20.145 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.20.143 to 2.20.145 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 7ab895c07..1dbb5b789 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 2.20.0 1.8 1.8 - 2.20.143 + 2.20.145 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 2ec7a0071..caceab211 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.144 + 2.20.145 com.amazonaws From 270b78fcdba4552b6efb0f8f3b6f3d8f73b41954 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Sep 2023 13:30:44 +0200 Subject: [PATCH 047/577] build(deps): bump aws.sdk.version from 2.20.144 to 2.20.146 (#1430) Bumps `aws.sdk.version` from 2.20.144 to 2.20.146. Updates `software.amazon.awssdk:bom` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:http-client-spi` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:url-connection-client` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:sqs` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:s3` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:dynamodb` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:lambda` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:kinesis` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:cloudwatch` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:xray` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:cloudformation` from 2.20.144 to 2.20.146 Updates `software.amazon.awssdk:sts` from 2.20.144 to 2.20.146 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 7d49819e4..5c01f3ce9 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.144 + 2.20.146 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index caceab211..5ae2f8b80 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.145 + 2.20.146 com.amazonaws diff --git a/pom.xml b/pom.xml index e688c5890..5bfa33373 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.144 + 2.20.146 2.14.0 2.1.3 UTF-8 From ff4571f359a870b2040befde9fa0df10cd287670 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Sep 2023 13:35:35 +0200 Subject: [PATCH 048/577] build(deps): bump aws.sdk.version from 2.20.146 to 2.20.147 (#1431) Bumps `aws.sdk.version` from 2.20.146 to 2.20.147. Updates `software.amazon.awssdk:bom` from 2.20.146 to 2.20.147 Updates `software.amazon.awssdk:http-client-spi` from 2.20.146 to 2.20.147 Updates `software.amazon.awssdk:url-connection-client` from 2.20.145 to 2.20.147 Updates `software.amazon.awssdk:sqs` from 2.20.145 to 2.20.147 Updates `software.amazon.awssdk:s3` from 2.20.146 to 2.20.147 Updates `software.amazon.awssdk:dynamodb` from 2.20.146 to 2.20.147 Updates `software.amazon.awssdk:lambda` from 2.20.146 to 2.20.147 Updates `software.amazon.awssdk:kinesis` from 2.20.145 to 2.20.147 Updates `software.amazon.awssdk:cloudwatch` from 2.20.146 to 2.20.147 Updates `software.amazon.awssdk:xray` from 2.20.146 to 2.20.147 Updates `software.amazon.awssdk:cloudformation` from 2.20.146 to 2.20.147 Updates `software.amazon.awssdk:sts` from 2.20.146 to 2.20.147 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 5c01f3ce9..dbb53f497 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.146 + 2.20.147 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 5ae2f8b80..75dd2472c 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.146 + 2.20.147 com.amazonaws diff --git a/pom.xml b/pom.xml index 5bfa33373..ba83e3d34 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.146 + 2.20.147 2.14.0 2.1.3 UTF-8 From 23b779d65a4044d9b369a7ecbf4e3e704c343f71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 13:45:05 +0200 Subject: [PATCH 049/577] build(deps): bump aws.sdk.version from 2.20.147 to 2.20.148 (#1433) Bumps `aws.sdk.version` from 2.20.147 to 2.20.148. Updates `software.amazon.awssdk:bom` from 2.20.147 to 2.20.148 Updates `software.amazon.awssdk:http-client-spi` from 2.20.147 to 2.20.148 Updates `software.amazon.awssdk:url-connection-client` from 2.20.145 to 2.20.148 Updates `software.amazon.awssdk:sqs` from 2.20.145 to 2.20.148 Updates `software.amazon.awssdk:s3` from 2.20.147 to 2.20.148 Updates `software.amazon.awssdk:dynamodb` from 2.20.147 to 2.20.148 Updates `software.amazon.awssdk:lambda` from 2.20.147 to 2.20.148 Updates `software.amazon.awssdk:kinesis` from 2.20.145 to 2.20.148 Updates `software.amazon.awssdk:cloudwatch` from 2.20.147 to 2.20.148 Updates `software.amazon.awssdk:xray` from 2.20.147 to 2.20.148 Updates `software.amazon.awssdk:cloudformation` from 2.20.147 to 2.20.148 Updates `software.amazon.awssdk:sts` from 2.20.147 to 2.20.148 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index dbb53f497..bdc55ab17 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.147 + 2.20.148 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 75dd2472c..1041242ff 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.147 + 2.20.148 com.amazonaws diff --git a/pom.xml b/pom.xml index ba83e3d34..ae79a72a1 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.147 + 2.20.148 2.14.0 2.1.3 UTF-8 From 4b0b5a862ce5921413a9440997f61ea4e1b297d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 13:47:39 +0200 Subject: [PATCH 050/577] build(deps): bump aws.sdk.version from 2.20.145 to 2.20.149 (#1436) Bumps `aws.sdk.version` from 2.20.145 to 2.20.149. Updates `software.amazon.awssdk:url-connection-client` from 2.20.145 to 2.20.149 Updates `software.amazon.awssdk:sqs` from 2.20.145 to 2.20.149 Updates `software.amazon.awssdk:sdk-core` from 2.20.145 to 2.20.149 Updates `software.amazon.awssdk:kinesis` from 2.20.145 to 2.20.149 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.20.145 to 2.20.149 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 1dbb5b789..031b9c6d8 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 2.20.0 1.8 1.8 - 2.20.145 + 2.20.149 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 1041242ff..a59f6193b 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.148 + 2.20.149 com.amazonaws From 61db38619d2178ec01175e357bbdf0a1cbbcc168 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:04:11 +0200 Subject: [PATCH 051/577] build(deps): bump aws.sdk.version from 2.20.148 to 2.20.150 (#1437) Bumps `aws.sdk.version` from 2.20.148 to 2.20.150. Updates `software.amazon.awssdk:bom` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:http-client-spi` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:url-connection-client` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:sqs` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:s3` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:dynamodb` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:lambda` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:kinesis` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:cloudwatch` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:xray` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:cloudformation` from 2.20.148 to 2.20.150 Updates `software.amazon.awssdk:sts` from 2.20.148 to 2.20.150 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index bdc55ab17..37b4c56a1 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.148 + 2.20.150 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index a59f6193b..0d932a53c 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.149 + 2.20.150 com.amazonaws diff --git a/pom.xml b/pom.xml index ae79a72a1..e36616b3a 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.148 + 2.20.150 2.14.0 2.1.3 UTF-8 From 49f2469667592227c0cbf5e9d4efaefbafa43981 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Sep 2023 13:37:38 +0200 Subject: [PATCH 052/577] build(deps): bump aws.sdk.version from 2.20.150 to 2.20.151 (#1438) Bumps `aws.sdk.version` from 2.20.150 to 2.20.151. Updates `software.amazon.awssdk:bom` from 2.20.150 to 2.20.151 Updates `software.amazon.awssdk:http-client-spi` from 2.20.150 to 2.20.151 Updates `software.amazon.awssdk:url-connection-client` from 2.20.149 to 2.20.151 Updates `software.amazon.awssdk:sqs` from 2.20.149 to 2.20.151 Updates `software.amazon.awssdk:s3` from 2.20.150 to 2.20.151 Updates `software.amazon.awssdk:dynamodb` from 2.20.150 to 2.20.151 Updates `software.amazon.awssdk:lambda` from 2.20.150 to 2.20.151 Updates `software.amazon.awssdk:kinesis` from 2.20.149 to 2.20.151 Updates `software.amazon.awssdk:cloudwatch` from 2.20.150 to 2.20.151 Updates `software.amazon.awssdk:xray` from 2.20.150 to 2.20.151 Updates `software.amazon.awssdk:cloudformation` from 2.20.150 to 2.20.151 Updates `software.amazon.awssdk:sts` from 2.20.150 to 2.20.151 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 37b4c56a1..6db211489 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.150 + 2.20.151 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 0d932a53c..6a2d9e6cf 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.150 + 2.20.151 com.amazonaws diff --git a/pom.xml b/pom.xml index e36616b3a..809f2af72 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.150 + 2.20.151 2.14.0 2.1.3 UTF-8 From 15d7a99a82e6703deee017727b35947977e51b7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Sep 2023 14:05:20 +0200 Subject: [PATCH 053/577] build(deps): bump aws.sdk.version from 2.20.149 to 2.20.152 (#1439) Bumps `aws.sdk.version` from 2.20.149 to 2.20.152. Updates `software.amazon.awssdk:url-connection-client` from 2.20.149 to 2.20.152 Updates `software.amazon.awssdk:sqs` from 2.20.149 to 2.20.152 Updates `software.amazon.awssdk:sdk-core` from 2.20.149 to 2.20.152 Updates `software.amazon.awssdk:kinesis` from 2.20.149 to 2.20.152 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.20.149 to 2.20.152 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 031b9c6d8..ea5d1e5f1 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 2.20.0 1.8 1.8 - 2.20.149 + 2.20.152 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 6a2d9e6cf..d9fa8fff1 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.151 + 2.20.152 com.amazonaws From 07d91184d5ff58169023c330d1c57e96f861014a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 13:44:45 +0200 Subject: [PATCH 054/577] build(deps): bump aws.sdk.version from 2.20.151 to 2.20.152 (#1440) Bumps `aws.sdk.version` from 2.20.151 to 2.20.152. Updates `software.amazon.awssdk:bom` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:http-client-spi` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:url-connection-client` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:sqs` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:s3` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:dynamodb` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:lambda` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:kinesis` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:cloudwatch` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:xray` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:cloudformation` from 2.20.151 to 2.20.152 Updates `software.amazon.awssdk:sts` from 2.20.151 to 2.20.152 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 6db211489..6b8e90ebd 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.151 + 2.20.152 diff --git a/pom.xml b/pom.xml index 809f2af72..a74e13fc2 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.151 + 2.20.152 2.14.0 2.1.3 UTF-8 From 49ae687b6580c9cc693b234a4b5187c6a17bb9cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 14:03:57 +0200 Subject: [PATCH 055/577] build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1443) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.93.0 to 2.97.1. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.93.0...v2.97.1) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index 6facf8a46..99598ba58 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -7,7 +7,7 @@ 1.18.0-SNAPSHOT UTF-8 - 2.93.0 + 2.97.1 [10.0.0,11.0.0) 5.10.0 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index d3acde3ea..c09d03c61 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ 1.8 1.8 10.2.69 - 2.93.0 + 2.97.1 From 6a94862bda9f26209f5762fc439f1076e23b19a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 14:14:30 +0200 Subject: [PATCH 056/577] build(deps-dev): bump software.constructs:constructs (#1407) Bumps [software.constructs:constructs](https://github.com/aws/constructs) from 10.2.69 to 10.2.70. - [Release notes](https://github.com/aws/constructs/releases) - [Commits](https://github.com/aws/constructs/compare/v10.2.69...v10.2.70) --- updated-dependencies: - dependency-name: software.constructs:constructs dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index c09d03c61..90427b797 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -30,7 +30,7 @@ 1.8 1.8 - 10.2.69 + 10.2.70 2.97.1 From 24393d8b3e27d2cef6654e12653766236bc70e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Wed, 27 Sep 2023 12:13:26 +0200 Subject: [PATCH 057/577] chore: Reporting size of the jars in GitHub comments (#1196) * reporting size of the jars in the github comments --- .github/workflows/pr_artifacts_size.yml | 57 +++++++++++++++++++ .github/workflows/{build.yml => pr_build.yml} | 0 pom.xml | 8 +++ 3 files changed, 65 insertions(+) create mode 100644 .github/workflows/pr_artifacts_size.yml rename .github/workflows/{build.yml => pr_build.yml} (100%) diff --git a/.github/workflows/pr_artifacts_size.yml b/.github/workflows/pr_artifacts_size.yml new file mode 100644 index 000000000..cbacd78da --- /dev/null +++ b/.github/workflows/pr_artifacts_size.yml @@ -0,0 +1,57 @@ +name: Artifacts Size + +on: + pull_request: + branches: + - master + paths: + - 'powertools-cloudformation/**' + - 'powertools-core/**' + - 'powertools-serialization/**' + - 'powertools-logging/**' + - 'powertools-sqs/**' + - 'powertools-tracing/**' + - 'powertools-validation/**' + - 'powertools-parameters/**' + - 'powertools-idempotency/**' + - 'powertools-metrics/**' + - 'pom.xml' +jobs: + codecheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Setup java JDK 11 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + with: + distribution: 'corretto' + java-version: 11 + - name: Build with Maven + run: mvn clean package --file pom.xml -DskipTests + - name: Get artifacts size & build report + id: artifacts-size-report + run: | + echo '## :floppy_disk: Artifacts Size Report' > report.md + echo '| Module | Version | Size (KB) |' >> report.md + echo '| --- | --- | --- |' >> report.md + artifact_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + for artifact in $(cat target/powertools-parent-*.buildinfo | grep 'outputs.*.jar' | grep -v 'sources.jar'); do + artifact_name=$(echo "$artifact" | cut -d '=' -f2) + artifact_name=${artifact_name%-$artifact_version.jar} + artifact_size=$(grep "${artifact%%.filename*}.length" target/powertools-parent-*.buildinfo | cut -d '=' -f2) + printf "| %s | %s | %.2f |\n" "$artifact_name" "$artifact_version" "$(bc <<< "scale=2; $artifact_size/1000")" >> report.md + done + - name: Find potential existing report + uses: peter-evans/find-comment@a54c31d7fa095754bfef525c0c8e5e5674c4b4b1 # 2.4.0 + id: find-comment + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: Artifacts Size Report + - name: Write artifacts size report in comment + uses: peter-evans/create-or-update-comment@c6c9a1a66007646a28c153e2a8580a5bad27bcfa # 3.0.2 + with: + comment-id: ${{ steps.find-comment.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body-path: 'report.md' + edit-mode: replace \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/pr_build.yml similarity index 100% rename from .github/workflows/build.yml rename to .github/workflows/pr_build.yml diff --git a/pom.xml b/pom.xml index a74e13fc2..36abf162e 100644 --- a/pom.xml +++ b/pom.xml @@ -368,6 +368,14 @@ false + + org.apache.maven.plugins + maven-artifact-plugin + 3.4.1 + + true + + dev.aspectj aspectj-maven-plugin From c862a8c53cbbf0988e0e6763a21e787837edffc4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:26:55 +0200 Subject: [PATCH 058/577] build(deps): bump aws.sdk.version from 2.20.152 to 2.20.153 (#1441) Bumps `aws.sdk.version` from 2.20.152 to 2.20.153. --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 6b8e90ebd..8fdcb8c08 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.152 + 2.20.153 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index d9fa8fff1..c0c302757 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.152 + 2.20.153 com.amazonaws diff --git a/pom.xml b/pom.xml index 36abf162e..9e23dcef2 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.152 + 2.20.153 2.14.0 2.1.3 UTF-8 From dd364dd6bbd93523e9669d2fd14eda377d9739a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 14:15:44 +0200 Subject: [PATCH 059/577] build(deps): bump com.github.spotbugs:spotbugs-maven-plugin (#1448) Bumps [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) from 4.7.3.5 to 4.7.3.6. - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.7.3.5...spotbugs-maven-plugin-4.7.3.6) --- updated-dependencies: - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9e23dcef2..4f4ccb2bd 100644 --- a/pom.xml +++ b/pom.xml @@ -505,7 +505,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.7.3.5 + 4.7.3.6 test From 4d3484fdea1a519f06569ef688efd2bf32a689b8 Mon Sep 17 00:00:00 2001 From: Alexey Soshin Date: Thu, 28 Sep 2023 08:12:20 +0100 Subject: [PATCH 060/577] docs: Add Serveless Framework example (#1363) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial * Add memory size and timeouts, same as SAM examples * Add useful Serverless commands * Remove redundant function * Update examples/powertools-examples-core/serverless/README.md Co-authored-by: Scott Gerring * Update examples/powertools-examples-core/serverless/README.md Co-authored-by: Scott Gerring * Update examples/powertools-examples-core/serverless/README.md Co-authored-by: Scott Gerring * Update examples/powertools-examples-core/serverless/README.md Co-authored-by: Scott Gerring * Update examples/powertools-examples-core/serverless/README.md Co-authored-by: Scott Gerring * Remove reduntant command from README * Move most of Powertools configuration to the service-wide environment * Remove more generated comments * Add newlines * Comment out annotations that are preceded by environment variables * Add link to the Serverless example * Update examples/powertools-examples-core/serverless/pom.xml Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Update examples/powertools-examples-core/serverless/pom.xml Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Update examples/powertools-examples-core/serverless/pom.xml Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Remove POWERTOOLS_LOGGER_LOG_EVENT, since it's unsupported --------- Co-authored-by: Scott Gerring Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> --- examples/README.md | 1 + examples/pom.xml | 1 + examples/powertools-examples-core/README.md | 1 + .../serverless/README.md | 26 +++ .../serverless/pom.xml | 209 ++++++++++++++++++ .../serverless/serverless.yml | 40 ++++ .../src/main/java/helloworld/App.java | 105 +++++++++ .../src/main/java/helloworld/AppStream.java | 38 ++++ .../serverless/src/main/resources/log4j2.xml | 16 ++ .../src/test/java/helloworld/AppTest.java | 59 +++++ 10 files changed, 496 insertions(+) create mode 100644 examples/powertools-examples-core/serverless/README.md create mode 100644 examples/powertools-examples-core/serverless/pom.xml create mode 100644 examples/powertools-examples-core/serverless/serverless.yml create mode 100644 examples/powertools-examples-core/serverless/src/main/java/helloworld/App.java create mode 100644 examples/powertools-examples-core/serverless/src/main/java/helloworld/AppStream.java create mode 100644 examples/powertools-examples-core/serverless/src/main/resources/log4j2.xml create mode 100644 examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java diff --git a/examples/README.md b/examples/README.md index 0744c2bb1..52dc0c1e9 100644 --- a/examples/README.md +++ b/examples/README.md @@ -8,6 +8,7 @@ Each example can be copied from its subdirectory and used independently of the r * [powertools-examples-core](powertools-examples-core) - Demonstrates the core logging, tracing, and metrics modules with different build tools * [SAM](./powertools-examples-core/sam) * [CDK](./powertools-examples-core/cdk) + * [Serverless](./powertools-examples-core/serverless) * [powertools-examples-idempotency](powertools-examples-idempotency) - An idempotent HTTP API * [powertools-examples-parameters](powertools-examples-parameters) - Uses the parameters module to provide runtime parameters to a function * [powertools-examples-serialization](powertools-examples-serialization) - Uses the serialization module to serialize and deserialize API Gateway & SQS payloads diff --git a/examples/pom.xml b/examples/pom.xml index eae9e10e5..810ec1b36 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -32,6 +32,7 @@ powertools-examples-core/sam powertools-examples-core/cdk/app powertools-examples-core/cdk/infra + powertools-examples-core/serverless powertools-examples-idempotency powertools-examples-parameters powertools-examples-serialization diff --git a/examples/powertools-examples-core/README.md b/examples/powertools-examples-core/README.md index d690b01c5..1d1dd031f 100644 --- a/examples/powertools-examples-core/README.md +++ b/examples/powertools-examples-core/README.md @@ -9,6 +9,7 @@ We provide examples for the following infrastructure-as-code tools: * [AWS SAM](sam/) * [AWS CDK](cdk/) +* [Serverless framework](serverless/) We also provide an example showing the integration of SAM, Powertools, and Gradle: diff --git a/examples/powertools-examples-core/serverless/README.md b/examples/powertools-examples-core/serverless/README.md new file mode 100644 index 000000000..aec093182 --- /dev/null +++ b/examples/powertools-examples-core/serverless/README.md @@ -0,0 +1,26 @@ +# Powertools for AWS Lambda (Java) - Core Utilities Example with Serverless Framework + +This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Framework](https://www.serverless.com/framework). +For general information on the deployed example itself, you can refer to the parent [README](../README.md). +To install Serverless Framework if you don't have it yet, you can follow the [Getting Started Guide](https://www.serverless.com/framework/docs/getting-started). + +## Configuration +Serverless Framework uses [serverless.yml](./serverless.yml) to define the application's AWS resources. +This file defines the Lambda function to be deployed as well as API Gateway for it. + +It is a [Maven](https://maven.apache.org/) based project, so you can open this project with any Maven compatible Java IDE to build and run tests. + + +## Deploy the sample application + +To deploy the app, simply run the following commands: +```bash +mvn package && sls deploy +``` + +## Useful commands + +Deploy a single function +```bash +sls deploy function -f hello +``` \ No newline at end of file diff --git a/examples/powertools-examples-core/serverless/pom.xml b/examples/powertools-examples-core/serverless/pom.xml new file mode 100644 index 000000000..793318da3 --- /dev/null +++ b/examples/powertools-examples-core/serverless/pom.xml @@ -0,0 +1,209 @@ + + 4.0.0 + + software.amazon.lambda.examples + 1.18.0-SNAPSHOT + powertools-examples-core-serverless + jar + + Powertools for AWS Lambda (Java) library Examples - Core + + + 2.20.0 + 1.8 + 1.8 + + + + + software.amazon.lambda + powertools-tracing + ${project.version} + + + software.amazon.lambda + powertools-logging + ${project.version} + + + software.amazon.lambda + powertools-metrics + ${project.version} + + + com.amazonaws + aws-lambda-java-core + 1.2.2 + + + com.amazonaws + aws-lambda-java-events + 3.11.2 + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + + junit + junit + 4.13.2 + test + + + + + helloworld-lambda + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + + com.github.edwgiz + maven-shade-plugin.log4j2-cachefile-transformer + 2.15 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + + + + jdk8 + + (,11) + + + 1.9.7 + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + + + dev.aspectj + aspectj-maven-plugin + ${aspectj.plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + test-compile + + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + + + + diff --git a/examples/powertools-examples-core/serverless/serverless.yml b/examples/powertools-examples-core/serverless/serverless.yml new file mode 100644 index 000000000..d8dec8080 --- /dev/null +++ b/examples/powertools-examples-core/serverless/serverless.yml @@ -0,0 +1,40 @@ +service: hello +# app and org for use with dashboard.serverless.com +#app: your-app-name +#org: your-org-name + +# You can pin your service to only deploy with a specific Serverless version +# Check out our docs for more details +frameworkVersion: '3' + +provider: + name: aws + runtime: java11 + +# you can overwrite defaults here +# stage: dev +# region: us-east-1 + +# you can define service wide environment variables here + environment: + POWERTOOLS_LOG_LEVEL: INFO + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 + POWERTOOLS_METRICS_NAMESPACE: Coreutilities + +# you can add packaging information here +package: + artifact: target/helloworld-lambda.jar + +functions: + hello: + handler: helloworld.App + memorySize: 512 + timeout: 20 + tracing: "Active" + events: + - httpApi: + path: /hello + method: get +# Define function environment variables here + environment: + POWERTOOLS_SERVICE_NAME: hello diff --git a/examples/powertools-examples-core/serverless/src/main/java/helloworld/App.java b/examples/powertools-examples-core/serverless/src/main/java/helloworld/App.java new file mode 100644 index 000000000..dacd7f1d4 --- /dev/null +++ b/examples/powertools-examples-core/serverless/src/main/java/helloworld/App.java @@ -0,0 +1,105 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; +import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; +import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.tracing.CaptureMode; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.tracing.TracingUtils; + +/** + * Handler for requests to Lambda function. + */ +public class App implements RequestHandler { + private final static Logger log = LogManager.getLogger(App.class); + + // This is controlled by POWERTOOLS_LOGGER_SAMPLE_RATE environment variable + // @Logging(logEvent = true, samplingRate = 0.7) + // This is controlled by POWERTOOLS_METRICS_NAMESPACE environment variable + // @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + // This is controlled by POWERTOOLS_TRACER_CAPTURE_ERROR environment variable + @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + Map headers = new HashMap<>(); + + headers.put("Content-Type", "application/json"); + headers.put("X-Custom-Header", "application/json"); + + metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + + withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> + { + metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); + metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); + }); + + LoggingUtils.appendKey("test", "willBeLogged"); + + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() + .withHeaders(headers); + try { + final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); + log.info(pageContents); + TracingUtils.putAnnotation("Test", "New"); + String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); + + TracingUtils.withSubsegment("loggingResponse", subsegment -> + { + String sampled = "log something out"; + log.info(sampled); + log.info(output); + }); + + log.info("After output"); + return response + .withStatusCode(200) + .withBody(output); + } catch (RuntimeException | IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + putMetadata("getPageContents", address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-core/serverless/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/serverless/src/main/java/helloworld/AppStream.java new file mode 100644 index 000000000..401ef8c48 --- /dev/null +++ b/examples/powertools-examples-core/serverless/src/main/java/helloworld/AppStream.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.Metrics; + +public class AppStream implements RequestStreamHandler { + private static final ObjectMapper mapper = new ObjectMapper(); + + @Override + @Logging(logEvent = true) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { + Map map = mapper.readValue(input, Map.class); + + System.out.println(map.size()); + } +} diff --git a/examples/powertools-examples-core/serverless/src/main/resources/log4j2.xml b/examples/powertools-examples-core/serverless/src/main/resources/log4j2.xml new file mode 100644 index 000000000..0cc0953f0 --- /dev/null +++ b/examples/powertools-examples-core/serverless/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java new file mode 100644 index 000000000..70dad8d71 --- /dev/null +++ b/examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import com.amazonaws.xray.AWSXRay; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class AppTest { + + @Before + public void setup() { + if (null == System.getenv("LAMBDA_TASK_ROOT")) { + AWSXRay.beginSegment("test"); + } + } + + @After + public void tearDown() { + if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) { + AWSXRay.endSubsegment(); + } + + if (null == System.getenv("LAMBDA_TASK_ROOT")) { + AWSXRay.endSegment(); + } + } + + @Test + public void successfulResponse() { + App app = new App(); + APIGatewayProxyResponseEvent result = app.handleRequest(null, null); + assertEquals(result.getStatusCode().intValue(), 200); + assertEquals(result.getHeaders().get("Content-Type"), "application/json"); + String content = result.getBody(); + assertNotNull(content); + assertTrue(content.contains("\"message\"")); + assertTrue(content.contains("\"hello world\"")); + assertTrue(content.contains("\"location\"")); + } +} From fa75c7499ab2a8566ad90e6f10dfe84bb873dd1d Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Mon, 2 Oct 2023 11:48:09 +0200 Subject: [PATCH 061/577] docs: apply line highlight only for default light mode (#1453) --- docs/stylesheets/extra.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index de2f3b5f9..d135d7210 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -3,7 +3,9 @@ } .highlight .hll { - background-color: lavender + [data-md-color-scheme="default"] { + background-color: lavender; + } } .md-typeset table:not([class]) { From 1140fcfb2ceb16a701608ec82dc255142ac6c815 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Thu, 5 Oct 2023 17:54:53 +0200 Subject: [PATCH 062/577] fix: Fix schema validation unit test build issues (#1456) * Is it just the one test? * What about this * Temporary fix --- .../validation/ValidationUtilsTest.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java index fa0d1394c..cd6ad160c 100644 --- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java @@ -70,12 +70,19 @@ public void testLoadMetaSchema_NoValidation() { }); } - @Test - public void testLoadMetaSchemaV2019() { - ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V201909); - JsonSchema jsonSchema = getJsonSchema("classpath:/schemas/meta_schema_V201909", true); - assertThat(jsonSchema).isNotNull(); - } + /** + * TODO - get this going again on github; commented out to unblock build, and seems to run outside of github + * workers still. See here --> + * + * https://github.com/aws-powertools/powertools-lambda-java/actions/runs/6417845031/job/17424409856?pr=1456 + * https://github.com/aws-powertools/powertools-lambda-java/issues/1455 + */ +// @Test +// public void testLoadMetaSchemaV2019() { +// ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V201909); +// JsonSchema jsonSchema = getJsonSchema("classpath:/schemas/meta_schema_V201909", true); +// assertThat(jsonSchema).isNotNull(); +// } @Test public void testLoadMetaSchemaV7() { From 3ea3fa101a5a6a6228051abc70958c10b5374c6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Fri, 6 Oct 2023 14:59:29 +0200 Subject: [PATCH 063/577] Use URITranslator to use local files instead of remote (#1457) Remove local schema files, use the ones provided in the dependency Add support for 202012 Update tests --- .../validation/ValidationConfig.java | 2 +- .../validation/ValidationUtils.java | 13 +- .../main/resources/schemas/meta/applicator | 56 ------ .../src/main/resources/schemas/meta/content | 17 -- .../src/main/resources/schemas/meta/core | 57 ------ .../src/main/resources/schemas/meta/format | 14 -- .../src/main/resources/schemas/meta/meta-data | 37 ---- .../main/resources/schemas/meta/validation | 98 ---------- .../resources/schemas/meta_schema_V201909 | 42 ----- .../src/main/resources/schemas/meta_schema_V4 | 149 --------------- .../src/main/resources/schemas/meta_schema_V6 | 155 ---------------- .../src/main/resources/schemas/meta_schema_V7 | 172 ------------------ .../validation/ValidationUtilsTest.java | 34 ++-- 13 files changed, 27 insertions(+), 819 deletions(-) delete mode 100644 powertools-validation/src/main/resources/schemas/meta/applicator delete mode 100644 powertools-validation/src/main/resources/schemas/meta/content delete mode 100644 powertools-validation/src/main/resources/schemas/meta/core delete mode 100644 powertools-validation/src/main/resources/schemas/meta/format delete mode 100644 powertools-validation/src/main/resources/schemas/meta/meta-data delete mode 100644 powertools-validation/src/main/resources/schemas/meta/validation delete mode 100644 powertools-validation/src/main/resources/schemas/meta_schema_V201909 delete mode 100644 powertools-validation/src/main/resources/schemas/meta_schema_V4 delete mode 100644 powertools-validation/src/main/resources/schemas/meta_schema_V6 delete mode 100644 powertools-validation/src/main/resources/schemas/meta_schema_V7 diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java index baf5e2465..143f0584d 100644 --- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java @@ -49,7 +49,7 @@ public SpecVersion.VersionFlag getSchemaVersion() { /** * Set the version of the json schema specifications (default is V7) * - * @param version May be V4, V6, V7 or V201909 + * @param version May be V4, V6, V7, V201909 or V202012 */ public void setSchemaVersion(SpecVersion.VersionFlag version) { if (version != jsonSchemaVersion) { diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java index 4eecb3ab5..221e5fb1d 100644 --- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java @@ -21,7 +21,9 @@ import com.fasterxml.jackson.databind.node.JsonNodeType; import com.fasterxml.jackson.databind.node.NullNode; import com.networknt.schema.JsonSchema; +import com.networknt.schema.SchemaValidatorsConfig; import com.networknt.schema.ValidationMessage; +import com.networknt.schema.uri.URITranslator; import io.burt.jmespath.Expression; import java.io.ByteArrayOutputStream; import java.io.InputStream; @@ -257,7 +259,10 @@ private static JsonSchema createJsonSchema(String schema) { String filePath = schema.substring(CLASSPATH.length()); try (InputStream schemaStream = ValidationAspect.class.getResourceAsStream(filePath)) { - jsonSchema = ValidationConfig.get().getFactory().getSchema(schemaStream); + SchemaValidatorsConfig config = new SchemaValidatorsConfig(); + config.addUriTranslator(URITranslator.prefix("https://json-schema.org", "resource:")); + + jsonSchema = ValidationConfig.get().getFactory().getSchema(schemaStream, config); } catch (Exception e) { throw new IllegalArgumentException( "'" + schema + "' is invalid, verify '" + filePath + "' is in your classpath"); @@ -270,13 +275,13 @@ private static JsonSchema createJsonSchema(String schema) { } private static void validateSchema(String schema, JsonSchema jsonSchema) { - String version = ValidationConfig.get().getSchemaVersion().toString(); + String schemaId = ValidationConfig.get().getSchemaVersion().getId().replace("https://json-schema.org", ""); try { validate(jsonSchema.getSchemaNode(), - getJsonSchema("classpath:/schemas/meta_schema_" + version)); + getJsonSchema(CLASSPATH + schemaId)); } catch (ValidationException ve) { throw new IllegalArgumentException( - "The schema " + schema + " is not valid, it does not respect the specification " + version, ve); + "The schema " + schema + " is not valid, it does not respect the specification " + schemaId, ve); } } diff --git a/powertools-validation/src/main/resources/schemas/meta/applicator b/powertools-validation/src/main/resources/schemas/meta/applicator deleted file mode 100644 index 24a1cc4f4..000000000 --- a/powertools-validation/src/main/resources/schemas/meta/applicator +++ /dev/null @@ -1,56 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/applicator", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/applicator": true - }, - "$recursiveAnchor": true, - - "title": "Applicator vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "additionalItems": { "$recursiveRef": "#" }, - "unevaluatedItems": { "$recursiveRef": "#" }, - "items": { - "anyOf": [ - { "$recursiveRef": "#" }, - { "$ref": "#/$defs/schemaArray" } - ] - }, - "contains": { "$recursiveRef": "#" }, - "additionalProperties": { "$recursiveRef": "#" }, - "unevaluatedProperties": { "$recursiveRef": "#" }, - "properties": { - "type": "object", - "additionalProperties": { "$recursiveRef": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "additionalProperties": { "$recursiveRef": "#" }, - "propertyNames": { "format": "regex" }, - "default": {} - }, - "dependentSchemas": { - "type": "object", - "additionalProperties": { - "$recursiveRef": "#" - } - }, - "propertyNames": { "$recursiveRef": "#" }, - "if": { "$recursiveRef": "#" }, - "then": { "$recursiveRef": "#" }, - "else": { "$recursiveRef": "#" }, - "allOf": { "$ref": "#/$defs/schemaArray" }, - "anyOf": { "$ref": "#/$defs/schemaArray" }, - "oneOf": { "$ref": "#/$defs/schemaArray" }, - "not": { "$recursiveRef": "#" } - }, - "$defs": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$recursiveRef": "#" } - } - } -} diff --git a/powertools-validation/src/main/resources/schemas/meta/content b/powertools-validation/src/main/resources/schemas/meta/content deleted file mode 100644 index f6752a8ef..000000000 --- a/powertools-validation/src/main/resources/schemas/meta/content +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/content", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/content": true - }, - "$recursiveAnchor": true, - - "title": "Content vocabulary meta-schema", - - "type": ["object", "boolean"], - "properties": { - "contentMediaType": { "type": "string" }, - "contentEncoding": { "type": "string" }, - "contentSchema": { "$recursiveRef": "#" } - } -} diff --git a/powertools-validation/src/main/resources/schemas/meta/core b/powertools-validation/src/main/resources/schemas/meta/core deleted file mode 100644 index eb708a560..000000000 --- a/powertools-validation/src/main/resources/schemas/meta/core +++ /dev/null @@ -1,57 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/core", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/core": true - }, - "$recursiveAnchor": true, - - "title": "Core vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "$id": { - "type": "string", - "format": "uri-reference", - "$comment": "Non-empty fragments not allowed.", - "pattern": "^[^#]*#?$" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "$anchor": { - "type": "string", - "pattern": "^[A-Za-z][-A-Za-z0-9.:_]*$" - }, - "$ref": { - "type": "string", - "format": "uri-reference" - }, - "$recursiveRef": { - "type": "string", - "format": "uri-reference" - }, - "$recursiveAnchor": { - "type": "boolean", - "default": false - }, - "$vocabulary": { - "type": "object", - "propertyNames": { - "type": "string", - "format": "uri" - }, - "additionalProperties": { - "type": "boolean" - } - }, - "$comment": { - "type": "string" - }, - "$defs": { - "type": "object", - "additionalProperties": { "$recursiveRef": "#" }, - "default": {} - } - } -} diff --git a/powertools-validation/src/main/resources/schemas/meta/format b/powertools-validation/src/main/resources/schemas/meta/format deleted file mode 100644 index 09bbfdda9..000000000 --- a/powertools-validation/src/main/resources/schemas/meta/format +++ /dev/null @@ -1,14 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/format", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/format": true - }, - "$recursiveAnchor": true, - - "title": "Format vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "format": { "type": "string" } - } -} diff --git a/powertools-validation/src/main/resources/schemas/meta/meta-data b/powertools-validation/src/main/resources/schemas/meta/meta-data deleted file mode 100644 index da04cff6d..000000000 --- a/powertools-validation/src/main/resources/schemas/meta/meta-data +++ /dev/null @@ -1,37 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/meta-data", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/meta-data": true - }, - "$recursiveAnchor": true, - - "title": "Meta-data vocabulary meta-schema", - - "type": ["object", "boolean"], - "properties": { - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": true, - "deprecated": { - "type": "boolean", - "default": false - }, - "readOnly": { - "type": "boolean", - "default": false - }, - "writeOnly": { - "type": "boolean", - "default": false - }, - "examples": { - "type": "array", - "items": true - } - } -} diff --git a/powertools-validation/src/main/resources/schemas/meta/validation b/powertools-validation/src/main/resources/schemas/meta/validation deleted file mode 100644 index 9f59677b3..000000000 --- a/powertools-validation/src/main/resources/schemas/meta/validation +++ /dev/null @@ -1,98 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/meta/validation", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/validation": true - }, - "$recursiveAnchor": true, - - "title": "Validation vocabulary meta-schema", - "type": ["object", "boolean"], - "properties": { - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { "$ref": "#/$defs/nonNegativeInteger" }, - "minLength": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "maxItems": { "$ref": "#/$defs/nonNegativeInteger" }, - "minItems": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "maxContains": { "$ref": "#/$defs/nonNegativeInteger" }, - "minContains": { - "$ref": "#/$defs/nonNegativeInteger", - "default": 1 - }, - "maxProperties": { "$ref": "#/$defs/nonNegativeInteger" }, - "minProperties": { "$ref": "#/$defs/nonNegativeIntegerDefault0" }, - "required": { "$ref": "#/$defs/stringArray" }, - "dependentRequired": { - "type": "object", - "additionalProperties": { - "$ref": "#/$defs/stringArray" - } - }, - "const": true, - "enum": { - "type": "array", - "items": true - }, - "type": { - "anyOf": [ - { "$ref": "#/$defs/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/$defs/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - } - }, - "$defs": { - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "$ref": "#/$defs/nonNegativeInteger", - "default": 0 - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "uniqueItems": true, - "default": [] - } - } -} diff --git a/powertools-validation/src/main/resources/schemas/meta_schema_V201909 b/powertools-validation/src/main/resources/schemas/meta_schema_V201909 deleted file mode 100644 index 2248a0c80..000000000 --- a/powertools-validation/src/main/resources/schemas/meta_schema_V201909 +++ /dev/null @@ -1,42 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2019-09/schema", - "$id": "https://json-schema.org/draft/2019-09/schema", - "$vocabulary": { - "https://json-schema.org/draft/2019-09/vocab/core": true, - "https://json-schema.org/draft/2019-09/vocab/applicator": true, - "https://json-schema.org/draft/2019-09/vocab/validation": true, - "https://json-schema.org/draft/2019-09/vocab/meta-data": true, - "https://json-schema.org/draft/2019-09/vocab/format": false, - "https://json-schema.org/draft/2019-09/vocab/content": true - }, - "$recursiveAnchor": true, - - "title": "Core and Validation specifications meta-schema", - "allOf": [ - {"$ref": "meta/core"}, - {"$ref": "meta/applicator"}, - {"$ref": "meta/validation"}, - {"$ref": "meta/meta-data"}, - {"$ref": "meta/format"}, - {"$ref": "meta/content"} - ], - "type": ["object", "boolean"], - "properties": { - "definitions": { - "$comment": "While no longer an official keyword as it is replaced by $defs, this keyword is retained in the meta-schema to prevent incompatible extensions as it remains in common use.", - "type": "object", - "additionalProperties": { "$recursiveRef": "#" }, - "default": {} - }, - "dependencies": { - "$comment": "\"dependencies\" is no longer a keyword, but schema authors should avoid redefining it to facilitate a smooth transition to \"dependentSchemas\" and \"dependentRequired\"", - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$recursiveRef": "#" }, - { "$ref": "meta/validation#/$defs/stringArray" } - ] - } - } - } -} diff --git a/powertools-validation/src/main/resources/schemas/meta_schema_V4 b/powertools-validation/src/main/resources/schemas/meta_schema_V4 deleted file mode 100644 index bcbb84743..000000000 --- a/powertools-validation/src/main/resources/schemas/meta_schema_V4 +++ /dev/null @@ -1,149 +0,0 @@ -{ - "id": "http://json-schema.org/draft-04/schema#", - "$schema": "http://json-schema.org/draft-04/schema#", - "description": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "positiveInteger": { - "type": "integer", - "minimum": 0 - }, - "positiveIntegerDefault0": { - "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ] - }, - "simpleTypes": { - "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "minItems": 1, - "uniqueItems": true - } - }, - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "$schema": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": {}, - "multipleOf": { - "type": "number", - "minimum": 0, - "exclusiveMinimum": true - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "boolean", - "default": false - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "boolean", - "default": false - }, - "maxLength": { "$ref": "#/definitions/positiveInteger" }, - "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { - "anyOf": [ - { "type": "boolean" }, - { "$ref": "#" } - ], - "default": {} - }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": {} - }, - "maxItems": { "$ref": "#/definitions/positiveInteger" }, - "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "maxProperties": { "$ref": "#/definitions/positiveInteger" }, - "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { - "anyOf": [ - { "type": "boolean" }, - { "$ref": "#" } - ], - "default": {} - }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "enum": { - "type": "array", - "minItems": 1, - "uniqueItems": true - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "format": { "type": "string" }, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" } - }, - "dependencies": { - "exclusiveMaximum": [ "maximum" ], - "exclusiveMinimum": [ "minimum" ] - }, - "default": {} -} diff --git a/powertools-validation/src/main/resources/schemas/meta_schema_V6 b/powertools-validation/src/main/resources/schemas/meta_schema_V6 deleted file mode 100644 index bd3e763bc..000000000 --- a/powertools-validation/src/main/resources/schemas/meta_schema_V6 +++ /dev/null @@ -1,155 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "http://json-schema.org/draft-06/schema#", - "title": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "allOf": [ - { "$ref": "#/definitions/nonNegativeInteger" }, - { "default": 0 } - ] - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "uniqueItems": true, - "default": [] - } - }, - "type": ["object", "boolean"], - "properties": { - "$id": { - "type": "string", - "format": "uri-reference" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "$ref": { - "type": "string", - "format": "uri-reference" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": {}, - "examples": { - "type": "array", - "items": {} - }, - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, - "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { "$ref": "#" }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": {} - }, - "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, - "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "contains": { "$ref": "#" }, - "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, - "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { "$ref": "#" }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "propertyNames": { "format": "regex" }, - "default": {} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "propertyNames": { "$ref": "#" }, - "const": {}, - "enum": { - "type": "array", - "minItems": 1, - "uniqueItems": true - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "format": { "type": "string" }, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" } - }, - "default": {} -} diff --git a/powertools-validation/src/main/resources/schemas/meta_schema_V7 b/powertools-validation/src/main/resources/schemas/meta_schema_V7 deleted file mode 100644 index fb92c7f75..000000000 --- a/powertools-validation/src/main/resources/schemas/meta_schema_V7 +++ /dev/null @@ -1,172 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "http://json-schema.org/draft-07/schema#", - "title": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "allOf": [ - { "$ref": "#/definitions/nonNegativeInteger" }, - { "default": 0 } - ] - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "uniqueItems": true, - "default": [] - } - }, - "type": ["object", "boolean"], - "properties": { - "$id": { - "type": "string", - "format": "uri-reference" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "$ref": { - "type": "string", - "format": "uri-reference" - }, - "$comment": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": true, - "readOnly": { - "type": "boolean", - "default": false - }, - "writeOnly": { - "type": "boolean", - "default": false - }, - "examples": { - "type": "array", - "items": true - }, - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, - "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { "$ref": "#" }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": true - }, - "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, - "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "contains": { "$ref": "#" }, - "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, - "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { "$ref": "#" }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "propertyNames": { "format": "regex" }, - "default": {} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "propertyNames": { "$ref": "#" }, - "const": true, - "enum": { - "type": "array", - "items": true, - "minItems": 1, - "uniqueItems": true - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "format": { "type": "string" }, - "contentMediaType": { "type": "string" }, - "contentEncoding": { "type": "string" }, - "if": { "$ref": "#" }, - "then": { "$ref": "#" }, - "else": { "$ref": "#" }, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" } - }, - "default": true -} diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java index cd6ad160c..d80670669 100644 --- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java @@ -57,7 +57,7 @@ public void testLoadSchemaV7KO() { assertThatThrownBy(() -> getJsonSchema("classpath:/schema_v7_ko.json", true)) .isInstanceOf(IllegalArgumentException.class) .hasMessage( - "The schema classpath:/schema_v7_ko.json is not valid, it does not respect the specification V7"); + "The schema classpath:/schema_v7_ko.json is not valid, it does not respect the specification /draft-07/schema"); } @Test @@ -70,38 +70,38 @@ public void testLoadMetaSchema_NoValidation() { }); } - /** - * TODO - get this going again on github; commented out to unblock build, and seems to run outside of github - * workers still. See here --> - * - * https://github.com/aws-powertools/powertools-lambda-java/actions/runs/6417845031/job/17424409856?pr=1456 - * https://github.com/aws-powertools/powertools-lambda-java/issues/1455 - */ -// @Test -// public void testLoadMetaSchemaV2019() { -// ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V201909); -// JsonSchema jsonSchema = getJsonSchema("classpath:/schemas/meta_schema_V201909", true); -// assertThat(jsonSchema).isNotNull(); -// } + @Test + public void testLoadMetaSchemaV2019() { + ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V201909); + JsonSchema jsonSchema = getJsonSchema("classpath:/draft/2019-09/schema", true); + assertThat(jsonSchema).isNotNull(); + } + + @Test + public void testLoadMetaSchemaV2020() { + ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V202012); + JsonSchema jsonSchema = getJsonSchema("classpath:/draft/2020-12/schema", true); + assertThat(jsonSchema).isNotNull(); + } @Test public void testLoadMetaSchemaV7() { ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V7); - JsonSchema jsonSchema = getJsonSchema("classpath:/schemas/meta_schema_V7", true); + JsonSchema jsonSchema = getJsonSchema("classpath:/draft-07/schema", true); assertThat(jsonSchema).isNotNull(); } @Test public void testLoadMetaSchemaV6() { ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V6); - JsonSchema jsonSchema = getJsonSchema("classpath:/schemas/meta_schema_V6", true); + JsonSchema jsonSchema = getJsonSchema("classpath:/draft-06/schema", true); assertThat(jsonSchema).isNotNull(); } @Test public void testLoadMetaSchemaV4() { ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V4); - JsonSchema jsonSchema = getJsonSchema("classpath:/schemas/meta_schema_V4", true); + JsonSchema jsonSchema = getJsonSchema("classpath:/draft-04/schema", true); assertThat(jsonSchema).isNotNull(); } From 965c897d00ef2995c1efb8413115c4a1e18ae098 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 13:42:53 +0200 Subject: [PATCH 064/577] build(deps): bump aws.sdk.version from 2.20.153 to 2.20.155 (#1447) Bumps `aws.sdk.version` from 2.20.153 to 2.20.155. Updates `software.amazon.awssdk:bom` from 2.20.153 to 2.20.155 Updates `software.amazon.awssdk:http-client-spi` from 2.20.153 to 2.20.155 Updates `software.amazon.awssdk:url-connection-client` from 2.20.152 to 2.20.155 Updates `software.amazon.awssdk:sqs` from 2.20.152 to 2.20.155 Updates `software.amazon.awssdk:s3` from 2.20.153 to 2.20.155 Updates `software.amazon.awssdk:dynamodb` from 2.20.153 to 2.20.155 Updates `software.amazon.awssdk:lambda` from 2.20.153 to 2.20.155 Updates `software.amazon.awssdk:kinesis` from 2.20.152 to 2.20.155 Updates `software.amazon.awssdk:cloudwatch` from 2.20.153 to 2.20.155 Updates `software.amazon.awssdk:xray` from 2.20.153 to 2.20.155 Updates `software.amazon.awssdk:cloudformation` from 2.20.153 to 2.20.155 Updates `software.amazon.awssdk:sts` from 2.20.153 to 2.20.155 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 8fdcb8c08..db66b8675 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.153 + 2.20.155 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index c0c302757..38b46c020 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.153 + 2.20.155 com.amazonaws diff --git a/pom.xml b/pom.xml index 4f4ccb2bd..ee3bc1c2e 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.153 + 2.20.155 2.14.0 2.1.3 UTF-8 From e99bfad9f93f3bbac7e4e32670be6d46017cdf1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 13:43:59 +0200 Subject: [PATCH 065/577] build(deps): bump com.networknt:json-schema-validator (#1446) Bumps [com.networknt:json-schema-validator](https://github.com/networknt/json-schema-validator) from 1.0.86 to 1.0.87. - [Release notes](https://github.com/networknt/json-schema-validator/releases) - [Changelog](https://github.com/networknt/json-schema-validator/blob/master/CHANGELOG.md) - [Commits](https://github.com/networknt/json-schema-validator/compare/1.0.86...1.0.87) --- updated-dependencies: - dependency-name: com.networknt:json-schema-validator dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-validation/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 23841777e..606f02139 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -87,7 +87,7 @@ com.networknt json-schema-validator - 1.0.86 + 1.0.87 com.amazonaws From 349ea0b937a1b39b7b8926ae6985f4545c9fe33f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 13:58:49 +0200 Subject: [PATCH 066/577] build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1461) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.97.1 to 2.100.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.97.1...v2.100.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index 99598ba58..216bf35d4 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -7,7 +7,7 @@ 1.18.0-SNAPSHOT UTF-8 - 2.97.1 + 2.100.0 [10.0.0,11.0.0) 5.10.0 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 90427b797..89a255c8b 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ 1.8 1.8 10.2.70 - 2.97.1 + 2.100.0 From aa53bd924573faf2ae3687d3b07c459a6640b419 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 13:19:10 +0200 Subject: [PATCH 067/577] build(deps): bump aws.sdk.version from 2.20.155 to 2.20.162 (#1462) Bumps `aws.sdk.version` from 2.20.155 to 2.20.162. --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index db66b8675..c696ef0a8 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.155 + 2.20.162 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 38b46c020..988291413 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.155 + 2.20.162 com.amazonaws diff --git a/pom.xml b/pom.xml index ee3bc1c2e..277f2f681 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.155 + 2.20.162 2.14.0 2.1.3 UTF-8 From 897f7e9af665299695f5613f3607348e613f46a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Oct 2023 14:02:49 +0200 Subject: [PATCH 068/577] build(deps): bump org.apache.maven.plugins:maven-javadoc-plugin (#1473) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.5.0 to 3.6.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.5.0...maven-javadoc-plugin-3.6.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 277f2f681..fd31bef37 100644 --- a/pom.xml +++ b/pom.xml @@ -88,7 +88,7 @@ 3.1.2 0.8.10 1.6.13 - 3.5.0 + 3.6.0 3.3.0 3.1.0 5.10.0 From c5ced4f70e8fcec8d635aadbc136a8cac7ba24d6 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Fri, 13 Oct 2023 13:55:58 +0200 Subject: [PATCH 069/577] Remove powertools-examples-core --- .../powertools-examples-core/cdk/README.md | 36 --- .../cdk/app/events/event.json | 63 ----- .../powertools-examples-core/cdk/app/pom.xml | 241 ----------------- .../cdk/app/src/main/java/helloworld/App.java | 107 -------- .../src/main/java/helloworld/AppStream.java | 38 --- .../cdk/app/src/main/resources/log4j2.xml | 16 -- .../app/src/test/java/helloworld/AppTest.java | 59 ----- .../cdk/infra/cdk.json | 36 --- .../cdk/infra/pom.xml | 63 ----- .../cdk/infra/src/main/java/cdk/CdkApp.java | 53 ---- .../cdk/infra/src/main/java/cdk/CdkStack.java | 144 ---------- .../infra/src/test/java/cdk/CdkStackTest.java | 48 ---- .../powertools-examples-core/gradle/README.md | 38 --- .../gradle/build.gradle | 35 --- .../gradle/events/event.json | 62 ----- .../gradle/gradle/wrapper/.gitignore | 2 - .../gradle/gradle/wrapper/gradle-wrapper.jar | Bin 63375 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - .../powertools-examples-core/gradle/gradlew | 248 ------------------ .../gradle/gradlew.bat | 92 ------- .../gradle/src/main/java/helloworld/App.java | 107 -------- .../src/main/java/helloworld/AppStream.java | 38 --- .../src/test/java/helloworld/AppTest.java | 24 -- .../gradle/template.yaml | 71 ----- .../powertools-examples-core/sam/README.md | 24 -- .../sam/events/event.json | 63 ----- examples/powertools-examples-core/sam/pom.xml | 207 --------------- .../sam/src/main/java/helloworld/App.java | 107 -------- .../src/main/java/helloworld/AppStream.java | 38 --- .../sam/src/main/resources/log4j2.xml | 16 -- .../sam/src/test/java/helloworld/AppTest.java | 59 ----- .../sam/template.yaml | 66 ----- .../serverless/README.md | 26 -- .../serverless/pom.xml | 209 --------------- .../serverless/serverless.yml | 40 --- .../src/main/java/helloworld/App.java | 117 --------- .../src/main/java/helloworld/AppStream.java | 38 --- .../serverless/src/main/resources/log4j2.xml | 16 -- .../src/test/java/helloworld/AppTest.java | 59 ----- 39 files changed, 2713 deletions(-) delete mode 100644 examples/powertools-examples-core/cdk/README.md delete mode 100644 examples/powertools-examples-core/cdk/app/events/event.json delete mode 100644 examples/powertools-examples-core/cdk/app/pom.xml delete mode 100644 examples/powertools-examples-core/cdk/app/src/main/java/helloworld/App.java delete mode 100644 examples/powertools-examples-core/cdk/app/src/main/java/helloworld/AppStream.java delete mode 100644 examples/powertools-examples-core/cdk/app/src/main/resources/log4j2.xml delete mode 100644 examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java delete mode 100644 examples/powertools-examples-core/cdk/infra/cdk.json delete mode 100644 examples/powertools-examples-core/cdk/infra/pom.xml delete mode 100644 examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkApp.java delete mode 100644 examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java delete mode 100644 examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java delete mode 100644 examples/powertools-examples-core/gradle/README.md delete mode 100644 examples/powertools-examples-core/gradle/build.gradle delete mode 100644 examples/powertools-examples-core/gradle/events/event.json delete mode 100644 examples/powertools-examples-core/gradle/gradle/wrapper/.gitignore delete mode 100644 examples/powertools-examples-core/gradle/gradle/wrapper/gradle-wrapper.jar delete mode 100644 examples/powertools-examples-core/gradle/gradle/wrapper/gradle-wrapper.properties delete mode 100755 examples/powertools-examples-core/gradle/gradlew delete mode 100644 examples/powertools-examples-core/gradle/gradlew.bat delete mode 100644 examples/powertools-examples-core/gradle/src/main/java/helloworld/App.java delete mode 100644 examples/powertools-examples-core/gradle/src/main/java/helloworld/AppStream.java delete mode 100644 examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java delete mode 100644 examples/powertools-examples-core/gradle/template.yaml delete mode 100644 examples/powertools-examples-core/sam/README.md delete mode 100644 examples/powertools-examples-core/sam/events/event.json delete mode 100644 examples/powertools-examples-core/sam/pom.xml delete mode 100644 examples/powertools-examples-core/sam/src/main/java/helloworld/App.java delete mode 100644 examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java delete mode 100644 examples/powertools-examples-core/sam/src/main/resources/log4j2.xml delete mode 100644 examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java delete mode 100644 examples/powertools-examples-core/sam/template.yaml delete mode 100644 examples/powertools-examples-core/serverless/README.md delete mode 100644 examples/powertools-examples-core/serverless/pom.xml delete mode 100644 examples/powertools-examples-core/serverless/serverless.yml delete mode 100644 examples/powertools-examples-core/serverless/src/main/java/helloworld/App.java delete mode 100644 examples/powertools-examples-core/serverless/src/main/java/helloworld/AppStream.java delete mode 100644 examples/powertools-examples-core/serverless/src/main/resources/log4j2.xml delete mode 100644 examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java diff --git a/examples/powertools-examples-core/cdk/README.md b/examples/powertools-examples-core/cdk/README.md deleted file mode 100644 index f15a24168..000000000 --- a/examples/powertools-examples-core/cdk/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Powertools for AWS Lambda (Java) - Core Utilities Example with CDK - -This project demonstrates the Lambda for Powertools Java module deployed using [Cloud Development Kit](https://aws.amazon.com/cdk/). - -For general information on the deployed example itself, you can refer to the parent [README](../README.md) - -## Configuration -CDK uses the following project structure: -- [app](./app) - stores the source code of your application, which is similar between all examples -- [infra](./infra) - stores the definition of your infrastructure - - [cdk.json](./infra/cdk.json) - tells the CDK Toolkit how to execute your app - - [CdkApp](./infra/src/main/java/cdk/CdkApp.java) - bootstraps your stack, taking AWS `account` and `region` as input - - [CdkStack](./infra/src/main/java/cdk/CdkStack.java) - defines the Lambda function to be deployed as well as API Gateway for it. - -It is a [Maven](https://maven.apache.org/) based project, so you can open this project with any Maven compatible Java IDE to build and run tests. - - -## Deploy the sample application - -The minimum to deploy the app should be -```bash -cdk deploy -``` - -If you're running CDK for the first time, you'll need to first run the bootstrap command: -```bash -cdk bootstrap -``` - -## Useful commands - -* `mvn package` compile and run tests -* `cdk synth` emits the synthesized CloudFormation template -* `cdk deploy` deploy this stack to your default AWS account/region -* `cdk diff` compare deployed stack with current state -* `cdk docs` open CDK documentation \ No newline at end of file diff --git a/examples/powertools-examples-core/cdk/app/events/event.json b/examples/powertools-examples-core/cdk/app/events/event.json deleted file mode 100644 index 3822fadaa..000000000 --- a/examples/powertools-examples-core/cdk/app/events/event.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "body": "{\"message\": \"hello world\"}", - "resource": "/{proxy+}", - "path": "/path/to/resource", - "httpMethod": "POST", - "isBase64Encoded": false, - "queryStringParameters": { - "foo": "bar" - }, - "pathParameters": { - "proxy": "/path/to/resource" - }, - "stageVariables": { - "baz": "qux" - }, - "headers": { - "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", - "Accept-Encoding": "gzip, deflate, sdch", - "Accept-Language": "en-US,en;q=0.8", - "Cache-Control": "max-age=0", - "CloudFront-Forwarded-Proto": "https", - "CloudFront-Is-Desktop-Viewer": "true", - "CloudFront-Is-Mobile-Viewer": "false", - "CloudFront-Is-SmartTV-Viewer": "false", - "CloudFront-Is-Tablet-Viewer": "false", - "CloudFront-Viewer-Country": "US", - "Host": "1234567890.execute-api.us-east-1.amazonaws.com", - "Upgrade-Insecure-Requests": "1", - "User-Agent": "Custom User Agent String", - "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", - "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", - "X-Forwarded-For": "127.0.0.1, 127.0.0.2", - "X-Forwarded-Port": "443", - "X-Forwarded-Proto": "https" - }, - "requestContext": { - "accountId": "123456789012", - "resourceId": "123456", - "stage": "prod", - "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", - "requestTime": "09/Apr/2015:12:34:56 +0000", - "requestTimeEpoch": 1428582896000, - "identity": { - "cognitoIdentityPoolId": null, - "accountId": null, - "cognitoIdentityId": null, - "caller": null, - "accessKey": null, - "sourceIp": "127.0.0.1", - "cognitoAuthenticationType": null, - "cognitoAuthenticationProvider": null, - "userArn": null, - "userAgent": "Custom User Agent String", - "user": null - }, - "path": "/prod/path/to/resource", - "resourcePath": "/{proxy+}", - "httpMethod": "POST", - "apiId": "1234567890", - "protocol": "HTTP/1.1" - } - } - \ No newline at end of file diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml deleted file mode 100644 index efc24a0ee..000000000 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ /dev/null @@ -1,241 +0,0 @@ - - 4.0.0 - - software.amazon.lambda.examples -<<<<<<<< HEAD:examples/powertools-examples-core-utilities/sam/pom.xml - 2.0.0-SNAPSHOT - powertools-examples-core-utilities-sam - jar - - Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) with SAM -======== - 1.16.1 - powertools-examples-core-cdk - jar - - Powertools for AWS Lambda (Java) library Examples - Core ->>>>>>>> main:examples/powertools-examples-core/cdk/app/pom.xml - - - 2.20.0 - 1.8 - 1.8 -<<<<<<<< HEAD:examples/powertools-examples-core-utilities/sam/pom.xml - 1.9.20 -======== ->>>>>>>> main:examples/powertools-examples-core/cdk/app/pom.xml - - - - - software.amazon.lambda - powertools-tracing - ${project.version} - - - software.amazon.lambda - powertools-logging - ${project.version} - - - software.amazon.lambda - powertools-metrics - ${project.version} - - - com.amazonaws - aws-lambda-java-core - 1.2.3 - - - com.amazonaws - aws-lambda-java-events -<<<<<<<< HEAD:examples/powertools-examples-core-utilities/sam/pom.xml - 3.11.2 -======== - 3.11.3 ->>>>>>>> main:examples/powertools-examples-core/cdk/app/pom.xml - - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - - - org.aspectj - aspectjrt - ${aspectj.version} - - - - junit - junit - 4.13.2 - test - - - - -<<<<<<<< HEAD:examples/powertools-examples-core-utilities/sam/pom.xml - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - -======== - helloworld-lambda - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - ->>>>>>>> main:examples/powertools-examples-core/cdk/app/pom.xml - - - - - jdk8 - - (,11) - - - 1.9.7 - - - - diff --git a/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/App.java b/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/App.java deleted file mode 100644 index 988da2a73..000000000 --- a/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/App.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; -import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.Unit; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; -import software.amazon.lambda.powertools.metrics.Metrics; -import software.amazon.lambda.powertools.tracing.CaptureMode; -import software.amazon.lambda.powertools.tracing.Tracing; -import software.amazon.lambda.powertools.tracing.TracingUtils; - -/** - * Handler for requests to Lambda function. - */ -public class App implements RequestHandler { - private final static Logger log = LogManager.getLogger(App.class); - - @Logging(logEvent = true, samplingRate = 0.7) - @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - Map headers = new HashMap<>(); - - headers.put("Content-Type", "application/json"); - headers.put("X-Custom-Header", "application/json"); - - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); - - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> - { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); - }); - - LoggingUtils.appendKey("test", "willBeLogged"); - - APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() - .withHeaders(headers); - try { - final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); - log.info(pageContents); - TracingUtils.putAnnotation("Test", "New"); - String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); - - TracingUtils.withSubsegment("loggingResponse", subsegment -> - { - String sampled = "log something out"; - log.info(sampled); - log.info(output); - }); - - log.info("After output"); - return response - .withStatusCode(200) - .withBody(output); - } catch (IOException e) { - return response - .withBody("{}") - .withStatusCode(500); - } - } - - @Tracing - private void log() { - log.info("inside threaded logging for function"); - } - - @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) - private String getPageContents(String address) throws IOException { - URL url = new URL(address); - putMetadata("getPageContents", address); - try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { - return br.lines().collect(Collectors.joining(System.lineSeparator())); - } - } -} diff --git a/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/AppStream.java deleted file mode 100644 index 401ef8c48..000000000 --- a/examples/powertools-examples-core/cdk/app/src/main/java/helloworld/AppStream.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Map; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class AppStream implements RequestStreamHandler { - private static final ObjectMapper mapper = new ObjectMapper(); - - @Override - @Logging(logEvent = true) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - Map map = mapper.readValue(input, Map.class); - - System.out.println(map.size()); - } -} diff --git a/examples/powertools-examples-core/cdk/app/src/main/resources/log4j2.xml b/examples/powertools-examples-core/cdk/app/src/main/resources/log4j2.xml deleted file mode 100644 index e1fd14cea..000000000 --- a/examples/powertools-examples-core/cdk/app/src/main/resources/log4j2.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java deleted file mode 100644 index 70dad8d71..000000000 --- a/examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.amazonaws.xray.AWSXRay; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class AppTest { - - @Before - public void setup() { - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.beginSegment("test"); - } - } - - @After - public void tearDown() { - if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) { - AWSXRay.endSubsegment(); - } - - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.endSegment(); - } - } - - @Test - public void successfulResponse() { - App app = new App(); - APIGatewayProxyResponseEvent result = app.handleRequest(null, null); - assertEquals(result.getStatusCode().intValue(), 200); - assertEquals(result.getHeaders().get("Content-Type"), "application/json"); - String content = result.getBody(); - assertNotNull(content); - assertTrue(content.contains("\"message\"")); - assertTrue(content.contains("\"hello world\"")); - assertTrue(content.contains("\"location\"")); - } -} diff --git a/examples/powertools-examples-core/cdk/infra/cdk.json b/examples/powertools-examples-core/cdk/infra/cdk.json deleted file mode 100644 index e24ee7b04..000000000 --- a/examples/powertools-examples-core/cdk/infra/cdk.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "app": "mvn -e -q compile exec:java", - "watch": { - "include": [ - "**" - ], - "exclude": [ - "README.md", - "cdk*.json", - "target", - "pom.xml", - "src/test" - ] - }, - "context": { - "@aws-cdk/aws-lambda:recognizeLayerVersion": true, - "@aws-cdk/core:checkSecretUsage": true, - "@aws-cdk/core:target-partitions": [ - "aws", - "aws-cn" - ], - "@aws-cdk/aws-iam:minimizePolicies": true, - "@aws-cdk/core:validateSnapshotRemovalPolicy": true, - "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, - "@aws-cdk/core:enablePartitionLiterals": true, - "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, - "@aws-cdk/aws-iam:standardizedServicePrincipals": true, - "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, - "@aws-cdk/customresources:installLatestAwsSdkDefault": false, - "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, - "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, - "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, - "@aws-cdk/aws-kms:aliasNameRef": true, - "@aws-cdk/core:includePrefixInUniqueNameGeneration": true - } -} diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml deleted file mode 100644 index 216bf35d4..000000000 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - 4.0.0 - software.amazon.lambda.examples - cdk - 1.18.0-SNAPSHOT - - UTF-8 - 2.100.0 - [10.0.0,11.0.0) - 5.10.0 - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - 1.8 - 1.8 - - - - org.codehaus.mojo - exec-maven-plugin - 3.1.0 - - cdk.CdkApp - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - - - - - software.amazon.awscdk - aws-cdk-lib - ${cdk.version} - - - software.constructs - constructs - ${constructs.version} - - - - org.junit.jupiter - junit-jupiter - ${junit.version} - test - - - diff --git a/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkApp.java b/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkApp.java deleted file mode 100644 index d564eb9a0..000000000 --- a/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkApp.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package cdk; - -import software.amazon.awscdk.App; -import software.amazon.awscdk.StackProps; - -public class CdkApp { - public static void main(final String[] args) { - App app = new App(); - - new CdkStack(app, "CdkStack", StackProps.builder() - // If you don't specify 'env', this stack will be environment-agnostic. - // Account/Region-dependent features and context lookups will not work, - // but a single synthesized template can be deployed anywhere. - - // Uncomment the next block to specialize this stack for the AWS Account - // and Region that are implied by the current CLI configuration. - /* - .env(Environment.builder() - .account(System.getenv("CDK_DEFAULT_ACCOUNT")) - .region(System.getenv("CDK_DEFAULT_REGION")) - .build()) - */ - - - // Uncomment the next block if you know exactly what Account and Region you - // want to deploy the stack to. - /* - .env(Environment.builder() - .account("1234567890") - .region("region") - .build()) - */ - - // For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html - .build()); - - app.synth(); - } -} diff --git a/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java b/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java deleted file mode 100644 index 8e6b44112..000000000 --- a/examples/powertools-examples-core/cdk/infra/src/main/java/cdk/CdkStack.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package cdk; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import software.amazon.awscdk.BundlingOptions; -import software.amazon.awscdk.CfnOutput; -import software.amazon.awscdk.Duration; -import software.amazon.awscdk.Stack; -import software.amazon.awscdk.StackProps; -import software.amazon.awscdk.services.apigateway.LambdaIntegration; -import software.amazon.awscdk.services.apigateway.RestApi; -import software.amazon.awscdk.services.lambda.Code; -import software.amazon.awscdk.services.lambda.Function; -import software.amazon.awscdk.services.lambda.Runtime; -import software.amazon.awscdk.services.lambda.Tracing; -import software.amazon.awscdk.services.s3.assets.AssetOptions; -import software.constructs.Construct; - -/** - * Defines a stack that consists of a single Java Lambda function and an API Gateway - */ -public class CdkStack extends Stack { - private static final String SHELL_COMMAND = "/bin/sh"; - private static final String MAVEN_PACKAGE = "mvn package"; - private static final String COPY_OUTPUT = "cp /asset-input/target/helloworld-lambda.jar /asset-output/"; - - public CdkStack(final Construct scope, final String id) { - this(scope, id, null); - } - - public CdkStack(final Construct scope, final String id, final StackProps props) { - super(scope, id, props); - - Function helloWorldFunction = createHelloWorldFunction(); - Function helloWorldStreamFunction = createHelloWorldStreamFunction(); - RestApi restApi = createHelloWorldApi(); - - restApi.getRoot().resourceForPath("/hello") - .addMethod("GET", LambdaIntegration.Builder.create(helloWorldFunction) - .build()); - - restApi.getRoot().resourceForPath("/hellostream") - .addMethod("GET", LambdaIntegration.Builder.create(helloWorldStreamFunction) - .build()); - - outputApiUrl(restApi); - } - - private static List createFunctionPackageInstructions() { - // CDK will use this command to package your Java Lambda - return Arrays.asList( - SHELL_COMMAND, - "-c", - MAVEN_PACKAGE + " && " + - COPY_OUTPUT - ); - } - - /** - * Adds API URL to the outputs - * - * @param restApi - */ - private void outputApiUrl(RestApi restApi) { - CfnOutput.Builder.create(this, "HelloWorldApiUrl") - .description("API Gateway endpoint URL for Prod stage for Hello World function") - .value(restApi.getUrl() + "hello").build(); - } - - // Method to create the Lambda function - private Function createHelloWorldFunction() { - List functionPackageInstructions = createFunctionPackageInstructions(); - - Map environment = new HashMap<>(); - environment.put("POWERTOOLS_LOG_LEVEL", "INFO"); - environment.put("POWERTOOLS_LOGGER_SAMPLE_RATE", "0.1"); - environment.put("POWERTOOLS_LOGGER_LOG_EVENT", "true"); - environment.put("POWERTOOLS_METRICS_NAMESPACE", "Coreutilities"); - - return Function.Builder.create(this, "HelloWorldFunction") - .runtime(Runtime.JAVA_11) - .memorySize(512) - .timeout(Duration.seconds(20)) - .tracing(Tracing.ACTIVE) - .code(Code.fromAsset("../app/", AssetOptions.builder() - .bundling(BundlingOptions.builder() - .image(Runtime.JAVA_11.getBundlingImage()) - .command(functionPackageInstructions) - .build()) - .build())) - .handler("helloworld.App") - .environment(environment) - .build(); - } - - private Function createHelloWorldStreamFunction() { - List functionPackageInstructions = createFunctionPackageInstructions(); - - Map environment = new HashMap<>(); - environment.put("POWERTOOLS_LOG_LEVEL", "INFO"); - environment.put("POWERTOOLS_LOGGER_SAMPLE_RATE", "0.7"); - environment.put("POWERTOOLS_LOGGER_LOG_EVENT", "true"); - environment.put("POWERTOOLS_METRICS_NAMESPACE", "Coreutilities"); - environment.put("POWERTOOLS_SERVICE_NAME", "hello"); - - return Function.Builder.create(this, "HelloWorldStreamFunction") - .runtime(Runtime.JAVA_11) - .memorySize(512) - .timeout(Duration.seconds(20)) - .tracing(Tracing.ACTIVE) - .code(Code.fromAsset("../app/", AssetOptions.builder() - .bundling(BundlingOptions.builder() - .image(Runtime.JAVA_11.getBundlingImage()) - .command(functionPackageInstructions) - .build()) - .build())) - .handler("helloworld.AppStream") - .environment(environment) - .build(); - } - - // Method to create the REST API - private RestApi createHelloWorldApi() { - return RestApi.Builder.create(this, "HelloWorldApi") - .description("API Gateway endpoint URL for Prod stage for Hello World function") - .build(); - } -} diff --git a/examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java b/examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java deleted file mode 100644 index 29cb15545..000000000 --- a/examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package cdk; - -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; -import software.amazon.awscdk.App; -import software.amazon.awscdk.assertions.Template; - -public class CdkStackTest { - - @Test - public void testStack() { - App app = new App(); - CdkStack stack = new CdkStack(app, "test"); - - Template template = Template.fromStack(stack); - - // There should be 2 lambda functions, one to handle regular input, and another for streaming - template.resourceCountIs("AWS::Lambda::Function", 2); - - // API Gateway should exist - template.resourceCountIs("AWS::ApiGateway::RestApi", 1); - - // API Gateway should have a path pointing to the regular Lambda - Map resourceProperties = new HashMap<>(); - resourceProperties.put("PathPart", "hello"); - template.hasResourceProperties("AWS::ApiGateway::Resource", resourceProperties); - - // API Gateway should have a path pointing to the streaming Lambda - resourceProperties = new HashMap<>(); - resourceProperties.put("PathPart", "hellostream"); - template.hasResourceProperties("AWS::ApiGateway::Resource", resourceProperties); - } -} diff --git a/examples/powertools-examples-core/gradle/README.md b/examples/powertools-examples-core/gradle/README.md deleted file mode 100644 index c7c798d5d..000000000 --- a/examples/powertools-examples-core/gradle/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Powertools for AWS Lambda (Java) - Core Utilities Example with Gradle - -This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) with -[Gradle](https://gradle.org/) running the build. This example is configured for Java 1.8 only; in order to use a newer version, check out the Gradle -configuration guide [in the main project README](../../../README.md). - -You can also use `sam init` to create a new Gradle-powered Powertools application - choose to use the **AWS Quick Start Templates**, -and then **Hello World Example with Powertools for AWS Lambda**, **Java 17** runtime, and finally **gradle**. - - -For general information on the deployed example itself, you can refer to the parent [README](../README.md) - -## Configuration -SAM uses [template.yaml](template.yaml) to define the application's AWS resources. -This file defines the Lambda function to be deployed as well as API Gateway for it. - -The build of the project is managed by Gradle, and configured in [build.gradle](build.gradle). - -## Deploy the sample application -To get started, you can use the Gradle wrapper to bootstrap Gradle and run the build: - -```bash -./gradlew build -``` - -Once this is done to deploy the example, check out the instructions for getting started with SAM in -[the examples directory](../../README.md) - -## Additional notes - -You can watch the trace information or log information using the SAM CLI: -```bash -# Tail the logs -sam logs --tail $MY_STACK - -# Tail the traces -sam traces --tail -``` \ No newline at end of file diff --git a/examples/powertools-examples-core/gradle/build.gradle b/examples/powertools-examples-core/gradle/build.gradle deleted file mode 100644 index e7367c246..000000000 --- a/examples/powertools-examples-core/gradle/build.gradle +++ /dev/null @@ -1,35 +0,0 @@ - -plugins { - id 'java' - id "io.freefair.aspectj.post-compile-weaving" version "6.6.3" -} - -wrapper { - gradleVersion = "7.6.1" -} - -compileJava { - sourceCompatibility = "1.8" - targetCompatibility = "1.8" - - ajc { - enabled = true - } -} - -repositories { - mavenCentral() -} - -dependencies { - implementation 'com.amazonaws:aws-lambda-java-core:1.2.2' - implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.2' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' - implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' - implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' - aspect 'software.amazon.lambda:powertools-tracing:1.17.0' - aspect 'software.amazon.lambda:powertools-logging:1.17.0' - aspect 'software.amazon.lambda:powertools-metrics:1.17.0' - testImplementation 'junit:junit:4.13.2' -} - diff --git a/examples/powertools-examples-core/gradle/events/event.json b/examples/powertools-examples-core/gradle/events/event.json deleted file mode 100644 index 070ad8e01..000000000 --- a/examples/powertools-examples-core/gradle/events/event.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "body": "{\"message\": \"hello world\"}", - "resource": "/{proxy+}", - "path": "/path/to/resource", - "httpMethod": "POST", - "isBase64Encoded": false, - "queryStringParameters": { - "foo": "bar" - }, - "pathParameters": { - "proxy": "/path/to/resource" - }, - "stageVariables": { - "baz": "qux" - }, - "headers": { - "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", - "Accept-Encoding": "gzip, deflate, sdch", - "Accept-Language": "en-US,en;q=0.8", - "Cache-Control": "max-age=0", - "CloudFront-Forwarded-Proto": "https", - "CloudFront-Is-Desktop-Viewer": "true", - "CloudFront-Is-Mobile-Viewer": "false", - "CloudFront-Is-SmartTV-Viewer": "false", - "CloudFront-Is-Tablet-Viewer": "false", - "CloudFront-Viewer-Country": "US", - "Host": "1234567890.execute-api.us-east-1.amazonaws.com", - "Upgrade-Insecure-Requests": "1", - "User-Agent": "Custom User Agent String", - "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", - "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", - "X-Forwarded-For": "127.0.0.1, 127.0.0.2", - "X-Forwarded-Port": "443", - "X-Forwarded-Proto": "https" - }, - "requestContext": { - "accountId": "123456789012", - "resourceId": "123456", - "stage": "prod", - "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", - "requestTime": "09/Apr/2015:12:34:56 +0000", - "requestTimeEpoch": 1428582896000, - "identity": { - "cognitoIdentityPoolId": null, - "accountId": null, - "cognitoIdentityId": null, - "caller": null, - "accessKey": null, - "sourceIp": "127.0.0.1", - "cognitoAuthenticationType": null, - "cognitoAuthenticationProvider": null, - "userArn": null, - "userAgent": "Custom User Agent String", - "user": null - }, - "path": "/prod/path/to/resource", - "resourcePath": "/{proxy+}", - "httpMethod": "POST", - "apiId": "1234567890", - "protocol": "HTTP/1.1" - } -} diff --git a/examples/powertools-examples-core/gradle/gradle/wrapper/.gitignore b/examples/powertools-examples-core/gradle/gradle/wrapper/.gitignore deleted file mode 100644 index 59c09e205..000000000 --- a/examples/powertools-examples-core/gradle/gradle/wrapper/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -!gradle-wrapper.jar - diff --git a/examples/powertools-examples-core/gradle/gradle/wrapper/gradle-wrapper.jar b/examples/powertools-examples-core/gradle/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 033e24c4cdf41af1ab109bc7f253b2b887023340..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63375 zcmb5VV{~QRw)Y#`wrv{~+qP{x72B%VwzFc}c2cp;N~)5ZbDrJayPv(!dGEd-##*zr z)#n-$y^sH|_dchh3@8{H5D*j;5D<{i*8l5IFJ|DjL!e)upfGNX(kojugZ3I`oH1PvW`wFW_ske0j@lB9bX zO;2)`y+|!@X(fZ1<2n!Qx*)_^Ai@Cv-dF&(vnudG?0CsddG_&Wtae(n|K59ew)6St z#dj7_(Cfwzh$H$5M!$UDd8=4>IQsD3xV=lXUq($;(h*$0^yd+b{qq63f0r_de#!o_ zXDngc>zy`uor)4A^2M#U*DC~i+dc<)Tb1Tv&~Ev@oM)5iJ4Sn#8iRw16XXuV50BS7 zdBL5Mefch(&^{luE{*5qtCZk$oFr3RH=H!c3wGR=HJ(yKc_re_X9pD` zJ;uxPzUfVpgU>DSq?J;I@a+10l0ONXPcDkiYcihREt5~T5Gb}sT0+6Q;AWHl`S5dV>lv%-p9l#xNNy7ZCr%cyqHY%TZ8Q4 zbp&#ov1*$#grNG#1vgfFOLJCaNG@K|2!W&HSh@3@Y%T?3YI75bJp!VP*$*!< z;(ffNS_;@RJ`=c7yX04!u3JP*<8jeqLHVJu#WV&v6wA!OYJS4h<_}^QI&97-;=ojW zQ-1t)7wnxG*5I%U4)9$wlv5Fr;cIizft@&N+32O%B{R1POm$oap@&f| zh+5J{>U6ftv|vAeKGc|zC=kO(+l7_cLpV}-D#oUltScw})N>~JOZLU_0{Ka2e1evz z{^a*ZrLr+JUj;)K&u2CoCAXLC2=fVScI(m_p~0FmF>>&3DHziouln?;sxW`NB}cSX z8?IsJB)Z=aYRz!X=yJn$kyOWK%rCYf-YarNqKzmWu$ZvkP12b4qH zhS9Q>j<}(*frr?z<%9hl*i^#@*O2q(Z^CN)c2c z>1B~D;@YpG?G!Yk+*yn4vM4sO-_!&m6+`k|3zd;8DJnxsBYtI;W3We+FN@|tQ5EW= z!VU>jtim0Mw#iaT8t_<+qKIEB-WwE04lBd%Letbml9N!?SLrEG$nmn7&W(W`VB@5S zaY=sEw2}i@F_1P4OtEw?xj4@D6>_e=m=797#hg}f*l^`AB|Y0# z9=)o|%TZFCY$SzgSjS|8AI-%J4x}J)!IMxY3_KYze`_I=c1nmrk@E8c9?MVRu)7+Ue79|)rBX7tVB7U|w4*h(;Gi3D9le49B38`wuv zp7{4X^p+K4*$@gU(Tq3K1a#3SmYhvI42)GzG4f|u zwQFT1n_=n|jpi=70-yE9LA+d*T8u z`=VmmXJ_f6WmZveZPct$Cgu^~gFiyL>Lnpj*6ee>*0pz=t$IJ}+rE zsf@>jlcG%Wx;Cp5x)YSVvB1$yyY1l&o zvwX=D7k)Dn;ciX?Z)Pn8$flC8#m`nB&(8?RSdBvr?>T9?E$U3uIX7T?$v4dWCa46 z+&`ot8ZTEgp7G+c52oHJ8nw5}a^dwb_l%MOh(ebVj9>_koQP^$2B~eUfSbw9RY$_< z&DDWf2LW;b0ZDOaZ&2^i^g+5uTd;GwO(-bbo|P^;CNL-%?9mRmxEw~5&z=X^Rvbo^WJW=n_%*7974RY}JhFv46> zd}`2|qkd;89l}R;i~9T)V-Q%K)O=yfVKNM4Gbacc7AOd>#^&W&)Xx!Uy5!BHnp9kh z`a(7MO6+Ren#>R^D0K)1sE{Bv>}s6Rb9MT14u!(NpZOe-?4V=>qZ>}uS)!y~;jEUK z&!U7Fj&{WdgU#L0%bM}SYXRtM5z!6M+kgaMKt%3FkjWYh=#QUpt$XX1!*XkpSq-pl zhMe{muh#knk{9_V3%qdDcWDv}v)m4t9 zQhv{;} zc{}#V^N3H>9mFM8`i`0p+fN@GqX+kl|M94$BK3J-X`Hyj8r!#x6Vt(PXjn?N)qedP z=o1T^#?1^a{;bZ&x`U{f?}TMo8ToN zkHj5v|}r}wDEi7I@)Gj+S1aE-GdnLN+$hw!=DzglMaj#{qjXi_dwpr|HL(gcCXwGLEmi|{4&4#OZ4ChceA zKVd4K!D>_N=_X;{poT~4Q+!Le+ZV>=H7v1*l%w`|`Dx8{)McN@NDlQyln&N3@bFpV z_1w~O4EH3fF@IzJ9kDk@7@QctFq8FbkbaH7K$iX=bV~o#gfh?2JD6lZf(XP>~DACF)fGFt)X%-h1yY~MJU{nA5 ze2zxWMs{YdX3q5XU*9hOH0!_S24DOBA5usB+Ws$6{|AMe*joJ?RxfV}*7AKN9V*~J zK+OMcE@bTD>TG1*yc?*qGqjBN8mgg@h1cJLDv)0!WRPIkC` zZrWXrceVw;fB%3`6kq=a!pq|hFIsQ%ZSlo~)D z|64!aCnw-?>}AG|*iOl44KVf8@|joXi&|)1rB;EQWgm+iHfVbgllP$f!$Wf42%NO5b(j9Bw6L z;0dpUUK$5GX4QbMlTmLM_jJt!ur`_0~$b#BB7FL*%XFf<b__1o)Ao3rlobbN8-(T!1d-bR8D3S0@d zLI!*GMb5s~Q<&sjd}lBb8Nr0>PqE6_!3!2d(KAWFxa{hm`@u|a(%#i(#f8{BP2wbs zt+N_slWF4IF_O|{w`c~)Xvh&R{Au~CFmW#0+}MBd2~X}t9lz6*E7uAD`@EBDe$>7W zzPUkJx<`f$0VA$=>R57^(K^h86>09?>_@M(R4q($!Ck6GG@pnu-x*exAx1jOv|>KH zjNfG5pwm`E-=ydcb+3BJwuU;V&OS=6yM^4Jq{%AVqnTTLwV`AorIDD}T&jWr8pB&j28fVtk_y*JRP^t@l*($UZ z6(B^-PBNZ+z!p?+e8@$&jCv^EWLb$WO=}Scr$6SM*&~B95El~;W_0(Bvoha|uQ1T< zO$%_oLAwf1bW*rKWmlD+@CP&$ObiDy=nh1b2ejz%LO9937N{LDe7gle4i!{}I$;&Y zkexJ9Ybr+lrCmKWg&}p=`2&Gf10orS?4$VrzWidT=*6{KzOGMo?KI0>GL0{iFWc;C z+LPq%VH5g}6V@-tg2m{C!-$fapJ9y}c$U}aUmS{9#0CM*8pC|sfer!)nG7Ji>mfRh z+~6CxNb>6eWKMHBz-w2{mLLwdA7dA-qfTu^A2yG1+9s5k zcF=le_UPYG&q!t5Zd_*E_P3Cf5T6821bO`daa`;DODm8Ih8k89=RN;-asHIigj`n=ux>*f!OC5#;X5i;Q z+V!GUy0|&Y_*8k_QRUA8$lHP;GJ3UUD08P|ALknng|YY13)}!!HW@0z$q+kCH%xet zlWf@BXQ=b=4}QO5eNnN~CzWBbHGUivG=`&eWK}beuV*;?zt=P#pM*eTuy3 zP}c#}AXJ0OIaqXji78l;YrP4sQe#^pOqwZUiiN6^0RCd#D271XCbEKpk`HI0IsN^s zES7YtU#7=8gTn#lkrc~6)R9u&SX6*Jk4GFX7){E)WE?pT8a-%6P+zS6o&A#ml{$WX zABFz#i7`DDlo{34)oo?bOa4Z_lNH>n;f0nbt$JfAl~;4QY@}NH!X|A$KgMmEsd^&Y zt;pi=>AID7ROQfr;MsMtClr5b0)xo|fwhc=qk33wQ|}$@?{}qXcmECh>#kUQ-If0$ zseb{Wf4VFGLNc*Rax#P8ko*=`MwaR-DQ8L8V8r=2N{Gaips2_^cS|oC$+yScRo*uF zUO|5=?Q?{p$inDpx*t#Xyo6=s?bbN}y>NNVxj9NZCdtwRI70jxvm3!5R7yiWjREEd zDUjrsZhS|P&|Ng5r+f^kA6BNN#|Se}_GF>P6sy^e8kBrgMv3#vk%m}9PCwUWJg-AD zFnZ=}lbi*mN-AOm zCs)r=*YQAA!`e#1N>aHF=bb*z*hXH#Wl$z^o}x##ZrUc=kh%OHWhp=7;?8%Xj||@V?1c ziWoaC$^&04;A|T)!Zd9sUzE&$ODyJaBpvqsw19Uiuq{i#VK1!htkdRWBnb z`{rat=nHArT%^R>u#CjjCkw-7%g53|&7z-;X+ewb?OLWiV|#nuc8mp*LuGSi3IP<<*Wyo9GKV7l0Noa4Jr0g3p_$ z*R9{qn=?IXC#WU>48-k5V2Oc_>P;4_)J@bo1|pf=%Rcbgk=5m)CJZ`caHBTm3%!Z9 z_?7LHr_BXbKKr=JD!%?KhwdYSdu8XxPoA{n8^%_lh5cjRHuCY9Zlpz8g+$f@bw@0V z+6DRMT9c|>1^3D|$Vzc(C?M~iZurGH2pXPT%F!JSaAMdO%!5o0uc&iqHx?ImcX6fI zCApkzc~OOnfzAd_+-DcMp&AOQxE_EsMqKM{%dRMI5`5CT&%mQO?-@F6tE*xL?aEGZ z8^wH@wRl`Izx4sDmU>}Ym{ybUm@F83qqZPD6nFm?t?(7>h*?`fw)L3t*l%*iw0Qu#?$5eq!Qc zpQvqgSxrd83NsdO@lL6#{%lsYXWen~d3p4fGBb7&5xqNYJ)yn84!e1PmPo7ChVd%4 zHUsV0Mh?VpzZD=A6%)Qrd~i7 z96*RPbid;BN{Wh?adeD_p8YU``kOrGkNox3D9~!K?w>#kFz!4lzOWR}puS(DmfjJD z`x0z|qB33*^0mZdM&6$|+T>fq>M%yoy(BEjuh9L0>{P&XJ3enGpoQRx`v6$txXt#c z0#N?b5%srj(4xmPvJxrlF3H%OMB!jvfy z;wx8RzU~lb?h_}@V=bh6p8PSb-dG|-T#A?`c&H2`_!u+uenIZe`6f~A7r)`9m8atC zt(b|6Eg#!Q*DfRU=Ix`#B_dK)nnJ_+>Q<1d7W)eynaVn`FNuN~%B;uO2}vXr5^zi2 z!ifIF5@Zlo0^h~8+ixFBGqtweFc`C~JkSq}&*a3C}L?b5Mh-bW=e)({F_g4O3 zb@SFTK3VD9QuFgFnK4Ve_pXc3{S$=+Z;;4+;*{H}Rc;845rP?DLK6G5Y-xdUKkA6E3Dz&5f{F^FjJQ(NSpZ8q-_!L3LL@H* zxbDF{gd^U3uD;)a)sJwAVi}7@%pRM&?5IaUH%+m{E)DlA_$IA1=&jr{KrhD5q&lTC zAa3c)A(K!{#nOvenH6XrR-y>*4M#DpTTOGQEO5Jr6kni9pDW`rvY*fs|ItV;CVITh z=`rxcH2nEJpkQ^(;1c^hfb8vGN;{{oR=qNyKtR1;J>CByul*+=`NydWnSWJR#I2lN zTvgnR|MBx*XFsfdA&;tr^dYaqRZp*2NwkAZE6kV@1f{76e56eUmGrZ>MDId)oqSWw z7d&r3qfazg+W2?bT}F)4jD6sWaw`_fXZGY&wnGm$FRPFL$HzVTH^MYBHWGCOk-89y zA+n+Q6EVSSCpgC~%uHfvyg@ufE^#u?JH?<73A}jj5iILz4Qqk5$+^U(SX(-qv5agK znUkfpke(KDn~dU0>gdKqjTkVk`0`9^0n_wzXO7R!0Thd@S;U`y)VVP&mOd-2 z(hT(|$=>4FY;CBY9#_lB$;|Wd$aOMT5O_3}DYXEHn&Jrc3`2JiB`b6X@EUOD zVl0S{ijm65@n^19T3l%>*;F(?3r3s?zY{thc4%AD30CeL_4{8x6&cN}zN3fE+x<9; zt2j1RRVy5j22-8U8a6$pyT+<`f+x2l$fd_{qEp_bfxfzu>ORJsXaJn4>U6oNJ#|~p z`*ZC&NPXl&=vq2{Ne79AkQncuxvbOG+28*2wU$R=GOmns3W@HE%^r)Fu%Utj=r9t` zd;SVOnA(=MXgnOzI2@3SGKHz8HN~Vpx&!Ea+Df~`*n@8O=0!b4m?7cE^K*~@fqv9q zF*uk#1@6Re_<^9eElgJD!nTA@K9C732tV~;B`hzZ321Ph=^BH?zXddiu{Du5*IPg} zqDM=QxjT!Rp|#Bkp$(mL)aar)f(dOAXUiw81pX0DC|Y4;>Vz>>DMshoips^8Frdv} zlTD=cKa48M>dR<>(YlLPOW%rokJZNF2gp8fwc8b2sN+i6&-pHr?$rj|uFgktK@jg~ zIFS(%=r|QJ=$kvm_~@n=ai1lA{7Z}i+zj&yzY+!t$iGUy|9jH#&oTNJ;JW-3n>DF+ z3aCOzqn|$X-Olu_p7brzn`uk1F*N4@=b=m;S_C?#hy{&NE#3HkATrg?enaVGT^$qIjvgc61y!T$9<1B@?_ibtDZ{G zeXInVr5?OD_nS_O|CK3|RzzMmu+8!#Zb8Ik;rkIAR%6?$pN@d<0dKD2c@k2quB%s( zQL^<_EM6ow8F6^wJN1QcPOm|ehA+dP(!>IX=Euz5qqIq}Y3;ibQtJnkDmZ8c8=Cf3 zu`mJ!Q6wI7EblC5RvP*@)j?}W=WxwCvF3*5Up_`3*a~z$`wHwCy)2risye=1mSp%p zu+tD6NAK3o@)4VBsM!@);qgsjgB$kkCZhaimHg&+k69~drbvRTacWKH;YCK(!rC?8 zP#cK5JPHSw;V;{Yji=55X~S+)%(8fuz}O>*F3)hR;STU`z6T1aM#Wd+FP(M5*@T1P z^06O;I20Sk!bxW<-O;E081KRdHZrtsGJflFRRFS zdi5w9OVDGSL3 zNrC7GVsGN=b;YH9jp8Z2$^!K@h=r-xV(aEH@#JicPy;A0k1>g1g^XeR`YV2HfmqXY zYbRwaxHvf}OlCAwHoVI&QBLr5R|THf?nAevV-=~V8;gCsX>jndvNOcFA+DI+zbh~# zZ7`qNk&w+_+Yp!}j;OYxIfx_{f0-ONc?mHCiCUak=>j>~>YR4#w# zuKz~UhT!L~GfW^CPqG8Lg)&Rc6y^{%3H7iLa%^l}cw_8UuG;8nn9)kbPGXS}p3!L_ zd#9~5CrH8xtUd?{d2y^PJg+z(xIfRU;`}^=OlehGN2=?}9yH$4Rag}*+AWotyxfCJ zHx=r7ZH>j2kV?%7WTtp+-HMa0)_*DBBmC{sd$)np&GEJ__kEd`xB5a2A z*J+yx>4o#ZxwA{;NjhU*1KT~=ZK~GAA;KZHDyBNTaWQ1+;tOFFthnD)DrCn`DjBZ% zk$N5B4^$`n^jNSOr=t(zi8TN4fpaccsb`zOPD~iY=UEK$0Y70bG{idLx@IL)7^(pL z{??Bnu=lDeguDrd%qW1)H)H`9otsOL-f4bSu};o9OXybo6J!Lek`a4ff>*O)BDT_g z<6@SrI|C9klY(>_PfA^qai7A_)VNE4c^ZjFcE$Isp>`e5fLc)rg@8Q_d^Uk24$2bn z9#}6kZ2ZxS9sI(RqT7?El2@B+($>eBQrNi_k#CDJ8D9}8$mmm z4oSKO^F$i+NG)-HE$O6s1--6EzJa?C{x=QgK&c=)b(Q9OVoAXYEEH20G|q$}Hue%~ zO3B^bF=t7t48sN zWh_zA`w~|){-!^g?6Mqf6ieV zFx~aPUOJGR=4{KsW7I?<=J2|lY`NTU=lt=%JE9H1vBpkcn=uq(q~=?iBt_-r(PLBM zP-0dxljJO>4Wq-;stY)CLB4q`-r*T$!K2o}?E-w_i>3_aEbA^MB7P5piwt1dI-6o!qWCy0 ztYy!x9arGTS?kabkkyv*yxvsPQ7Vx)twkS6z2T@kZ|kb8yjm+^$|sEBmvACeqbz)RmxkkDQX-A*K!YFziuhwb|ym>C$}U|J)4y z$(z#)GH%uV6{ec%Zy~AhK|+GtG8u@c884Nq%w`O^wv2#A(&xH@c5M`Vjk*SR_tJnq z0trB#aY)!EKW_}{#L3lph5ow=@|D5LzJYUFD6 z7XnUeo_V0DVSIKMFD_T0AqAO|#VFDc7c?c-Q%#u00F%!_TW1@JVnsfvm@_9HKWflBOUD~)RL``-!P;(bCON_4eVdduMO>?IrQ__*zE@7(OX zUtfH@AX*53&xJW*Pu9zcqxGiM>xol0I~QL5B%Toog3Jlenc^WbVgeBvV8C8AX^Vj& z^I}H})B=VboO%q1;aU5ACMh{yK4J;xlMc`jCnZR^!~LDs_MP&8;dd@4LDWw~*>#OT zeZHwdQWS!tt5MJQI~cw|Ka^b4c|qyd_ly(+Ql2m&AAw^ zQeSXDOOH!!mAgzAp0z)DD>6Xo``b6QwzUV@w%h}Yo>)a|xRi$jGuHQhJVA%>)PUvK zBQ!l0hq<3VZ*RnrDODP)>&iS^wf64C;MGqDvx>|p;35%6(u+IHoNbK z;Gb;TneFo*`zUKS6kwF*&b!U8e5m4YAo03a_e^!5BP42+r)LFhEy?_7U1IR<; z^0v|DhCYMSj<-;MtY%R@Fg;9Kky^pz_t2nJfKWfh5Eu@_l{^ph%1z{jkg5jQrkvD< z#vdK!nku*RrH~TdN~`wDs;d>XY1PH?O<4^U4lmA|wUW{Crrv#r%N>7k#{Gc44Fr|t z@UZP}Y-TrAmnEZ39A*@6;ccsR>)$A)S>$-Cj!=x$rz7IvjHIPM(TB+JFf{ehuIvY$ zsDAwREg*%|=>Hw$`us~RP&3{QJg%}RjJKS^mC_!U;E5u>`X`jW$}P`Mf}?7G7FX#{ zE(9u1SO;3q@ZhDL9O({-RD+SqqPX)`0l5IQu4q)49TUTkxR(czeT}4`WV~pV*KY&i zAl3~X%D2cPVD^B43*~&f%+Op)wl<&|D{;=SZwImydWL6@_RJjxP2g)s=dH)u9Npki zs~z9A+3fj0l?yu4N0^4aC5x)Osnm0qrhz@?nwG_`h(71P znbIewljU%T*cC=~NJy|)#hT+lx#^5MuDDnkaMb*Efw9eThXo|*WOQzJ*#3dmRWm@! zfuSc@#kY{Um^gBc^_Xdxnl!n&y&}R4yAbK&RMc+P^Ti;YIUh|C+K1|=Z^{nZ}}rxH*v{xR!i%qO~o zTr`WDE@k$M9o0r4YUFFeQO7xCu_Zgy)==;fCJ94M_rLAv&~NhfvcLWCoaGg2ao~3e zBG?Ms9B+efMkp}7BhmISGWmJsKI@a8b}4lLI48oWKY|8?zuuNc$lt5Npr+p7a#sWu zh!@2nnLBVJK!$S~>r2-pN||^w|fY`CT{TFnJy`B|e5;=+_v4l8O-fkN&UQbA4NKTyntd zqK{xEKh}U{NHoQUf!M=2(&w+eef77VtYr;xs%^cPfKLObyOV_9q<(%76-J%vR>w9!us-0c-~Y?_EVS%v!* z15s2s3eTs$Osz$JayyH|5nPAIPEX=U;r&p;K14G<1)bvn@?bM5kC{am|C5%hyxv}a z(DeSKI5ZfZ1*%dl8frIX2?);R^^~LuDOpNpk-2R8U1w92HmG1m&|j&J{EK=|p$;f9 z7Rs5|jr4r8k5El&qcuM+YRlKny%t+1CgqEWO>3;BSRZi(LA3U%Jm{@{y+A+w(gzA< z7dBq6a1sEWa4cD0W7=Ld9z0H7RI^Z7vl(bfA;72j?SWCo`#5mVC$l1Q2--%V)-uN* z9ha*s-AdfbDZ8R8*fpwjzx=WvOtmSzGFjC#X)hD%Caeo^OWjS(3h|d9_*U)l%{Ab8 zfv$yoP{OuUl@$(-sEVNt{*=qi5P=lpxWVuz2?I7Dc%BRc+NGNw+323^ z5BXGfS71oP^%apUo(Y#xkxE)y?>BFzEBZ}UBbr~R4$%b7h3iZu3S(|A;&HqBR{nK& z$;GApNnz=kNO^FL&nYcfpB7Qg;hGJPsCW44CbkG1@l9pn0`~oKy5S777uH)l{irK!ru|X+;4&0D;VE*Ii|<3P zUx#xUqvZT5kVQxsF#~MwKnv7;1pR^0;PW@$@T7I?s`_rD1EGUdSA5Q(C<>5SzE!vw z;{L&kKFM-MO>hy#-8z`sdVx})^(Dc-dw;k-h*9O2_YZw}|9^y-|8RQ`BWJUJL(Cer zP5Z@fNc>pTXABbTRY-B5*MphpZv6#i802giwV&SkFCR zGMETyUm(KJbh+&$8X*RB#+{surjr;8^REEt`2&Dubw3$mx>|~B5IKZJ`s_6fw zKAZx9&PwBqW1Oz0r0A4GtnZd7XTKViX2%kPfv+^X3|_}RrQ2e3l=KG_VyY`H?I5&CS+lAX5HbA%TD9u6&s#v!G> zzW9n4J%d5ye7x0y`*{KZvqyXUfMEE^ZIffzI=Hh|3J}^yx7eL=s+TPH(Q2GT-sJ~3 zI463C{(ag7-hS1ETtU;_&+49ABt5!A7CwLwe z=SoA8mYZIQeU;9txI=zcQVbuO%q@E)JI+6Q!3lMc=Gbj(ASg-{V27u>z2e8n;Nc*pf}AqKz1D>p9G#QA+7mqqrEjGfw+85Uyh!=tTFTv3|O z+)-kFe_8FF_EkTw!YzwK^Hi^_dV5x-Ob*UWmD-})qKj9@aE8g240nUh=g|j28^?v7 zHRTBo{0KGaWBbyX2+lx$wgXW{3aUab6Bhm1G1{jTC7ota*JM6t+qy)c5<@ zpc&(jVdTJf(q3xB=JotgF$X>cxh7k*(T`-V~AR+`%e?YOeALQ2Qud( zz35YizXt(aW3qndR}fTw1p()Ol4t!D1pitGNL95{SX4ywzh0SF;=!wf=?Q?_h6!f* zh7<+GFi)q|XBsvXZ^qVCY$LUa{5?!CgwY?EG;*)0ceFe&=A;!~o`ae}Z+6me#^sv- z1F6=WNd6>M(~ z+092z>?Clrcp)lYNQl9jN-JF6n&Y0mp7|I0dpPx+4*RRK+VQI~>en0Dc;Zfl+x z_e_b7s`t1_A`RP3$H}y7F9_na%D7EM+**G_Z0l_nwE+&d_kc35n$Fxkd4r=ltRZhh zr9zER8>j(EdV&Jgh(+i}ltESBK62m0nGH6tCBr90!4)-`HeBmz54p~QP#dsu%nb~W z7sS|(Iydi>C@6ZM(Us!jyIiszMkd)^u<1D+R@~O>HqZIW&kearPWmT>63%_t2B{_G zX{&a(gOYJx!Hq=!T$RZ&<8LDnxsmx9+TBL0gTk$|vz9O5GkK_Yx+55^R=2g!K}NJ3 zW?C;XQCHZl7H`K5^BF!Q5X2^Mj93&0l_O3Ea3!Ave|ixx+~bS@Iv18v2ctpSt4zO{ zp#7pj!AtDmti$T`e9{s^jf(ku&E|83JIJO5Qo9weT6g?@vX!{7)cNwymo1+u(YQ94 zopuz-L@|5=h8A!(g-MXgLJC0MA|CgQF8qlonnu#j z;uCeq9ny9QSD|p)9sp3ebgY3rk#y0DA(SHdh$DUm^?GI<>%e1?&}w(b zdip1;P2Z=1wM+$q=TgLP$}svd!vk+BZ@h<^4R=GS2+sri7Z*2f`9 z5_?i)xj?m#pSVchk-SR!2&uNhzEi+#5t1Z$o0PoLGz*pT64%+|Wa+rd5Z}60(j?X= z{NLjtgRb|W?CUADqOS@(*MA-l|E342NxRaxLTDqsOyfWWe%N(jjBh}G zm7WPel6jXijaTiNita+z(5GCO0NM=Melxud57PP^d_U## zbA;9iVi<@wr0DGB8=T9Ab#2K_#zi=$igyK48@;V|W`fg~7;+!q8)aCOo{HA@vpSy-4`^!ze6-~8|QE||hC{ICKllG9fbg_Y7v z$jn{00!ob3!@~-Z%!rSZ0JO#@>|3k10mLK0JRKP-Cc8UYFu>z93=Ab-r^oL2 zl`-&VBh#=-?{l1TatC;VweM^=M7-DUE>m+xO7Xi6vTEsReyLs8KJ+2GZ&rxw$d4IT zPXy6pu^4#e;;ZTsgmG+ZPx>piodegkx2n0}SM77+Y*j^~ICvp#2wj^BuqRY*&cjmL zcKp78aZt>e{3YBb4!J_2|K~A`lN=u&5j!byw`1itV(+Q_?RvV7&Z5XS1HF)L2v6ji z&kOEPmv+k_lSXb{$)of~(BkO^py&7oOzpjdG>vI1kcm_oPFHy38%D4&A4h_CSo#lX z2#oqMCTEP7UvUR3mwkPxbl8AMW(e{ARi@HCYLPSHE^L<1I}OgZD{I#YH#GKnpRmW3 z2jkz~Sa(D)f?V?$gNi?6)Y;Sm{&?~2p=0&BUl_(@hYeX8YjaRO=IqO7neK0RsSNdYjD zaw$g2sG(>JR=8Iz1SK4`*kqd_3-?;_BIcaaMd^}<@MYbYisWZm2C2|Np_l|8r9yM|JkUngSo@?wci(7&O9a z%|V(4C1c9pps0xxzPbXH=}QTxc2rr7fXk$9`a6TbWKPCz&p=VsB8^W96W=BsB|7bc zf(QR8&Ktj*iz)wK&mW`#V%4XTM&jWNnDF56O+2bo<3|NyUhQ%#OZE8$Uv2a@J>D%t zMVMiHh?es!Ex19q&6eC&L=XDU_BA&uR^^w>fpz2_`U87q_?N2y;!Z!bjoeKrzfC)} z?m^PM=(z{%n9K`p|7Bz$LuC7!>tFOuN74MFELm}OD9?%jpT>38J;=1Y-VWtZAscaI z_8jUZ#GwWz{JqvGEUmL?G#l5E=*m>`cY?m*XOc*yOCNtpuIGD+Z|kn4Xww=BLrNYS zGO=wQh}Gtr|7DGXLF%|`G>J~l{k^*{;S-Zhq|&HO7rC_r;o`gTB7)uMZ|WWIn@e0( zX$MccUMv3ABg^$%_lNrgU{EVi8O^UyGHPNRt%R!1#MQJn41aD|_93NsBQhP80yP<9 zG4(&0u7AtJJXLPcqzjv`S~5;Q|5TVGccN=Uzm}K{v)?f7W!230C<``9(64}D2raRU zAW5bp%}VEo{4Rko`bD%Ehf=0voW?-4Mk#d3_pXTF!-TyIt6U+({6OXWVAa;s-`Ta5 zTqx&8msH3+DLrVmQOTBOAj=uoxKYT3DS1^zBXM?1W+7gI!aQNPYfUl{3;PzS9*F7g zWJN8x?KjBDx^V&6iCY8o_gslO16=kh(|Gp)kz8qlQ`dzxQv;)V&t+B}wwdi~uBs4? zu~G|}y!`3;8#vIMUdyC7YEx6bb^1o}G!Jky4cN?BV9ejBfN<&!4M)L&lRKiuMS#3} z_B}Nkv+zzxhy{dYCW$oGC&J(Ty&7%=5B$sD0bkuPmj7g>|962`(Q{ZZMDv%YMuT^KweiRDvYTEop3IgFv#)(w>1 zSzH>J`q!LK)c(AK>&Ib)A{g`Fdykxqd`Yq@yB}E{gnQV$K!}RsgMGWqC3DKE(=!{}ekB3+(1?g}xF>^icEJbc z5bdxAPkW90atZT+&*7qoLqL#p=>t-(-lsnl2XMpZcYeW|o|a322&)yO_8p(&Sw{|b zn(tY$xn5yS$DD)UYS%sP?c|z>1dp!QUD)l;aW#`%qMtQJjE!s2z`+bTSZmLK7SvCR z=@I4|U^sCwZLQSfd*ACw9B@`1c1|&i^W_OD(570SDLK`MD0wTiR8|$7+%{cF&){$G zU~|$^Ed?TIxyw{1$e|D$050n8AjJvvOWhLtLHbSB|HIfhMpqVf>AF&}ZQHhOJ14Bz zww+XL+qP}nww+W`F>b!by|=&a(cM4JIDhsTXY8@|ntQG}-}jm0&Bcj|LV(#sc=BNS zRjh;k9l>EdAFdd)=H!U`~$WP*}~^3HZ_?H>gKw>NBa;tA8M1{>St|)yDF_=~{KEPAGkg3VB`QCHol!AQ0|?e^W?81f{@()Wy!vQ$bY; z0ctx)l7VK83d6;dp!s{Nu=SwXZ8lHQHC*J2g@P0a={B8qHdv(+O3wV=4-t4HK1+smO#=S; z3cSI#Nh+N@AqM#6wPqjDmQM|x95JG|l1#sAU|>I6NdF*G@bD?1t|ytHlkKD+z9}#j zbU+x_cR-j9yX4s{_y>@zk*ElG1yS({BInGJcIT>l4N-DUs6fufF#GlF2lVUNOAhJT zGZThq54GhwCG(h4?yWR&Ax8hU<*U)?g+HY5-@{#ls5CVV(Wc>Bavs|l<}U|hZn z_%m+5i_gaakS*Pk7!v&w3&?R5Xb|AkCdytTY;r+Z7f#Id=q+W8cn)*9tEet=OG+Y} z58U&!%t9gYMx2N=8F?gZhIjtkH!`E*XrVJ?$2rRxLhV1z82QX~PZi8^N5z6~f-MUE zLKxnNoPc-SGl7{|Oh?ZM$jq67sSa)Wr&3)0YxlJt(vKf!-^L)a|HaPv*IYXb;QmWx zsqM>qY;tpK3RH-omtta+Xf2Qeu^$VKRq7`e$N-UCe1_2|1F{L3&}M0XbJ@^xRe&>P zRdKTgD6601x#fkDWkoYzRkxbn#*>${dX+UQ;FbGnTE-+kBJ9KPn)501#_L4O_k`P3 zm+$jI{|EC?8BXJY{P~^f-{**E53k%kVO$%p+=H5DiIdwMmUo>2euq0UzU90FWL!>; z{5@sd0ecqo5j!6AH@g6Mf3keTP$PFztq}@)^ZjK;H6Go$#SV2|2bAFI0%?aXgVH$t zb4Kl`$Xh8qLrMbZUS<2*7^F0^?lrOE=$DHW+O zvLdczsu0^TlA6RhDy3=@s!k^1D~Awulk!Iyo#}W$xq8{yTAK!CLl={H0@YGhg-g~+ z(u>pss4k#%8{J%~%8=H5!T`rqK6w^es-cNVE}=*lP^`i&K4R=peg1tdmT~UAbDKc& zg%Y*1E{hBf<)xO>HDWV7BaMWX6FW4ou1T2m^6{Jb!Su1UaCCYY8RR8hAV$7ho|FyEyP~ zEgK`@%a$-C2`p zV*~G>GOAs*3KN;~IY_UR$ISJxB(N~K>=2C2V6>xTmuX4klRXdrJd&UPAw7&|KEwF8Zcy2j-*({gSNR1^p02Oj88GN9a_Hq;Skdp}kO0;FLbje%2ZvPiltDZgv^ z#pb4&m^!79;O8F+Wr9X71laPY!CdNXG?J6C9KvdAE2xWW1>U~3;0v≫L+crb^Bz zc+Nw%zgpZ6>!A3%lau!Pw6`Y#WPVBtAfKSsqwYDWQK-~ zz(mx=nJ6-8t`YXB{6gaZ%G}Dmn&o500Y}2Rd?e&@=hBEmB1C=$OMBfxX__2c2O4K2#(0ksclP$SHp*8jq-1&(<6(#=6&H`Nlc2RVC4->r6U}sTY<1? zn@tv7XwUs-c>Lcmrm5AE0jHI5={WgHIow6cX=UK)>602(=arbuAPZ37;{HTJSIO%9EL`Et5%J7$u_NaC(55x zH^qX^H}*RPDx)^c46x>js=%&?y?=iFs^#_rUl@*MgLD92E5y4B7#EDe9yyn*f-|pQ zi>(!bIg6zY5fLSn@;$*sN|D2A{}we*7+2(4&EhUV%Qqo5=uuN^xt_hll7=`*mJq6s zCWUB|s$)AuS&=)T&_$w>QXHqCWB&ndQ$y4-9fezybZb0bYD^zeuZ>WZF{rc>c4s`` zgKdppTB|o>L1I1hAbnW%H%EkFt%yWC|0~+o7mIyFCTyb?@*Ho)eu(x`PuO8pLikN> z6YeI`V?AUWD(~3=8>}a6nZTu~#QCK(H0+4!ql3yS`>JX;j4+YkeG$ZTm33~PLa3L} zksw7@%e-mBM*cGfz$tS4LC^SYVdBLsR}nAprwg8h2~+Cv*W0%izK+WPVK}^SsL5R_ zpA}~G?VNhJhqx2he2;2$>7>DUB$wN9_-adL@TqVLe=*F8Vsw-yho@#mTD6*2WAr6B zjtLUh`E(;#p0-&$FVw(r$hn+5^Z~9J0}k;j$jL1;?2GN9s?}LASm?*Rvo@?E+(}F& z+=&M-n`5EIz%%F^e)nnWjkQUdG|W^~O|YeY4Fz}>qH2juEere}vN$oJN~9_Th^&b{ z%IBbET*E8%C@jLTxV~h#mxoRrJCF{!CJOghjuKOyl_!Jr?@4Upo7u>fTGtfm|CH2v z&9F+>;6aFbYXLj3{yZ~Yn1J2%!)A3~j2$`jOy{XavW@t)g}}KUVjCWG0OUc7aBc=2 zR3^u=dT47=5SmT{K1aGaVZkOx|24T-J0O$b9dfB25J|7yb6frwS6wZ1^y%EWOm}S< zc1SdYhfsdLG*FB-;!QLV3D!d~hnXTGVQVck9x%=B(Kk8c3y%f0nR95_TbY;l=obSl zEE@fp0|8Q$b3(+DXh?d0FEloGhO0#11CLQT5qtEckBLe-VN-I>9ys}PVK0r;0!jIG zH_q$;a`3Xv9P_V2ekV1SMzd#SKo<1~Dq2?M{(V;AwhH_2x@mN$=|=cG0<3o^j_0OF z7|WJ-f2G=7sA4NVGU2X5`o*D2T7(MbmZ2(oipooE{R?9!{WxX!%ofhsrPAxoIk!Kr z>I$a{Zq=%KaLrDCIL^gmA3z{2z%Wkr)b$QHcNUA^QwydWMJmxymO0QS22?mo%4(Md zgME(zE}ub--3*wGjV`3eBMCQG-@Gel1NKZDGuqobN|mAt0{@ZC9goI|BSmGBTUZ(`Xt z^e2LiMg?6E?G*yw(~K8lO(c4)RY7UWxrXzW^iCg-P41dUiE(i+gDmmAoB?XOB}+Ln z_}rApiR$sqNaT4frw69Wh4W?v(27IlK$Toy<1o)GeF+sGzYVeJ`F)3`&2WDi^_v67 zg;@ehwl3=t+}(DJtOYO!s`jHyo-}t@X|U*9^sIfaZfh;YLqEFmZ^E;$_XK}%eq;>0 zl?+}*kh)5jGA}3daJ*v1knbW0GusR1+_xD`MFPZc3qqYMXd>6*5?%O5pC7UVs!E-` zuMHc6igdeFQ`plm+3HhP)+3I&?5bt|V8;#1epCsKnz0%7m9AyBmz06r90n~9o;K30 z=fo|*`Qq%dG#23bVV9Jar*zRcV~6fat9_w;x-quAwv@BkX0{9e@y0NB(>l3#>82H6 z^US2<`=M@6zX=Pz>kb8Yt4wmeEo%TZ=?h+KP2e3U9?^Nm+OTx5+mVGDvgFee%}~~M zK+uHmj44TVs}!A}0W-A92LWE%2=wIma(>jYx;eVB*%a>^WqC7IVN9{o?iw{e4c=CG zC#i=cRJZ#v3 zF^9V+7u?W=xCY%2dvV_0dCP%5)SH*Xm|c#rXhwEl*^{Ar{NVoK*H6f5qCSy`+|85e zjGaKqB)p7zKNKI)iWe6A9qkl=rTjs@W1Crh(3G57qdT0w2ig^{*xerzm&U>YY{+fZbkQ#;^<$JniUifmAuEd^_M(&?sTrd(a*cD! zF*;`m80MrZ^> zaF{}rDhEFLeH#`~rM`o903FLO?qw#_Wyb5}13|0agjSTVkSI6Uls)xAFZifu@N~PM zQ%o?$k)jbY0u|45WTLAirUg3Zi1E&=G#LnSa89F3t3>R?RPcmkF}EL-R!OF_r1ZN` z?x-uHH+4FEy>KrOD-$KHg3$-Xl{Cf0;UD4*@eb~G{CK-DXe3xpEEls?SCj^p z$Uix(-j|9f^{z0iUKXcZQen}*`Vhqq$T?^)Ab2i|joV;V-qw5reCqbh(8N)c%!aB< zVs+l#_)*qH_iSZ_32E~}>=wUO$G_~k0h@ch`a6Wa zsk;<)^y=)cPpHt@%~bwLBy;>TNrTf50BAHUOtt#9JRq1ro{w80^sm-~fT>a$QC;<| zZIN%&Uq>8`Js_E((_1sewXz3VlX|-n8XCfScO`eL|H&2|BPZhDn}UAf_6s}|!XpmUr90v|nCutzMjb9|&}#Y7fj_)$alC zM~~D6!dYxhQof{R;-Vp>XCh1AL@d-+)KOI&5uKupy8PryjMhTpCZnSIQ9^Aq+7=Mb zCYCRvm4;H=Q8nZWkiWdGspC_Wvggg|7N`iED~Eap)Th$~wsxc(>(KI>{i#-~Dd8iQ zzonqc9DW1w4a*}k`;rxykUk+~N)|*I?@0901R`xy zN{20p@Ls<%`1G1Bx87Vm6Z#CA`QR(x@t8Wc?tpaunyV^A*-9K9@P>hAWW9Ev)E$gb z<(t?Te6GcJX2&0% z403pe>e)>m-^qlJU^kYIH)AutgOnq!J>FoMXhA-aEx-((7|(*snUyxa+5$wx8FNxS zKuVAVWArlK#kDzEM zqR?&aXIdyvxq~wF?iYPho*(h?k zD(SBpRDZ}z$A})*Qh!9&pZZRyNixD!8)B5{SK$PkVET(yd<8kImQ3ILe%jhx8Ga-1 zE}^k+Eo^?c4Y-t2_qXiVwW6i9o2qosBDj%DRPNT*UXI0=D9q{jB*22t4HHcd$T&Xi zT=Vte*Gz2E^qg%b7ev04Z&(;=I4IUtVJkg<`N6i7tjUn-lPE(Y4HPyJKcSjFnEzCH zPO(w%LmJ_=D~}PyfA91H4gCaf-qur3_KK}}>#9A}c5w@N;-#cHph=x}^mQ3`oo`Y$ope#)H9(kQK zGyt<7eNPuSAs$S%O>2ElZ{qtDIHJ!_THqTwcc-xfv<@1>IJ;YTv@!g-zDKBKAH<

Zet1e^8c}8fE97XH}+lF{qbF<`Y%dU|I!~Y`ZrVfKX82i z)(%!Tcf~eE^%2_`{WBPGPU@1NB5SCXe1sAI<4&n1IwO{&S$ThWn37heGOSW%nW7*L zxh0WK!E7zh%6yF-7%~l@I~b`2=*$;RYbi(I#zp$gL_d39U4A)KuB( zcS0bt48&%G_I~( zL(}w&2NA6#$=|g)J+-?ehHflD^lr77ngdz=dszFI;?~ZxeJv=gsm?4$$6#V==H{fa zqO!EkT>1-OQSJoX)cN}XsB;shvrHRwTH(I2^Ah4|rizn!V7T7fLh~Z<`Q+?zEMVxh z$=-x^RR*PlhkV_8mshTvs+zmZWY&Jk{9LX0Nx|+NAEq-^+Rh|ZlinVZ=e8=`WQt;e@= zPU}^1cG*O;G7l{Y#nl znp`y%CO_SC7gk0i0gY&phM04Y)~vU0!3$V$2T+h(1ZS+cCgc zaC?3M;B48^faGo>h~--#FNFauH?0BJJ6_nG5qOlr>k~%DCSJaOfl%KWHusw>tGrTxAhlEVDxc8R2C-)LCt&$Rt9IKor=ml7jirX@?WW+M z^I{b}MD5r$s>^^sN@&g`cXD~S_u09xo;{;noKZatIuzqd zW1e7oTl9>g8opPBT(p+&fo0F#!c{NFYYpIZ6u8hOB{F#{nP)@})X20$3iJtG$cO zJ$Oxl_qH{sL5d?=D$2M4C3Ajc;GN0(B-HVT;@pJ-LvIrN%|SY?t}g!J>ufQrR%hoY z!nr$tq~N%)9}^tEip93XW=MQ1@XovSvn`PTqXeT9@_7hGv4%LK1M**Q%UKi|(v@1_ zKGe*@+1%Y4v&`;5vUL`C&{tc+_7HFs7*OtjY8@Gg`C4O&#An{0xOvgNSehTHS~_1V z=daxCMzI5b_ydM5$z zZl`a{mM}i@x;=QyaqJY&{Q^R*^1Yzq!dHH~UwCCga+Us~2wk59ArIYtSw9}tEmjbo z5!JA=`=HP*Ae~Z4Pf7sC^A3@Wfa0Ax!8@H_&?WVe*)9B2y!8#nBrP!t1fqhI9jNMd zM_5I)M5z6Ss5t*f$Eh{aH&HBeh310Q~tRl3wCEcZ>WCEq%3tnoHE)eD=)XFQ7NVG5kM zaUtbnq2LQomJSWK)>Zz1GBCIHL#2E>T8INWuN4O$fFOKe$L|msB3yTUlXES68nXRX zP6n*zB+kXqqkpQ3OaMc9GqepmV?Ny!T)R@DLd`|p5ToEvBn(~aZ%+0q&vK1)w4v0* zgW44F2ixZj0!oB~^3k|vni)wBh$F|xQN>~jNf-wFstgiAgB!=lWzM&7&&OYS=C{ce zRJw|)PDQ@3koZfm`RQ$^_hEN$GuTIwoTQIDb?W&wEo@c75$dW(ER6q)qhF`{#7UTuPH&)w`F!w z0EKs}=33m}_(cIkA2rBWvApydi0HSOgc>6tu&+hmRSB%)s`v_NujJNhKLS3r6hv~- z)Hm@?PU{zd0Tga)cJWb2_!!9p3sP%Z zAFT|jy;k>4X)E>4fh^6=SxV5w6oo`mus&nWo*gJL zZH{SR!x)V)y=Qc7WEv-xLR zhD4OcBwjW5r+}pays`o)i$rcJb2MHLGPmeOmt5XJDg@(O3PCbxdDn{6qqb09X44T zh6I|s=lM6Nr#cGaA5-eq*T=LQ6SlRq*`~`b+dVi5^>el1p;#si6}kK}>w;1 z6B1dz{q_;PY{>DBQ+v@1pfXTd5a*^H9U*;qdj@XBF}MoSSQxVXeUpEM5Z0909&8$pRfR|B(t0ox&xl8{8mUNd#(zWONW{oycv$VjP1>q;jU@ z@+8E~fjz*I54OFFaQ{A5jn1w>r;l!NRlI(8q3*%&+tM?lov_G3wB`<}bQ>1=&xUht zmti5VZzV1Cx006Yzt|%Vwid>QPX8Nfa8|sue7^un@C+!3h!?-YK>lSfNIHh|0kL8v zbv_BklQ4HOqje|@Fyxn%IvL$N&?m(KN;%`I$N|muStjSsgG;gP4Smgz$2u(mG;DXP zf~uQ z212x^l6!MW>V@ORUGSFLAAjz3i5zO$=UmD_zhIk2OXUz^LkDLWjla*PW?l;`LLos> z7FBvCr)#)XBByDm(=n%{D>BcUq>0GOV9`i-(ZSI;RH1rdrAJ--f0uuAQ4odl z_^$^U_)0BBJwl@6R#&ZtJN+@a(4~@oYF)yG+G#3=)ll8O#Zv3SjV#zSXTW3h9kqn* z@AHL=vf~KMas}6{+u=}QFumr-!c=(BFP_dwvrdehzTyqco)m@xRc=6b#Dy+KD*-Bq zK=y*1VAPJ;d(b?$2cz{CUeG(0`k9_BIuUki@iRS5lp3=1#g)A5??1@|p=LOE|FNd; z-?5MLKd-5>yQ7n__5W^3C!_`hP(o%_E3BKEmo1h=H(7;{6$XRRW6{u+=oQX<((xAJ zNRY`Egtn#B1EBGHLy^eM5y}Jy0h!GAGhb7gZJoZI-9WuSRw)GVQAAcKd4Qm)pH`^3 zq6EIM}Q zxZGx%aLnNP1an=;o8p9+U^>_Bi`e23E^X|}MB&IkS+R``plrRzTE%ncmfvEW#AHJ~ znmJ`x&ez6eT21aLnoI`%pYYj zzQ?f^ob&Il;>6Fe>HPhAtTZa*B*!;;foxS%NGYmg!#X%)RBFe-acahHs3nkV61(E= zhekiPp1d@ACtA=cntbjuv+r-Zd`+lwKFdqZuYba_ey`&H<Psu;Tzwt;-LQxvv<_D5;ik7 zwETZe`+voUhk%$s2-7Rqfl`Ti_{(fydI(DAHKr<66;rYa6p8AD+NEc@Fd@%m`tiK% z=Mebzrtp=*Q%a}2UdK4J&5#tCN5PX>W=(9rUEXZ8yjRu+7)mFpKh{6;n%!bI(qA9kfyOtstGtOl zX!@*O0fly*L4k##fsm&V0j9Lj<_vu1)i?!#xTB7@2H&)$Kzt@r(GH=xRZlIimTDd_o(%9xO388LwC#;vQ?7OvRU_s< zDS@6@g}VnvQ+tn(C#sx0`J^T4WvFxYI17;uPs-Ub{R`J-NTdtBGl+Q>e81Z3#tDUr ztnVc*p{o|RNnMYts4pdw=P!uJkF@8~h)oV4dXu5F7-j0AW|=mt!QhP&ZV!!82*c7t zuOm>B*2gFtq;A8ynZ~Ms?!gEi5<{R_8tRN%aGM!saR4LJQ|?9w>Ff_61(+|ol_vL4 z-+N>fushRbkB4(e{{SQ}>6@m}s1L!-#20N&h%srA=L50?W9skMF9NGfQ5wU*+0<@> zLww8%f+E0Rc81H3e_5^DB@Dn~TWYk}3tqhO{7GDY;K7b*WIJ-tXnYM@z4rn(LGi?z z8%$wivs)fC#FiJh?(SbH-1bgdmHw&--rn7zBWe1xAhDdv#IRB@DGy}}zS%M0(F_3_ zLb-pWsdJ@xXE;=tpRAw?yj(Gz=i$;bsh&o2XN%24b6+?_gJDBeY zws3PE2u!#Cec>aFMk#ECxDlAs;|M7@LT8)Y4(`M}N6IQ{0YtcA*8e42!n^>`0$LFU zUCq2IR2(L`f++=85M;}~*E($nE&j;p{l%xchiTau*tB9bI= zn~Ygd@<+9DrXxoGPq}@vI1Q3iEfKRleuy*)_$+hg?+GOgf1r?d@Or42|s|D>XMa;ebr1uiTNUq@heusd6%WwJqyCCv!L*qou9l!B22H$bQ z)<)IA>Yo77S;|`fqBk!_PhLJEQb0wd1Z|`pCF;hol!34iQYtqu3K=$QxLW7(HFx~v>`vVRr zyqk^B4~!3F8t8Q_D|GLRrAbbQDf??D&Jd|mgw*t1YCd)CM2$76#Cqj1bD*vADwavp zS<`n@gLU4pwCqNPsIfHKl{5}gu9t-o+O< z??!fMqMrt$s}02pdBbOScUrc1T*{*-ideR6(1q4@oC6mxg8v8Y^h^^hfx6| z|Mld6Ax1CuSlmSJmHwdOix?$8emihK#&8&}u8m!#T1+c5u!H)>QW<7&R$eih)xkov zHvvEIJHbkt+2KQ<-bMR;2SYX?8SI=_<-J!GD5@P2FJ}K z5u82YFotCJF(dUeJFRX_3u8%iIYbRS??A?;iVO?84c}4Du9&jG<#urlZ_Unrcg8dR z!5I3%9F*`qwk#joKG_Q%5_xpU7|jm4h0+l$p;g%Tr>i74#3QnMXdz|1l2MQN$yw|5 zThMw15BxjWf2{KM)XtZ+e#N)ihlkxPe=5ymT9>@Ym%_LF}o z1XhCP`3E1A{iVoHA#|O|&5=w;=j*Qf`;{mBAK3={y-YS$`!0UmtrvzHBfR*s{z<0m zW>4C=%N98hZlUhwAl1X`rR)oL0&A`gv5X79??p_==g*n4$$8o5g9V<)F^u7v0Vv^n z1sp8{W@g6eWv2;A31Rhf5j?KJhITYfXWZsl^`7z`CFtnFrHUWiD?$pwU6|PQjs|7RA0o9ARk^9$f`u3&C|#Z3iYdh<0R`l2`)6+ z6tiDj@xO;Q5PDTYSxsx6n>bj+$JK8IPJ=U5#dIOS-zwyK?+t^V`zChdW|jpZuReE_ z)e~ywgFe!0q|jzsBn&(H*N`%AKpR@qM^|@qFai0};6mG_TvXjJ`;qZ{lGDZHScZk( z>pO+%icp)SaPJUwtIPo1BvGyP8E@~w2y}=^PnFJ$iHod^JH%j1>nXl<3f!nY9K$e` zq-?XYl)K`u*cVXM=`ym{N?z=dHQNR23M8uA-(vsA$6(xn+#B-yY!CB2@`Uz({}}w+ z0sni*39>rMC!Ay|1B@;al%T&xE(wCf+`3w>N)*LxZZZYi{5sqiVWgbNd>W*X?V}C- zjQ4F7e_uCUOHbtewQkq?m$*#@ZvWbu{4i$`aeKM8tc^ zL5!GL8gX}c+qNUtUIcps1S)%Gsx*MQLlQeoZz2y2OQb(A73Jc3`LmlQf0N{RTt;wa`6h|ljX1V7UugML=W5-STDbeWTiEMjPQ$({hn_s&NDXzs6?PLySp$?L`0ilH3vCUO{JS0Dp`z;Ry$6}R@1NdY7rxccbm$+;ApSe=2q!0 z()3$vYN0S$Cs)#-OBs{_2uFf}L4h$;7^2w20=l%5r9ui&pTEgg4U!FoCqyA6r2 zC5s72l}i*9y|KTjDE5gVlYe4I2gGZD)e`Py2gq7cK4at{bT~DSbQQ4Z4sl)kqXbbr zqvXtSqMrDdT2qt-%-HMoqeFEMsv~u)-NJ%Z*ipSJUm$)EJ+we|4*-Mi900K{K|e0; z1_j{X5)a%$+vM7;3j>skgrji92K1*Ip{SfM)=ob^E374JaF!C(cZ$R_E>Wv+?Iy9M z?@`#XDy#=z%3d9&)M=F8Xq5Zif%ldIT#wrlw(D_qOKo4wD(fyDHM5(wm1%7hy6euJ z%Edg!>Egs;ZC6%ktLFtyN0VvxN?*4C=*tOEw`{KQvS7;c514!FP98Nf#d#)+Y-wsl zP3N^-Pnk*{o(3~m=3DX$b76Clu=jMf9E?c^cbUk_h;zMF&EiVz*4I(rFoaHK7#5h0 zW7CQx+xhp}Ev+jw;SQ6P$QHINCxeF8_VX=F3&BWUd(|PVViKJl@-sYiUp@xLS2NuF z8W3JgUSQ&lUp@2E(7MG`sh4X!LQFa6;lInWqx}f#Q z4xhgK1%}b(Z*rZn=W{wBOe7YQ@1l|jQ|9ELiXx+}aZ(>{c7Ltv4d>PJf7f+qjRU8i%XZZFJkj&6D^s;!>`u%OwLa*V5Js9Y$b-mc!t@{C415$K38iVu zP7!{3Ff%i_e!^LzJWhBgQo=j5k<<($$b&%%Xm_f8RFC_(97&nk83KOy@I4k?(k<(6 zthO$3yl&0x!Pz#!79bv^?^85K5e7uS$ zJ33yka2VzOGUhQXeD{;?%?NTYmN3{b0|AMtr(@bCx+c=F)&_>PXgAG}4gwi>g82n> zL3DlhdL|*^WTmn;XPo62HhH-e*XIPSTF_h{#u=NY8$BUW=5@PD{P5n~g5XDg?Fzvb_u ziK&CJqod4srfY2T?+4x@)g9%3%*(Q2%YdCA3yM{s=+QD0&IM`8k8N&-6%iIL3kon> z0>p3BUe!lrz&_ZX2FiP%MeuQY-xVV%K?=bGPOM&XM0XRd7or< zy}jn_eEzuQ>t2fM9ict#ZNxD7HUycsq76IavfoNl$G1|t*qpUSX;YgpmJrr_8yOJ2 z(AwL;Ugi{gJ29@!G-mD82Z)46T`E+s86Qw|YSPO*OoooraA!8x_jQXYq5vUw!5f_x zubF$}lHjIWxFar8)tTg8z-FEz)a=xa`xL~^)jIdezZsg4%ePL$^`VN#c!c6`NHQ9QU zkC^<0f|Ksp45+YoX!Sv>+57q}Rwk*2)f{j8`d8Ctz^S~me>RSakEvxUa^Pd~qe#fb zN7rnAQc4u$*Y9p~li!Itp#iU=*D4>dvJ{Z~}kqAOBcL8ln3YjR{Sp!O`s=5yM zWRNP#;2K#+?I&?ZSLu)^z-|*$C}=0yi7&~vZE$s``IE^PY|dj^HcWI$9ZRm>3w(u` z-1%;;MJbzHFNd^!Ob!^PLO-xhhj@XrI81Y)x4@FdsI( za`o4Gy(`T$P?PB?s>o+eIOtuirMykbuAi65Y_UN1(?jTCy@J8Px`%;bcNmPm#Fr!= z5V!YViFJ!FBfEq>nJFk0^RAV1(7w+X`HRgP;nJHJdMa!}&vvduCMoslwHTes_I76|h>;(-9lbfGnt zoZomakOt759AuTX4b$)G8TzJ&m*BV8!vMs9#=e0tWa z%)84R=3?tfh72~=Rc;fXwj+x z+25xapYK@2@;}6)@8IL+F6iuJ_B{&A-0=U=U6WMbY>~ykVFp$XkH)f**b>TE5)shN z39E2L@JPCSl!?pkvFeh@6dCv9oE}|{GbbVM!XIgByN#md&tXy@>QscU0#z!I&X4;d z&B&ZA4lbrHJ!x4lCN4KC-)u#gT^cE{Xnhu`0RXVKn|j$vz8m}v^%*cQ{(h%FW8_8a zFM{$PirSI8@#*xg2T){A+EKX(eTC66Fb})w{vg%Vw)hvV-$tttI^V5wvU?a{(G}{G z@ob7Urk1@hDN&C$N!Nio9YrkiUC{5qA`KH*7CriaB;2~2Od>2l=WytBRl#~j`EYsj}jqK2xD*3 ztEUiPZzEJC??#Tj^?f)=sRXOJ_>5aO(|V#Yqro05p6)F$j5*wYr1zz|T4qz$0K(5! zr`6Pqd+)%a9Xq3aNKrY9843)O56F%=j_Yy_;|w8l&RU1+B4;pP*O_}X8!qD?IMiyT zLXBOOPg<*BZtT4LJ7DfyghK|_*mMP7a1>zS{8>?}#_XXaLoUBAz(Wi>$Q!L;oQ&cL z6O|T6%Dxq3E35$0g5areq9$2+R(911!Z9=wRPq-pju7DnN9LAfOu3%&onnfx^Px5( zT2^sU>Y)88F5#ATiVoS$jzC-M`vY8!{8#9O#3c&{7J1lo-rcNK7rlF0Zt*AKE(WN* z*o?Tv?Sdz<1v6gfCok8MG6Pzecx9?C zrQG5j^2{V556Hj=xTiU-seOCr2ni@b<&!j>GyHbv!&uBbHjH-U5Ai-UuXx0lcz$D7%=! z&zXD#Jqzro@R=hy8bv>D_CaOdqo6)vFjZldma5D+R;-)y1NGOFYqEr?h zd_mTwQ@K2veZTxh1aaV4F;YnaWA~|<8$p}-eFHashbWW6Dzj=3L=j-C5Ta`w-=QTw zA*k9!Ua~-?eC{Jc)xa;PzkUJ#$NfGJOfbiV^1au;`_Y8|{eJ(~W9pP9q?gLl5E6|e{xkT@s|Ac;yk01+twk_3nuk|lRu{7-zOjLAGe!)j?g+@-;wC_=NPIhk(W zfEpQrdRy z^Q$YBs%>$=So>PAMkrm%yc28YPi%&%=c!<}a=)sVCM51j+x#<2wz?2l&UGHhOv-iu z64x*^E1$55$wZou`E=qjP1MYz0xErcpMiNYM4+Qnb+V4MbM;*7vM_Yp^uXUuf`}-* z_2CnbQ);j5;Rz?7q)@cGmwE^P>4_u9;K|BFlOz_|c^1n~%>!uO#nA?5o4A>XLO{X2 z=8M%*n=IdnXQ}^+`DXRKM;3juVrXdgv79;E=ovQa^?d7wuw~nbu%%lsjUugE8HJ9zvZIM^nWvjLc-HKc2 zbj{paA}ub~4N4Vw5oY{wyop9SqPbWRq=i@Tbce`r?6e`?`iOoOF;~pRyJlKcIJf~G z)=BF$B>YF9>qV#dK^Ie#{0X(QPnOuu((_-u?(mxB7c9;LSS-DYJ8Wm4gz1&DPQ8;0 z=Wao(zb1RHXjwbu_Zv<=9njK28sS}WssjOL!3-E5>d17Lfnq0V$+IU84N z-4i$~!$V-%Ik;`Z3MOqYZdiZ^3nqqzIjLE+zpfQC+LlomQu-uNCStj%MsH(hsimN# z%l4vpJBs_2t7C)x@6*-k_2v0FOk<1nIRO3F{E?2DnS}w> z#%9Oa{`RB5FL5pKLkg59#x~)&I7GzfhiVC@LVFSmxZuiRUPVW*&2ToCGST0K`kRK) z02#c8W{o)w1|*YmjGSUO?`}ukX*rHIqGtFH#!5d1Jd}&%4Kc~Vz`S7_M;wtM|6PgI zNb-Dy-GI%dr3G3J?_yBX#NevuYzZgzZ!vN>$-aWOGXqX!3qzCIOzvA5PLC6GLIo|8 zQP^c)?NS29hPmk5WEP>cHV!6>u-2rR!tit#F6`_;%4{q^6){_CHGhvAs=1X8Fok+l zt&mk>{4ARXVvE-{^tCO?inl{)o}8(48az1o=+Y^r*AIe%0|{D_5_e>nUu`S%zR6|1 zu0$ov7c`pQEKr0sIIdm7hm{4K_s0V%M-_Mh;^A0*=$V9G1&lzvN9(98PEo=Zh$`Vj zXh?fZ;9$d!6sJRSjTkOhb7@jgSV^2MOgU^s2Z|w*e*@;4h?A8?;v8JaLPCoKP_1l- z=Jp0PYDf(d2Z`;O7mb6(_X_~z0O2yq?H`^c=h|8%gfywg#}wIyv&_uW{-e8e)YmGR zI0NNSDoJWa%0ztGzkwl>IYW*DesPRY?oH+ow^(>(47XUm^F`fAa0B~ja-ae$e>4-A z64lb_;|W0ppKI+ zxu2VLZzv4?Mr~mi?WlS-1L4a^5k+qb5#C)ktAYGUE1H?Vbg9qsRDHAvwJUN=w~AuT zUXYioFg2Dx-W)}w9VdFK#vpjoSc!WcvRZ_;TgHu;LSY*i7K_>Px{%C4-IL?6q?Qa_ zL7l=EEo|@X&$gX;fYP02qJF~LN9?E-OL2G(Fo4hW)G{`qnW zTIuc+-1VJvKgph0jAc(LzM);Pg$MPln?U|ek{_5nNJHfm-Y#ec+n#Yf_e>XfbLbN)eqHEDr0#?<;TskL5-0JGv|Ut{=$Xk8hlwbaMXdcI3GL zY-hykR{zX9liy$Z2F3!z346uu%9@-y6Gda`X2*ixlD_P@<}K?AoV?(%lM%* z(xNk=|A()443aGj)-~IDf3J+UA2p2lh6ei^pG*HL#SiThnIr5WZDXebI)F7X zGmP-3bH$i$+(IwqgbM7h%G5oJ@4{Z~qZ#Zs*k7eXJIqg;@0kAGV|b=F#hZs)2BYu1 zr8sj#Zd+Iu^G}|@-dR5S*U-;DqzkX3V0@q-k8&VHW?h0b0?tJ-Atqmg^J8iF7DP6k z)W{g?5~F*$5x?6W)3YKcrNu8%%(DglnzMx5rsU{#AD+WPpRBf``*<8F-x75D$$13U zcaNXYC0|;r&(F@!+E=%+;bFKwKAB$?6R%E_QG5Yn5xX#h+zeI-=mdXD5+D+lEuM`M ze+*G!zX^xbnA?~LnPI=D2`825Ax8rM()i*{G0gcV5MATV?<7mh+HDA7-f6nc@95st zzC_si${|&=$MUj@nLxl_HwEXb2PDH+V?vg zA^DJ%dn069O9TNK-jV}cQKh|$L4&Uh`?(z$}#d+{X zm&=KTJ$+KvLZv-1GaHJm{>v=zXW%NSDr8$0kSQx(DQ)6S?%sWSHUazXSEg_g3agt2@0nyD?A?B%9NYr(~CYX^&U#B4XwCg{%YMYo%e68HVJ7`9KR`mE*Wl7&5t71*R3F>*&hVIaZXaI;2a$?;{Ew{e3Hr1* zbf$&Fyhnrq7^hNC+0#%}n^U2{ma&eS)7cWH$bA@)m59rXlh96piJu@lcKl<>+!1#s zW#6L5Ov%lS(?d66-(n`A%UuiIqs|J|Ulq0RYq-m&RR0>wfA1?<34tI?MBI#a8lY{m z{F2m|A@=`DpZpwdIH#4)9$#H3zr4kn2OX!UE=r8FEUFAwq6VB?DJ8h59z$GXud$#+ zjneIq8uSi&rnG0IR8}UEn5OcZC?@-;$&Ry9hG{-1ta`8aAcOe1|82R7EH`$Qd3sf* zbrOk@G%H7R`j;hOosRVIP_2_-TuyB@rdj?(+k-qQwnhV3niH+CMl>ELX(;X3VzZVJ ztRais0C^L*lmaE(nmhvep+peCqr!#|F?iVagZcL>NKvMS_=*Yl%*OASDl3(mMOY9! z=_J$@nWpA-@><43m4olSQV8(PwhsO@+7#qs@0*1fDj70^UfQ(ORV0N?H{ceLX4<43 zEn)3CGoF&b{t2hbIz;Og+$+WiGf+x5mdWASEWIA*HQ9K9a?-Pf9f1gO6LanVTls)t z^f6_SD|>2Kx8mdQuiJwc_SmZOZP|wD7(_ti#0u=io|w~gq*Odv>@8JBblRCzMKK_4 zM-uO0Ud9>VD>J;zZzueo#+jbS7k#?W%`AF1@ZPI&q%}beZ|ThISf-ly)}HsCS~b^g zktgqOZ@~}1h&x50UQD~!xsW-$K~whDQNntLW=$oZDClUJeSr2$r3}94Wk1>co3beS zoY-7t{rGv|6T?5PNkY zj*XjF()ybvnVz5=BFnLO=+1*jG>E7F%&vm6up*QgyNcJJPD|pHoZ!H6?o3Eig0>-! zt^i-H@bJ;^!$6ZSH}@quF#RO)j>7A5kq4e+7gK=@g;POXcGV28Zv$jybL1J`g@wC# z_DW1ck}3+n@h2LFQhwVfaV@D+-kff4celZC0;0ef?pA#*PPd8Kk8sO1wza&BHQFblVU8P1=-qScHff^^fR zycH!hlHQs7iejITpc4UaBxzqTJ}Z#^lk{W(cr`qtW~Ap;HvuUf#MxgEG?tEU+B?G% znub0I(s@XvI(lva}$Z7<}Qg=rWd5n)}rX{nb+Aw;}?l9LZI-`N-*hts=c6XgjfJs ztp>-686v6ug{glEZ}K=jVG|N1WSWrU*&ue|4Q|O@;s0#L5P*U%Vx;)w7S0ZmLuvwA z@zs2Kut)n1K7qaywO#TbBR`Q~%mdr`V)D`|gN0!07C1!r3{+!PYf9*;h?;dE@#z(k z;o`g~<>P|Sy$ldHTUR3v=_X0Iw6F>3GllrFXVW?gU0q6|ocjd!glA)#f0G7i20ly>qxRljgfO2)RVpvmg#BSrN)GbGsrIb}9 z1t+r;Q>?MGLk#LI5*vR*C8?McB|=AoAjuDk&Pn`KQo z`!|mi{Cz@BGJ!TwMUUTkKXKNtS#OVNxfFI_Gfq3Kpw0`2AsJv9PZPq9x?~kNNR9BR zw#2jp%;FJNoOzW>tE#zskPICp>XSs?|B0E%DaJH)rtLA}$Y>?P+vEOvr#8=pylh zch;H3J`RE1{97O+1(1msdshZx$it^VfM$`-Gw>%NN`K|Tr$0}U`J?EBgR%bg=;et0 z_en)!x`~3so^V9-jffh3G*8Iy6sUq=uFq%=OkYvHaL~#3jHtr4sGM?&uY&U8N1G}QTMdqBM)#oLTLdKYOdOY%{5#Tgy$7QA! zWQmP!Wny$3YEm#Lt8TA^CUlTa{Cpp=x<{9W$A9fyKD0ApHfl__Dz4!HVVt(kseNzV z5Fb`|7Mo>YDTJ>g;7_MOpRi?kl>n(ydAf7~`Y6wBVEaxqK;l;}6x8(SD7}Tdhe2SR zncsdn&`eI}u}@^~_9(0^r!^wuKTKbs-MYjXy#-_#?F=@T*vUG@p4X+l^SgwF>TM}d zr2Ree{TP5x@ZtVcWd3++o|1`BCFK(ja-QP?zj6=ZOq)xf$CfSv{v;jCcNt4{r8f+m zz#dP|-~weHla%rsyYhB_&LHkwuj83RuCO0p;wyXsxW5o6{)zFAC~2%&NL? z=mA}szjHKsVSSnH#hM|C%;r0D$7)T`HQ1K5vZGOyUbgXjxD%4xbs$DAEz)-;iO?3& zXcyU*Z8zm?pP}w&9ot_5I;x#jIn^Joi5jBDOBP1)+p@G1U)pL6;SIO>Nhw?9St2UN zMedM(m(T6bNcPPD`%|9dvXAB&IS=W4?*7-tqldqALH=*UapL!4`2TM_{`W&pm*{?| z0DcsaTdGA%RN={Ikvaa&6p=Ux5ycM){F1OgOh(^Yk-T}a5zHH|=%Jk)S^vv9dY~`x zG+!=lsDjp!D}7o94RSQ-o_g#^CnBJlJ@?saH&+j0P+o=eKqrIApyR7ttQu*0 z1f;xPyH2--)F9uP2#Mw}OQhOFqXF#)W#BAxGP8?an<=JBiokg;21gKG_G8X!&Hv;7 zP9Vpzm#@;^-lf=6POs>UrGm-F>-! zm;3qp!Uw?VuXW~*Fw@LC)M%cvbe9!F(Oa^Y6~mb=8%$lg=?a0KcGtC$5y?`L5}*-j z7KcU8WT>2PpKx<58`m((l9^aYa3uP{PMb)nvu zgt;ia9=ZofxkrW7TfSrQf4(2juZRBgcE1m;WF{v1Fbm}zqsK^>sj=yN(x}v9#_{+C zR4r7abT2cS%Wz$RVt!wp;9U7FEW&>T>YAjpIm6ZSM4Q<{Gy+aN`Vb2_#Q5g@62uR_>II@eiHaay+JU$J=#>DY9jX*2A=&y8G%b zIY6gcJ@q)uWU^mSK$Q}?#Arq;HfChnkAOZ6^002J>fjPyPGz^D5p}o;h2VLNTI{HGg!obo3K!*I~a7)p-2Z3hCV_hnY?|6i`29b zoszLpkmch$mJeupLbt4_u-<3k;VivU+ww)a^ekoIRj4IW4S z{z%4_dfc&HAtm(o`d{CZ^AAIE5XCMvwQSlkzx3cLi?`4q8;iFTzuBAddTSWjfcZp* zn{@Am!pl&fv#k|kj86e$2%NK1G4kU=E~z9L^`@%2<%Dx%1TKk_hb-K>tq8A9bCDfW z@;Dc3KqLafkhN6414^46Hl8Tcv1+$q_sYjj%oHz)bsoGLEY1)ia5p=#eii(5AM|TW zA8=;pt?+U~>`|J(B85BKE0cB4n> zWrgZ)Rbu}^A=_oz65LfebZ(1xMjcj_g~eeoj74-Ex@v-q9`Q{J;M!mITVEfk6cn!u zn;Mj8C&3^8Kn%<`Di^~Y%Z$0pb`Q3TA}$TiOnRd`P1XM=>5)JN9tyf4O_z}-cN|i> zwpp9g`n%~CEa!;)nW@WUkF&<|wcWqfL35A}<`YRxV~$IpHnPQs2?+Fg3)wOHqqAA* zPv<6F6s)c^o%@YqS%P{tB%(Lxm`hsKv-Hb}MM3=U|HFgh8R-|-K(3m(eU$L@sg=uW zB$vAK`@>E`iM_rSo;Cr*?&wss@UXi19B9*0m3t3q^<)>L%4j(F85Ql$i^;{3UIP0c z*BFId*_mb>SC)d#(WM1%I}YiKoleKqQswkdhRt9%_dAnDaKM4IEJ|QK&BnQ@D;i-ame%MR5XbAfE0K1pcxt z{B5_&OhL2cx9@Sso@u2T56tE0KC`f4IXd_R3ymMZ%-!e^d}v`J?XC{nv1mAbaNJX| zXau+s`-`vAuf+&yi2bsd5%xdqyi&9o;h&fcO+W|XsKRFOD+pQw-p^pnwwYGu=hF7& z{cZj$O5I)4B1-dEuG*tU7wgYxNEhqAxH?p4Y1Naiu8Lt>FD%AxJ811`W5bveUp%*e z9H+S}!nLI;j$<*Dn~I*_H`zM^j;!rYf!Xf#X;UJW<0gic?y>NoFw}lBB6f#rl%t?k zm~}eCw{NR_%aosL*t$bmlf$u|U2hJ*_rTcTwgoi_N=wDhpimYnf5j!bj0lQ*Go`F& z6Wg+xRv55a(|?sCjOIshTEgM}2`dN-yV>)Wf$J58>lNVhjRagGZw?U9#2p!B5C3~Nc%S>p`H4PK z7vX@|Uo^*F4GXiFnMf4gwHB;Uk8X4TaLX4A>B&L?mw4&`XBnLCBrK2FYJLrA{*))0 z$*~X?2^Q0KS?Yp##T#ohH1B)y4P+rR7Ut^7(kCwS8QqgjP!aJ89dbv^XBbLhTO|=A z|3FNkH1{2Nh*j{p-58N=KA#6ZS}Ir&QWV0CU)a~{P%yhd-!ehF&~gkMh&Slo9gAT+ zM_&3ms;1Um8Uy0S|0r{{8xCB&Tg{@xotF!nU=YOpug~QlZRKR{DHGDuk(l{)d$1VD zj)3zgPeP%wb@6%$zYbD;Uhvy4(D|u{Q_R=fC+9z#sJ|I<$&j$|kkJiY?AY$ik9_|% z?Z;gOQG5I%{2{-*)Bk|Tia8n>TbrmjnK+8u*_cS%*;%>R|K|?urtIdgTM{&}Yn1;| zk`xq*Bn5HP5a`ANv`B$IKaqA4e-XC`sRn3Z{h!hN0=?x(kTP+fE1}-<3eL+QDFXN- z1JmcDt0|7lZN8sh^=$e;P*8;^33pN>?S7C0BqS)ow4{6ODm~%3018M6P^b~(Gos!k z2AYScAdQf36C)D`w&p}V89Lh1s88Dw@zd27Rv0iE7k#|U4jWDqoUP;-He5cd4V7Ql)4S+t>u9W;R-8#aee-Ct1{fPD+jv&zV(L&k z)!65@R->DB?K6Aml57?psj5r;%w9Vc3?zzGs&kTA>J9CmtMp^Wm#1a@cCG!L46h-j z8ZUL4#HSfW;2DHyGD|cXHNARk*{ql-J2W`9DMxzI0V*($9{tr|O3c;^)V4jwp^RvW z2wzIi`B8cYISb;V5lK}@xtm3NB;88)Kn}2fCH(WRH1l@3XaO7{R*Lc7{ZN1m+#&diI7_qzE z?BS+v<)xVMwt{IJ4yS2Q4(77II<>kqm$Jc3yWL42^gG6^Idg+y3)q$-(m2>E49-fV zyvsCzJ5EM4hyz1r#cOh5vgrzNGCBS}(Bupe`v6z{e z)cP*a8VCbRuhPp%BUwIRvj-$`3vrbp;V3wmAUt{?F z0OO?Mw`AS?y@>w%(pBO=0lohnxFWx`>Hs}V$j{XI2?}BtlvIl7!ZMZukDF7 z^6Rq2H*36KHxJ1xWm5uTy@%7;N0+|<>Up>MmxKhb;WbH1+=S94nOS-qN(IKDIw-yr zi`Ll^h%+%k`Yw?o3Z|ObJWtfO|AvPOc96m5AIw;4;USG|6jQKr#QP}+BLy*5%pnG2 zyN@VMHkD`(66oJ!GvsiA`UP;0kTmUST4|P>jTRfbf&Wii8~a`wMwVZoJ@waA{(t(V zwoc9l*4F>YUM8!aE1{?%{P4IM=;NUF|8YkmG0^Y_jTJtKClDV3D3~P7NSm7BO^r7& zWn!YrNc-ryEvhN$$!P%l$Y_P$s8E>cdAe3=@!Igo^0diL6`y}enr`+mQD;RC?w zb8}gXT!aC`%rdxx2_!`Qps&&w4i0F95>;6;NQ-ys;?j#Gt~HXzG^6j=Pv{3l1x{0( z4~&GNUEbH=9_^f@%o&BADqxb54EAq=8rKA~4~A!iDp9%eFHeA1L!Bb8Lz#kF(p#)X zn`CglEJ(+tr=h4bIIHlLkxP>exGw~{Oe3@L^zA)|Vx~2yNuPKtF^cV6X^5lw8hU*b zK-w6x4l&YWVB%0SmN{O|!`Sh6H45!7}oYPOc+a#a|n3f%G@eO)N>W!C|!FNXV3taFdpEK*A1TFGcRK zV$>xN%??ii7jx5D69O>W6O`$M)iQU7o!TPG*+>v6{TWI@p)Yg$;8+WyE9DVBMB=vnONSQ6k1v z;u&C4wZ_C`J-M0MV&MpOHuVWbq)2LZGR0&@A!4fZwTM^i;GaN?xA%0)q*g(F0PIB( zwGrCC#}vtILC_irDXI5{vuVO-(`&lf2Q4MvmXuU8G0+oVvzZp0Y)zf}Co0D+mUEZz zgwR+5y!d(V>s1} zji+mrd_6KG;$@Le2Ic&am6O+Rk1+QS?urB4$FQNyg2%9t%!*S5Ts{8j*&(H1+W;0~ z$frd%jJjlV;>bXD7!a-&!n52H^6Yp}2h3&v=}xyi>EXXZDtOIq@@&ljEJG{D`7Bjr zaibxip6B6Mf3t#-*Tn7p z96yx1Qv-&r3)4vg`)V~f8>>1_?E4&$bR~uR;$Nz=@U(-vyap|Jx zZ;6Ed+b#GXN+gN@ICTHx{=c@J|97TIPWs(_kjEIwZFHfc!rl8Ep-ZALBEZEr3^R-( z7ER1YXOgZ)&_=`WeHfWsWyzzF&a;AwTqzg~m1lOEJ0Su=C2<{pjK;{d#;E zr2~LgXN?ol2ua5Y*1)`(be0tpiFpKbRG+IK(`N?mIgdd9&e6vxzqxzaa`e7zKa3D_ zHi+c1`|720|dn(z4Qos^e7sn(PU%NYLv$&!|4kEse%DK;YAD06@XO3!EpKpz!^*?(?-Ip zC_Zlb(-_as+-D?0Ag9`|4?)bN)5o(J=&udAY|YgV(YuK9k=E>0z`$dSaL(wmxd!1f zME&3wwv@#{dgeMlZ4}GL!I`VZxtdQY$lmauCN_|mGXqEEj@i~du$|>5UvLjsbq!{; z@jEf;21iC1jFEmIPE^4gykHQzCMLj=2Ek4&FvlpqTlS(0YT%*W<>XgH$4ww`D`aihBGkPM(&EG};Cl&wzg8!jL z`rkqPzvH(0Kd{2n=?Bt8aAU&0IyiA+V-qnXVId^qG!SWZ7%_f&i!D{R#7Jo$%tICxY%j)ebORE>3H_c|to}c#HX;HAC?~B;2mmQrMp2;8T zmzde!k7BYg^Z1r|DUvSD3@{6S<1kndb%Qt%GA# z+sB2&F5L`R&fLRdAlpU_pVsJsYDEz{^ zKGaAz#%W+MPGT+D$+xowMY0=ipM)0p?zym&Aoi)qL(pO_weO(k?s|ELHl^W zviJiFUXRL&?`;3_;mvc02A@sbsW9}#{anvGafZ#ST;}za?XS3}ZG3B4m(SW{>w}Fh z)T5Yi*``Tstmi9SHXmuWSND@cj}qtY!`tuD29Dpu+-D3$h<5FY>jE>YJvqBmhw?oll`x7Ono(}R~P zle_eBwYy0Rr7kmf_SEt_gn4)AO-r`}^Z5Y%Rm8)K-?X>rvDL+QT?#)QwDsQ2c$tc* z&#hbgkL6}GnBDH;+lREM6MGIskRa@r>5Iq(ll2IepuhW86w@14=E{6$cz*cBDQ)CT>}v-DLM-v8)xaPBnmGBKM63RgDGqh!<*j90tSE4|G^+r@#-7g2 zs8KE8eZPZhQuN>wBU%8CmkE9LH1%O;-*ty0&K~01>F3XB>6sAm*m3535)9T&Fz}A4 zwGjZYVea@Fesd=Rv?ROE#q=}yfvQEP8*4zoEw4@^Qvw54utUfaR1T6gLmq?c9sON> z>Np6|0hdP_VURy81;`8{ZYS)EpU9-3;huFq)N3r{yP1ZBCHH7=b?Ig6OFK~%!GwtQ z3`RLKe8O&%^V`x=J4%^Oqg4ZN9rW`UQN^rslcr_Utzd-@u-Sm{rphS-y}{k41)Y4E zfzu}IC=J0JmRCV6a3E38nWl1G495grsDDc^H0Fn%^E0FZ=CSHB4iG<6jW1dY`2gUr zF>nB!y@2%rouAUe9m0VQIg$KtA~k^(f{C*Af_tOl=>vz>$>7qh+fPrSD0YVUnTt)? z;@1E0a*#AT{?oUs#bol@SPm0U5g<`AEF^=b-~&4Er)MsNnPsLb^;fL2kwp|$dwiE3 zNc5VDOQ%Q8j*d5vY##)PGXx51s8`0}2_X9u&r(k?s7|AgtW0LYbtlh!KJ;C9QZuz< zq>??uxAI1YP|JpN$+{X=97Cdu^mkwlB={`aUp+Uyu1P139=t%pSVKo7ZGi_v(0z>l zHLGxV%0w&#xvev)KCQ{7GC$nc3H?1VOsYGgjTK;Px(;o0`lerxB<+EJX9G9f8b+)VJdm(Ia)xjD&5ZL45Np?9 zB%oU;z05XN7zt{Q!#R~gcV^5~Y^gn+Lbad7C{UDX2Nznj8e{)TLH|zEc|{a#idm@z z6(zon+{a>FopmQsCXIs*4-dLGgTc)iOhO3r=l?imNUR-pWl!ktO0r_a0Nqo@bu8MzyjSq9zkqPe*`Sxz75rZ zr9X%(=PVqCRB=zfX+_u&*k4#s1k4OV11YgkCrlr6V;vz<{99HKC@qQ+H8xv5)sc63 z69;U4O&{fb5(fN``jJH#3=GHsV56@{d@7`VhA$K^;GU+R-V%%cnmjYs?>c5^6Ugv} zn<}L&i;2`zzW@(kxf$$gVH@7nh}2%G%ciQ_B?r{13?Q@=Q+6msQGtnyY%Gkjeor?g z7F*tMqLdhcq+LCCo^D;CtOACCBhXgK-M&w{*dcUdmtv@XFTofmmpcWKtCn^`#?oZC zUOm52 z7sK$hR|Vh6y&pfIUK&!`8HH*>12$nWA)Ynp+XwOj=jNLD z{QA4gezbe>wiP?`jJO;c&EId;=2u80s_r97;TX!6@*(<%WL+^bmxheMB3pKx0OpH^ zPs}knV+jpJ4TaD@r^V`mTsjf`7!z^H}eHQ#Rp z72(>Dm#QO!ZYR*O@yHic`3*T^t7jc=d`Jz6Lk@Y-bL%cOp_~=#xzIJl?`{Qu;$uC~NkePE+7wSW_FM`&V{gFN zl;lq@;FtAsl!h;tnOvj z#gYx!q$5MdZ0Jxjy=t*q)HFeeyI-vgaGdh1QNhqGRy8qS)|6S0QK7Gj9R?Co{Knh> za>xkQZ0}bBx!9@EUxRBYGm25^G}&j-`0VWX04E|J!kJ8^WoZ(jbhU_twFwWIH32fv zi=pg~(b#ajW=`)Vikwwe39lpML?|sY$?*6*kYBxku_<=#$gfTqQ_F!9F0=OkHnzBo zEwR!H_h|MNjuG$Tj6zaaouO}HYWCF8vN4C%EX-%Iu%ho;q$G#ErnafhXR*4J2Rp5* zhsi0;wlSwE*inVFO>{(8?N~82zijpt+9Y_-^>xnE%T*zk9gi|j7b@s<5{|qEquUD( zS;-%RySZOCOEh*>!kvbsQ265* z>X8*_Wy&~FB@aDHz%glyiAujXq-|2kDUjFTn9Rafsl+XNyFP%PG|l&ZGWBcEXxy=9 zeDn2PIoVuL$gX0RgVK1O$x3%pOzS7x^U5Pi;mtT)%cY;&e&M7GLM}zP+IPbqLt=^5 z7qLfri8myf;~2psc@^cA6mG&{C%e_(M$$!wC^5p^T1QzrS%I?(U{qcd+oJJkQxe10 zON{Q*?iz%F4MbEsoEc+x3E?&2wVR^v3|Q0lDaMvgS7mNjI{2w! z9|~=!83T%GW*iaChSS!`Xd^beFp9N4%K+k*j#jFumk}U?=WKL_kJAltxnxp~+lZzT zp@&&kSPTg3oSGos`rVBhK0|4NdHM_hnKuw1#0JV{gi_dKDJLB+ix~~HpU9%jD)@YY zOK)L7kgbLyN2%Dx#fuY}8swh4ACk7%BpP-n5(RhDq{gEHP*Fo4IviX{C49|B5h~SC zFr`=0)=h2^F5UpCAgt?R5u{6VvpUf#*nC zCQ`$!|C;L2lpjlG?(>T$(_$O3_YNNbPT~(?!j3aD8k=yu^ogw4bkjvgF|3BOq(hB& zG;^cPXmcUP$ox8zElCJ-zMbK9q^8{rri#8Cek5Ydr0YT-KTh@J z6^AcB9ejew8BY5kzZUZX(7Po==eW<(;uV~E7(BY5c0^xr`cuRwn)47bN?zOb!0?cw z#v}R$z66&m#+AHfo@(^V2#S~bhoUkkTArg+6w>JzZ52r96^({1W!?>4$h0l|-jDfj z>7(<+%67#(A|4hZ3>Y;hd&S?}F;`Vtqz|pK&B>NJ=Faci;gkf-+GmfQR8^zo_vul2 zB!)kfu4Dq_g)8TBBo52*sB6F`qa&JCR=_A$QWgX_K}fZm{Cb2#1q`^S3+WaS>sS#@ z-4k*G=#?z6d_e7JJ+Z8^(t0tNdL{K5F;2nfQbXgld}a(X)Gr;WojOy`^?es~AClT$ z5^lD{WJek0!p-QEH5E7n6DKQ0%_ZBZ=|jfV_MM{VmL8y-Wd|>OmeemP=C@xI@@M~1 zW2S*im@Rc=O>V886_UJ@oh1!2H$Ku&U*Hh_oxd{32)vf1$cRiepv28ricM;}#p!+k zaK{z1I=9Y%3m4|Pj*BD*Fn5Vh?O@oD^1UcjyeNh0fbhh~V6xb#4njlGW8OehUe!MnoR(wn#nsoyL1m!Rov)Nv4~&JEVl7L z#^qYdTpNI#u`N0UbVMiDmD>g2VQcG3>4D6gErgddZnSQTs){BExxRJRB?bIxTdZa z;!S8FHJPPiIDQ*FAUiWSYnjILFjDvxvSC zk z=j4Kx@Pg~&2Z?cmMDa;)#xVeorJrxDBqy{+`kG+ZPQqC@#ku-c3ucU+69$#q_*se` z-H#PFW^>-C0>++|6r=<$Z8)ZFaK=ZjwsNYXqRpl9G|yme@Eld5B-*I69Nx_TResHi z!5nm+>6zaJYQO#%D{~o-oOJ;q`fa5}l!8G*U-E$OM&7@dqciBCWtd}|SrDXz$TB($&m*=Epuolu2k`KUwO7maP3P0ok zmF57lSh0Ba@&sO1iZ5^+3s8{B8t|M;Pg&O+{tZJCiLWd6H@{b~9{CLF9s3Kn zt5)Rs9ejne?o{%f>B$Dl%X7fd~KY)I|(pxUeHj;gNsK6;ZR>`ciu;GxvhDUt!+31Knss2U(%ts8K z18)8;<2ax9RG?!|Lwdt^i5L^&O788roKmVAB)=EdK~HqR2Q=)H_VW}xY=95MP_Ov< zPEz3%DRK}+(aUBwsr83H8>`H^v~|A_t}0vPmRwKPt1{|qOY|PZu}j9+{ZhF&-H_TB zU9xWLpNTc`enI|)h9jQeqf5RfGLFk_vfX`40iMpd%KZF!lKbZTdBw$<^G6nuS+$fT zrbK)xo&;buPJcpOZ=x>n+bRXVFDs(23Xr=rDE&!)pVXZ;;A07NXGl_0m`{Z)DQIu$ zFDvY4xu-ifTe_$|n2B83eI;KUg6pVbw+N!nyLj~wnRi{4mNy{WDV)G1!6$y=+x6U{ z%4_9=Q^L!x_gAYp?J3+u5hA5cO8aHeI=6AC8^S{mzhqCBvBLYEutUC(X0>hKg|AvN zvkmJCQNA45_KjW{aEcyrBppcO6G0zTy%v1&@~+2!n?kA9?>0>AjFN|JdCnHQ8$hEU zw#mwGifHppLP?89LMb(Y3Li9iCPx7W%ek}2FgD2YSzjsR4Xj<=zN{Yo@7s7(k%mP4 znT2p&4EQ@q_chd-E z78uvD*C@oba`U3W2Iw`M#`5C8jOHv8^Li<|j^SI>>>`77Dp71Vtz=J?4Zck4SdRbd zfF}C_>Y(#)r@y!Q0`tMlG#b9>5`fAI$B&tWJfbGlYW$J4V+-s=HH!`+;1XeL@USdx zR0$G&&XBf9lQtkH5)p=U!8J!1{oc4E!N-~Abxl6E;;=3-hMYZ+44?u}zabmCE)yB?*_w91m$n1Yskp&@ z;kxeJX-#ioX^{elyLu~gzx|_KxLpX62MF%Axq3$!Z_P`pBWR?zP8OI`PV~6Aa0Oi0 zv_Ot1m&plf-ZF{e(z(Ms3*S5q$e|j;gOwGrmWsCHfLi(h8y?gc$(2H{884C1FvHQQ12tX=qFUsK~zM!W=K>;zaRsu4Xmcc@8nSs!vK+{ z?}bq}-m&p5jRSam67n>yG9ez=I^|J1O;Np8s=P~9MXYLxD+cFQK7PhG=bkjo{Naae zjp3NWWrlFWDb3Z5D07Q|WjZ=wOQ=aKA%en=O@hL$QCKpIXNZE=InFk|Fhq-&H!6&X z*MVy8=hL7Aw&pQjHrFf27C%3B<>FX{@fOLNhUoxL4*@nY}&M3G*T-p67a zo}~_&yGOB)#vbU|Q3FA8S^X)c-yBlmN(_%}`7Ha3uWFe?>9f=3hlO{^gv~$p`v?vk z_P*r43|(S{%ihs;)YH|jAMpP=-Ms7Ne75_YZZiL3CHVjSU`X1|?Ehh&gA=Xn7W7d@ zf8bM9Y>lG!`PWFDDA9G;x*{1Eh^55u66*9D+-4^dYZ{xXP@?sQLVrY%(azM;C^4FuN7CQ%$!3sr1JL=!Be& zuOZL^bLp$Qo2rL=WDzQIls%s!Go z{s}Q0b#+#8bKga|01t%^9Z=wEsevvXM_{$dCR97ed3@1kX)mtSS!JN^rtqKOj}p~> zfpCI@DX*DqcB6ZnBcl~}sGO~1s$AtfkX6fy3N8*ebvZc*KBW;dA=)?#BE&}-or74i zZUt5;{FBPnkZD8YUXDsx&2LvSziAlec3oc>&Lf1Doc3g?H9{OO_$M4B0qTat0UsWP zTlxUeQ3B;oJ%en4n?zQB6*Fb#wH7`$SQN5GI|=DnJKiYm{?-?#-H;#sIjz7kQ4&VW zN9d1(1$_W~S=<%qDD!mwRytas=eqX^iW}YSx3;wJ#)Xp_`Qk1DFiXac$-3;jQbCif zLA-T_s~5yP@Q@W>pXKl^gipQ>gp@HlBB>WDVpW199;V%?N1`U$ovLE;NI2?|_q2~5 zlg>xT9NADWkv5-*FjS~nP^7$k!N2z?dr!)&l0+4xDK7=-6Rkd$+_^`{bVx!5LgC#N z-dv-k@OlYCEvBfcr1*RsNwcV?QT0bm(q-IyJJ$hm2~mq{6zIn!D20k5)fe(+iM6DJ ze-w_*F|c%@)HREgpRrl@W5;_J5vB4c?UW8~%o0)(A4`%-yNk1(H z5CGuzH(uHQ`&j+IRmTOKoJ?#Ct$+1grR|IitpDGt!~ZdqSJ?cOtw-R=EQ+q4UvclH zdX=xlK-fhQKoKCPBoFAZ*(~11O6-tXo>i0w!T$u{lg!#itEUX3V{$S*naW!C@%rll zS{L(1t%xz(*B`{1NL!*aMc<~fE=g;gXi&Gb$HpD!P)8?JzfN;4F&wv(5HH<=c>>)n z({271)xREH89=C(5YKL{mmJJ_d>qHz;;gTvTlgM*vz9@YTTYZ#%_2A zS0G-t9oMQEpvfv(UjfQ8T$vAHi)zOj3>D*{xSRiu3acc=7cvLyD?_ZObdu$5@b*!y zaZ#u?7uF}SrHVQa=sTOhGW{6WUlq#RhPPm^GsRH#qlX8{Kq-i~98l;eq>KdCnWyKl zUu&UWBqu#Tt9jQ97U4}3)&(p2-eCLznXMEm!>i^EMpeVzPg%p;?@O;dJBQQY(vV;d z3v+-3oTPC!2LTUAx^S2t{v;S_h(EZ^0_dS5g^F*m{TEIy^Qal~%mu3h7*o`jWOH}i ztv8M)3X3a*+ry_KkYXYE4dB0?M|t}#Tp+(}6CQ zBbq;xhoHj}b@j-@koDB#XcCY~>_x&Y;i%MH|3tF^X2h{36UCVfQ-;oEA+4ZkJ`^Qi zQf^8}6eFO$Z+Dj-F1wkG##tTx>FjR2oOXFmbKFj6K3+=kePQ<4d7%z5R5cOB;zO6| zm9^m#U4lcA;7t&*=q|a-!`!)}SgYXT#i8hnxtx@kaoBF$QAS-hT7N5kH^l zB^i+})V>L;9_0Qqf-dyF%ky8Mp-dp#%!Nls3vCt}q3QLM3M-(Zs1k}1bqQ9PVU)U` ztE=?;^6=x}_VD%N@${>qhpkU*)AuUBu_cqYiY&@;O$HV*z@~#Tzh?#=CK`=KwBv+o zh%zu%0xPKYtyC)DaQ zpDW}*86g%>BH3IcWMq`g$j()0kWE(qkIL8A&A0mf&+BzxpKF}=`#jG% z&*wa!&pGFLs5_b#QTZE4Bp+})qzyPQ7B4Z7Y*&?0PSX&|FIR;WBP1|coF9ZeP*$9w z!6aJ_3%Sh=HY3FAt8V144|yfu}IAyYHr1OYKIZ51F>_uY^%N#!k~eU53at-_E-Gh?ahmM5y* z+BTIbeH;%v1}Cjo{8d%UeSMWg(nphxEU`sL< zQR~LrTq>Da(FqSP2%&^1ZL#DTo5Sbl9;&57tQ-@U&I#lj)aNSkcfEJwQD!33?anVU z?pw2q7WtMvfji493`rSFnyp7{w87cW`ak=UEYlk5PCB1K6UDVKXyozOChH4yHh~Q< zv>yvKw6WLfi!PZUx60JZcTNM7jo{ww9b8Q+S7C3WA5&llSwdwh$=Q(*(f3ofqcz=nwOmOy z(J!K=*wNoRU*${{Mbwapi9pTB(&VVKefqd-qrUb9*Eyr2E@oZ9Cgf}Mc;QP<0D)R4 zz=!*^VIG4T*7Xl=sJxrWv9hW^eJ%qYp5(d0?E6LZzJ}=7E+1{?GQA;z+!^VBD81}O z0kJ^dKy&WMw+1+aGVYY-v@i28@Gm+sX5=@U%F=Z?W)oar}2~Rc&F|+3A)n-U2GF10+QdxDb^iA@7eL$c7yhBtL z>lABrh^qy9XZ${E1}Ss5!N4;ig0-pUh6@|RPCHOWvgG{|l}2enRgJftsN%D|ck0YO zuAQd2aMPSyGuJ~jm)aY=+p~mGudw4erwE%P^)5f<*$$2C-4^I=e8-}7##ZQ!8!Tep z+Z_!}CAI~sry$|XK$ktXaxP*x<_ijCPp`2=6sNLZU<@9Sz-rz7^BCE9yh0jV4(I!Z zxmA4d;>B-!vD}Xp*&*N%`b^e&R;D97WS}{~{O-EtXeZNfdf51tw!WR6Noo4hjHPv5 z?heYYRSBPjMc}tFEU^|U8a1CxxK%)WTcn9P%`wR^I$QSeMn6=w>Z9OoVvcrl`zYlZ z2y`mAu0bV(Scc>G_EmIo_4 zm*~h`mxYZC&+U>C5G1FZH5L^U>Cq-9UDRQa35jz&NBj*0{uJKfZs5=Fn@&)Xh6aX(H3w9m9BGLePqVotxTeSPh5-mc7$# z-80t6yB0$Nx<54ohdO*QL7m_(&+#*=eoNiYDB4rE4Cag@qfyZS};Fx;Vf1;oync2k z9v#-w?d6R& zOI`CCS_d=tf3|?g3Z}b6-_Rdg3y~enQhmgkni0Cvf9m6%Ft8r;NC5|b%t&?lkl*4{ z8Ui^;Ds^gq6ti(1xB7y_$zA!i-M~#!!tl$ErTR>P~>T=Yky)8(uvPbvLmB=UfoD zrfl}8<1OQrm?8#j1!?s*T>AoectQl&m!o&*^JcIW`_&bk3tN}k^0rjl=HL$z*uIYt z?7l?^Dqr?q1210Sp$xoAy!&{2^{^Anl460 zI&7urrc&|Y{rjv04VOl{y7c82N6xzg5ueYmQ(q(zC3w_C#x*~%yf5j7MI{W`tsoxzA*PrmK)cTskU| zf2C}Bq$>S$-1JgIh0aW@LxI|-8(OGuD#^M01ghh}&#ObO>tZgSw_LW`zdf&IN$YO# z)|X_9m#JwLW5pErZB3ScggKcNzxA9(hyKkK9I#pR&79&*+SV_eu={00{HF=Bb+AEe znaSof+r1jZ!EL5XgqXWkckaFSSyEk}o!%p8XsD}O>borZ6x%X2b&q!s&1-O(>`kZ$ zB2l^5Cx9xQx9)PXN1xPM)@+LxACH_iZ8zGc(>wnFS_O|@hKsxpMjXOzLEa7OvSlM&&G9ioQw9~RsD4F zK7Q+_&|Q6{eZ^8Rx@pKL`le6kH+(fLc{=V&{b%I5=n}VHV4)X_2Y!pYxgC8wU)yP! zPF3t$?(jsC>Ge=&{kmPGUEETpaw(QTAl)m#{qR3_aq9!wK%6XHfV4C>Y^>Z|%ns7j z{Ja?^IA{+@;kR#IjHxkar%3$eJT4?xNBKUVmoO z`A8Zo-{~_;vcikZ(p}EZzU4kO6WPqkMyE{VvS?;44Z@lj zz^fKX9UL!8Wc(9VgI?P4*zpis8dzl};I>yr1>dtXU=FTAlx}Eht4-*7RACL^AflGh zyZb1hTf(~CkMo%#Q%NMgM9tE2D+)joqbtHYA89Ql1nqVTt+MxZ^*FRd&n5YlIi!8m z>$Ysd!l{+C)y;Wa(ZV-=<+NZKV;v4mt}v2m>`v$-$3b;GsLxf= zd~f(rmfpl``{0aVwN7y!>eGyJFP`L+TxHjHTOS{K^$L2`@6(Rli`{EFwpH@R%eZ6g zwf7rc43Yk!=k;{ z-Rn%~B3amGr}}SxfE$vS8FIPL=Qt57$|R#sSoFgdNUT?fYOYjPl%ZBFpi=jq=DWby7Zxm@y;B<89!9= zbgEH*Uy)~iq5kJLX$+ps$kV`#6jW#|9BGz^`ivNeid(wVbk4jl)VBpW&~;eXNi{#` zwx?{DXR~*sqQcFhY0XCfQ4-*2aN1BGX>$_swtKEqnd>j6vcZ!#0)pXRi?<{!P?tGw z2x_`RD$W)qD{?z}VDPt?+)8*rqLWFIPQ(9-VbBdf{7ff?w9CZ{sIi_gnuC$I0(+P8 zms9XB%}VQ>>pve##}jog6+cD?v~n4Pa9Vmc zg#K$|+`adO=B7`uj35Y}6EZ z{dY`x@w8;R-7zrsr1O_~Jvl*|o-x%jF=Rr1C}GXP^|IYN`1sqmG-oI@R#%X66c#5W z$$tQB)sqwiVm;Y^`Dw3mo|firP{*HsOQJre5%Dm^H@we0FN88VWJ0dja?_U38z73f zrCV!b3qNP0kM#%9T!W5`ynGcg%BL28FW1J-J1_S`BJGCaReQ!am(2%qZ3lLgzq|ns z!!fF@`0=*z)J2BwZ*hO|Yu^cI_nF$9l-Pb3jE7=P8gZ#!xiuZ7-cSa`gb`6mxGTgg z-DLdID?M!Z%+hHB#{?&0$GFRpf+_}q<_wbzX6K?w;%6szz1RbySDSr2r^h_qi$khs zXdZ9A0!_Bf)TR2-^-K~q`FQ!#1x(U4VbV%AA@Ei{%cA(EwC{XfjRi?`&9rav5;Q5% zO1`Rn@OA_ZB@N*mC#)?d3P!}Eh;=NgpIKsy{(yr`hv=aouwt@r&P&}Z3DNWo9ro30 zX52~(aTV$*HHlgB66-4GQru!_AZ|)V*I5X=WG)`N@U&D>e@@C#V@JwEL*L`7#$yes z62C^5%Qniaow2$3HrAc7U{qzpb&FA*xLI1JSWR@`RF=JCcvTI)%dH7;sWInt9JLu# z|Ao|Q?K)cDg_JKsym=joo5gR80wtv01N`um1nQ@Ms0Y*bVzxL34} zo?gizp?`=Y{*W>^Hy2%Jl)y?A+&7s1UVHFixuIy~sawXjcDCL`129cK7|ZQS0u;A} zTJC#WNmqkIrnHpAhHVcM(U^vJA~dl@jf_bs*3?i+=&vuC?Aiy_pcB~=1syDni4 zw+FLuz>F773u#$;NUQ9WDtUPY@+rA3WBhQdKFKOyzkA(URa7;4tW>3jQIfi8v0h3g zJC_HVDXS#>DWb|&se7FHnr=q&l#xg9o02}}u=b-R>@sw={Z zHF*?t2FmhqZ=|qa>x=A!*$S+0T zhO*D*M?NTf-eX`eO)9TIQu{7Dm77Acnj4b1jI9@c*ZL8wL%8kLEhd$KM8=Y!fbN@9 zC7B5#y>JM1n5M)!&im==EgHs2j+xCZG~+~QWCi?s!QyFo2kqx{%jE2n3^N*Ayz6Lp zhg5g^3# z+5FoJ@$u@9WJgPKpUWEd4}4AK9TJKU8W%ms!d0p%OIOX+bY+55zl!vIaz$XFI9Ep+ z;bL_}7PDI2Y`Ng*XY(65 zh0%`@Lve%fc;)N4_g12bNrt6gH=N#OHtxO`$lpWlw=Z6MF+E@;>GkZ#lAZTn`aHwf z&I1|aV#b_VHMIgBN*RzU9i@Z@m}0i>o?({&%fpEfaOpFeaJ7V37;m0?kzd}}Lk@9$ zL}8TEo7WZAcRi%zFZxkr6<0k#X-;lTD`Oc~cDb@olwgWCewvk{GJ}hCXbF!AdiLpd z|Cck$ZTKI?Ack{34Lva7+k=H8K2HTZiurox6F+>dy+@R9T^awxj590D$|kXUg+Ygc z(f)jlRwN(4z$#%PnOVc;#Fv{nAi{#UcXPNcmP#5O{zh_*`=q^JCeia{sN4zHjk2*y zqUVh{Ya{j>SPmP^i#Qfcq_MTqo8g52Fi^F zKBc$$HVI!xFx*4Y9l+nt)$AoZORD}%5I10oI3kx`-N30QueiwIw#0VV2E*Fb-nKW% z=+r^hos`Y-7~{cA1FVbK$_=~*z53+Q8KGjg;>ztg((H12%QTf4OYU8y)C}h5yo#$% z&Q$`vMM*g?ZcatAn2j!hFv8KuN(dw)T*}sF#THDHxo8xC^?vJ zc`U6bVo~hOr6I!8*GTZ<^D~;unKjK=!IR|GB4E>Mcvt*2GK);93jIDd<(nNjHO z4Hi@2^%Uyx=^Z~5eZ!5rO5%4H|eFoNjD#+Kcu%_57zZb4Z@Ak#X6txD^{U3wBl^r+W- zLorkK;uc;NgTj7dGxHQS+@T*T>Q*j4^Ll$ejQqWrwcHyG9y%Mk%m8nBVG5hvSaYm5 zJN^#-Q46kZG)@T8n2^QCjxIwxUVi%s>EY`E?#@_(A~njFrTiDq;8v|W-1jT|ROlNI zU$h|YoD4PVTE^&NC6_m{EAFBVqsM`P*`-AcDGWQygURzM32Xeq2xng~XQsYeTZ5v$ zQLaa2M_Iplw}4eL6fLPu`6`PYcVMysO>`{8CB~glD=TX7?JZcHfHNmykBM?QD)#D) zGp>R*<^D?WhFQKRc^}22l6F=D2RPrxaX2ZF!b1X0XF*d4%=!sbNcS1q2WOUE(7e4$ z^L8f;F)__d3>&KQFE8%$I4h^y5FYBfB&fWzn71_OSrPe-DHV{O#Q;GP z+Tw!J?eVjX19RKH?*hKQWQt8r7B#lYX8xoSHFGCW-*DSQ4EM4M3Mw%gkSYNK18@(e zfzMF}WWaCyS@1y%-~Xg0ry~tkQkUmKuI5lGAua{{vn22V!2T()AU5FpKh@Nv)s^Js zv~@VuUG;=CnLmQR{PeUBQf2;lAV!vG>^Z0N zL88rrjL-*J!43;7C=w9xhcw`yjRKq7o4L9=0SmR9PA-nX12@#h(iIu-0N_xm2OV)( zU_raT0y>$wm^oMi2|U3N;OhF9uy}`<-xVka#DV*l{O0yHzi9vUxa1Qtpi$buR*8cU zd4~lS1pT$L^!0=6qUKOpM+XPsy{f7W#1bjrEwaeN!Ik9(zySIT^pEHvHgJUneFN4) zk=k|$55(g8slmS|@+*4fr2urd3LwjIIZA**g+%l(SZNn4HwQ}y6o`vw>2&mR1X+&q zDa1Af0B;4rAMZMOlHbAqK|R_xuwJ7ANARtFE({-P2o{tJJR<>2KVp)ZK-M;)ejx zd*E~Mka<{OL7%CAhk4n|1qg?97-I!l0rOinjVi#arbgg4bi5;nY5oFL`UWtPk5&L#grSxv zE3!}=1px!ZTLT90aYc^s`~{VojjJml&<`@e41dFP+XU6D0AOkbn2rlI3>^LcqauG& zc$m3Z{!u8LvUrm^fT{qX5yD9{?r(CCiUdck%!T`KIZd2oQJz1joB&M(Teg_>;yS<2-5>BWfSPpG`Rt{!j6>kqMAvl^zk0JUEfy$HVJMkxP-GkwZuxL62me2#pj_5*ZIU zP~#C^OZLfl$HO)v;~~c&JHivn|1I9H5y_CDkt0JLLGKm(4*KLVhJ2jh2#vJuM6`b& zE==-lvME^Oj022xF&IV*? '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/examples/powertools-examples-core/gradle/gradlew.bat b/examples/powertools-examples-core/gradle/gradlew.bat deleted file mode 100644 index 6689b85be..000000000 --- a/examples/powertools-examples-core/gradle/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/examples/powertools-examples-core/gradle/src/main/java/helloworld/App.java b/examples/powertools-examples-core/gradle/src/main/java/helloworld/App.java deleted file mode 100644 index fccc63b9a..000000000 --- a/examples/powertools-examples-core/gradle/src/main/java/helloworld/App.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; -import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.Unit; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; -import software.amazon.lambda.powertools.metrics.Metrics; -import software.amazon.lambda.powertools.tracing.CaptureMode; -import software.amazon.lambda.powertools.tracing.Tracing; -import software.amazon.lambda.powertools.tracing.TracingUtils; - -/** - * Handler for requests to Lambda function. - */ -public class App implements RequestHandler { - private final static Logger log = LogManager.getLogger(App.class); - - @Logging(logEvent = true, samplingRate = 0.7) - @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - Map headers = new HashMap<>(); - - headers.put("Content-Type", "application/json"); - headers.put("X-Custom-Header", "application/json"); - - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); - - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> - { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); - }); - - LoggingUtils.appendKey("test", "willBeLogged"); - - APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() - .withHeaders(headers); - try { - final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); - log.info(pageContents); - TracingUtils.putAnnotation("Test", "New"); - String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); - - TracingUtils.withSubsegment("loggingResponse", subsegment -> - { - String sampled = "log something out"; - log.info(sampled); - log.info(output); - }); - - log.info("After output"); - return response - .withStatusCode(200) - .withBody(output); - } catch (RuntimeException | IOException e) { - return response - .withBody("{}") - .withStatusCode(500); - } - } - - @Tracing - private void log() { - log.info("inside threaded logging for function"); - } - - @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) - private String getPageContents(String address) throws IOException { - URL url = new URL(address); - putMetadata("getPageContents", address); - try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { - return br.lines().collect(Collectors.joining(System.lineSeparator())); - } - } -} diff --git a/examples/powertools-examples-core/gradle/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/gradle/src/main/java/helloworld/AppStream.java deleted file mode 100644 index 401ef8c48..000000000 --- a/examples/powertools-examples-core/gradle/src/main/java/helloworld/AppStream.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Map; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class AppStream implements RequestStreamHandler { - private static final ObjectMapper mapper = new ObjectMapper(); - - @Override - @Logging(logEvent = true) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - Map map = mapper.readValue(input, Map.class); - - System.out.println(map.size()); - } -} diff --git a/examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java deleted file mode 100644 index af3ec1275..000000000 --- a/examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package helloworld; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class AppTest { - @Test - public void successfulResponse() { - App app = new App(); - APIGatewayProxyResponseEvent result = app.handleRequest(null, null); - assertEquals(200, result.getStatusCode().intValue()); - assertEquals("application/json", result.getHeaders().get("Content-Type")); - String content = result.getBody(); - assertNotNull(content); - assertTrue(content.contains("\"message\"")); - assertTrue(content.contains("\"hello world\"")); - assertTrue(content.contains("\"location\"")); - } -} diff --git a/examples/powertools-examples-core/gradle/template.yaml b/examples/powertools-examples-core/gradle/template.yaml deleted file mode 100644 index a717c2998..000000000 --- a/examples/powertools-examples-core/gradle/template.yaml +++ /dev/null @@ -1,71 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: > - gradle - - Sample SAM Template for gradle - -# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst -Globals: - Function: - Timeout: 20 - Runtime: java11 - MemorySize: 512 - Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html - Environment: - Variables: - # Powertools for AWS Lambda (Java) env vars: https://docs.powertools.aws.dev/lambda/java/#environment-variables - POWERTOOLS_LOG_LEVEL: INFO - POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 - POWERTOOLS_LOGGER_LOG_EVENT: true - POWERTOOLS_METRICS_NAMESPACE: Coreutilities - -Resources: - HelloWorldFunction: - Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction - Properties: - CodeUri: . - Handler: helloworld.App::handleRequest - Runtime: java8 - MemorySize: 512 - Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object - Variables: - POWERTOOLS_SERVICE_NAME: hello - Events: - HelloWorld: - Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api - Properties: - Path: /hello - Method: get - - HelloWorldStreamFunction: - Type: AWS::Serverless::Function - Properties: - CodeUri: . - Handler: helloworld.AppStream::handleRequest - Runtime: java8 - MemorySize: 512 - Tracing: Active - Environment: - Variables: - POWERTOOLS_LOGGER_SAMPLE_RATE: 0.7 - Events: - HelloWorld: - Type: Api - Properties: - Path: /hellostream - Method: get - -Outputs: - # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function - # Find out more about other implicit resources you can reference within SAM - # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api - HelloWorldApi: - Description: "API Gateway endpoint URL for Prod stage for Hello World function" - Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" - HelloWorldFunction: - Description: "Hello World Lambda Function ARN" - Value: !GetAtt HelloWorldFunction.Arn - HelloWorldFunctionIamRole: - Description: "Implicit IAM Role created for Hello World function" - Value: !GetAtt HelloWorldFunctionRole.Arn diff --git a/examples/powertools-examples-core/sam/README.md b/examples/powertools-examples-core/sam/README.md deleted file mode 100644 index 7a4279ae3..000000000 --- a/examples/powertools-examples-core/sam/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Powertools for AWS Lambda (Java) - Core Utilities Example with SAM - -This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/). - -For general information on the deployed example itself, you can refer to the parent [README](../README.md) - -## Configuration -SAM uses [template.yaml](template.yaml) to define the application's AWS resources. -This file defines the Lambda function to be deployed as well as API Gateway for it. - -## Deploy the sample application -To deploy the example, check out the instructions for getting -started with SAM in [the examples directory](../../README.md) - -## Additional notes - -You can watch the trace information or log information using the SAM CLI: -```bash -# Tail the logs -sam logs --tail $MY_STACK - -# Tail the traces -sam traces --tail -``` \ No newline at end of file diff --git a/examples/powertools-examples-core/sam/events/event.json b/examples/powertools-examples-core/sam/events/event.json deleted file mode 100644 index 3822fadaa..000000000 --- a/examples/powertools-examples-core/sam/events/event.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "body": "{\"message\": \"hello world\"}", - "resource": "/{proxy+}", - "path": "/path/to/resource", - "httpMethod": "POST", - "isBase64Encoded": false, - "queryStringParameters": { - "foo": "bar" - }, - "pathParameters": { - "proxy": "/path/to/resource" - }, - "stageVariables": { - "baz": "qux" - }, - "headers": { - "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", - "Accept-Encoding": "gzip, deflate, sdch", - "Accept-Language": "en-US,en;q=0.8", - "Cache-Control": "max-age=0", - "CloudFront-Forwarded-Proto": "https", - "CloudFront-Is-Desktop-Viewer": "true", - "CloudFront-Is-Mobile-Viewer": "false", - "CloudFront-Is-SmartTV-Viewer": "false", - "CloudFront-Is-Tablet-Viewer": "false", - "CloudFront-Viewer-Country": "US", - "Host": "1234567890.execute-api.us-east-1.amazonaws.com", - "Upgrade-Insecure-Requests": "1", - "User-Agent": "Custom User Agent String", - "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", - "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", - "X-Forwarded-For": "127.0.0.1, 127.0.0.2", - "X-Forwarded-Port": "443", - "X-Forwarded-Proto": "https" - }, - "requestContext": { - "accountId": "123456789012", - "resourceId": "123456", - "stage": "prod", - "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", - "requestTime": "09/Apr/2015:12:34:56 +0000", - "requestTimeEpoch": 1428582896000, - "identity": { - "cognitoIdentityPoolId": null, - "accountId": null, - "cognitoIdentityId": null, - "caller": null, - "accessKey": null, - "sourceIp": "127.0.0.1", - "cognitoAuthenticationType": null, - "cognitoAuthenticationProvider": null, - "userArn": null, - "userAgent": "Custom User Agent String", - "user": null - }, - "path": "/prod/path/to/resource", - "resourcePath": "/{proxy+}", - "httpMethod": "POST", - "apiId": "1234567890", - "protocol": "HTTP/1.1" - } - } - \ No newline at end of file diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml deleted file mode 100644 index 93c858556..000000000 --- a/examples/powertools-examples-core/sam/pom.xml +++ /dev/null @@ -1,207 +0,0 @@ - - 4.0.0 - - software.amazon.lambda.examples - 1.18.0-SNAPSHOT - powertools-examples-core-sam - jar - - Powertools for AWS Lambda (Java) library Examples - Core - - - 2.20.0 - 1.8 - 1.8 - - - - - software.amazon.lambda - powertools-tracing - ${project.version} - - - software.amazon.lambda - powertools-logging - ${project.version} - - - software.amazon.lambda - powertools-metrics - ${project.version} - - - com.amazonaws - aws-lambda-java-core - 1.2.3 - - - com.amazonaws - aws-lambda-java-events - 3.11.3 - - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - - - - junit - junit - 4.13.2 - test - - - - - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - - - - - jdk8 - - (,11) - - - 1.9.7 - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - test-compile - - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - - diff --git a/examples/powertools-examples-core/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-core/sam/src/main/java/helloworld/App.java deleted file mode 100644 index fccc63b9a..000000000 --- a/examples/powertools-examples-core/sam/src/main/java/helloworld/App.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; -import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.Unit; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; -import software.amazon.lambda.powertools.metrics.Metrics; -import software.amazon.lambda.powertools.tracing.CaptureMode; -import software.amazon.lambda.powertools.tracing.Tracing; -import software.amazon.lambda.powertools.tracing.TracingUtils; - -/** - * Handler for requests to Lambda function. - */ -public class App implements RequestHandler { - private final static Logger log = LogManager.getLogger(App.class); - - @Logging(logEvent = true, samplingRate = 0.7) - @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - Map headers = new HashMap<>(); - - headers.put("Content-Type", "application/json"); - headers.put("X-Custom-Header", "application/json"); - - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); - - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> - { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); - }); - - LoggingUtils.appendKey("test", "willBeLogged"); - - APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() - .withHeaders(headers); - try { - final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); - log.info(pageContents); - TracingUtils.putAnnotation("Test", "New"); - String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); - - TracingUtils.withSubsegment("loggingResponse", subsegment -> - { - String sampled = "log something out"; - log.info(sampled); - log.info(output); - }); - - log.info("After output"); - return response - .withStatusCode(200) - .withBody(output); - } catch (RuntimeException | IOException e) { - return response - .withBody("{}") - .withStatusCode(500); - } - } - - @Tracing - private void log() { - log.info("inside threaded logging for function"); - } - - @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) - private String getPageContents(String address) throws IOException { - URL url = new URL(address); - putMetadata("getPageContents", address); - try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { - return br.lines().collect(Collectors.joining(System.lineSeparator())); - } - } -} diff --git a/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java deleted file mode 100644 index 401ef8c48..000000000 --- a/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Map; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class AppStream implements RequestStreamHandler { - private static final ObjectMapper mapper = new ObjectMapper(); - - @Override - @Logging(logEvent = true) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - Map map = mapper.readValue(input, Map.class); - - System.out.println(map.size()); - } -} diff --git a/examples/powertools-examples-core/sam/src/main/resources/log4j2.xml b/examples/powertools-examples-core/sam/src/main/resources/log4j2.xml deleted file mode 100644 index e1fd14cea..000000000 --- a/examples/powertools-examples-core/sam/src/main/resources/log4j2.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java deleted file mode 100644 index 70dad8d71..000000000 --- a/examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.amazonaws.xray.AWSXRay; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class AppTest { - - @Before - public void setup() { - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.beginSegment("test"); - } - } - - @After - public void tearDown() { - if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) { - AWSXRay.endSubsegment(); - } - - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.endSegment(); - } - } - - @Test - public void successfulResponse() { - App app = new App(); - APIGatewayProxyResponseEvent result = app.handleRequest(null, null); - assertEquals(result.getStatusCode().intValue(), 200); - assertEquals(result.getHeaders().get("Content-Type"), "application/json"); - String content = result.getBody(); - assertNotNull(content); - assertTrue(content.contains("\"message\"")); - assertTrue(content.contains("\"hello world\"")); - assertTrue(content.contains("\"location\"")); - } -} diff --git a/examples/powertools-examples-core/sam/template.yaml b/examples/powertools-examples-core/sam/template.yaml deleted file mode 100644 index 9a51a1ba9..000000000 --- a/examples/powertools-examples-core/sam/template.yaml +++ /dev/null @@ -1,66 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: > - CoreUtilities - -# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst -Globals: - Function: - Timeout: 20 - Runtime: java11 - MemorySize: 512 - Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html - Environment: - Variables: - # Powertools for AWS Lambda (Java) env vars: https://docs.powertools.aws.dev/lambda/java/#environment-variables - POWERTOOLS_LOG_LEVEL: INFO - POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 - POWERTOOLS_LOGGER_LOG_EVENT: true - POWERTOOLS_METRICS_NAMESPACE: Coreutilities - -Resources: - HelloWorldFunction: - Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction - Properties: - CodeUri: . - Handler: helloworld.App::handleRequest - Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object - Variables: - POWERTOOLS_SERVICE_NAME: hello - Events: - HelloWorld: - Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api - Properties: - Path: /hello - Method: get - - HelloWorldStreamFunction: - Type: AWS::Serverless::Function - Properties: - CodeUri: . - Handler: helloworld.AppStream::handleRequest - MemorySize: 512 - Tracing: Active - Environment: - Variables: - POWERTOOLS_LOGGER_SAMPLE_RATE: 0.7 - Events: - HelloWorld: - Type: Api - Properties: - Path: /hellostream - Method: get - -Outputs: - # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function - # Find out more about other implicit resources you can reference within SAM - # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api - HelloWorldApi: - Description: "API Gateway endpoint URL for Prod stage for Hello World function" - Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" - HelloWorldFunction: - Description: "Hello World Lambda Function ARN" - Value: !GetAtt HelloWorldFunction.Arn - HelloWorldFunctionIamRole: - Description: "Implicit IAM Role created for Hello World function" - Value: !GetAtt HelloWorldFunctionRole.Arn diff --git a/examples/powertools-examples-core/serverless/README.md b/examples/powertools-examples-core/serverless/README.md deleted file mode 100644 index aec093182..000000000 --- a/examples/powertools-examples-core/serverless/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Powertools for AWS Lambda (Java) - Core Utilities Example with Serverless Framework - -This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Framework](https://www.serverless.com/framework). -For general information on the deployed example itself, you can refer to the parent [README](../README.md). -To install Serverless Framework if you don't have it yet, you can follow the [Getting Started Guide](https://www.serverless.com/framework/docs/getting-started). - -## Configuration -Serverless Framework uses [serverless.yml](./serverless.yml) to define the application's AWS resources. -This file defines the Lambda function to be deployed as well as API Gateway for it. - -It is a [Maven](https://maven.apache.org/) based project, so you can open this project with any Maven compatible Java IDE to build and run tests. - - -## Deploy the sample application - -To deploy the app, simply run the following commands: -```bash -mvn package && sls deploy -``` - -## Useful commands - -Deploy a single function -```bash -sls deploy function -f hello -``` \ No newline at end of file diff --git a/examples/powertools-examples-core/serverless/pom.xml b/examples/powertools-examples-core/serverless/pom.xml deleted file mode 100644 index 793318da3..000000000 --- a/examples/powertools-examples-core/serverless/pom.xml +++ /dev/null @@ -1,209 +0,0 @@ - - 4.0.0 - - software.amazon.lambda.examples - 1.18.0-SNAPSHOT - powertools-examples-core-serverless - jar - - Powertools for AWS Lambda (Java) library Examples - Core - - - 2.20.0 - 1.8 - 1.8 - - - - - software.amazon.lambda - powertools-tracing - ${project.version} - - - software.amazon.lambda - powertools-logging - ${project.version} - - - software.amazon.lambda - powertools-metrics - ${project.version} - - - com.amazonaws - aws-lambda-java-core - 1.2.2 - - - com.amazonaws - aws-lambda-java-events - 3.11.2 - - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - - - - junit - junit - 4.13.2 - test - - - - - helloworld-lambda - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - - com.github.edwgiz - maven-shade-plugin.log4j2-cachefile-transformer - 2.15 - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - - - - - - jdk8 - - (,11) - - - 1.9.7 - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - test-compile - - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - - diff --git a/examples/powertools-examples-core/serverless/serverless.yml b/examples/powertools-examples-core/serverless/serverless.yml deleted file mode 100644 index d8dec8080..000000000 --- a/examples/powertools-examples-core/serverless/serverless.yml +++ /dev/null @@ -1,40 +0,0 @@ -service: hello -# app and org for use with dashboard.serverless.com -#app: your-app-name -#org: your-org-name - -# You can pin your service to only deploy with a specific Serverless version -# Check out our docs for more details -frameworkVersion: '3' - -provider: - name: aws - runtime: java11 - -# you can overwrite defaults here -# stage: dev -# region: us-east-1 - -# you can define service wide environment variables here - environment: - POWERTOOLS_LOG_LEVEL: INFO - POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 - POWERTOOLS_METRICS_NAMESPACE: Coreutilities - -# you can add packaging information here -package: - artifact: target/helloworld-lambda.jar - -functions: - hello: - handler: helloworld.App - memorySize: 512 - timeout: 20 - tracing: "Active" - events: - - httpApi: - path: /hello - method: get -# Define function environment variables here - environment: - POWERTOOLS_SERVICE_NAME: hello diff --git a/examples/powertools-examples-core/serverless/src/main/java/helloworld/App.java b/examples/powertools-examples-core/serverless/src/main/java/helloworld/App.java deleted file mode 100644 index 727e048f2..000000000 --- a/examples/powertools-examples-core/serverless/src/main/java/helloworld/App.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; -import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.Unit; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; -import software.amazon.lambda.powertools.metrics.Metrics; -import software.amazon.lambda.powertools.tracing.CaptureMode; -import software.amazon.lambda.powertools.tracing.Tracing; -import software.amazon.lambda.powertools.tracing.TracingUtils; - -/** - * Handler for requests to Lambda function. - */ -public class App implements RequestHandler { - private final static Logger log = LogManager.getLogger(App.class); - - // This is controlled by POWERTOOLS_LOGGER_SAMPLE_RATE environment variable - // @Logging(logEvent = true, samplingRate = 0.7) - // This is controlled by POWERTOOLS_METRICS_NAMESPACE environment variable - // @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - // This is controlled by POWERTOOLS_TRACER_CAPTURE_ERROR environment variable - @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - Map headers = new HashMap<>(); - - headers.put("Content-Type", "application/json"); - headers.put("X-Custom-Header", "application/json"); - - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); - - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> - { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); - }); - - LoggingUtils.appendKey("test", "willBeLogged"); - - APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() - .withHeaders(headers); - try { - final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); - log.info(pageContents); - TracingUtils.putAnnotation("Test", "New"); - String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); - - TracingUtils.withSubsegment("loggingResponse", subsegment -> - { - String sampled = "log something out"; - log.info(sampled); - log.info(output); - }); - - log.info("After output"); - return response - .withStatusCode(200) - .withBody(output); -<<<<<<<< HEAD:examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java - } catch (IOException e) { -======== - } catch (RuntimeException | IOException e) { ->>>>>>>> main:examples/powertools-examples-core/serverless/src/main/java/helloworld/App.java - return response - .withBody("{}") - .withStatusCode(500); - } - } - -<<<<<<<< HEAD:examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java - @Tracing - private void log() { - log.info("inside threaded logging for function"); - } - -======== ->>>>>>>> main:examples/powertools-examples-core/serverless/src/main/java/helloworld/App.java - @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) - private String getPageContents(String address) throws IOException { - URL url = new URL(address); - putMetadata("getPageContents", address); - try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { - return br.lines().collect(Collectors.joining(System.lineSeparator())); - } - } -} diff --git a/examples/powertools-examples-core/serverless/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/serverless/src/main/java/helloworld/AppStream.java deleted file mode 100644 index 401ef8c48..000000000 --- a/examples/powertools-examples-core/serverless/src/main/java/helloworld/AppStream.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Map; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class AppStream implements RequestStreamHandler { - private static final ObjectMapper mapper = new ObjectMapper(); - - @Override - @Logging(logEvent = true) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - Map map = mapper.readValue(input, Map.class); - - System.out.println(map.size()); - } -} diff --git a/examples/powertools-examples-core/serverless/src/main/resources/log4j2.xml b/examples/powertools-examples-core/serverless/src/main/resources/log4j2.xml deleted file mode 100644 index 0cc0953f0..000000000 --- a/examples/powertools-examples-core/serverless/src/main/resources/log4j2.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java deleted file mode 100644 index 70dad8d71..000000000 --- a/examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.amazonaws.xray.AWSXRay; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class AppTest { - - @Before - public void setup() { - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.beginSegment("test"); - } - } - - @After - public void tearDown() { - if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) { - AWSXRay.endSubsegment(); - } - - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.endSegment(); - } - } - - @Test - public void successfulResponse() { - App app = new App(); - APIGatewayProxyResponseEvent result = app.handleRequest(null, null); - assertEquals(result.getStatusCode().intValue(), 200); - assertEquals(result.getHeaders().get("Content-Type"), "application/json"); - String content = result.getBody(); - assertNotNull(content); - assertTrue(content.contains("\"message\"")); - assertTrue(content.contains("\"hello world\"")); - assertTrue(content.contains("\"location\"")); - } -} From 533ac9a4aeab3ddfc7b191214dfa6be0a5d62489 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Oct 2023 14:13:40 +0200 Subject: [PATCH 070/577] build(deps-dev): bump com.amazonaws:amazon-sqs-java-extended-client-lib (#1476) Bumps [com.amazonaws:amazon-sqs-java-extended-client-lib](https://github.com/awslabs/amazon-sqs-java-extended-client-lib) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/awslabs/amazon-sqs-java-extended-client-lib/releases) - [Commits](https://github.com/awslabs/amazon-sqs-java-extended-client-lib/compare/2.0.3...2.0.4) --- updated-dependencies: - dependency-name: com.amazonaws:amazon-sqs-java-extended-client-lib dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 89a255c8b..0a760bd0d 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -84,7 +84,7 @@ com.amazonaws amazon-sqs-java-extended-client-lib - 2.0.3 + 2.0.4 test From fc9f0ec03638bafd19a92914056bc5756d5954a4 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Fri, 13 Oct 2023 17:46:32 +0200 Subject: [PATCH 071/577] Resolve merge issues --- examples/pom.xml | 8 +- examples/powertools-examples-batch/pom.xml | 2 + .../pom.xml | 4 +- .../cdk/README.md | 10 +- .../cdk/app/pom.xml | 147 ++++++++--------- .../cdk/app/src/main/java/helloworld/App.java | 14 +- .../gradle/README.md | 2 +- .../sam/pom.xml | 88 +--------- .../serverless/README.md | 26 +++ .../serverless/pom.xml | 155 ++++++++++++++++++ .../serverless/serverless.yml | 40 +++++ .../src/main/java/helloworld/App.java | 99 +++++++++++ .../src/main/java/helloworld/AppStream.java | 38 +++++ .../serverless/src/main/resources/log4j2.xml | 16 ++ .../src/test/java/helloworld/AppTest.java | 59 +++++++ .../powertools-examples-idempotency/pom.xml | 16 +- .../powertools-examples-parameters/pom.xml | 11 +- .../powertools-examples-validation/pom.xml | 21 ++- powertools-e2e-tests/handlers/pom.xml | 11 +- powertools-e2e-tests/pom.xml | 3 +- 20 files changed, 562 insertions(+), 208 deletions(-) create mode 100644 examples/powertools-examples-core-utilities/serverless/README.md create mode 100644 examples/powertools-examples-core-utilities/serverless/pom.xml create mode 100644 examples/powertools-examples-core-utilities/serverless/serverless.yml create mode 100644 examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/App.java create mode 100644 examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/AppStream.java create mode 100644 examples/powertools-examples-core-utilities/serverless/src/main/resources/log4j2.xml create mode 100644 examples/powertools-examples-core-utilities/serverless/src/test/java/helloworld/AppTest.java diff --git a/examples/pom.xml b/examples/pom.xml index baa07eb5e..be52778da 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -29,10 +29,10 @@ - powertools-examples-core/sam - powertools-examples-core/cdk/app - powertools-examples-core/cdk/infra - powertools-examples-core/serverless + powertools-examples-core-utilities/sam + powertools-examples-core-utilities/cdk/app + powertools-examples-core-utilities/cdk/infra + powertools-examples-core-utilities/serverless powertools-examples-idempotency powertools-examples-parameters powertools-examples-serialization diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 35984ef12..a3eb332f4 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -15,6 +15,8 @@ 1.8 1.8 2.20.152 + 1.9.20 + diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 6b4e850e1..cc95a2dfc 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.17.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-examples-cloudformation jar @@ -16,6 +16,8 @@ 1.2.3 3.11.3 2.20.162 + 1.9.20 + diff --git a/examples/powertools-examples-core-utilities/cdk/README.md b/examples/powertools-examples-core-utilities/cdk/README.md index acd857ed7..f15a24168 100644 --- a/examples/powertools-examples-core-utilities/cdk/README.md +++ b/examples/powertools-examples-core-utilities/cdk/README.md @@ -6,11 +6,11 @@ For general information on the deployed example itself, you can refer to the par ## Configuration CDK uses the following project structure: -- [app](app) - stores the source code of your application, which is similar between all examples -- [infra](infra) - stores the definition of your infrastructure - - [cdk.json](infra/cdk.json) - tells the CDK Toolkit how to execute your app - - [CdkApp](infra/src/main/java/cdk/CdkApp.java) - bootstraps your stack, taking AWS `account` and `region` as input - - [CdkStack](infra/src/main/java/cdk/CdkStack.java) - defines the Lambda function to be deployed as well as API Gateway for it. +- [app](./app) - stores the source code of your application, which is similar between all examples +- [infra](./infra) - stores the definition of your infrastructure + - [cdk.json](./infra/cdk.json) - tells the CDK Toolkit how to execute your app + - [CdkApp](./infra/src/main/java/cdk/CdkApp.java) - bootstraps your stack, taking AWS `account` and `region` as input + - [CdkStack](./infra/src/main/java/cdk/CdkStack.java) - defines the Lambda function to be deployed as well as API Gateway for it. It is a [Maven](https://maven.apache.org/) based project, so you can open this project with any Maven compatible Java IDE to build and run tests. diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 51c222a07..07e9d126f 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -3,11 +3,12 @@ 4.0.0 software.amazon.lambda.examples + 1.17.0 powertools-examples-core-utilities-cdk jar - - Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) with CDK + Powertools for AWS Lambda (Java) library Examples - Core 2.20.0 @@ -40,7 +41,7 @@ com.amazonaws aws-lambda-java-events - 3.11.2 + 3.11.3 org.apache.logging.log4j @@ -67,80 +68,72 @@ - helloworld-lambda - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - + helloworld-lambda + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + - - org.apache.maven.plugins - maven-deploy-plugin - - true - - - ->>>>>>>> main:examples/powertools-examples-core/cdk/app/pom.xml + + jdk8 + + (,11) + + + 1.9.7 + + + + diff --git a/examples/powertools-examples-core-utilities/serverless/serverless.yml b/examples/powertools-examples-core-utilities/serverless/serverless.yml new file mode 100644 index 000000000..d8dec8080 --- /dev/null +++ b/examples/powertools-examples-core-utilities/serverless/serverless.yml @@ -0,0 +1,40 @@ +service: hello +# app and org for use with dashboard.serverless.com +#app: your-app-name +#org: your-org-name + +# You can pin your service to only deploy with a specific Serverless version +# Check out our docs for more details +frameworkVersion: '3' + +provider: + name: aws + runtime: java11 + +# you can overwrite defaults here +# stage: dev +# region: us-east-1 + +# you can define service wide environment variables here + environment: + POWERTOOLS_LOG_LEVEL: INFO + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 + POWERTOOLS_METRICS_NAMESPACE: Coreutilities + +# you can add packaging information here +package: + artifact: target/helloworld-lambda.jar + +functions: + hello: + handler: helloworld.App + memorySize: 512 + timeout: 20 + tracing: "Active" + events: + - httpApi: + path: /hello + method: get +# Define function environment variables here + environment: + POWERTOOLS_SERVICE_NAME: hello diff --git a/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/App.java new file mode 100644 index 000000000..c89545fc9 --- /dev/null +++ b/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/App.java @@ -0,0 +1,99 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; +import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; +import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.tracing.CaptureMode; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.tracing.TracingUtils; + +/** + * Handler for requests to Lambda function. + */ +public class App implements RequestHandler { + private final static Logger log = LogManager.getLogger(App.class); + @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + Map headers = new HashMap<>(); + + headers.put("Content-Type", "application/json"); + headers.put("X-Custom-Header", "application/json"); + + metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + + withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> + { + metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); + metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); + }); + + LoggingUtils.appendKey("test", "willBeLogged"); + + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() + .withHeaders(headers); + try { + final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); + log.info(pageContents); + TracingUtils.putAnnotation("Test", "New"); + String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); + + TracingUtils.withSubsegment("loggingResponse", subsegment -> + { + String sampled = "log something out"; + log.info(sampled); + log.info(output); + }); + + log.info("After output"); + return response + .withStatusCode(200) + .withBody(output); + } catch (RuntimeException | IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + putMetadata("getPageContents", address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/AppStream.java new file mode 100644 index 000000000..401ef8c48 --- /dev/null +++ b/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/AppStream.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.Metrics; + +public class AppStream implements RequestStreamHandler { + private static final ObjectMapper mapper = new ObjectMapper(); + + @Override + @Logging(logEvent = true) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { + Map map = mapper.readValue(input, Map.class); + + System.out.println(map.size()); + } +} diff --git a/examples/powertools-examples-core-utilities/serverless/src/main/resources/log4j2.xml b/examples/powertools-examples-core-utilities/serverless/src/main/resources/log4j2.xml new file mode 100644 index 000000000..0cc0953f0 --- /dev/null +++ b/examples/powertools-examples-core-utilities/serverless/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/examples/powertools-examples-core-utilities/serverless/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core-utilities/serverless/src/test/java/helloworld/AppTest.java new file mode 100644 index 000000000..70dad8d71 --- /dev/null +++ b/examples/powertools-examples-core-utilities/serverless/src/test/java/helloworld/AppTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import com.amazonaws.xray.AWSXRay; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class AppTest { + + @Before + public void setup() { + if (null == System.getenv("LAMBDA_TASK_ROOT")) { + AWSXRay.beginSegment("test"); + } + } + + @After + public void tearDown() { + if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) { + AWSXRay.endSubsegment(); + } + + if (null == System.getenv("LAMBDA_TASK_ROOT")) { + AWSXRay.endSegment(); + } + } + + @Test + public void successfulResponse() { + App app = new App(); + APIGatewayProxyResponseEvent result = app.handleRequest(null, null); + assertEquals(result.getStatusCode().intValue(), 200); + assertEquals(result.getHeaders().get("Content-Type"), "application/json"); + String content = result.getBody(); + assertNotNull(content); + assertTrue(content.contains("\"message\"")); + assertTrue(content.contains("\"hello world\"")); + assertTrue(content.contains("\"location\"")); + } +} diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 849d3764b..b97eee7cc 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -15,7 +15,7 @@ 4.0.0 - + software.amazon.lambda.examples 2.0.0-SNAPSHOT powertools-examples-idempotency @@ -26,6 +26,7 @@ 2.20.0 1.8 1.8 + 1.9.20 @@ -52,7 +53,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.11.2 org.apache.logging.log4j @@ -127,6 +128,13 @@ + + + org.aspectj + aspectjtools + ${aspectj.version} + + org.apache.maven.plugins @@ -173,8 +181,7 @@ - + @@ -187,7 +194,6 @@ - org.apache.maven.plugins maven-deploy-plugin diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 6ca0c33bf..81081035c 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -10,6 +10,7 @@ 1.8 1.8 + 1.9.20 @@ -31,7 +32,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.11.2 org.aspectj @@ -90,8 +91,14 @@ + + + org.aspectj + aspectjtools + ${aspectj.version} + + - org.apache.maven.plugins maven-deploy-plugin diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 8551e02a2..679e698e9 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -24,6 +24,7 @@ 1.8 1.8 + 1.9.20 @@ -42,6 +43,11 @@ aws-lambda-java-core 1.2.3 + + org.aspectj + aspectjrt + ${aspectj.version} + @@ -94,14 +100,13 @@ - - - - org.apache.maven.plugins - maven-deploy-plugin - - true - + + + org.aspectj + aspectjtools + ${aspectj.version} + + diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index db0236146..fbe2e6d8b 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -23,6 +23,7 @@ 3.11.0 2.20.108 2.20.0 + 1.9.20 @@ -131,11 +132,11 @@ - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index cb365cc72..70c3a4105 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -32,6 +32,7 @@ 1.8 10.2.69 2.93.0 + 1.9.20 @@ -40,7 +41,6 @@ log4j-slf4j2-impl test - software.amazon.awssdk lambda @@ -165,6 +165,7 @@ org.aspectj aspectjrt + ${aspectj.version} compile From 653e98adb9bd066fb28960a1017b26566a677b9b Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Fri, 13 Oct 2023 17:53:53 +0200 Subject: [PATCH 072/577] Fix aspectj issue --- powertools-e2e-tests/pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 70c3a4105..cb365cc72 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -32,7 +32,6 @@ 1.8 10.2.69 2.93.0 - 1.9.20 @@ -41,6 +40,7 @@ log4j-slf4j2-impl test + software.amazon.awssdk lambda @@ -165,7 +165,6 @@ org.aspectj aspectjrt - ${aspectj.version} compile From 0fe0d2c4a2fd958d9ed6b35e28a1af386b5be5d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 14:01:04 +0200 Subject: [PATCH 073/577] build(deps): bump aws.sdk.version from 2.20.162 to 2.21.0 (#1480) Bumps `aws.sdk.version` from 2.20.162 to 2.21.0. Updates `software.amazon.awssdk:bom` from 2.20.162 to 2.21.0 Updates `software.amazon.awssdk:http-client-spi` from 2.20.162 to 2.21.0 Updates `software.amazon.awssdk:url-connection-client` from 2.20.152 to 2.21.0 Updates `software.amazon.awssdk:sqs` from 2.20.152 to 2.21.0 Updates `software.amazon.awssdk:s3` from 2.20.162 to 2.21.0 Updates `software.amazon.awssdk:dynamodb` from 2.20.162 to 2.21.0 Updates `software.amazon.awssdk:lambda` from 2.20.162 to 2.21.0 Updates `software.amazon.awssdk:kinesis` from 2.20.152 to 2.21.0 Updates `software.amazon.awssdk:cloudwatch` from 2.20.162 to 2.21.0 Updates `software.amazon.awssdk:xray` from 2.20.162 to 2.21.0 Updates `software.amazon.awssdk:cloudformation` from 2.20.162 to 2.21.0 Updates `software.amazon.awssdk:sts` from 2.20.162 to 2.21.0 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index c696ef0a8..01aedcaaf 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.20.162 + 2.21.0 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 988291413..52766608a 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.20.162 + 2.21.0 com.amazonaws diff --git a/pom.xml b/pom.xml index fd31bef37..be696094f 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.20.0 2.15.2 1.9.7 - 2.20.162 + 2.21.0 2.14.0 2.1.3 UTF-8 From 857fd4cb706a7a81fda0cfc6be43600d05087574 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 16 Oct 2023 20:34:29 +0200 Subject: [PATCH 074/577] Fix up merge --- examples/powertools-examples-batch/pom.xml | 2 +- .../cdk/app/pom.xml | 141 ++++++++++-------- .../powertools-examples-idempotency/pom.xml | 2 +- .../powertools-examples-parameters/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/pom.xml | 4 +- 6 files changed, 81 insertions(+), 72 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index a3eb332f4..1387cca6d 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 2.20.0 1.8 1.8 - 2.20.152 + 2.20.162 1.9.20 diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 07e9d126f..891a7c7f6 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -68,72 +68,81 @@ - helloworld-lambda - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - + helloworld-lambda + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + handler + + + + + + + + + jdk8 + + (,11) + + + 1.9.7 + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + + + dev.aspectj + aspectj-maven-plugin + ${aspectj.plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + test-compile + + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + + + + diff --git a/examples/powertools-examples-core/terraform/src/main/java/helloworld/App.java b/examples/powertools-examples-core/terraform/src/main/java/helloworld/App.java new file mode 100644 index 000000000..dacd7f1d4 --- /dev/null +++ b/examples/powertools-examples-core/terraform/src/main/java/helloworld/App.java @@ -0,0 +1,105 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; +import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; +import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.tracing.CaptureMode; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.tracing.TracingUtils; + +/** + * Handler for requests to Lambda function. + */ +public class App implements RequestHandler { + private final static Logger log = LogManager.getLogger(App.class); + + // This is controlled by POWERTOOLS_LOGGER_SAMPLE_RATE environment variable + // @Logging(logEvent = true, samplingRate = 0.7) + // This is controlled by POWERTOOLS_METRICS_NAMESPACE environment variable + // @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + // This is controlled by POWERTOOLS_TRACER_CAPTURE_ERROR environment variable + @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + Map headers = new HashMap<>(); + + headers.put("Content-Type", "application/json"); + headers.put("X-Custom-Header", "application/json"); + + metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + + withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> + { + metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); + metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); + }); + + LoggingUtils.appendKey("test", "willBeLogged"); + + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() + .withHeaders(headers); + try { + final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); + log.info(pageContents); + TracingUtils.putAnnotation("Test", "New"); + String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); + + TracingUtils.withSubsegment("loggingResponse", subsegment -> + { + String sampled = "log something out"; + log.info(sampled); + log.info(output); + }); + + log.info("After output"); + return response + .withStatusCode(200) + .withBody(output); + } catch (RuntimeException | IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + putMetadata("getPageContents", address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-core/terraform/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/terraform/src/main/java/helloworld/AppStream.java new file mode 100644 index 000000000..401ef8c48 --- /dev/null +++ b/examples/powertools-examples-core/terraform/src/main/java/helloworld/AppStream.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.Metrics; + +public class AppStream implements RequestStreamHandler { + private static final ObjectMapper mapper = new ObjectMapper(); + + @Override + @Logging(logEvent = true) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { + Map map = mapper.readValue(input, Map.class); + + System.out.println(map.size()); + } +} diff --git a/examples/powertools-examples-core/terraform/src/main/resources/log4j2.xml b/examples/powertools-examples-core/terraform/src/main/resources/log4j2.xml new file mode 100644 index 000000000..0cc0953f0 --- /dev/null +++ b/examples/powertools-examples-core/terraform/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/examples/powertools-examples-core/terraform/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/terraform/src/test/java/helloworld/AppTest.java new file mode 100644 index 000000000..0ca4f264d --- /dev/null +++ b/examples/powertools-examples-core/terraform/src/test/java/helloworld/AppTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import org.junit.Test; + +public class AppTest { + + @Test + public void successfulResponse() { + App app = new App(); + APIGatewayProxyResponseEvent result = app.handleRequest(null, null); + assertEquals(result.getStatusCode().intValue(), 200); + assertEquals(result.getHeaders().get("Content-Type"), "application/json"); + String content = result.getBody(); + assertNotNull(content); + assertTrue(content.contains("\"message\"")); + assertTrue(content.contains("\"hello world\"")); + assertTrue(content.contains("\"location\"")); + } +} From aed398bd0a99165dc8614147a921393775571af7 Mon Sep 17 00:00:00 2001 From: Jason Harris Date: Mon, 23 Oct 2023 19:18:33 +0100 Subject: [PATCH 081/577] docs: Adding Kotlin example. (#1454) * Setting up Kotlin environment. Converting test to Kotlin. * Deploying via SAM successfully. * Added Kotlin example. * Removing unused Gradle build file. * Adding SAM template so can be used as an existing project and Java target compatibility * Adding SAM template so can be used as an existing project * Updating guidance to use SAM for build and deploy * Restructuring separate Java and Kotlin examples. * Updating core examples readme to represent new structure for Java and Kotlin examples. * Refactoring application code for efficiency, updating build to cover tests too and is more idiomatic and readme to be more descriptive * Updating to fix trailing \n * Updating guidance to be more specific for examples * Adopting new mechanism for specifying jvm target. * accommodating new project structure * Fixing link typo after refactoring * Setting up Kotlin environment. Converting test to Kotlin. * Deploying via SAM successfully. * Added Kotlin example. * Removing unused Gradle build file. * Adding SAM template so can be used as an existing project and Java target compatibility * Adding SAM template so can be used as an existing project * Updating guidance to use SAM for build and deploy * Restructuring separate Java and Kotlin examples. * Updating core examples readme to represent new structure for Java and Kotlin examples. * Refactoring application code for efficiency, updating build to cover tests too and is more idiomatic and readme to be more descriptive * Updating to fix trailing \n * Updating guidance to be more specific for examples * Adopting new mechanism for specifying jvm target. * accommodating new project structure * Fixing link typo after refactoring * Flattening structure back to original to make merging easier for v2 * Adding build for Kotlin Gradle * Adding build for Kotlin Gradle - Restructuring Java examples to v1 approach * Correcting paths * Adding SNAPSHOT support and local capability for Maven. Testing using Java 1.8 * Reviewed and updated against PR comments. * Un-commenting examples --------- Co-authored-by: Jason Harris Co-authored-by: Scott Gerring --- .github/workflows/pr_build.yml | 6 +- examples/README.md | 6 +- examples/powertools-examples-core/README.md | 36 ++- .../powertools-examples-core/cdk/README.md | 6 +- .../gradle/gradlew.bat | 184 ++++++------- .../powertools-examples-core/kotlin/README.md | 38 +++ .../kotlin/build.gradle.kts | 39 +++ .../kotlin/events/event.json | 62 +++++ .../kotlin/gradle/wrapper/.gitignore | 2 + .../kotlin/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63375 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../powertools-examples-core/kotlin/gradlew | 248 ++++++++++++++++++ .../kotlin/gradlew.bat | 92 +++++++ .../kotlin/src/main/kotlin/helloworld/App.kt | 96 +++++++ .../src/main/kotlin/helloworld/AppStream.kt | 37 +++ .../src/test/kotlin/helloworld/AppTest.kt | 20 ++ .../kotlin/template.yaml | 71 +++++ .../serverless/README.md | 2 +- 18 files changed, 840 insertions(+), 112 deletions(-) create mode 100644 examples/powertools-examples-core/kotlin/README.md create mode 100644 examples/powertools-examples-core/kotlin/build.gradle.kts create mode 100644 examples/powertools-examples-core/kotlin/events/event.json create mode 100644 examples/powertools-examples-core/kotlin/gradle/wrapper/.gitignore create mode 100644 examples/powertools-examples-core/kotlin/gradle/wrapper/gradle-wrapper.jar create mode 100644 examples/powertools-examples-core/kotlin/gradle/wrapper/gradle-wrapper.properties create mode 100755 examples/powertools-examples-core/kotlin/gradlew create mode 100644 examples/powertools-examples-core/kotlin/gradlew.bat create mode 100644 examples/powertools-examples-core/kotlin/src/main/kotlin/helloworld/App.kt create mode 100644 examples/powertools-examples-core/kotlin/src/main/kotlin/helloworld/AppStream.kt create mode 100644 examples/powertools-examples-core/kotlin/src/test/kotlin/helloworld/AppTest.kt create mode 100644 examples/powertools-examples-core/kotlin/template.yaml diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 79945f237..e99900ce5 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -66,11 +66,15 @@ jobs: cache: 'maven' - name: Build with Maven run: mvn -B install --file pom.xml - - name: Build Gradle Example + - name: Build Gradle Example - Java if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 run: | cd examples/powertools-examples-core/gradle ./gradlew build + - name: Build Gradle Example - Kotlin + run: | + cd examples/powertools-examples-core/kotlin + ./gradlew build - name: Setup Terraform if: ${{ matrix.java == '11' }} uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 #v2.0.3 diff --git a/examples/README.md b/examples/README.md index 52dc0c1e9..6dbe00185 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,10 +5,12 @@ Each example can be copied from its subdirectory and used independently of the r ## Examples -* [powertools-examples-core](powertools-examples-core) - Demonstrates the core logging, tracing, and metrics modules with different build tools - * [SAM](./powertools-examples-core/sam) +* [powertools-examples-core](powertools-examples-core) - Demonstrates the core logging, tracing, and metrics modules with different build tools and languages * [CDK](./powertools-examples-core/cdk) + * [Gradle](./powertools-examples-core/gradle) + * [SAM](./powertools-examples-core/sam) * [Serverless](./powertools-examples-core/serverless) + * [Kotlin](./powertools-examples-core/kotlin) * [powertools-examples-idempotency](powertools-examples-idempotency) - An idempotent HTTP API * [powertools-examples-parameters](powertools-examples-parameters) - Uses the parameters module to provide runtime parameters to a function * [powertools-examples-serialization](powertools-examples-serialization) - Uses the serialization module to serialize and deserialize API Gateway & SQS payloads diff --git a/examples/powertools-examples-core/README.md b/examples/powertools-examples-core/README.md index a0ffb125d..c9ca60f57 100644 --- a/examples/powertools-examples-core/README.md +++ b/examples/powertools-examples-core/README.md @@ -1,12 +1,13 @@ -# Powertools for AWS Lambda (Java) - Core Utilities Example +# Powertools for AWS Lambda (Java) - Core Utilities Example This project demonstrates the Lambda for Powertools Java module - including [logging](https://docs.powertools.aws.dev/lambda/java/core/logging/), [tracing](https://docs.powertools.aws.dev/lambda/java/core/tracing/), and [metrics](https://docs.powertools.aws.dev/lambda/java/core/metrics/). -We provide examples for the following infrastructure-as-code tools: +The example application is the same, and you can now also use Kotlin! +## Java * [AWS SAM](sam/) * [AWS CDK](cdk/) * [Serverless framework](serverless/) @@ -16,11 +17,21 @@ We also provide an example showing the integration of SAM, Powertools, and Gradl * [AWS SAM with a Gradle build](gradle/) -For each of the tools, the example application is the same, and consists of the following files: +- App.java - Code for the application's Lambda function. +- AppTests.java - Unit tests for the application code. +- events - Invocation events that you can use to invoke the function. -- [App.java](sam/src/main/java/helloworld/App.java) - Code for the application's Lambda function. -- [AppTests.java](sam/src/test/java/helloworld/AppTest.java) - Unit tests for the application code. -- [events](sam/events/event.json) - Invocation events that you can use to invoke the function. +Configuration files and deployment process for each tool are described in corresponding README files. + +## Kotlin + +- [Gradle](kotlin/) + +Example application consists of the following files: + +- App.kt - Code for the application's Lambda function. +- AppTests.kt - Unit tests for the application code. +- events - Invocation events that you can use to invoke the function. Configuration files and deployment process for each tool are described in corresponding README files. @@ -32,14 +43,13 @@ Once the app is deployed, you can invoke the endpoint like this: curl https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/hello/ ``` -The response itself isn't particularly interesting - you will get back some information about your IP address. If +The response itself isn't particularly interesting - you will get back some information about your IP address. If you go to the Lambda Console and locate the lambda you have deployed, then click the "Monitoring" tab you will be able to find: -* **View X-Ray traces** - Display the traces captured by the traces module. These include subsegments for the -different function calls within the example -* **View Cloudwatch logs** - Display the structured logging output of the example +- **View X-Ray traces** - Display the traces captured by the traces module. These include subsegments for the + different function calls within the example +- **View Cloudwatch logs** - Display the structured logging output of the example -Likewise, from the CloudWatch dashboard, under **Metrics**, **all metrics**, you will find the namespaces `Another` -and `ServerlessAirline`. The values in each of these are published by the code in -[App.java](sam/src/main/java/helloworld/App.java). +Likewise, from the CloudWatch dashboard, under **Metrics**, **all metrics**, you will find the namespaces `Another` +and `ServerlessAirline`. The values in each of these are published by the code in the respective application's Lambda function. diff --git a/examples/powertools-examples-core/cdk/README.md b/examples/powertools-examples-core/cdk/README.md index f15a24168..fbc558943 100644 --- a/examples/powertools-examples-core/cdk/README.md +++ b/examples/powertools-examples-core/cdk/README.md @@ -6,9 +6,9 @@ For general information on the deployed example itself, you can refer to the par ## Configuration CDK uses the following project structure: -- [app](./app) - stores the source code of your application, which is similar between all examples -- [infra](./infra) - stores the definition of your infrastructure - - [cdk.json](./infra/cdk.json) - tells the CDK Toolkit how to execute your app +- [app](app) - stores the source code of your application, which is similar between all examples +- [infra](infra) - stores the definition of your infrastructure + - [cdk.json](infra/cdk.json) - tells the CDK Toolkit how to execute your app - [CdkApp](./infra/src/main/java/cdk/CdkApp.java) - bootstraps your stack, taking AWS `account` and `region` as input - [CdkStack](./infra/src/main/java/cdk/CdkStack.java) - defines the Lambda function to be deployed as well as API Gateway for it. diff --git a/examples/powertools-examples-core/gradle/gradlew.bat b/examples/powertools-examples-core/gradle/gradlew.bat index 6689b85be..93e3f59f1 100644 --- a/examples/powertools-examples-core/gradle/gradlew.bat +++ b/examples/powertools-examples-core/gradle/gradlew.bat @@ -1,92 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/examples/powertools-examples-core/kotlin/README.md b/examples/powertools-examples-core/kotlin/README.md new file mode 100644 index 000000000..da9ec5b52 --- /dev/null +++ b/examples/powertools-examples-core/kotlin/README.md @@ -0,0 +1,38 @@ +# Powertools for AWS Lambda (Kotlin) - Core Utilities Example + +This project demonstrates the Lambda for Powertools Kotlin module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) with +[Gradle](https://gradle.org/) running the build. This example is configured for Java 1.8 only; in order to use a newer version, check out the Gradle +configuration guide [in the main project README](../../../README.md). + +You can also use `sam init` to create a new Gradle-powered Powertools application - choose to use the **AWS Quick Start Templates**, +and then **Hello World Example with Powertools for AWS Lambda**, **Java 17** runtime, and finally **gradle**. + +For general information on the deployed example itself, you can refer to the parent [README](../README.md) + +## Configuration +SAM uses [template.yaml](template.yaml) to define the application's AWS resources. +This file defines the Lambda function to be deployed as well as API Gateway for it. + +The build of the project is managed by Gradle, and configured in [build.gradle.kts](build.gradle.kts) +. + +## Deploy the sample application +To get started, you can use the included template with SAM to run the build and deploy to your AWS environment: + +```bash +sam build && sam deploy --guided +``` + +Once this is done to deploy the example, check out the instructions for getting started with SAM in +[the examples directory](../../README.md) + +## Additional notes + +You can watch the trace information or log information using the SAM CLI: +```bash +# Tail the logs +sam logs --tail $MY_STACK + +# Tail the traces +sam traces --tail +``` \ No newline at end of file diff --git a/examples/powertools-examples-core/kotlin/build.gradle.kts b/examples/powertools-examples-core/kotlin/build.gradle.kts new file mode 100644 index 000000000..fc363c1b9 --- /dev/null +++ b/examples/powertools-examples-core/kotlin/build.gradle.kts @@ -0,0 +1,39 @@ +plugins { + id("io.freefair.aspectj.post-compile-weaving") version "6.6.3" + kotlin("jvm") version "1.9.10" +} + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + implementation("com.amazonaws:aws-lambda-java-core:1.2.2") + implementation("com.fasterxml.jackson.core:jackson-annotations:2.13.2") + implementation("com.fasterxml.jackson.core:jackson-databind:2.13.2.2") + implementation("com.amazonaws:aws-lambda-java-events:3.11.0") + implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2") + aspect("software.amazon.lambda:powertools-tracing:1.18.0-SNAPSHOT") + aspect("software.amazon.lambda:powertools-logging:1.18.0-SNAPSHOT") + aspect("software.amazon.lambda:powertools-metrics:1.18.0-SNAPSHOT") + testImplementation("junit:junit:4.13.2") + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") +} + +tasks.compileKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} + +tasks.compileTestKotlin { + kotlinOptions { + jvmTarget = "1.8" + } +} + +// If using JDK 11 or higher, use the following instead: +//kotlin { +// jvmToolchain(11) +//} \ No newline at end of file diff --git a/examples/powertools-examples-core/kotlin/events/event.json b/examples/powertools-examples-core/kotlin/events/event.json new file mode 100644 index 000000000..070ad8e01 --- /dev/null +++ b/examples/powertools-examples-core/kotlin/events/event.json @@ -0,0 +1,62 @@ +{ + "body": "{\"message\": \"hello world\"}", + "resource": "/{proxy+}", + "path": "/path/to/resource", + "httpMethod": "POST", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/path/to/resource", + "resourcePath": "/{proxy+}", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } +} diff --git a/examples/powertools-examples-core/kotlin/gradle/wrapper/.gitignore b/examples/powertools-examples-core/kotlin/gradle/wrapper/.gitignore new file mode 100644 index 000000000..59c09e205 --- /dev/null +++ b/examples/powertools-examples-core/kotlin/gradle/wrapper/.gitignore @@ -0,0 +1,2 @@ +!gradle-wrapper.jar + diff --git a/examples/powertools-examples-core/kotlin/gradle/wrapper/gradle-wrapper.jar b/examples/powertools-examples-core/kotlin/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..033e24c4cdf41af1ab109bc7f253b2b887023340 GIT binary patch literal 63375 zcmb5VV{~QRw)Y#`wrv{~+qP{x72B%VwzFc}c2cp;N~)5ZbDrJayPv(!dGEd-##*zr z)#n-$y^sH|_dchh3@8{H5D*j;5D<{i*8l5IFJ|DjL!e)upfGNX(kojugZ3I`oH1PvW`wFW_ske0j@lB9bX zO;2)`y+|!@X(fZ1<2n!Qx*)_^Ai@Cv-dF&(vnudG?0CsddG_&Wtae(n|K59ew)6St z#dj7_(Cfwzh$H$5M!$UDd8=4>IQsD3xV=lXUq($;(h*$0^yd+b{qq63f0r_de#!o_ zXDngc>zy`uor)4A^2M#U*DC~i+dc<)Tb1Tv&~Ev@oM)5iJ4Sn#8iRw16XXuV50BS7 zdBL5Mefch(&^{luE{*5qtCZk$oFr3RH=H!c3wGR=HJ(yKc_re_X9pD` zJ;uxPzUfVpgU>DSq?J;I@a+10l0ONXPcDkiYcihREt5~T5Gb}sT0+6Q;AWHl`S5dV>lv%-p9l#xNNy7ZCr%cyqHY%TZ8Q4 zbp&#ov1*$#grNG#1vgfFOLJCaNG@K|2!W&HSh@3@Y%T?3YI75bJp!VP*$*!< z;(ffNS_;@RJ`=c7yX04!u3JP*<8jeqLHVJu#WV&v6wA!OYJS4h<_}^QI&97-;=ojW zQ-1t)7wnxG*5I%U4)9$wlv5Fr;cIizft@&N+32O%B{R1POm$oap@&f| zh+5J{>U6ftv|vAeKGc|zC=kO(+l7_cLpV}-D#oUltScw})N>~JOZLU_0{Ka2e1evz z{^a*ZrLr+JUj;)K&u2CoCAXLC2=fVScI(m_p~0FmF>>&3DHziouln?;sxW`NB}cSX z8?IsJB)Z=aYRz!X=yJn$kyOWK%rCYf-YarNqKzmWu$ZvkP12b4qH zhS9Q>j<}(*frr?z<%9hl*i^#@*O2q(Z^CN)c2c z>1B~D;@YpG?G!Yk+*yn4vM4sO-_!&m6+`k|3zd;8DJnxsBYtI;W3We+FN@|tQ5EW= z!VU>jtim0Mw#iaT8t_<+qKIEB-WwE04lBd%Letbml9N!?SLrEG$nmn7&W(W`VB@5S zaY=sEw2}i@F_1P4OtEw?xj4@D6>_e=m=797#hg}f*l^`AB|Y0# z9=)o|%TZFCY$SzgSjS|8AI-%J4x}J)!IMxY3_KYze`_I=c1nmrk@E8c9?MVRu)7+Ue79|)rBX7tVB7U|w4*h(;Gi3D9le49B38`wuv zp7{4X^p+K4*$@gU(Tq3K1a#3SmYhvI42)GzG4f|u zwQFT1n_=n|jpi=70-yE9LA+d*T8u z`=VmmXJ_f6WmZveZPct$Cgu^~gFiyL>Lnpj*6ee>*0pz=t$IJ}+rE zsf@>jlcG%Wx;Cp5x)YSVvB1$yyY1l&o zvwX=D7k)Dn;ciX?Z)Pn8$flC8#m`nB&(8?RSdBvr?>T9?E$U3uIX7T?$v4dWCa46 z+&`ot8ZTEgp7G+c52oHJ8nw5}a^dwb_l%MOh(ebVj9>_koQP^$2B~eUfSbw9RY$_< z&DDWf2LW;b0ZDOaZ&2^i^g+5uTd;GwO(-bbo|P^;CNL-%?9mRmxEw~5&z=X^Rvbo^WJW=n_%*7974RY}JhFv46> zd}`2|qkd;89l}R;i~9T)V-Q%K)O=yfVKNM4Gbacc7AOd>#^&W&)Xx!Uy5!BHnp9kh z`a(7MO6+Ren#>R^D0K)1sE{Bv>}s6Rb9MT14u!(NpZOe-?4V=>qZ>}uS)!y~;jEUK z&!U7Fj&{WdgU#L0%bM}SYXRtM5z!6M+kgaMKt%3FkjWYh=#QUpt$XX1!*XkpSq-pl zhMe{muh#knk{9_V3%qdDcWDv}v)m4t9 zQhv{;} zc{}#V^N3H>9mFM8`i`0p+fN@GqX+kl|M94$BK3J-X`Hyj8r!#x6Vt(PXjn?N)qedP z=o1T^#?1^a{;bZ&x`U{f?}TMo8ToN zkHj5v|}r}wDEi7I@)Gj+S1aE-GdnLN+$hw!=DzglMaj#{qjXi_dwpr|HL(gcCXwGLEmi|{4&4#OZ4ChceA zKVd4K!D>_N=_X;{poT~4Q+!Le+ZV>=H7v1*l%w`|`Dx8{)McN@NDlQyln&N3@bFpV z_1w~O4EH3fF@IzJ9kDk@7@QctFq8FbkbaH7K$iX=bV~o#gfh?2JD6lZf(XP>~DACF)fGFt)X%-h1yY~MJU{nA5 ze2zxWMs{YdX3q5XU*9hOH0!_S24DOBA5usB+Ws$6{|AMe*joJ?RxfV}*7AKN9V*~J zK+OMcE@bTD>TG1*yc?*qGqjBN8mgg@h1cJLDv)0!WRPIkC` zZrWXrceVw;fB%3`6kq=a!pq|hFIsQ%ZSlo~)D z|64!aCnw-?>}AG|*iOl44KVf8@|joXi&|)1rB;EQWgm+iHfVbgllP$f!$Wf42%NO5b(j9Bw6L z;0dpUUK$5GX4QbMlTmLM_jJt!ur`_0~$b#BB7FL*%XFf<b__1o)Ao3rlobbN8-(T!1d-bR8D3S0@d zLI!*GMb5s~Q<&sjd}lBb8Nr0>PqE6_!3!2d(KAWFxa{hm`@u|a(%#i(#f8{BP2wbs zt+N_slWF4IF_O|{w`c~)Xvh&R{Au~CFmW#0+}MBd2~X}t9lz6*E7uAD`@EBDe$>7W zzPUkJx<`f$0VA$=>R57^(K^h86>09?>_@M(R4q($!Ck6GG@pnu-x*exAx1jOv|>KH zjNfG5pwm`E-=ydcb+3BJwuU;V&OS=6yM^4Jq{%AVqnTTLwV`AorIDD}T&jWr8pB&j28fVtk_y*JRP^t@l*($UZ z6(B^-PBNZ+z!p?+e8@$&jCv^EWLb$WO=}Scr$6SM*&~B95El~;W_0(Bvoha|uQ1T< zO$%_oLAwf1bW*rKWmlD+@CP&$ObiDy=nh1b2ejz%LO9937N{LDe7gle4i!{}I$;&Y zkexJ9Ybr+lrCmKWg&}p=`2&Gf10orS?4$VrzWidT=*6{KzOGMo?KI0>GL0{iFWc;C z+LPq%VH5g}6V@-tg2m{C!-$fapJ9y}c$U}aUmS{9#0CM*8pC|sfer!)nG7Ji>mfRh z+~6CxNb>6eWKMHBz-w2{mLLwdA7dA-qfTu^A2yG1+9s5k zcF=le_UPYG&q!t5Zd_*E_P3Cf5T6821bO`daa`;DODm8Ih8k89=RN;-asHIigj`n=ux>*f!OC5#;X5i;Q z+V!GUy0|&Y_*8k_QRUA8$lHP;GJ3UUD08P|ALknng|YY13)}!!HW@0z$q+kCH%xet zlWf@BXQ=b=4}QO5eNnN~CzWBbHGUivG=`&eWK}beuV*;?zt=P#pM*eTuy3 zP}c#}AXJ0OIaqXji78l;YrP4sQe#^pOqwZUiiN6^0RCd#D271XCbEKpk`HI0IsN^s zES7YtU#7=8gTn#lkrc~6)R9u&SX6*Jk4GFX7){E)WE?pT8a-%6P+zS6o&A#ml{$WX zABFz#i7`DDlo{34)oo?bOa4Z_lNH>n;f0nbt$JfAl~;4QY@}NH!X|A$KgMmEsd^&Y zt;pi=>AID7ROQfr;MsMtClr5b0)xo|fwhc=qk33wQ|}$@?{}qXcmECh>#kUQ-If0$ zseb{Wf4VFGLNc*Rax#P8ko*=`MwaR-DQ8L8V8r=2N{Gaips2_^cS|oC$+yScRo*uF zUO|5=?Q?{p$inDpx*t#Xyo6=s?bbN}y>NNVxj9NZCdtwRI70jxvm3!5R7yiWjREEd zDUjrsZhS|P&|Ng5r+f^kA6BNN#|Se}_GF>P6sy^e8kBrgMv3#vk%m}9PCwUWJg-AD zFnZ=}lbi*mN-AOm zCs)r=*YQAA!`e#1N>aHF=bb*z*hXH#Wl$z^o}x##ZrUc=kh%OHWhp=7;?8%Xj||@V?1c ziWoaC$^&04;A|T)!Zd9sUzE&$ODyJaBpvqsw19Uiuq{i#VK1!htkdRWBnb z`{rat=nHArT%^R>u#CjjCkw-7%g53|&7z-;X+ewb?OLWiV|#nuc8mp*LuGSi3IP<<*Wyo9GKV7l0Noa4Jr0g3p_$ z*R9{qn=?IXC#WU>48-k5V2Oc_>P;4_)J@bo1|pf=%Rcbgk=5m)CJZ`caHBTm3%!Z9 z_?7LHr_BXbKKr=JD!%?KhwdYSdu8XxPoA{n8^%_lh5cjRHuCY9Zlpz8g+$f@bw@0V z+6DRMT9c|>1^3D|$Vzc(C?M~iZurGH2pXPT%F!JSaAMdO%!5o0uc&iqHx?ImcX6fI zCApkzc~OOnfzAd_+-DcMp&AOQxE_EsMqKM{%dRMI5`5CT&%mQO?-@F6tE*xL?aEGZ z8^wH@wRl`Izx4sDmU>}Ym{ybUm@F83qqZPD6nFm?t?(7>h*?`fw)L3t*l%*iw0Qu#?$5eq!Qc zpQvqgSxrd83NsdO@lL6#{%lsYXWen~d3p4fGBb7&5xqNYJ)yn84!e1PmPo7ChVd%4 zHUsV0Mh?VpzZD=A6%)Qrd~i7 z96*RPbid;BN{Wh?adeD_p8YU``kOrGkNox3D9~!K?w>#kFz!4lzOWR}puS(DmfjJD z`x0z|qB33*^0mZdM&6$|+T>fq>M%yoy(BEjuh9L0>{P&XJ3enGpoQRx`v6$txXt#c z0#N?b5%srj(4xmPvJxrlF3H%OMB!jvfy z;wx8RzU~lb?h_}@V=bh6p8PSb-dG|-T#A?`c&H2`_!u+uenIZe`6f~A7r)`9m8atC zt(b|6Eg#!Q*DfRU=Ix`#B_dK)nnJ_+>Q<1d7W)eynaVn`FNuN~%B;uO2}vXr5^zi2 z!ifIF5@Zlo0^h~8+ixFBGqtweFc`C~JkSq}&*a3C}L?b5Mh-bW=e)({F_g4O3 zb@SFTK3VD9QuFgFnK4Ve_pXc3{S$=+Z;;4+;*{H}Rc;845rP?DLK6G5Y-xdUKkA6E3Dz&5f{F^FjJQ(NSpZ8q-_!L3LL@H* zxbDF{gd^U3uD;)a)sJwAVi}7@%pRM&?5IaUH%+m{E)DlA_$IA1=&jr{KrhD5q&lTC zAa3c)A(K!{#nOvenH6XrR-y>*4M#DpTTOGQEO5Jr6kni9pDW`rvY*fs|ItV;CVITh z=`rxcH2nEJpkQ^(;1c^hfb8vGN;{{oR=qNyKtR1;J>CByul*+=`NydWnSWJR#I2lN zTvgnR|MBx*XFsfdA&;tr^dYaqRZp*2NwkAZE6kV@1f{76e56eUmGrZ>MDId)oqSWw z7d&r3qfazg+W2?bT}F)4jD6sWaw`_fXZGY&wnGm$FRPFL$HzVTH^MYBHWGCOk-89y zA+n+Q6EVSSCpgC~%uHfvyg@ufE^#u?JH?<73A}jj5iILz4Qqk5$+^U(SX(-qv5agK znUkfpke(KDn~dU0>gdKqjTkVk`0`9^0n_wzXO7R!0Thd@S;U`y)VVP&mOd-2 z(hT(|$=>4FY;CBY9#_lB$;|Wd$aOMT5O_3}DYXEHn&Jrc3`2JiB`b6X@EUOD zVl0S{ijm65@n^19T3l%>*;F(?3r3s?zY{thc4%AD30CeL_4{8x6&cN}zN3fE+x<9; zt2j1RRVy5j22-8U8a6$pyT+<`f+x2l$fd_{qEp_bfxfzu>ORJsXaJn4>U6oNJ#|~p z`*ZC&NPXl&=vq2{Ne79AkQncuxvbOG+28*2wU$R=GOmns3W@HE%^r)Fu%Utj=r9t` zd;SVOnA(=MXgnOzI2@3SGKHz8HN~Vpx&!Ea+Df~`*n@8O=0!b4m?7cE^K*~@fqv9q zF*uk#1@6Re_<^9eElgJD!nTA@K9C732tV~;B`hzZ321Ph=^BH?zXddiu{Du5*IPg} zqDM=QxjT!Rp|#Bkp$(mL)aar)f(dOAXUiw81pX0DC|Y4;>Vz>>DMshoips^8Frdv} zlTD=cKa48M>dR<>(YlLPOW%rokJZNF2gp8fwc8b2sN+i6&-pHr?$rj|uFgktK@jg~ zIFS(%=r|QJ=$kvm_~@n=ai1lA{7Z}i+zj&yzY+!t$iGUy|9jH#&oTNJ;JW-3n>DF+ z3aCOzqn|$X-Olu_p7brzn`uk1F*N4@=b=m;S_C?#hy{&NE#3HkATrg?enaVGT^$qIjvgc61y!T$9<1B@?_ibtDZ{G zeXInVr5?OD_nS_O|CK3|RzzMmu+8!#Zb8Ik;rkIAR%6?$pN@d<0dKD2c@k2quB%s( zQL^<_EM6ow8F6^wJN1QcPOm|ehA+dP(!>IX=Euz5qqIq}Y3;ibQtJnkDmZ8c8=Cf3 zu`mJ!Q6wI7EblC5RvP*@)j?}W=WxwCvF3*5Up_`3*a~z$`wHwCy)2risye=1mSp%p zu+tD6NAK3o@)4VBsM!@);qgsjgB$kkCZhaimHg&+k69~drbvRTacWKH;YCK(!rC?8 zP#cK5JPHSw;V;{Yji=55X~S+)%(8fuz}O>*F3)hR;STU`z6T1aM#Wd+FP(M5*@T1P z^06O;I20Sk!bxW<-O;E081KRdHZrtsGJflFRRFS zdi5w9OVDGSL3 zNrC7GVsGN=b;YH9jp8Z2$^!K@h=r-xV(aEH@#JicPy;A0k1>g1g^XeR`YV2HfmqXY zYbRwaxHvf}OlCAwHoVI&QBLr5R|THf?nAevV-=~V8;gCsX>jndvNOcFA+DI+zbh~# zZ7`qNk&w+_+Yp!}j;OYxIfx_{f0-ONc?mHCiCUak=>j>~>YR4#w# zuKz~UhT!L~GfW^CPqG8Lg)&Rc6y^{%3H7iLa%^l}cw_8UuG;8nn9)kbPGXS}p3!L_ zd#9~5CrH8xtUd?{d2y^PJg+z(xIfRU;`}^=OlehGN2=?}9yH$4Rag}*+AWotyxfCJ zHx=r7ZH>j2kV?%7WTtp+-HMa0)_*DBBmC{sd$)np&GEJ__kEd`xB5a2A z*J+yx>4o#ZxwA{;NjhU*1KT~=ZK~GAA;KZHDyBNTaWQ1+;tOFFthnD)DrCn`DjBZ% zk$N5B4^$`n^jNSOr=t(zi8TN4fpaccsb`zOPD~iY=UEK$0Y70bG{idLx@IL)7^(pL z{??Bnu=lDeguDrd%qW1)H)H`9otsOL-f4bSu};o9OXybo6J!Lek`a4ff>*O)BDT_g z<6@SrI|C9klY(>_PfA^qai7A_)VNE4c^ZjFcE$Isp>`e5fLc)rg@8Q_d^Uk24$2bn z9#}6kZ2ZxS9sI(RqT7?El2@B+($>eBQrNi_k#CDJ8D9}8$mmm z4oSKO^F$i+NG)-HE$O6s1--6EzJa?C{x=QgK&c=)b(Q9OVoAXYEEH20G|q$}Hue%~ zO3B^bF=t7t48sN zWh_zA`w~|){-!^g?6Mqf6ieV zFx~aPUOJGR=4{KsW7I?<=J2|lY`NTU=lt=%JE9H1vBpkcn=uq(q~=?iBt_-r(PLBM zP-0dxljJO>4Wq-;stY)CLB4q`-r*T$!K2o}?E-w_i>3_aEbA^MB7P5piwt1dI-6o!qWCy0 ztYy!x9arGTS?kabkkyv*yxvsPQ7Vx)twkS6z2T@kZ|kb8yjm+^$|sEBmvACeqbz)RmxkkDQX-A*K!YFziuhwb|ym>C$}U|J)4y z$(z#)GH%uV6{ec%Zy~AhK|+GtG8u@c884Nq%w`O^wv2#A(&xH@c5M`Vjk*SR_tJnq z0trB#aY)!EKW_}{#L3lph5ow=@|D5LzJYUFD6 z7XnUeo_V0DVSIKMFD_T0AqAO|#VFDc7c?c-Q%#u00F%!_TW1@JVnsfvm@_9HKWflBOUD~)RL``-!P;(bCON_4eVdduMO>?IrQ__*zE@7(OX zUtfH@AX*53&xJW*Pu9zcqxGiM>xol0I~QL5B%Toog3Jlenc^WbVgeBvV8C8AX^Vj& z^I}H})B=VboO%q1;aU5ACMh{yK4J;xlMc`jCnZR^!~LDs_MP&8;dd@4LDWw~*>#OT zeZHwdQWS!tt5MJQI~cw|Ka^b4c|qyd_ly(+Ql2m&AAw^ zQeSXDOOH!!mAgzAp0z)DD>6Xo``b6QwzUV@w%h}Yo>)a|xRi$jGuHQhJVA%>)PUvK zBQ!l0hq<3VZ*RnrDODP)>&iS^wf64C;MGqDvx>|p;35%6(u+IHoNbK z;Gb;TneFo*`zUKS6kwF*&b!U8e5m4YAo03a_e^!5BP42+r)LFhEy?_7U1IR<; z^0v|DhCYMSj<-;MtY%R@Fg;9Kky^pz_t2nJfKWfh5Eu@_l{^ph%1z{jkg5jQrkvD< z#vdK!nku*RrH~TdN~`wDs;d>XY1PH?O<4^U4lmA|wUW{Crrv#r%N>7k#{Gc44Fr|t z@UZP}Y-TrAmnEZ39A*@6;ccsR>)$A)S>$-Cj!=x$rz7IvjHIPM(TB+JFf{ehuIvY$ zsDAwREg*%|=>Hw$`us~RP&3{QJg%}RjJKS^mC_!U;E5u>`X`jW$}P`Mf}?7G7FX#{ zE(9u1SO;3q@ZhDL9O({-RD+SqqPX)`0l5IQu4q)49TUTkxR(czeT}4`WV~pV*KY&i zAl3~X%D2cPVD^B43*~&f%+Op)wl<&|D{;=SZwImydWL6@_RJjxP2g)s=dH)u9Npki zs~z9A+3fj0l?yu4N0^4aC5x)Osnm0qrhz@?nwG_`h(71P znbIewljU%T*cC=~NJy|)#hT+lx#^5MuDDnkaMb*Efw9eThXo|*WOQzJ*#3dmRWm@! zfuSc@#kY{Um^gBc^_Xdxnl!n&y&}R4yAbK&RMc+P^Ti;YIUh|C+K1|=Z^{nZ}}rxH*v{xR!i%qO~o zTr`WDE@k$M9o0r4YUFFeQO7xCu_Zgy)==;fCJ94M_rLAv&~NhfvcLWCoaGg2ao~3e zBG?Ms9B+efMkp}7BhmISGWmJsKI@a8b}4lLI48oWKY|8?zuuNc$lt5Npr+p7a#sWu zh!@2nnLBVJK!$S~>r2-pN||^w|fY`CT{TFnJy`B|e5;=+_v4l8O-fkN&UQbA4NKTyntd zqK{xEKh}U{NHoQUf!M=2(&w+eef77VtYr;xs%^cPfKLObyOV_9q<(%76-J%vR>w9!us-0c-~Y?_EVS%v!* z15s2s3eTs$Osz$JayyH|5nPAIPEX=U;r&p;K14G<1)bvn@?bM5kC{am|C5%hyxv}a z(DeSKI5ZfZ1*%dl8frIX2?);R^^~LuDOpNpk-2R8U1w92HmG1m&|j&J{EK=|p$;f9 z7Rs5|jr4r8k5El&qcuM+YRlKny%t+1CgqEWO>3;BSRZi(LA3U%Jm{@{y+A+w(gzA< z7dBq6a1sEWa4cD0W7=Ld9z0H7RI^Z7vl(bfA;72j?SWCo`#5mVC$l1Q2--%V)-uN* z9ha*s-AdfbDZ8R8*fpwjzx=WvOtmSzGFjC#X)hD%Caeo^OWjS(3h|d9_*U)l%{Ab8 zfv$yoP{OuUl@$(-sEVNt{*=qi5P=lpxWVuz2?I7Dc%BRc+NGNw+323^ z5BXGfS71oP^%apUo(Y#xkxE)y?>BFzEBZ}UBbr~R4$%b7h3iZu3S(|A;&HqBR{nK& z$;GApNnz=kNO^FL&nYcfpB7Qg;hGJPsCW44CbkG1@l9pn0`~oKy5S777uH)l{irK!ru|X+;4&0D;VE*Ii|<3P zUx#xUqvZT5kVQxsF#~MwKnv7;1pR^0;PW@$@T7I?s`_rD1EGUdSA5Q(C<>5SzE!vw z;{L&kKFM-MO>hy#-8z`sdVx})^(Dc-dw;k-h*9O2_YZw}|9^y-|8RQ`BWJUJL(Cer zP5Z@fNc>pTXABbTRY-B5*MphpZv6#i802giwV&SkFCR zGMETyUm(KJbh+&$8X*RB#+{surjr;8^REEt`2&Dubw3$mx>|~B5IKZJ`s_6fw zKAZx9&PwBqW1Oz0r0A4GtnZd7XTKViX2%kPfv+^X3|_}RrQ2e3l=KG_VyY`H?I5&CS+lAX5HbA%TD9u6&s#v!G> zzW9n4J%d5ye7x0y`*{KZvqyXUfMEE^ZIffzI=Hh|3J}^yx7eL=s+TPH(Q2GT-sJ~3 zI463C{(ag7-hS1ETtU;_&+49ABt5!A7CwLwe z=SoA8mYZIQeU;9txI=zcQVbuO%q@E)JI+6Q!3lMc=Gbj(ASg-{V27u>z2e8n;Nc*pf}AqKz1D>p9G#QA+7mqqrEjGfw+85Uyh!=tTFTv3|O z+)-kFe_8FF_EkTw!YzwK^Hi^_dV5x-Ob*UWmD-})qKj9@aE8g240nUh=g|j28^?v7 zHRTBo{0KGaWBbyX2+lx$wgXW{3aUab6Bhm1G1{jTC7ota*JM6t+qy)c5<@ zpc&(jVdTJf(q3xB=JotgF$X>cxh7k*(T`-V~AR+`%e?YOeALQ2Qud( zz35YizXt(aW3qndR}fTw1p()Ol4t!D1pitGNL95{SX4ywzh0SF;=!wf=?Q?_h6!f* zh7<+GFi)q|XBsvXZ^qVCY$LUa{5?!CgwY?EG;*)0ceFe&=A;!~o`ae}Z+6me#^sv- z1F6=WNd6>M(~ z+092z>?Clrcp)lYNQl9jN-JF6n&Y0mp7|I0dpPx+4*RRK+VQI~>en0Dc;Zfl+x z_e_b7s`t1_A`RP3$H}y7F9_na%D7EM+**G_Z0l_nwE+&d_kc35n$Fxkd4r=ltRZhh zr9zER8>j(EdV&Jgh(+i}ltESBK62m0nGH6tCBr90!4)-`HeBmz54p~QP#dsu%nb~W z7sS|(Iydi>C@6ZM(Us!jyIiszMkd)^u<1D+R@~O>HqZIW&kearPWmT>63%_t2B{_G zX{&a(gOYJx!Hq=!T$RZ&<8LDnxsmx9+TBL0gTk$|vz9O5GkK_Yx+55^R=2g!K}NJ3 zW?C;XQCHZl7H`K5^BF!Q5X2^Mj93&0l_O3Ea3!Ave|ixx+~bS@Iv18v2ctpSt4zO{ zp#7pj!AtDmti$T`e9{s^jf(ku&E|83JIJO5Qo9weT6g?@vX!{7)cNwymo1+u(YQ94 zopuz-L@|5=h8A!(g-MXgLJC0MA|CgQF8qlonnu#j z;uCeq9ny9QSD|p)9sp3ebgY3rk#y0DA(SHdh$DUm^?GI<>%e1?&}w(b zdip1;P2Z=1wM+$q=TgLP$}svd!vk+BZ@h<^4R=GS2+sri7Z*2f`9 z5_?i)xj?m#pSVchk-SR!2&uNhzEi+#5t1Z$o0PoLGz*pT64%+|Wa+rd5Z}60(j?X= z{NLjtgRb|W?CUADqOS@(*MA-l|E342NxRaxLTDqsOyfWWe%N(jjBh}G zm7WPel6jXijaTiNita+z(5GCO0NM=Melxud57PP^d_U## zbA;9iVi<@wr0DGB8=T9Ab#2K_#zi=$igyK48@;V|W`fg~7;+!q8)aCOo{HA@vpSy-4`^!ze6-~8|QE||hC{ICKllG9fbg_Y7v z$jn{00!ob3!@~-Z%!rSZ0JO#@>|3k10mLK0JRKP-Cc8UYFu>z93=Ab-r^oL2 zl`-&VBh#=-?{l1TatC;VweM^=M7-DUE>m+xO7Xi6vTEsReyLs8KJ+2GZ&rxw$d4IT zPXy6pu^4#e;;ZTsgmG+ZPx>piodegkx2n0}SM77+Y*j^~ICvp#2wj^BuqRY*&cjmL zcKp78aZt>e{3YBb4!J_2|K~A`lN=u&5j!byw`1itV(+Q_?RvV7&Z5XS1HF)L2v6ji z&kOEPmv+k_lSXb{$)of~(BkO^py&7oOzpjdG>vI1kcm_oPFHy38%D4&A4h_CSo#lX z2#oqMCTEP7UvUR3mwkPxbl8AMW(e{ARi@HCYLPSHE^L<1I}OgZD{I#YH#GKnpRmW3 z2jkz~Sa(D)f?V?$gNi?6)Y;Sm{&?~2p=0&BUl_(@hYeX8YjaRO=IqO7neK0RsSNdYjD zaw$g2sG(>JR=8Iz1SK4`*kqd_3-?;_BIcaaMd^}<@MYbYisWZm2C2|Np_l|8r9yM|JkUngSo@?wci(7&O9a z%|V(4C1c9pps0xxzPbXH=}QTxc2rr7fXk$9`a6TbWKPCz&p=VsB8^W96W=BsB|7bc zf(QR8&Ktj*iz)wK&mW`#V%4XTM&jWNnDF56O+2bo<3|NyUhQ%#OZE8$Uv2a@J>D%t zMVMiHh?es!Ex19q&6eC&L=XDU_BA&uR^^w>fpz2_`U87q_?N2y;!Z!bjoeKrzfC)} z?m^PM=(z{%n9K`p|7Bz$LuC7!>tFOuN74MFELm}OD9?%jpT>38J;=1Y-VWtZAscaI z_8jUZ#GwWz{JqvGEUmL?G#l5E=*m>`cY?m*XOc*yOCNtpuIGD+Z|kn4Xww=BLrNYS zGO=wQh}Gtr|7DGXLF%|`G>J~l{k^*{;S-Zhq|&HO7rC_r;o`gTB7)uMZ|WWIn@e0( zX$MccUMv3ABg^$%_lNrgU{EVi8O^UyGHPNRt%R!1#MQJn41aD|_93NsBQhP80yP<9 zG4(&0u7AtJJXLPcqzjv`S~5;Q|5TVGccN=Uzm}K{v)?f7W!230C<``9(64}D2raRU zAW5bp%}VEo{4Rko`bD%Ehf=0voW?-4Mk#d3_pXTF!-TyIt6U+({6OXWVAa;s-`Ta5 zTqx&8msH3+DLrVmQOTBOAj=uoxKYT3DS1^zBXM?1W+7gI!aQNPYfUl{3;PzS9*F7g zWJN8x?KjBDx^V&6iCY8o_gslO16=kh(|Gp)kz8qlQ`dzxQv;)V&t+B}wwdi~uBs4? zu~G|}y!`3;8#vIMUdyC7YEx6bb^1o}G!Jky4cN?BV9ejBfN<&!4M)L&lRKiuMS#3} z_B}Nkv+zzxhy{dYCW$oGC&J(Ty&7%=5B$sD0bkuPmj7g>|962`(Q{ZZMDv%YMuT^KweiRDvYTEop3IgFv#)(w>1 zSzH>J`q!LK)c(AK>&Ib)A{g`Fdykxqd`Yq@yB}E{gnQV$K!}RsgMGWqC3DKE(=!{}ekB3+(1?g}xF>^icEJbc z5bdxAPkW90atZT+&*7qoLqL#p=>t-(-lsnl2XMpZcYeW|o|a322&)yO_8p(&Sw{|b zn(tY$xn5yS$DD)UYS%sP?c|z>1dp!QUD)l;aW#`%qMtQJjE!s2z`+bTSZmLK7SvCR z=@I4|U^sCwZLQSfd*ACw9B@`1c1|&i^W_OD(570SDLK`MD0wTiR8|$7+%{cF&){$G zU~|$^Ed?TIxyw{1$e|D$050n8AjJvvOWhLtLHbSB|HIfhMpqVf>AF&}ZQHhOJ14Bz zww+XL+qP}nww+W`F>b!by|=&a(cM4JIDhsTXY8@|ntQG}-}jm0&Bcj|LV(#sc=BNS zRjh;k9l>EdAFdd)=H!U`~$WP*}~^3HZ_?H>gKw>NBa;tA8M1{>St|)yDF_=~{KEPAGkg3VB`QCHol!AQ0|?e^W?81f{@()Wy!vQ$bY; z0ctx)l7VK83d6;dp!s{Nu=SwXZ8lHQHC*J2g@P0a={B8qHdv(+O3wV=4-t4HK1+smO#=S; z3cSI#Nh+N@AqM#6wPqjDmQM|x95JG|l1#sAU|>I6NdF*G@bD?1t|ytHlkKD+z9}#j zbU+x_cR-j9yX4s{_y>@zk*ElG1yS({BInGJcIT>l4N-DUs6fufF#GlF2lVUNOAhJT zGZThq54GhwCG(h4?yWR&Ax8hU<*U)?g+HY5-@{#ls5CVV(Wc>Bavs|l<}U|hZn z_%m+5i_gaakS*Pk7!v&w3&?R5Xb|AkCdytTY;r+Z7f#Id=q+W8cn)*9tEet=OG+Y} z58U&!%t9gYMx2N=8F?gZhIjtkH!`E*XrVJ?$2rRxLhV1z82QX~PZi8^N5z6~f-MUE zLKxnNoPc-SGl7{|Oh?ZM$jq67sSa)Wr&3)0YxlJt(vKf!-^L)a|HaPv*IYXb;QmWx zsqM>qY;tpK3RH-omtta+Xf2Qeu^$VKRq7`e$N-UCe1_2|1F{L3&}M0XbJ@^xRe&>P zRdKTgD6601x#fkDWkoYzRkxbn#*>${dX+UQ;FbGnTE-+kBJ9KPn)501#_L4O_k`P3 zm+$jI{|EC?8BXJY{P~^f-{**E53k%kVO$%p+=H5DiIdwMmUo>2euq0UzU90FWL!>; z{5@sd0ecqo5j!6AH@g6Mf3keTP$PFztq}@)^ZjK;H6Go$#SV2|2bAFI0%?aXgVH$t zb4Kl`$Xh8qLrMbZUS<2*7^F0^?lrOE=$DHW+O zvLdczsu0^TlA6RhDy3=@s!k^1D~Awulk!Iyo#}W$xq8{yTAK!CLl={H0@YGhg-g~+ z(u>pss4k#%8{J%~%8=H5!T`rqK6w^es-cNVE}=*lP^`i&K4R=peg1tdmT~UAbDKc& zg%Y*1E{hBf<)xO>HDWV7BaMWX6FW4ou1T2m^6{Jb!Su1UaCCYY8RR8hAV$7ho|FyEyP~ zEgK`@%a$-C2`p zV*~G>GOAs*3KN;~IY_UR$ISJxB(N~K>=2C2V6>xTmuX4klRXdrJd&UPAw7&|KEwF8Zcy2j-*({gSNR1^p02Oj88GN9a_Hq;Skdp}kO0;FLbje%2ZvPiltDZgv^ z#pb4&m^!79;O8F+Wr9X71laPY!CdNXG?J6C9KvdAE2xWW1>U~3;0v≫L+crb^Bz zc+Nw%zgpZ6>!A3%lau!Pw6`Y#WPVBtAfKSsqwYDWQK-~ zz(mx=nJ6-8t`YXB{6gaZ%G}Dmn&o500Y}2Rd?e&@=hBEmB1C=$OMBfxX__2c2O4K2#(0ksclP$SHp*8jq-1&(<6(#=6&H`Nlc2RVC4->r6U}sTY<1? zn@tv7XwUs-c>Lcmrm5AE0jHI5={WgHIow6cX=UK)>602(=arbuAPZ37;{HTJSIO%9EL`Et5%J7$u_NaC(55x zH^qX^H}*RPDx)^c46x>js=%&?y?=iFs^#_rUl@*MgLD92E5y4B7#EDe9yyn*f-|pQ zi>(!bIg6zY5fLSn@;$*sN|D2A{}we*7+2(4&EhUV%Qqo5=uuN^xt_hll7=`*mJq6s zCWUB|s$)AuS&=)T&_$w>QXHqCWB&ndQ$y4-9fezybZb0bYD^zeuZ>WZF{rc>c4s`` zgKdppTB|o>L1I1hAbnW%H%EkFt%yWC|0~+o7mIyFCTyb?@*Ho)eu(x`PuO8pLikN> z6YeI`V?AUWD(~3=8>}a6nZTu~#QCK(H0+4!ql3yS`>JX;j4+YkeG$ZTm33~PLa3L} zksw7@%e-mBM*cGfz$tS4LC^SYVdBLsR}nAprwg8h2~+Cv*W0%izK+WPVK}^SsL5R_ zpA}~G?VNhJhqx2he2;2$>7>DUB$wN9_-adL@TqVLe=*F8Vsw-yho@#mTD6*2WAr6B zjtLUh`E(;#p0-&$FVw(r$hn+5^Z~9J0}k;j$jL1;?2GN9s?}LASm?*Rvo@?E+(}F& z+=&M-n`5EIz%%F^e)nnWjkQUdG|W^~O|YeY4Fz}>qH2juEere}vN$oJN~9_Th^&b{ z%IBbET*E8%C@jLTxV~h#mxoRrJCF{!CJOghjuKOyl_!Jr?@4Upo7u>fTGtfm|CH2v z&9F+>;6aFbYXLj3{yZ~Yn1J2%!)A3~j2$`jOy{XavW@t)g}}KUVjCWG0OUc7aBc=2 zR3^u=dT47=5SmT{K1aGaVZkOx|24T-J0O$b9dfB25J|7yb6frwS6wZ1^y%EWOm}S< zc1SdYhfsdLG*FB-;!QLV3D!d~hnXTGVQVck9x%=B(Kk8c3y%f0nR95_TbY;l=obSl zEE@fp0|8Q$b3(+DXh?d0FEloGhO0#11CLQT5qtEckBLe-VN-I>9ys}PVK0r;0!jIG zH_q$;a`3Xv9P_V2ekV1SMzd#SKo<1~Dq2?M{(V;AwhH_2x@mN$=|=cG0<3o^j_0OF z7|WJ-f2G=7sA4NVGU2X5`o*D2T7(MbmZ2(oipooE{R?9!{WxX!%ofhsrPAxoIk!Kr z>I$a{Zq=%KaLrDCIL^gmA3z{2z%Wkr)b$QHcNUA^QwydWMJmxymO0QS22?mo%4(Md zgME(zE}ub--3*wGjV`3eBMCQG-@Gel1NKZDGuqobN|mAt0{@ZC9goI|BSmGBTUZ(`Xt z^e2LiMg?6E?G*yw(~K8lO(c4)RY7UWxrXzW^iCg-P41dUiE(i+gDmmAoB?XOB}+Ln z_}rApiR$sqNaT4frw69Wh4W?v(27IlK$Toy<1o)GeF+sGzYVeJ`F)3`&2WDi^_v67 zg;@ehwl3=t+}(DJtOYO!s`jHyo-}t@X|U*9^sIfaZfh;YLqEFmZ^E;$_XK}%eq;>0 zl?+}*kh)5jGA}3daJ*v1knbW0GusR1+_xD`MFPZc3qqYMXd>6*5?%O5pC7UVs!E-` zuMHc6igdeFQ`plm+3HhP)+3I&?5bt|V8;#1epCsKnz0%7m9AyBmz06r90n~9o;K30 z=fo|*`Qq%dG#23bVV9Jar*zRcV~6fat9_w;x-quAwv@BkX0{9e@y0NB(>l3#>82H6 z^US2<`=M@6zX=Pz>kb8Yt4wmeEo%TZ=?h+KP2e3U9?^Nm+OTx5+mVGDvgFee%}~~M zK+uHmj44TVs}!A}0W-A92LWE%2=wIma(>jYx;eVB*%a>^WqC7IVN9{o?iw{e4c=CG zC#i=cRJZ#v3 zF^9V+7u?W=xCY%2dvV_0dCP%5)SH*Xm|c#rXhwEl*^{Ar{NVoK*H6f5qCSy`+|85e zjGaKqB)p7zKNKI)iWe6A9qkl=rTjs@W1Crh(3G57qdT0w2ig^{*xerzm&U>YY{+fZbkQ#;^<$JniUifmAuEd^_M(&?sTrd(a*cD! zF*;`m80MrZ^> zaF{}rDhEFLeH#`~rM`o903FLO?qw#_Wyb5}13|0agjSTVkSI6Uls)xAFZifu@N~PM zQ%o?$k)jbY0u|45WTLAirUg3Zi1E&=G#LnSa89F3t3>R?RPcmkF}EL-R!OF_r1ZN` z?x-uHH+4FEy>KrOD-$KHg3$-Xl{Cf0;UD4*@eb~G{CK-DXe3xpEEls?SCj^p z$Uix(-j|9f^{z0iUKXcZQen}*`Vhqq$T?^)Ab2i|joV;V-qw5reCqbh(8N)c%!aB< zVs+l#_)*qH_iSZ_32E~}>=wUO$G_~k0h@ch`a6Wa zsk;<)^y=)cPpHt@%~bwLBy;>TNrTf50BAHUOtt#9JRq1ro{w80^sm-~fT>a$QC;<| zZIN%&Uq>8`Js_E((_1sewXz3VlX|-n8XCfScO`eL|H&2|BPZhDn}UAf_6s}|!XpmUr90v|nCutzMjb9|&}#Y7fj_)$alC zM~~D6!dYxhQof{R;-Vp>XCh1AL@d-+)KOI&5uKupy8PryjMhTpCZnSIQ9^Aq+7=Mb zCYCRvm4;H=Q8nZWkiWdGspC_Wvggg|7N`iED~Eap)Th$~wsxc(>(KI>{i#-~Dd8iQ zzonqc9DW1w4a*}k`;rxykUk+~N)|*I?@0901R`xy zN{20p@Ls<%`1G1Bx87Vm6Z#CA`QR(x@t8Wc?tpaunyV^A*-9K9@P>hAWW9Ev)E$gb z<(t?Te6GcJX2&0% z403pe>e)>m-^qlJU^kYIH)AutgOnq!J>FoMXhA-aEx-((7|(*snUyxa+5$wx8FNxS zKuVAVWArlK#kDzEM zqR?&aXIdyvxq~wF?iYPho*(h?k zD(SBpRDZ}z$A})*Qh!9&pZZRyNixD!8)B5{SK$PkVET(yd<8kImQ3ILe%jhx8Ga-1 zE}^k+Eo^?c4Y-t2_qXiVwW6i9o2qosBDj%DRPNT*UXI0=D9q{jB*22t4HHcd$T&Xi zT=Vte*Gz2E^qg%b7ev04Z&(;=I4IUtVJkg<`N6i7tjUn-lPE(Y4HPyJKcSjFnEzCH zPO(w%LmJ_=D~}PyfA91H4gCaf-qur3_KK}}>#9A}c5w@N;-#cHph=x}^mQ3`oo`Y$ope#)H9(kQK zGyt<7eNPuSAs$S%O>2ElZ{qtDIHJ!_THqTwcc-xfv<@1>IJ;YTv@!g-zDKBKAH<

Zet1e^8c}8fE97XH}+lF{qbF<`Y%dU|I!~Y`ZrVfKX82i z)(%!Tcf~eE^%2_`{WBPGPU@1NB5SCXe1sAI<4&n1IwO{&S$ThWn37heGOSW%nW7*L zxh0WK!E7zh%6yF-7%~l@I~b`2=*$;RYbi(I#zp$gL_d39U4A)KuB( zcS0bt48&%G_I~( zL(}w&2NA6#$=|g)J+-?ehHflD^lr77ngdz=dszFI;?~ZxeJv=gsm?4$$6#V==H{fa zqO!EkT>1-OQSJoX)cN}XsB;shvrHRwTH(I2^Ah4|rizn!V7T7fLh~Z<`Q+?zEMVxh z$=-x^RR*PlhkV_8mshTvs+zmZWY&Jk{9LX0Nx|+NAEq-^+Rh|ZlinVZ=e8=`WQt;e@= zPU}^1cG*O;G7l{Y#nl znp`y%CO_SC7gk0i0gY&phM04Y)~vU0!3$V$2T+h(1ZS+cCgc zaC?3M;B48^faGo>h~--#FNFauH?0BJJ6_nG5qOlr>k~%DCSJaOfl%KWHusw>tGrTxAhlEVDxc8R2C-)LCt&$Rt9IKor=ml7jirX@?WW+M z^I{b}MD5r$s>^^sN@&g`cXD~S_u09xo;{;noKZatIuzqd zW1e7oTl9>g8opPBT(p+&fo0F#!c{NFYYpIZ6u8hOB{F#{nP)@})X20$3iJtG$cO zJ$Oxl_qH{sL5d?=D$2M4C3Ajc;GN0(B-HVT;@pJ-LvIrN%|SY?t}g!J>ufQrR%hoY z!nr$tq~N%)9}^tEip93XW=MQ1@XovSvn`PTqXeT9@_7hGv4%LK1M**Q%UKi|(v@1_ zKGe*@+1%Y4v&`;5vUL`C&{tc+_7HFs7*OtjY8@Gg`C4O&#An{0xOvgNSehTHS~_1V z=daxCMzI5b_ydM5$z zZl`a{mM}i@x;=QyaqJY&{Q^R*^1Yzq!dHH~UwCCga+Us~2wk59ArIYtSw9}tEmjbo z5!JA=`=HP*Ae~Z4Pf7sC^A3@Wfa0Ax!8@H_&?WVe*)9B2y!8#nBrP!t1fqhI9jNMd zM_5I)M5z6Ss5t*f$Eh{aH&HBeh310Q~tRl3wCEcZ>WCEq%3tnoHE)eD=)XFQ7NVG5kM zaUtbnq2LQomJSWK)>Zz1GBCIHL#2E>T8INWuN4O$fFOKe$L|msB3yTUlXES68nXRX zP6n*zB+kXqqkpQ3OaMc9GqepmV?Ny!T)R@DLd`|p5ToEvBn(~aZ%+0q&vK1)w4v0* zgW44F2ixZj0!oB~^3k|vni)wBh$F|xQN>~jNf-wFstgiAgB!=lWzM&7&&OYS=C{ce zRJw|)PDQ@3koZfm`RQ$^_hEN$GuTIwoTQIDb?W&wEo@c75$dW(ER6q)qhF`{#7UTuPH&)w`F!w z0EKs}=33m}_(cIkA2rBWvApydi0HSOgc>6tu&+hmRSB%)s`v_NujJNhKLS3r6hv~- z)Hm@?PU{zd0Tga)cJWb2_!!9p3sP%Z zAFT|jy;k>4X)E>4fh^6=SxV5w6oo`mus&nWo*gJL zZH{SR!x)V)y=Qc7WEv-xLR zhD4OcBwjW5r+}pays`o)i$rcJb2MHLGPmeOmt5XJDg@(O3PCbxdDn{6qqb09X44T zh6I|s=lM6Nr#cGaA5-eq*T=LQ6SlRq*`~`b+dVi5^>el1p;#si6}kK}>w;1 z6B1dz{q_;PY{>DBQ+v@1pfXTd5a*^H9U*;qdj@XBF}MoSSQxVXeUpEM5Z0909&8$pRfR|B(t0ox&xl8{8mUNd#(zWONW{oycv$VjP1>q;jU@ z@+8E~fjz*I54OFFaQ{A5jn1w>r;l!NRlI(8q3*%&+tM?lov_G3wB`<}bQ>1=&xUht zmti5VZzV1Cx006Yzt|%Vwid>QPX8Nfa8|sue7^un@C+!3h!?-YK>lSfNIHh|0kL8v zbv_BklQ4HOqje|@Fyxn%IvL$N&?m(KN;%`I$N|muStjSsgG;gP4Smgz$2u(mG;DXP zf~uQ z212x^l6!MW>V@ORUGSFLAAjz3i5zO$=UmD_zhIk2OXUz^LkDLWjla*PW?l;`LLos> z7FBvCr)#)XBByDm(=n%{D>BcUq>0GOV9`i-(ZSI;RH1rdrAJ--f0uuAQ4odl z_^$^U_)0BBJwl@6R#&ZtJN+@a(4~@oYF)yG+G#3=)ll8O#Zv3SjV#zSXTW3h9kqn* z@AHL=vf~KMas}6{+u=}QFumr-!c=(BFP_dwvrdehzTyqco)m@xRc=6b#Dy+KD*-Bq zK=y*1VAPJ;d(b?$2cz{CUeG(0`k9_BIuUki@iRS5lp3=1#g)A5??1@|p=LOE|FNd; z-?5MLKd-5>yQ7n__5W^3C!_`hP(o%_E3BKEmo1h=H(7;{6$XRRW6{u+=oQX<((xAJ zNRY`Egtn#B1EBGHLy^eM5y}Jy0h!GAGhb7gZJoZI-9WuSRw)GVQAAcKd4Qm)pH`^3 zq6EIM}Q zxZGx%aLnNP1an=;o8p9+U^>_Bi`e23E^X|}MB&IkS+R``plrRzTE%ncmfvEW#AHJ~ znmJ`x&ez6eT21aLnoI`%pYYj zzQ?f^ob&Il;>6Fe>HPhAtTZa*B*!;;foxS%NGYmg!#X%)RBFe-acahHs3nkV61(E= zhekiPp1d@ACtA=cntbjuv+r-Zd`+lwKFdqZuYba_ey`&H<Psu;Tzwt;-LQxvv<_D5;ik7 zwETZe`+voUhk%$s2-7Rqfl`Ti_{(fydI(DAHKr<66;rYa6p8AD+NEc@Fd@%m`tiK% z=Mebzrtp=*Q%a}2UdK4J&5#tCN5PX>W=(9rUEXZ8yjRu+7)mFpKh{6;n%!bI(qA9kfyOtstGtOl zX!@*O0fly*L4k##fsm&V0j9Lj<_vu1)i?!#xTB7@2H&)$Kzt@r(GH=xRZlIimTDd_o(%9xO388LwC#;vQ?7OvRU_s< zDS@6@g}VnvQ+tn(C#sx0`J^T4WvFxYI17;uPs-Ub{R`J-NTdtBGl+Q>e81Z3#tDUr ztnVc*p{o|RNnMYts4pdw=P!uJkF@8~h)oV4dXu5F7-j0AW|=mt!QhP&ZV!!82*c7t zuOm>B*2gFtq;A8ynZ~Ms?!gEi5<{R_8tRN%aGM!saR4LJQ|?9w>Ff_61(+|ol_vL4 z-+N>fushRbkB4(e{{SQ}>6@m}s1L!-#20N&h%srA=L50?W9skMF9NGfQ5wU*+0<@> zLww8%f+E0Rc81H3e_5^DB@Dn~TWYk}3tqhO{7GDY;K7b*WIJ-tXnYM@z4rn(LGi?z z8%$wivs)fC#FiJh?(SbH-1bgdmHw&--rn7zBWe1xAhDdv#IRB@DGy}}zS%M0(F_3_ zLb-pWsdJ@xXE;=tpRAw?yj(Gz=i$;bsh&o2XN%24b6+?_gJDBeY zws3PE2u!#Cec>aFMk#ECxDlAs;|M7@LT8)Y4(`M}N6IQ{0YtcA*8e42!n^>`0$LFU zUCq2IR2(L`f++=85M;}~*E($nE&j;p{l%xchiTau*tB9bI= zn~Ygd@<+9DrXxoGPq}@vI1Q3iEfKRleuy*)_$+hg?+GOgf1r?d@Or42|s|D>XMa;ebr1uiTNUq@heusd6%WwJqyCCv!L*qou9l!B22H$bQ z)<)IA>Yo77S;|`fqBk!_PhLJEQb0wd1Z|`pCF;hol!34iQYtqu3K=$QxLW7(HFx~v>`vVRr zyqk^B4~!3F8t8Q_D|GLRrAbbQDf??D&Jd|mgw*t1YCd)CM2$76#Cqj1bD*vADwavp zS<`n@gLU4pwCqNPsIfHKl{5}gu9t-o+O< z??!fMqMrt$s}02pdBbOScUrc1T*{*-ideR6(1q4@oC6mxg8v8Y^h^^hfx6| z|Mld6Ax1CuSlmSJmHwdOix?$8emihK#&8&}u8m!#T1+c5u!H)>QW<7&R$eih)xkov zHvvEIJHbkt+2KQ<-bMR;2SYX?8SI=_<-J!GD5@P2FJ}K z5u82YFotCJF(dUeJFRX_3u8%iIYbRS??A?;iVO?84c}4Du9&jG<#urlZ_Unrcg8dR z!5I3%9F*`qwk#joKG_Q%5_xpU7|jm4h0+l$p;g%Tr>i74#3QnMXdz|1l2MQN$yw|5 zThMw15BxjWf2{KM)XtZ+e#N)ihlkxPe=5ymT9>@Ym%_LF}o z1XhCP`3E1A{iVoHA#|O|&5=w;=j*Qf`;{mBAK3={y-YS$`!0UmtrvzHBfR*s{z<0m zW>4C=%N98hZlUhwAl1X`rR)oL0&A`gv5X79??p_==g*n4$$8o5g9V<)F^u7v0Vv^n z1sp8{W@g6eWv2;A31Rhf5j?KJhITYfXWZsl^`7z`CFtnFrHUWiD?$pwU6|PQjs|7RA0o9ARk^9$f`u3&C|#Z3iYdh<0R`l2`)6+ z6tiDj@xO;Q5PDTYSxsx6n>bj+$JK8IPJ=U5#dIOS-zwyK?+t^V`zChdW|jpZuReE_ z)e~ywgFe!0q|jzsBn&(H*N`%AKpR@qM^|@qFai0};6mG_TvXjJ`;qZ{lGDZHScZk( z>pO+%icp)SaPJUwtIPo1BvGyP8E@~w2y}=^PnFJ$iHod^JH%j1>nXl<3f!nY9K$e` zq-?XYl)K`u*cVXM=`ym{N?z=dHQNR23M8uA-(vsA$6(xn+#B-yY!CB2@`Uz({}}w+ z0sni*39>rMC!Ay|1B@;al%T&xE(wCf+`3w>N)*LxZZZYi{5sqiVWgbNd>W*X?V}C- zjQ4F7e_uCUOHbtewQkq?m$*#@ZvWbu{4i$`aeKM8tc^ zL5!GL8gX}c+qNUtUIcps1S)%Gsx*MQLlQeoZz2y2OQb(A73Jc3`LmlQf0N{RTt;wa`6h|ljX1V7UugML=W5-STDbeWTiEMjPQ$({hn_s&NDXzs6?PLySp$?L`0ilH3vCUO{JS0Dp`z;Ry$6}R@1NdY7rxccbm$+;ApSe=2q!0 z()3$vYN0S$Cs)#-OBs{_2uFf}L4h$;7^2w20=l%5r9ui&pTEgg4U!FoCqyA6r2 zC5s72l}i*9y|KTjDE5gVlYe4I2gGZD)e`Py2gq7cK4at{bT~DSbQQ4Z4sl)kqXbbr zqvXtSqMrDdT2qt-%-HMoqeFEMsv~u)-NJ%Z*ipSJUm$)EJ+we|4*-Mi900K{K|e0; z1_j{X5)a%$+vM7;3j>skgrji92K1*Ip{SfM)=ob^E374JaF!C(cZ$R_E>Wv+?Iy9M z?@`#XDy#=z%3d9&)M=F8Xq5Zif%ldIT#wrlw(D_qOKo4wD(fyDHM5(wm1%7hy6euJ z%Edg!>Egs;ZC6%ktLFtyN0VvxN?*4C=*tOEw`{KQvS7;c514!FP98Nf#d#)+Y-wsl zP3N^-Pnk*{o(3~m=3DX$b76Clu=jMf9E?c^cbUk_h;zMF&EiVz*4I(rFoaHK7#5h0 zW7CQx+xhp}Ev+jw;SQ6P$QHINCxeF8_VX=F3&BWUd(|PVViKJl@-sYiUp@xLS2NuF z8W3JgUSQ&lUp@2E(7MG`sh4X!LQFa6;lInWqx}f#Q z4xhgK1%}b(Z*rZn=W{wBOe7YQ@1l|jQ|9ELiXx+}aZ(>{c7Ltv4d>PJf7f+qjRU8i%XZZFJkj&6D^s;!>`u%OwLa*V5Js9Y$b-mc!t@{C415$K38iVu zP7!{3Ff%i_e!^LzJWhBgQo=j5k<<($$b&%%Xm_f8RFC_(97&nk83KOy@I4k?(k<(6 zthO$3yl&0x!Pz#!79bv^?^85K5e7uS$ zJ33yka2VzOGUhQXeD{;?%?NTYmN3{b0|AMtr(@bCx+c=F)&_>PXgAG}4gwi>g82n> zL3DlhdL|*^WTmn;XPo62HhH-e*XIPSTF_h{#u=NY8$BUW=5@PD{P5n~g5XDg?Fzvb_u ziK&CJqod4srfY2T?+4x@)g9%3%*(Q2%YdCA3yM{s=+QD0&IM`8k8N&-6%iIL3kon> z0>p3BUe!lrz&_ZX2FiP%MeuQY-xVV%K?=bGPOM&XM0XRd7or< zy}jn_eEzuQ>t2fM9ict#ZNxD7HUycsq76IavfoNl$G1|t*qpUSX;YgpmJrr_8yOJ2 z(AwL;Ugi{gJ29@!G-mD82Z)46T`E+s86Qw|YSPO*OoooraA!8x_jQXYq5vUw!5f_x zubF$}lHjIWxFar8)tTg8z-FEz)a=xa`xL~^)jIdezZsg4%ePL$^`VN#c!c6`NHQ9QU zkC^<0f|Ksp45+YoX!Sv>+57q}Rwk*2)f{j8`d8Ctz^S~me>RSakEvxUa^Pd~qe#fb zN7rnAQc4u$*Y9p~li!Itp#iU=*D4>dvJ{Z~}kqAOBcL8ln3YjR{Sp!O`s=5yM zWRNP#;2K#+?I&?ZSLu)^z-|*$C}=0yi7&~vZE$s``IE^PY|dj^HcWI$9ZRm>3w(u` z-1%;;MJbzHFNd^!Ob!^PLO-xhhj@XrI81Y)x4@FdsI( za`o4Gy(`T$P?PB?s>o+eIOtuirMykbuAi65Y_UN1(?jTCy@J8Px`%;bcNmPm#Fr!= z5V!YViFJ!FBfEq>nJFk0^RAV1(7w+X`HRgP;nJHJdMa!}&vvduCMoslwHTes_I76|h>;(-9lbfGnt zoZomakOt759AuTX4b$)G8TzJ&m*BV8!vMs9#=e0tWa z%)84R=3?tfh72~=Rc;fXwj+x z+25xapYK@2@;}6)@8IL+F6iuJ_B{&A-0=U=U6WMbY>~ykVFp$XkH)f**b>TE5)shN z39E2L@JPCSl!?pkvFeh@6dCv9oE}|{GbbVM!XIgByN#md&tXy@>QscU0#z!I&X4;d z&B&ZA4lbrHJ!x4lCN4KC-)u#gT^cE{Xnhu`0RXVKn|j$vz8m}v^%*cQ{(h%FW8_8a zFM{$PirSI8@#*xg2T){A+EKX(eTC66Fb})w{vg%Vw)hvV-$tttI^V5wvU?a{(G}{G z@ob7Urk1@hDN&C$N!Nio9YrkiUC{5qA`KH*7CriaB;2~2Od>2l=WytBRl#~j`EYsj}jqK2xD*3 ztEUiPZzEJC??#Tj^?f)=sRXOJ_>5aO(|V#Yqro05p6)F$j5*wYr1zz|T4qz$0K(5! zr`6Pqd+)%a9Xq3aNKrY9843)O56F%=j_Yy_;|w8l&RU1+B4;pP*O_}X8!qD?IMiyT zLXBOOPg<*BZtT4LJ7DfyghK|_*mMP7a1>zS{8>?}#_XXaLoUBAz(Wi>$Q!L;oQ&cL z6O|T6%Dxq3E35$0g5areq9$2+R(911!Z9=wRPq-pju7DnN9LAfOu3%&onnfx^Px5( zT2^sU>Y)88F5#ATiVoS$jzC-M`vY8!{8#9O#3c&{7J1lo-rcNK7rlF0Zt*AKE(WN* z*o?Tv?Sdz<1v6gfCok8MG6Pzecx9?C zrQG5j^2{V556Hj=xTiU-seOCr2ni@b<&!j>GyHbv!&uBbHjH-U5Ai-UuXx0lcz$D7%=! z&zXD#Jqzro@R=hy8bv>D_CaOdqo6)vFjZldma5D+R;-)y1NGOFYqEr?h zd_mTwQ@K2veZTxh1aaV4F;YnaWA~|<8$p}-eFHashbWW6Dzj=3L=j-C5Ta`w-=QTw zA*k9!Ua~-?eC{Jc)xa;PzkUJ#$NfGJOfbiV^1au;`_Y8|{eJ(~W9pP9q?gLl5E6|e{xkT@s|Ac;yk01+twk_3nuk|lRu{7-zOjLAGe!)j?g+@-;wC_=NPIhk(W zfEpQrdRy z^Q$YBs%>$=So>PAMkrm%yc28YPi%&%=c!<}a=)sVCM51j+x#<2wz?2l&UGHhOv-iu z64x*^E1$55$wZou`E=qjP1MYz0xErcpMiNYM4+Qnb+V4MbM;*7vM_Yp^uXUuf`}-* z_2CnbQ);j5;Rz?7q)@cGmwE^P>4_u9;K|BFlOz_|c^1n~%>!uO#nA?5o4A>XLO{X2 z=8M%*n=IdnXQ}^+`DXRKM;3juVrXdgv79;E=ovQa^?d7wuw~nbu%%lsjUugE8HJ9zvZIM^nWvjLc-HKc2 zbj{paA}ub~4N4Vw5oY{wyop9SqPbWRq=i@Tbce`r?6e`?`iOoOF;~pRyJlKcIJf~G z)=BF$B>YF9>qV#dK^Ie#{0X(QPnOuu((_-u?(mxB7c9;LSS-DYJ8Wm4gz1&DPQ8;0 z=Wao(zb1RHXjwbu_Zv<=9njK28sS}WssjOL!3-E5>d17Lfnq0V$+IU84N z-4i$~!$V-%Ik;`Z3MOqYZdiZ^3nqqzIjLE+zpfQC+LlomQu-uNCStj%MsH(hsimN# z%l4vpJBs_2t7C)x@6*-k_2v0FOk<1nIRO3F{E?2DnS}w> z#%9Oa{`RB5FL5pKLkg59#x~)&I7GzfhiVC@LVFSmxZuiRUPVW*&2ToCGST0K`kRK) z02#c8W{o)w1|*YmjGSUO?`}ukX*rHIqGtFH#!5d1Jd}&%4Kc~Vz`S7_M;wtM|6PgI zNb-Dy-GI%dr3G3J?_yBX#NevuYzZgzZ!vN>$-aWOGXqX!3qzCIOzvA5PLC6GLIo|8 zQP^c)?NS29hPmk5WEP>cHV!6>u-2rR!tit#F6`_;%4{q^6){_CHGhvAs=1X8Fok+l zt&mk>{4ARXVvE-{^tCO?inl{)o}8(48az1o=+Y^r*AIe%0|{D_5_e>nUu`S%zR6|1 zu0$ov7c`pQEKr0sIIdm7hm{4K_s0V%M-_Mh;^A0*=$V9G1&lzvN9(98PEo=Zh$`Vj zXh?fZ;9$d!6sJRSjTkOhb7@jgSV^2MOgU^s2Z|w*e*@;4h?A8?;v8JaLPCoKP_1l- z=Jp0PYDf(d2Z`;O7mb6(_X_~z0O2yq?H`^c=h|8%gfywg#}wIyv&_uW{-e8e)YmGR zI0NNSDoJWa%0ztGzkwl>IYW*DesPRY?oH+ow^(>(47XUm^F`fAa0B~ja-ae$e>4-A z64lb_;|W0ppKI+ zxu2VLZzv4?Mr~mi?WlS-1L4a^5k+qb5#C)ktAYGUE1H?Vbg9qsRDHAvwJUN=w~AuT zUXYioFg2Dx-W)}w9VdFK#vpjoSc!WcvRZ_;TgHu;LSY*i7K_>Px{%C4-IL?6q?Qa_ zL7l=EEo|@X&$gX;fYP02qJF~LN9?E-OL2G(Fo4hW)G{`qnW zTIuc+-1VJvKgph0jAc(LzM);Pg$MPln?U|ek{_5nNJHfm-Y#ec+n#Yf_e>XfbLbN)eqHEDr0#?<;TskL5-0JGv|Ut{=$Xk8hlwbaMXdcI3GL zY-hykR{zX9liy$Z2F3!z346uu%9@-y6Gda`X2*ixlD_P@<}K?AoV?(%lM%* z(xNk=|A()443aGj)-~IDf3J+UA2p2lh6ei^pG*HL#SiThnIr5WZDXebI)F7X zGmP-3bH$i$+(IwqgbM7h%G5oJ@4{Z~qZ#Zs*k7eXJIqg;@0kAGV|b=F#hZs)2BYu1 zr8sj#Zd+Iu^G}|@-dR5S*U-;DqzkX3V0@q-k8&VHW?h0b0?tJ-Atqmg^J8iF7DP6k z)W{g?5~F*$5x?6W)3YKcrNu8%%(DglnzMx5rsU{#AD+WPpRBf``*<8F-x75D$$13U zcaNXYC0|;r&(F@!+E=%+;bFKwKAB$?6R%E_QG5Yn5xX#h+zeI-=mdXD5+D+lEuM`M ze+*G!zX^xbnA?~LnPI=D2`825Ax8rM()i*{G0gcV5MATV?<7mh+HDA7-f6nc@95st zzC_si${|&=$MUj@nLxl_HwEXb2PDH+V?vg zA^DJ%dn069O9TNK-jV}cQKh|$L4&Uh`?(z$}#d+{X zm&=KTJ$+KvLZv-1GaHJm{>v=zXW%NSDr8$0kSQx(DQ)6S?%sWSHUazXSEg_g3agt2@0nyD?A?B%9NYr(~CYX^&U#B4XwCg{%YMYo%e68HVJ7`9KR`mE*Wl7&5t71*R3F>*&hVIaZXaI;2a$?;{Ew{e3Hr1* zbf$&Fyhnrq7^hNC+0#%}n^U2{ma&eS)7cWH$bA@)m59rXlh96piJu@lcKl<>+!1#s zW#6L5Ov%lS(?d66-(n`A%UuiIqs|J|Ulq0RYq-m&RR0>wfA1?<34tI?MBI#a8lY{m z{F2m|A@=`DpZpwdIH#4)9$#H3zr4kn2OX!UE=r8FEUFAwq6VB?DJ8h59z$GXud$#+ zjneIq8uSi&rnG0IR8}UEn5OcZC?@-;$&Ry9hG{-1ta`8aAcOe1|82R7EH`$Qd3sf* zbrOk@G%H7R`j;hOosRVIP_2_-TuyB@rdj?(+k-qQwnhV3niH+CMl>ELX(;X3VzZVJ ztRais0C^L*lmaE(nmhvep+peCqr!#|F?iVagZcL>NKvMS_=*Yl%*OASDl3(mMOY9! z=_J$@nWpA-@><43m4olSQV8(PwhsO@+7#qs@0*1fDj70^UfQ(ORV0N?H{ceLX4<43 zEn)3CGoF&b{t2hbIz;Og+$+WiGf+x5mdWASEWIA*HQ9K9a?-Pf9f1gO6LanVTls)t z^f6_SD|>2Kx8mdQuiJwc_SmZOZP|wD7(_ti#0u=io|w~gq*Odv>@8JBblRCzMKK_4 zM-uO0Ud9>VD>J;zZzueo#+jbS7k#?W%`AF1@ZPI&q%}beZ|ThISf-ly)}HsCS~b^g zktgqOZ@~}1h&x50UQD~!xsW-$K~whDQNntLW=$oZDClUJeSr2$r3}94Wk1>co3beS zoY-7t{rGv|6T?5PNkY zj*XjF()ybvnVz5=BFnLO=+1*jG>E7F%&vm6up*QgyNcJJPD|pHoZ!H6?o3Eig0>-! zt^i-H@bJ;^!$6ZSH}@quF#RO)j>7A5kq4e+7gK=@g;POXcGV28Zv$jybL1J`g@wC# z_DW1ck}3+n@h2LFQhwVfaV@D+-kff4celZC0;0ef?pA#*PPd8Kk8sO1wza&BHQFblVU8P1=-qScHff^^fR zycH!hlHQs7iejITpc4UaBxzqTJ}Z#^lk{W(cr`qtW~Ap;HvuUf#MxgEG?tEU+B?G% znub0I(s@XvI(lva}$Z7<}Qg=rWd5n)}rX{nb+Aw;}?l9LZI-`N-*hts=c6XgjfJs ztp>-686v6ug{glEZ}K=jVG|N1WSWrU*&ue|4Q|O@;s0#L5P*U%Vx;)w7S0ZmLuvwA z@zs2Kut)n1K7qaywO#TbBR`Q~%mdr`V)D`|gN0!07C1!r3{+!PYf9*;h?;dE@#z(k z;o`g~<>P|Sy$ldHTUR3v=_X0Iw6F>3GllrFXVW?gU0q6|ocjd!glA)#f0G7i20ly>qxRljgfO2)RVpvmg#BSrN)GbGsrIb}9 z1t+r;Q>?MGLk#LI5*vR*C8?McB|=AoAjuDk&Pn`KQo z`!|mi{Cz@BGJ!TwMUUTkKXKNtS#OVNxfFI_Gfq3Kpw0`2AsJv9PZPq9x?~kNNR9BR zw#2jp%;FJNoOzW>tE#zskPICp>XSs?|B0E%DaJH)rtLA}$Y>?P+vEOvr#8=pylh zch;H3J`RE1{97O+1(1msdshZx$it^VfM$`-Gw>%NN`K|Tr$0}U`J?EBgR%bg=;et0 z_en)!x`~3so^V9-jffh3G*8Iy6sUq=uFq%=OkYvHaL~#3jHtr4sGM?&uY&U8N1G}QTMdqBM)#oLTLdKYOdOY%{5#Tgy$7QA! zWQmP!Wny$3YEm#Lt8TA^CUlTa{Cpp=x<{9W$A9fyKD0ApHfl__Dz4!HVVt(kseNzV z5Fb`|7Mo>YDTJ>g;7_MOpRi?kl>n(ydAf7~`Y6wBVEaxqK;l;}6x8(SD7}Tdhe2SR zncsdn&`eI}u}@^~_9(0^r!^wuKTKbs-MYjXy#-_#?F=@T*vUG@p4X+l^SgwF>TM}d zr2Ree{TP5x@ZtVcWd3++o|1`BCFK(ja-QP?zj6=ZOq)xf$CfSv{v;jCcNt4{r8f+m zz#dP|-~weHla%rsyYhB_&LHkwuj83RuCO0p;wyXsxW5o6{)zFAC~2%&NL? z=mA}szjHKsVSSnH#hM|C%;r0D$7)T`HQ1K5vZGOyUbgXjxD%4xbs$DAEz)-;iO?3& zXcyU*Z8zm?pP}w&9ot_5I;x#jIn^Joi5jBDOBP1)+p@G1U)pL6;SIO>Nhw?9St2UN zMedM(m(T6bNcPPD`%|9dvXAB&IS=W4?*7-tqldqALH=*UapL!4`2TM_{`W&pm*{?| z0DcsaTdGA%RN={Ikvaa&6p=Ux5ycM){F1OgOh(^Yk-T}a5zHH|=%Jk)S^vv9dY~`x zG+!=lsDjp!D}7o94RSQ-o_g#^CnBJlJ@?saH&+j0P+o=eKqrIApyR7ttQu*0 z1f;xPyH2--)F9uP2#Mw}OQhOFqXF#)W#BAxGP8?an<=JBiokg;21gKG_G8X!&Hv;7 zP9Vpzm#@;^-lf=6POs>UrGm-F>-! zm;3qp!Uw?VuXW~*Fw@LC)M%cvbe9!F(Oa^Y6~mb=8%$lg=?a0KcGtC$5y?`L5}*-j z7KcU8WT>2PpKx<58`m((l9^aYa3uP{PMb)nvu zgt;ia9=ZofxkrW7TfSrQf4(2juZRBgcE1m;WF{v1Fbm}zqsK^>sj=yN(x}v9#_{+C zR4r7abT2cS%Wz$RVt!wp;9U7FEW&>T>YAjpIm6ZSM4Q<{Gy+aN`Vb2_#Q5g@62uR_>II@eiHaay+JU$J=#>DY9jX*2A=&y8G%b zIY6gcJ@q)uWU^mSK$Q}?#Arq;HfChnkAOZ6^002J>fjPyPGz^D5p}o;h2VLNTI{HGg!obo3K!*I~a7)p-2Z3hCV_hnY?|6i`29b zoszLpkmch$mJeupLbt4_u-<3k;VivU+ww)a^ekoIRj4IW4S z{z%4_dfc&HAtm(o`d{CZ^AAIE5XCMvwQSlkzx3cLi?`4q8;iFTzuBAddTSWjfcZp* zn{@Am!pl&fv#k|kj86e$2%NK1G4kU=E~z9L^`@%2<%Dx%1TKk_hb-K>tq8A9bCDfW z@;Dc3KqLafkhN6414^46Hl8Tcv1+$q_sYjj%oHz)bsoGLEY1)ia5p=#eii(5AM|TW zA8=;pt?+U~>`|J(B85BKE0cB4n> zWrgZ)Rbu}^A=_oz65LfebZ(1xMjcj_g~eeoj74-Ex@v-q9`Q{J;M!mITVEfk6cn!u zn;Mj8C&3^8Kn%<`Di^~Y%Z$0pb`Q3TA}$TiOnRd`P1XM=>5)JN9tyf4O_z}-cN|i> zwpp9g`n%~CEa!;)nW@WUkF&<|wcWqfL35A}<`YRxV~$IpHnPQs2?+Fg3)wOHqqAA* zPv<6F6s)c^o%@YqS%P{tB%(Lxm`hsKv-Hb}MM3=U|HFgh8R-|-K(3m(eU$L@sg=uW zB$vAK`@>E`iM_rSo;Cr*?&wss@UXi19B9*0m3t3q^<)>L%4j(F85Ql$i^;{3UIP0c z*BFId*_mb>SC)d#(WM1%I}YiKoleKqQswkdhRt9%_dAnDaKM4IEJ|QK&BnQ@D;i-ame%MR5XbAfE0K1pcxt z{B5_&OhL2cx9@Sso@u2T56tE0KC`f4IXd_R3ymMZ%-!e^d}v`J?XC{nv1mAbaNJX| zXau+s`-`vAuf+&yi2bsd5%xdqyi&9o;h&fcO+W|XsKRFOD+pQw-p^pnwwYGu=hF7& z{cZj$O5I)4B1-dEuG*tU7wgYxNEhqAxH?p4Y1Naiu8Lt>FD%AxJ811`W5bveUp%*e z9H+S}!nLI;j$<*Dn~I*_H`zM^j;!rYf!Xf#X;UJW<0gic?y>NoFw}lBB6f#rl%t?k zm~}eCw{NR_%aosL*t$bmlf$u|U2hJ*_rTcTwgoi_N=wDhpimYnf5j!bj0lQ*Go`F& z6Wg+xRv55a(|?sCjOIshTEgM}2`dN-yV>)Wf$J58>lNVhjRagGZw?U9#2p!B5C3~Nc%S>p`H4PK z7vX@|Uo^*F4GXiFnMf4gwHB;Uk8X4TaLX4A>B&L?mw4&`XBnLCBrK2FYJLrA{*))0 z$*~X?2^Q0KS?Yp##T#ohH1B)y4P+rR7Ut^7(kCwS8QqgjP!aJ89dbv^XBbLhTO|=A z|3FNkH1{2Nh*j{p-58N=KA#6ZS}Ir&QWV0CU)a~{P%yhd-!ehF&~gkMh&Slo9gAT+ zM_&3ms;1Um8Uy0S|0r{{8xCB&Tg{@xotF!nU=YOpug~QlZRKR{DHGDuk(l{)d$1VD zj)3zgPeP%wb@6%$zYbD;Uhvy4(D|u{Q_R=fC+9z#sJ|I<$&j$|kkJiY?AY$ik9_|% z?Z;gOQG5I%{2{-*)Bk|Tia8n>TbrmjnK+8u*_cS%*;%>R|K|?urtIdgTM{&}Yn1;| zk`xq*Bn5HP5a`ANv`B$IKaqA4e-XC`sRn3Z{h!hN0=?x(kTP+fE1}-<3eL+QDFXN- z1JmcDt0|7lZN8sh^=$e;P*8;^33pN>?S7C0BqS)ow4{6ODm~%3018M6P^b~(Gos!k z2AYScAdQf36C)D`w&p}V89Lh1s88Dw@zd27Rv0iE7k#|U4jWDqoUP;-He5cd4V7Ql)4S+t>u9W;R-8#aee-Ct1{fPD+jv&zV(L&k z)!65@R->DB?K6Aml57?psj5r;%w9Vc3?zzGs&kTA>J9CmtMp^Wm#1a@cCG!L46h-j z8ZUL4#HSfW;2DHyGD|cXHNARk*{ql-J2W`9DMxzI0V*($9{tr|O3c;^)V4jwp^RvW z2wzIi`B8cYISb;V5lK}@xtm3NB;88)Kn}2fCH(WRH1l@3XaO7{R*Lc7{ZN1m+#&diI7_qzE z?BS+v<)xVMwt{IJ4yS2Q4(77II<>kqm$Jc3yWL42^gG6^Idg+y3)q$-(m2>E49-fV zyvsCzJ5EM4hyz1r#cOh5vgrzNGCBS}(Bupe`v6z{e z)cP*a8VCbRuhPp%BUwIRvj-$`3vrbp;V3wmAUt{?F z0OO?Mw`AS?y@>w%(pBO=0lohnxFWx`>Hs}V$j{XI2?}BtlvIl7!ZMZukDF7 z^6Rq2H*36KHxJ1xWm5uTy@%7;N0+|<>Up>MmxKhb;WbH1+=S94nOS-qN(IKDIw-yr zi`Ll^h%+%k`Yw?o3Z|ObJWtfO|AvPOc96m5AIw;4;USG|6jQKr#QP}+BLy*5%pnG2 zyN@VMHkD`(66oJ!GvsiA`UP;0kTmUST4|P>jTRfbf&Wii8~a`wMwVZoJ@waA{(t(V zwoc9l*4F>YUM8!aE1{?%{P4IM=;NUF|8YkmG0^Y_jTJtKClDV3D3~P7NSm7BO^r7& zWn!YrNc-ryEvhN$$!P%l$Y_P$s8E>cdAe3=@!Igo^0diL6`y}enr`+mQD;RC?w zb8}gXT!aC`%rdxx2_!`Qps&&w4i0F95>;6;NQ-ys;?j#Gt~HXzG^6j=Pv{3l1x{0( z4~&GNUEbH=9_^f@%o&BADqxb54EAq=8rKA~4~A!iDp9%eFHeA1L!Bb8Lz#kF(p#)X zn`CglEJ(+tr=h4bIIHlLkxP>exGw~{Oe3@L^zA)|Vx~2yNuPKtF^cV6X^5lw8hU*b zK-w6x4l&YWVB%0SmN{O|!`Sh6H45!7}oYPOc+a#a|n3f%G@eO)N>W!C|!FNXV3taFdpEK*A1TFGcRK zV$>xN%??ii7jx5D69O>W6O`$M)iQU7o!TPG*+>v6{TWI@p)Yg$;8+WyE9DVBMB=vnONSQ6k1v z;u&C4wZ_C`J-M0MV&MpOHuVWbq)2LZGR0&@A!4fZwTM^i;GaN?xA%0)q*g(F0PIB( zwGrCC#}vtILC_irDXI5{vuVO-(`&lf2Q4MvmXuU8G0+oVvzZp0Y)zf}Co0D+mUEZz zgwR+5y!d(V>s1} zji+mrd_6KG;$@Le2Ic&am6O+Rk1+QS?urB4$FQNyg2%9t%!*S5Ts{8j*&(H1+W;0~ z$frd%jJjlV;>bXD7!a-&!n52H^6Yp}2h3&v=}xyi>EXXZDtOIq@@&ljEJG{D`7Bjr zaibxip6B6Mf3t#-*Tn7p z96yx1Qv-&r3)4vg`)V~f8>>1_?E4&$bR~uR;$Nz=@U(-vyap|Jx zZ;6Ed+b#GXN+gN@ICTHx{=c@J|97TIPWs(_kjEIwZFHfc!rl8Ep-ZALBEZEr3^R-( z7ER1YXOgZ)&_=`WeHfWsWyzzF&a;AwTqzg~m1lOEJ0Su=C2<{pjK;{d#;E zr2~LgXN?ol2ua5Y*1)`(be0tpiFpKbRG+IK(`N?mIgdd9&e6vxzqxzaa`e7zKa3D_ zHi+c1`|720|dn(z4Qos^e7sn(PU%NYLv$&!|4kEse%DK;YAD06@XO3!EpKpz!^*?(?-Ip zC_Zlb(-_as+-D?0Ag9`|4?)bN)5o(J=&udAY|YgV(YuK9k=E>0z`$dSaL(wmxd!1f zME&3wwv@#{dgeMlZ4}GL!I`VZxtdQY$lmauCN_|mGXqEEj@i~du$|>5UvLjsbq!{; z@jEf;21iC1jFEmIPE^4gykHQzCMLj=2Ek4&FvlpqTlS(0YT%*W<>XgH$4ww`D`aihBGkPM(&EG};Cl&wzg8!jL z`rkqPzvH(0Kd{2n=?Bt8aAU&0IyiA+V-qnXVId^qG!SWZ7%_f&i!D{R#7Jo$%tICxY%j)ebORE>3H_c|to}c#HX;HAC?~B;2mmQrMp2;8T zmzde!k7BYg^Z1r|DUvSD3@{6S<1kndb%Qt%GA# z+sB2&F5L`R&fLRdAlpU_pVsJsYDEz{^ zKGaAz#%W+MPGT+D$+xowMY0=ipM)0p?zym&Aoi)qL(pO_weO(k?s|ELHl^W zviJiFUXRL&?`;3_;mvc02A@sbsW9}#{anvGafZ#ST;}za?XS3}ZG3B4m(SW{>w}Fh z)T5Yi*``Tstmi9SHXmuWSND@cj}qtY!`tuD29Dpu+-D3$h<5FY>jE>YJvqBmhw?oll`x7Ono(}R~P zle_eBwYy0Rr7kmf_SEt_gn4)AO-r`}^Z5Y%Rm8)K-?X>rvDL+QT?#)QwDsQ2c$tc* z&#hbgkL6}GnBDH;+lREM6MGIskRa@r>5Iq(ll2IepuhW86w@14=E{6$cz*cBDQ)CT>}v-DLM-v8)xaPBnmGBKM63RgDGqh!<*j90tSE4|G^+r@#-7g2 zs8KE8eZPZhQuN>wBU%8CmkE9LH1%O;-*ty0&K~01>F3XB>6sAm*m3535)9T&Fz}A4 zwGjZYVea@Fesd=Rv?ROE#q=}yfvQEP8*4zoEw4@^Qvw54utUfaR1T6gLmq?c9sON> z>Np6|0hdP_VURy81;`8{ZYS)EpU9-3;huFq)N3r{yP1ZBCHH7=b?Ig6OFK~%!GwtQ z3`RLKe8O&%^V`x=J4%^Oqg4ZN9rW`UQN^rslcr_Utzd-@u-Sm{rphS-y}{k41)Y4E zfzu}IC=J0JmRCV6a3E38nWl1G495grsDDc^H0Fn%^E0FZ=CSHB4iG<6jW1dY`2gUr zF>nB!y@2%rouAUe9m0VQIg$KtA~k^(f{C*Af_tOl=>vz>$>7qh+fPrSD0YVUnTt)? z;@1E0a*#AT{?oUs#bol@SPm0U5g<`AEF^=b-~&4Er)MsNnPsLb^;fL2kwp|$dwiE3 zNc5VDOQ%Q8j*d5vY##)PGXx51s8`0}2_X9u&r(k?s7|AgtW0LYbtlh!KJ;C9QZuz< zq>??uxAI1YP|JpN$+{X=97Cdu^mkwlB={`aUp+Uyu1P139=t%pSVKo7ZGi_v(0z>l zHLGxV%0w&#xvev)KCQ{7GC$nc3H?1VOsYGgjTK;Px(;o0`lerxB<+EJX9G9f8b+)VJdm(Ia)xjD&5ZL45Np?9 zB%oU;z05XN7zt{Q!#R~gcV^5~Y^gn+Lbad7C{UDX2Nznj8e{)TLH|zEc|{a#idm@z z6(zon+{a>FopmQsCXIs*4-dLGgTc)iOhO3r=l?imNUR-pWl!ktO0r_a0Nqo@bu8MzyjSq9zkqPe*`Sxz75rZ zr9X%(=PVqCRB=zfX+_u&*k4#s1k4OV11YgkCrlr6V;vz<{99HKC@qQ+H8xv5)sc63 z69;U4O&{fb5(fN``jJH#3=GHsV56@{d@7`VhA$K^;GU+R-V%%cnmjYs?>c5^6Ugv} zn<}L&i;2`zzW@(kxf$$gVH@7nh}2%G%ciQ_B?r{13?Q@=Q+6msQGtnyY%Gkjeor?g z7F*tMqLdhcq+LCCo^D;CtOACCBhXgK-M&w{*dcUdmtv@XFTofmmpcWKtCn^`#?oZC zUOm52 z7sK$hR|Vh6y&pfIUK&!`8HH*>12$nWA)Ynp+XwOj=jNLD z{QA4gezbe>wiP?`jJO;c&EId;=2u80s_r97;TX!6@*(<%WL+^bmxheMB3pKx0OpH^ zPs}knV+jpJ4TaD@r^V`mTsjf`7!z^H}eHQ#Rp z72(>Dm#QO!ZYR*O@yHic`3*T^t7jc=d`Jz6Lk@Y-bL%cOp_~=#xzIJl?`{Qu;$uC~NkePE+7wSW_FM`&V{gFN zl;lq@;FtAsl!h;tnOvj z#gYx!q$5MdZ0Jxjy=t*q)HFeeyI-vgaGdh1QNhqGRy8qS)|6S0QK7Gj9R?Co{Knh> za>xkQZ0}bBx!9@EUxRBYGm25^G}&j-`0VWX04E|J!kJ8^WoZ(jbhU_twFwWIH32fv zi=pg~(b#ajW=`)Vikwwe39lpML?|sY$?*6*kYBxku_<=#$gfTqQ_F!9F0=OkHnzBo zEwR!H_h|MNjuG$Tj6zaaouO}HYWCF8vN4C%EX-%Iu%ho;q$G#ErnafhXR*4J2Rp5* zhsi0;wlSwE*inVFO>{(8?N~82zijpt+9Y_-^>xnE%T*zk9gi|j7b@s<5{|qEquUD( zS;-%RySZOCOEh*>!kvbsQ265* z>X8*_Wy&~FB@aDHz%glyiAujXq-|2kDUjFTn9Rafsl+XNyFP%PG|l&ZGWBcEXxy=9 zeDn2PIoVuL$gX0RgVK1O$x3%pOzS7x^U5Pi;mtT)%cY;&e&M7GLM}zP+IPbqLt=^5 z7qLfri8myf;~2psc@^cA6mG&{C%e_(M$$!wC^5p^T1QzrS%I?(U{qcd+oJJkQxe10 zON{Q*?iz%F4MbEsoEc+x3E?&2wVR^v3|Q0lDaMvgS7mNjI{2w! z9|~=!83T%GW*iaChSS!`Xd^beFp9N4%K+k*j#jFumk}U?=WKL_kJAltxnxp~+lZzT zp@&&kSPTg3oSGos`rVBhK0|4NdHM_hnKuw1#0JV{gi_dKDJLB+ix~~HpU9%jD)@YY zOK)L7kgbLyN2%Dx#fuY}8swh4ACk7%BpP-n5(RhDq{gEHP*Fo4IviX{C49|B5h~SC zFr`=0)=h2^F5UpCAgt?R5u{6VvpUf#*nC zCQ`$!|C;L2lpjlG?(>T$(_$O3_YNNbPT~(?!j3aD8k=yu^ogw4bkjvgF|3BOq(hB& zG;^cPXmcUP$ox8zElCJ-zMbK9q^8{rri#8Cek5Ydr0YT-KTh@J z6^AcB9ejew8BY5kzZUZX(7Po==eW<(;uV~E7(BY5c0^xr`cuRwn)47bN?zOb!0?cw z#v}R$z66&m#+AHfo@(^V2#S~bhoUkkTArg+6w>JzZ52r96^({1W!?>4$h0l|-jDfj z>7(<+%67#(A|4hZ3>Y;hd&S?}F;`Vtqz|pK&B>NJ=Faci;gkf-+GmfQR8^zo_vul2 zB!)kfu4Dq_g)8TBBo52*sB6F`qa&JCR=_A$QWgX_K}fZm{Cb2#1q`^S3+WaS>sS#@ z-4k*G=#?z6d_e7JJ+Z8^(t0tNdL{K5F;2nfQbXgld}a(X)Gr;WojOy`^?es~AClT$ z5^lD{WJek0!p-QEH5E7n6DKQ0%_ZBZ=|jfV_MM{VmL8y-Wd|>OmeemP=C@xI@@M~1 zW2S*im@Rc=O>V886_UJ@oh1!2H$Ku&U*Hh_oxd{32)vf1$cRiepv28ricM;}#p!+k zaK{z1I=9Y%3m4|Pj*BD*Fn5Vh?O@oD^1UcjyeNh0fbhh~V6xb#4njlGW8OehUe!MnoR(wn#nsoyL1m!Rov)Nv4~&JEVl7L z#^qYdTpNI#u`N0UbVMiDmD>g2VQcG3>4D6gErgddZnSQTs){BExxRJRB?bIxTdZa z;!S8FHJPPiIDQ*FAUiWSYnjILFjDvxvSC zk z=j4Kx@Pg~&2Z?cmMDa;)#xVeorJrxDBqy{+`kG+ZPQqC@#ku-c3ucU+69$#q_*se` z-H#PFW^>-C0>++|6r=<$Z8)ZFaK=ZjwsNYXqRpl9G|yme@Eld5B-*I69Nx_TResHi z!5nm+>6zaJYQO#%D{~o-oOJ;q`fa5}l!8G*U-E$OM&7@dqciBCWtd}|SrDXz$TB($&m*=Epuolu2k`KUwO7maP3P0ok zmF57lSh0Ba@&sO1iZ5^+3s8{B8t|M;Pg&O+{tZJCiLWd6H@{b~9{CLF9s3Kn zt5)Rs9ejne?o{%f>B$Dl%X7fd~KY)I|(pxUeHj;gNsK6;ZR>`ciu;GxvhDUt!+31Knss2U(%ts8K z18)8;<2ax9RG?!|Lwdt^i5L^&O788roKmVAB)=EdK~HqR2Q=)H_VW}xY=95MP_Ov< zPEz3%DRK}+(aUBwsr83H8>`H^v~|A_t}0vPmRwKPt1{|qOY|PZu}j9+{ZhF&-H_TB zU9xWLpNTc`enI|)h9jQeqf5RfGLFk_vfX`40iMpd%KZF!lKbZTdBw$<^G6nuS+$fT zrbK)xo&;buPJcpOZ=x>n+bRXVFDs(23Xr=rDE&!)pVXZ;;A07NXGl_0m`{Z)DQIu$ zFDvY4xu-ifTe_$|n2B83eI;KUg6pVbw+N!nyLj~wnRi{4mNy{WDV)G1!6$y=+x6U{ z%4_9=Q^L!x_gAYp?J3+u5hA5cO8aHeI=6AC8^S{mzhqCBvBLYEutUC(X0>hKg|AvN zvkmJCQNA45_KjW{aEcyrBppcO6G0zTy%v1&@~+2!n?kA9?>0>AjFN|JdCnHQ8$hEU zw#mwGifHppLP?89LMb(Y3Li9iCPx7W%ek}2FgD2YSzjsR4Xj<=zN{Yo@7s7(k%mP4 znT2p&4EQ@q_chd-E z78uvD*C@oba`U3W2Iw`M#`5C8jOHv8^Li<|j^SI>>>`77Dp71Vtz=J?4Zck4SdRbd zfF}C_>Y(#)r@y!Q0`tMlG#b9>5`fAI$B&tWJfbGlYW$J4V+-s=HH!`+;1XeL@USdx zR0$G&&XBf9lQtkH5)p=U!8J!1{oc4E!N-~Abxl6E;;=3-hMYZ+44?u}zabmCE)yB?*_w91m$n1Yskp&@ z;kxeJX-#ioX^{elyLu~gzx|_KxLpX62MF%Axq3$!Z_P`pBWR?zP8OI`PV~6Aa0Oi0 zv_Ot1m&plf-ZF{e(z(Ms3*S5q$e|j;gOwGrmWsCHfLi(h8y?gc$(2H{884C1FvHQQ12tX=qFUsK~zM!W=K>;zaRsu4Xmcc@8nSs!vK+{ z?}bq}-m&p5jRSam67n>yG9ez=I^|J1O;Np8s=P~9MXYLxD+cFQK7PhG=bkjo{Naae zjp3NWWrlFWDb3Z5D07Q|WjZ=wOQ=aKA%en=O@hL$QCKpIXNZE=InFk|Fhq-&H!6&X z*MVy8=hL7Aw&pQjHrFf27C%3B<>FX{@fOLNhUoxL4*@nY}&M3G*T-p67a zo}~_&yGOB)#vbU|Q3FA8S^X)c-yBlmN(_%}`7Ha3uWFe?>9f=3hlO{^gv~$p`v?vk z_P*r43|(S{%ihs;)YH|jAMpP=-Ms7Ne75_YZZiL3CHVjSU`X1|?Ehh&gA=Xn7W7d@ zf8bM9Y>lG!`PWFDDA9G;x*{1Eh^55u66*9D+-4^dYZ{xXP@?sQLVrY%(azM;C^4FuN7CQ%$!3sr1JL=!Be& zuOZL^bLp$Qo2rL=WDzQIls%s!Go z{s}Q0b#+#8bKga|01t%^9Z=wEsevvXM_{$dCR97ed3@1kX)mtSS!JN^rtqKOj}p~> zfpCI@DX*DqcB6ZnBcl~}sGO~1s$AtfkX6fy3N8*ebvZc*KBW;dA=)?#BE&}-or74i zZUt5;{FBPnkZD8YUXDsx&2LvSziAlec3oc>&Lf1Doc3g?H9{OO_$M4B0qTat0UsWP zTlxUeQ3B;oJ%en4n?zQB6*Fb#wH7`$SQN5GI|=DnJKiYm{?-?#-H;#sIjz7kQ4&VW zN9d1(1$_W~S=<%qDD!mwRytas=eqX^iW}YSx3;wJ#)Xp_`Qk1DFiXac$-3;jQbCif zLA-T_s~5yP@Q@W>pXKl^gipQ>gp@HlBB>WDVpW199;V%?N1`U$ovLE;NI2?|_q2~5 zlg>xT9NADWkv5-*FjS~nP^7$k!N2z?dr!)&l0+4xDK7=-6Rkd$+_^`{bVx!5LgC#N z-dv-k@OlYCEvBfcr1*RsNwcV?QT0bm(q-IyJJ$hm2~mq{6zIn!D20k5)fe(+iM6DJ ze-w_*F|c%@)HREgpRrl@W5;_J5vB4c?UW8~%o0)(A4`%-yNk1(H z5CGuzH(uHQ`&j+IRmTOKoJ?#Ct$+1grR|IitpDGt!~ZdqSJ?cOtw-R=EQ+q4UvclH zdX=xlK-fhQKoKCPBoFAZ*(~11O6-tXo>i0w!T$u{lg!#itEUX3V{$S*naW!C@%rll zS{L(1t%xz(*B`{1NL!*aMc<~fE=g;gXi&Gb$HpD!P)8?JzfN;4F&wv(5HH<=c>>)n z({271)xREH89=C(5YKL{mmJJ_d>qHz;;gTvTlgM*vz9@YTTYZ#%_2A zS0G-t9oMQEpvfv(UjfQ8T$vAHi)zOj3>D*{xSRiu3acc=7cvLyD?_ZObdu$5@b*!y zaZ#u?7uF}SrHVQa=sTOhGW{6WUlq#RhPPm^GsRH#qlX8{Kq-i~98l;eq>KdCnWyKl zUu&UWBqu#Tt9jQ97U4}3)&(p2-eCLznXMEm!>i^EMpeVzPg%p;?@O;dJBQQY(vV;d z3v+-3oTPC!2LTUAx^S2t{v;S_h(EZ^0_dS5g^F*m{TEIy^Qal~%mu3h7*o`jWOH}i ztv8M)3X3a*+ry_KkYXYE4dB0?M|t}#Tp+(}6CQ zBbq;xhoHj}b@j-@koDB#XcCY~>_x&Y;i%MH|3tF^X2h{36UCVfQ-;oEA+4ZkJ`^Qi zQf^8}6eFO$Z+Dj-F1wkG##tTx>FjR2oOXFmbKFj6K3+=kePQ<4d7%z5R5cOB;zO6| zm9^m#U4lcA;7t&*=q|a-!`!)}SgYXT#i8hnxtx@kaoBF$QAS-hT7N5kH^l zB^i+})V>L;9_0Qqf-dyF%ky8Mp-dp#%!Nls3vCt}q3QLM3M-(Zs1k}1bqQ9PVU)U` ztE=?;^6=x}_VD%N@${>qhpkU*)AuUBu_cqYiY&@;O$HV*z@~#Tzh?#=CK`=KwBv+o zh%zu%0xPKYtyC)DaQ zpDW}*86g%>BH3IcWMq`g$j()0kWE(qkIL8A&A0mf&+BzxpKF}=`#jG% z&*wa!&pGFLs5_b#QTZE4Bp+})qzyPQ7B4Z7Y*&?0PSX&|FIR;WBP1|coF9ZeP*$9w z!6aJ_3%Sh=HY3FAt8V144|yfu}IAyYHr1OYKIZ51F>_uY^%N#!k~eU53at-_E-Gh?ahmM5y* z+BTIbeH;%v1}Cjo{8d%UeSMWg(nphxEU`sL< zQR~LrTq>Da(FqSP2%&^1ZL#DTo5Sbl9;&57tQ-@U&I#lj)aNSkcfEJwQD!33?anVU z?pw2q7WtMvfji493`rSFnyp7{w87cW`ak=UEYlk5PCB1K6UDVKXyozOChH4yHh~Q< zv>yvKw6WLfi!PZUx60JZcTNM7jo{ww9b8Q+S7C3WA5&llSwdwh$=Q(*(f3ofqcz=nwOmOy z(J!K=*wNoRU*${{Mbwapi9pTB(&VVKefqd-qrUb9*Eyr2E@oZ9Cgf}Mc;QP<0D)R4 zz=!*^VIG4T*7Xl=sJxrWv9hW^eJ%qYp5(d0?E6LZzJ}=7E+1{?GQA;z+!^VBD81}O z0kJ^dKy&WMw+1+aGVYY-v@i28@Gm+sX5=@U%F=Z?W)oar}2~Rc&F|+3A)n-U2GF10+QdxDb^iA@7eL$c7yhBtL z>lABrh^qy9XZ${E1}Ss5!N4;ig0-pUh6@|RPCHOWvgG{|l}2enRgJftsN%D|ck0YO zuAQd2aMPSyGuJ~jm)aY=+p~mGudw4erwE%P^)5f<*$$2C-4^I=e8-}7##ZQ!8!Tep z+Z_!}CAI~sry$|XK$ktXaxP*x<_ijCPp`2=6sNLZU<@9Sz-rz7^BCE9yh0jV4(I!Z zxmA4d;>B-!vD}Xp*&*N%`b^e&R;D97WS}{~{O-EtXeZNfdf51tw!WR6Noo4hjHPv5 z?heYYRSBPjMc}tFEU^|U8a1CxxK%)WTcn9P%`wR^I$QSeMn6=w>Z9OoVvcrl`zYlZ z2y`mAu0bV(Scc>G_EmIo_4 zm*~h`mxYZC&+U>C5G1FZH5L^U>Cq-9UDRQa35jz&NBj*0{uJKfZs5=Fn@&)Xh6aX(H3w9m9BGLePqVotxTeSPh5-mc7$# z-80t6yB0$Nx<54ohdO*QL7m_(&+#*=eoNiYDB4rE4Cag@qfyZS};Fx;Vf1;oync2k z9v#-w?d6R& zOI`CCS_d=tf3|?g3Z}b6-_Rdg3y~enQhmgkni0Cvf9m6%Ft8r;NC5|b%t&?lkl*4{ z8Ui^;Ds^gq6ti(1xB7y_$zA!i-M~#!!tl$ErTR>P~>T=Yky)8(uvPbvLmB=UfoD zrfl}8<1OQrm?8#j1!?s*T>AoectQl&m!o&*^JcIW`_&bk3tN}k^0rjl=HL$z*uIYt z?7l?^Dqr?q1210Sp$xoAy!&{2^{^Anl460 zI&7urrc&|Y{rjv04VOl{y7c82N6xzg5ueYmQ(q(zC3w_C#x*~%yf5j7MI{W`tsoxzA*PrmK)cTskU| zf2C}Bq$>S$-1JgIh0aW@LxI|-8(OGuD#^M01ghh}&#ObO>tZgSw_LW`zdf&IN$YO# z)|X_9m#JwLW5pErZB3ScggKcNzxA9(hyKkK9I#pR&79&*+SV_eu={00{HF=Bb+AEe znaSof+r1jZ!EL5XgqXWkckaFSSyEk}o!%p8XsD}O>borZ6x%X2b&q!s&1-O(>`kZ$ zB2l^5Cx9xQx9)PXN1xPM)@+LxACH_iZ8zGc(>wnFS_O|@hKsxpMjXOzLEa7OvSlM&&G9ioQw9~RsD4F zK7Q+_&|Q6{eZ^8Rx@pKL`le6kH+(fLc{=V&{b%I5=n}VHV4)X_2Y!pYxgC8wU)yP! zPF3t$?(jsC>Ge=&{kmPGUEETpaw(QTAl)m#{qR3_aq9!wK%6XHfV4C>Y^>Z|%ns7j z{Ja?^IA{+@;kR#IjHxkar%3$eJT4?xNBKUVmoO z`A8Zo-{~_;vcikZ(p}EZzU4kO6WPqkMyE{VvS?;44Z@lj zz^fKX9UL!8Wc(9VgI?P4*zpis8dzl};I>yr1>dtXU=FTAlx}Eht4-*7RACL^AflGh zyZb1hTf(~CkMo%#Q%NMgM9tE2D+)joqbtHYA89Ql1nqVTt+MxZ^*FRd&n5YlIi!8m z>$Ysd!l{+C)y;Wa(ZV-=<+NZKV;v4mt}v2m>`v$-$3b;GsLxf= zd~f(rmfpl``{0aVwN7y!>eGyJFP`L+TxHjHTOS{K^$L2`@6(Rli`{EFwpH@R%eZ6g zwf7rc43Yk!=k;{ z-Rn%~B3amGr}}SxfE$vS8FIPL=Qt57$|R#sSoFgdNUT?fYOYjPl%ZBFpi=jq=DWby7Zxm@y;B<89!9= zbgEH*Uy)~iq5kJLX$+ps$kV`#6jW#|9BGz^`ivNeid(wVbk4jl)VBpW&~;eXNi{#` zwx?{DXR~*sqQcFhY0XCfQ4-*2aN1BGX>$_swtKEqnd>j6vcZ!#0)pXRi?<{!P?tGw z2x_`RD$W)qD{?z}VDPt?+)8*rqLWFIPQ(9-VbBdf{7ff?w9CZ{sIi_gnuC$I0(+P8 zms9XB%}VQ>>pve##}jog6+cD?v~n4Pa9Vmc zg#K$|+`adO=B7`uj35Y}6EZ z{dY`x@w8;R-7zrsr1O_~Jvl*|o-x%jF=Rr1C}GXP^|IYN`1sqmG-oI@R#%X66c#5W z$$tQB)sqwiVm;Y^`Dw3mo|firP{*HsOQJre5%Dm^H@we0FN88VWJ0dja?_U38z73f zrCV!b3qNP0kM#%9T!W5`ynGcg%BL28FW1J-J1_S`BJGCaReQ!am(2%qZ3lLgzq|ns z!!fF@`0=*z)J2BwZ*hO|Yu^cI_nF$9l-Pb3jE7=P8gZ#!xiuZ7-cSa`gb`6mxGTgg z-DLdID?M!Z%+hHB#{?&0$GFRpf+_}q<_wbzX6K?w;%6szz1RbySDSr2r^h_qi$khs zXdZ9A0!_Bf)TR2-^-K~q`FQ!#1x(U4VbV%AA@Ei{%cA(EwC{XfjRi?`&9rav5;Q5% zO1`Rn@OA_ZB@N*mC#)?d3P!}Eh;=NgpIKsy{(yr`hv=aouwt@r&P&}Z3DNWo9ro30 zX52~(aTV$*HHlgB66-4GQru!_AZ|)V*I5X=WG)`N@U&D>e@@C#V@JwEL*L`7#$yes z62C^5%Qniaow2$3HrAc7U{qzpb&FA*xLI1JSWR@`RF=JCcvTI)%dH7;sWInt9JLu# z|Ao|Q?K)cDg_JKsym=joo5gR80wtv01N`um1nQ@Ms0Y*bVzxL34} zo?gizp?`=Y{*W>^Hy2%Jl)y?A+&7s1UVHFixuIy~sawXjcDCL`129cK7|ZQS0u;A} zTJC#WNmqkIrnHpAhHVcM(U^vJA~dl@jf_bs*3?i+=&vuC?Aiy_pcB~=1syDni4 zw+FLuz>F773u#$;NUQ9WDtUPY@+rA3WBhQdKFKOyzkA(URa7;4tW>3jQIfi8v0h3g zJC_HVDXS#>DWb|&se7FHnr=q&l#xg9o02}}u=b-R>@sw={Z zHF*?t2FmhqZ=|qa>x=A!*$S+0T zhO*D*M?NTf-eX`eO)9TIQu{7Dm77Acnj4b1jI9@c*ZL8wL%8kLEhd$KM8=Y!fbN@9 zC7B5#y>JM1n5M)!&im==EgHs2j+xCZG~+~QWCi?s!QyFo2kqx{%jE2n3^N*Ayz6Lp zhg5g^3# z+5FoJ@$u@9WJgPKpUWEd4}4AK9TJKU8W%ms!d0p%OIOX+bY+55zl!vIaz$XFI9Ep+ z;bL_}7PDI2Y`Ng*XY(65 zh0%`@Lve%fc;)N4_g12bNrt6gH=N#OHtxO`$lpWlw=Z6MF+E@;>GkZ#lAZTn`aHwf z&I1|aV#b_VHMIgBN*RzU9i@Z@m}0i>o?({&%fpEfaOpFeaJ7V37;m0?kzd}}Lk@9$ zL}8TEo7WZAcRi%zFZxkr6<0k#X-;lTD`Oc~cDb@olwgWCewvk{GJ}hCXbF!AdiLpd z|Cck$ZTKI?Ack{34Lva7+k=H8K2HTZiurox6F+>dy+@R9T^awxj590D$|kXUg+Ygc z(f)jlRwN(4z$#%PnOVc;#Fv{nAi{#UcXPNcmP#5O{zh_*`=q^JCeia{sN4zHjk2*y zqUVh{Ya{j>SPmP^i#Qfcq_MTqo8g52Fi^F zKBc$$HVI!xFx*4Y9l+nt)$AoZORD}%5I10oI3kx`-N30QueiwIw#0VV2E*Fb-nKW% z=+r^hos`Y-7~{cA1FVbK$_=~*z53+Q8KGjg;>ztg((H12%QTf4OYU8y)C}h5yo#$% z&Q$`vMM*g?ZcatAn2j!hFv8KuN(dw)T*}sF#THDHxo8xC^?vJ zc`U6bVo~hOr6I!8*GTZ<^D~;unKjK=!IR|GB4E>Mcvt*2GK);93jIDd<(nNjHO z4Hi@2^%Uyx=^Z~5eZ!5rO5%4H|eFoNjD#+Kcu%_57zZb4Z@Ak#X6txD^{U3wBl^r+W- zLorkK;uc;NgTj7dGxHQS+@T*T>Q*j4^Ll$ejQqWrwcHyG9y%Mk%m8nBVG5hvSaYm5 zJN^#-Q46kZG)@T8n2^QCjxIwxUVi%s>EY`E?#@_(A~njFrTiDq;8v|W-1jT|ROlNI zU$h|YoD4PVTE^&NC6_m{EAFBVqsM`P*`-AcDGWQygURzM32Xeq2xng~XQsYeTZ5v$ zQLaa2M_Iplw}4eL6fLPu`6`PYcVMysO>`{8CB~glD=TX7?JZcHfHNmykBM?QD)#D) zGp>R*<^D?WhFQKRc^}22l6F=D2RPrxaX2ZF!b1X0XF*d4%=!sbNcS1q2WOUE(7e4$ z^L8f;F)__d3>&KQFE8%$I4h^y5FYBfB&fWzn71_OSrPe-DHV{O#Q;GP z+Tw!J?eVjX19RKH?*hKQWQt8r7B#lYX8xoSHFGCW-*DSQ4EM4M3Mw%gkSYNK18@(e zfzMF}WWaCyS@1y%-~Xg0ry~tkQkUmKuI5lGAua{{vn22V!2T()AU5FpKh@Nv)s^Js zv~@VuUG;=CnLmQR{PeUBQf2;lAV!vG>^Z0N zL88rrjL-*J!43;7C=w9xhcw`yjRKq7o4L9=0SmR9PA-nX12@#h(iIu-0N_xm2OV)( zU_raT0y>$wm^oMi2|U3N;OhF9uy}`<-xVka#DV*l{O0yHzi9vUxa1Qtpi$buR*8cU zd4~lS1pT$L^!0=6qUKOpM+XPsy{f7W#1bjrEwaeN!Ik9(zySIT^pEHvHgJUneFN4) zk=k|$55(g8slmS|@+*4fr2urd3LwjIIZA**g+%l(SZNn4HwQ}y6o`vw>2&mR1X+&q zDa1Af0B;4rAMZMOlHbAqK|R_xuwJ7ANARtFE({-P2o{tJJR<>2KVp)ZK-M;)ejx zd*E~Mka<{OL7%CAhk4n|1qg?97-I!l0rOinjVi#arbgg4bi5;nY5oFL`UWtPk5&L#grSxv zE3!}=1px!ZTLT90aYc^s`~{VojjJml&<`@e41dFP+XU6D0AOkbn2rlI3>^LcqauG& zc$m3Z{!u8LvUrm^fT{qX5yD9{?r(CCiUdck%!T`KIZd2oQJz1joB&M(Teg_>;yS<2-5>BWfSPpG`Rt{!j6>kqMAvl^zk0JUEfy$HVJMkxP-GkwZuxL62me2#pj_5*ZIU zP~#C^OZLfl$HO)v;~~c&JHivn|1I9H5y_CDkt0JLLGKm(4*KLVhJ2jh2#vJuM6`b& zE==-lvME^Oj022xF&IV*? '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/examples/powertools-examples-core/kotlin/gradlew.bat b/examples/powertools-examples-core/kotlin/gradlew.bat new file mode 100644 index 000000000..6689b85be --- /dev/null +++ b/examples/powertools-examples-core/kotlin/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/examples/powertools-examples-core/kotlin/src/main/kotlin/helloworld/App.kt b/examples/powertools-examples-core/kotlin/src/main/kotlin/helloworld/App.kt new file mode 100644 index 000000000..ed4cf267a --- /dev/null +++ b/examples/powertools-examples-core/kotlin/src/main/kotlin/helloworld/App.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package helloworld + +import com.amazonaws.services.lambda.runtime.Context +import com.amazonaws.services.lambda.runtime.RequestHandler +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent +import com.amazonaws.xray.entities.Subsegment +import org.apache.logging.log4j.LogManager +import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger +import software.amazon.cloudwatchlogs.emf.model.DimensionSet +import software.amazon.cloudwatchlogs.emf.model.Unit +import software.amazon.lambda.powertools.logging.Logging +import software.amazon.lambda.powertools.logging.LoggingUtils +import software.amazon.lambda.powertools.metrics.Metrics +import software.amazon.lambda.powertools.metrics.MetricsUtils +import software.amazon.lambda.powertools.tracing.CaptureMode +import software.amazon.lambda.powertools.tracing.Tracing +import software.amazon.lambda.powertools.tracing.TracingUtils +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStreamReader +import java.net.URL +import java.util.stream.Collectors + +/** + * Handler for requests to Lambda function. + */ + +class App : RequestHandler { + @Logging(logEvent = true, samplingRate = 0.7) + @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + + override fun handleRequest(input: APIGatewayProxyRequestEvent?, context: Context?): APIGatewayProxyResponseEvent { + val headers = mapOf("Content-Type" to "application/json", "X-Custom-Header" to "application/json") + MetricsUtils.metricsLogger().putMetric("CustomMetric1", 1.0, Unit.COUNT) + MetricsUtils.withSingleMetric("CustomMetrics2", 1.0, Unit.COUNT, "Another") { metric: MetricsLogger -> + metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")) + metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")) + } + LoggingUtils.appendKey("test", "willBeLogged") + val response = APIGatewayProxyResponseEvent().withHeaders(headers) + return try { + val pageContents = getPageContents("https://checkip.amazonaws.com") + log.info(pageContents) + TracingUtils.putAnnotation("Test", "New") + val output = """ + { + "message": "hello world", + "location": "$pageContents" + } + """.trimIndent() + TracingUtils.withSubsegment("loggingResponse") { _: Subsegment? -> + val sampled = "log something out" + log.info(sampled) + log.info(output) + } + log.info("After output") + response.withStatusCode(200).withBody(output) + } catch (e: RuntimeException) { + response.withBody("{}").withStatusCode(500) + } catch (e: IOException) { + response.withBody("{}").withStatusCode(500) + } + } + + @Tracing + private fun log() { + log.info("inside threaded logging for function") + } + + @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) + @Throws(IOException::class) + private fun getPageContents(address: String): String { + val url = URL(address) + TracingUtils.putMetadata("getPageContents", address) + return InputStreamReader(url.openStream()).use { reader -> + reader.readText().trim() + } + } + + private val log = LogManager.getLogger(App::class) +} diff --git a/examples/powertools-examples-core/kotlin/src/main/kotlin/helloworld/AppStream.kt b/examples/powertools-examples-core/kotlin/src/main/kotlin/helloworld/AppStream.kt new file mode 100644 index 000000000..99f6bbfa0 --- /dev/null +++ b/examples/powertools-examples-core/kotlin/src/main/kotlin/helloworld/AppStream.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package helloworld + +import com.amazonaws.services.lambda.runtime.Context +import com.amazonaws.services.lambda.runtime.RequestStreamHandler +import com.fasterxml.jackson.databind.ObjectMapper +import software.amazon.lambda.powertools.logging.Logging +import software.amazon.lambda.powertools.metrics.Metrics +import java.io.IOException +import java.io.InputStream +import java.io.OutputStream + +class AppStream : RequestStreamHandler { + @Logging(logEvent = true) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @Throws(IOException::class) + override fun handleRequest(input: InputStream, output: OutputStream, context: Context) { + val map: Map<*, *> = mapper.readValue(input, MutableMap::class.java) + println(map.size) + } + + companion object { + private val mapper = ObjectMapper() + } +} diff --git a/examples/powertools-examples-core/kotlin/src/test/kotlin/helloworld/AppTest.kt b/examples/powertools-examples-core/kotlin/src/test/kotlin/helloworld/AppTest.kt new file mode 100644 index 000000000..8aae081e8 --- /dev/null +++ b/examples/powertools-examples-core/kotlin/src/test/kotlin/helloworld/AppTest.kt @@ -0,0 +1,20 @@ +package helloworld + + +import org.junit.Assert +import org.junit.Test + +class AppTest { + @Test + fun successfulResponse() { + val app = App() + val result = app.handleRequest(null, null) + Assert.assertEquals(200, result.statusCode.toLong()) + Assert.assertEquals("application/json", result.headers["Content-Type"]) + val content = result.body + Assert.assertNotNull(content) + Assert.assertTrue(""""message"""" in content) + Assert.assertTrue(""""hello world"""" in content) + Assert.assertTrue(""""location"""" in content) + } +} diff --git a/examples/powertools-examples-core/kotlin/template.yaml b/examples/powertools-examples-core/kotlin/template.yaml new file mode 100644 index 000000000..1a1572fca --- /dev/null +++ b/examples/powertools-examples-core/kotlin/template.yaml @@ -0,0 +1,71 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + gradle + + Sample SAM Template for gradle + +# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst +Globals: + Function: + Timeout: 20 + Runtime: java11 + MemorySize: 512 + Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html + Environment: + Variables: + # Powertools for AWS Lambda (Java) env vars: https://docs.powertools.aws.dev/lambda/java/#environment-variables + POWERTOOLS_LOG_LEVEL: INFO + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 + POWERTOOLS_LOGGER_LOG_EVENT: true + POWERTOOLS_METRICS_NAMESPACE: Coreutilities + +Resources: + HelloWorldFunction: + Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + Properties: + CodeUri: . + Handler: helloworld.App::handleRequest + Runtime: java11 + MemorySize: 512 + Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object + Variables: + POWERTOOLS_SERVICE_NAME: hello + Events: + HelloWorld: + Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api + Properties: + Path: /hello + Method: get + + HelloWorldStreamFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: helloworld.AppStream::handleRequest + Runtime: java11 + MemorySize: 512 + Tracing: Active + Environment: + Variables: + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.7 + Events: + HelloWorld: + Type: Api + Properties: + Path: /hellostream + Method: get + +Outputs: + # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function + # Find out more about other implicit resources you can reference within SAM + # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api + HelloWorldApi: + Description: "API Gateway endpoint URL for Prod stage for Hello World function" + Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" + HelloWorldFunction: + Description: "Hello World Lambda Function ARN" + Value: !GetAtt HelloWorldFunction.Arn + HelloWorldFunctionIamRole: + Description: "Implicit IAM Role created for Hello World function" + Value: !GetAtt HelloWorldFunctionRole.Arn diff --git a/examples/powertools-examples-core/serverless/README.md b/examples/powertools-examples-core/serverless/README.md index aec093182..9e33aa9ff 100644 --- a/examples/powertools-examples-core/serverless/README.md +++ b/examples/powertools-examples-core/serverless/README.md @@ -5,7 +5,7 @@ For general information on the deployed example itself, you can refer to the par To install Serverless Framework if you don't have it yet, you can follow the [Getting Started Guide](https://www.serverless.com/framework/docs/getting-started). ## Configuration -Serverless Framework uses [serverless.yml](./serverless.yml) to define the application's AWS resources. +Serverless Framework uses [serverless.yml](serverless.yml) to define the application's AWS resources. This file defines the Lambda function to be deployed as well as API Gateway for it. It is a [Maven](https://maven.apache.org/) based project, so you can open this project with any Maven compatible Java IDE to build and run tests. From 228c0d8f3b66613d19a59f18b436de9907668ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Tue, 24 Oct 2023 12:15:46 +0200 Subject: [PATCH 082/577] chore: java21 support in our build (#1488) --- .github/workflows/pr_build.yml | 2 +- examples/powertools-examples-batch/pom.xml | 1 + .../pom.xml | 1 + .../powertools-examples-core/cdk/app/pom.xml | 8 +- .../app/src/test/java/helloworld/AppTest.java | 59 ---------- .../gradle/build.gradle | 1 - .../src/test/java/helloworld/AppTest.java | 24 ---- examples/powertools-examples-core/sam/pom.xml | 8 +- .../sam/src/test/java/helloworld/AppTest.java | 59 ---------- .../serverless/pom.xml | 8 +- .../src/test/java/helloworld/AppTest.java | 59 ---------- .../terraform/pom.xml | 8 +- .../src/test/java/helloworld/AppTest.java | 38 ------- .../powertools-examples-idempotency/pom.xml | 25 +---- .../src/test/java/helloworld/AppTest.java | 105 ------------------ .../src/test/resources/event.json | 63 ----------- .../powertools-examples-parameters/pom.xml | 20 ---- .../powertools-examples-serialization/pom.xml | 26 ----- ...wayRequestDeserializationFunctionTest.java | 49 -------- .../SQSEventDeserializationFunctionTest.java | 59 ---------- examples/powertools-examples-sqs/pom.xml | 1 + .../powertools-examples-validation/pom.xml | 26 ----- .../validation/InboundValidationTest.java | 65 ----------- pom.xml | 74 ++++++++++-- powertools-batch/pom.xml | 10 -- powertools-cloudformation/pom.xml | 5 - powertools-core/pom.xml | 11 -- powertools-idempotency/pom.xml | 10 -- powertools-large-messages/pom.xml | 10 -- powertools-logging/pom.xml | 10 -- powertools-metrics/pom.xml | 10 -- powertools-parameters/pom.xml | 10 -- powertools-sqs/pom.xml | 5 - powertools-test-suite/pom.xml | 5 - powertools-tracing/pom.xml | 10 -- powertools-validation/pom.xml | 5 - 36 files changed, 71 insertions(+), 819 deletions(-) delete mode 100644 examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java delete mode 100644 examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java delete mode 100644 examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java delete mode 100644 examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java delete mode 100644 examples/powertools-examples-core/terraform/src/test/java/helloworld/AppTest.java delete mode 100644 examples/powertools-examples-idempotency/src/test/java/helloworld/AppTest.java delete mode 100644 examples/powertools-examples-idempotency/src/test/resources/event.json delete mode 100644 examples/powertools-examples-serialization/src/test/java/org/demo/serialization/APIGatewayRequestDeserializationFunctionTest.java delete mode 100644 examples/powertools-examples-serialization/src/test/java/org/demo/serialization/SQSEventDeserializationFunctionTest.java delete mode 100644 examples/powertools-examples-validation/src/test/java/org/demo/validation/InboundValidationTest.java diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index e99900ce5..04f35c63b 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -48,7 +48,7 @@ jobs: strategy: max-parallel: 5 matrix: - java: [8, 11, 15, 16, 17, 18, 19, 20 ] + java: [8, 11, 15, 16, 17, 18, 19, 20, 21 ] name: Java ${{ matrix.java }} env: JAVA: ${{ matrix.java }} diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index bbdc19b9f..99d3a97cc 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -105,6 +105,7 @@ shade + false diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 01aedcaaf..c195cd262 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -130,6 +130,7 @@ shade + false diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml index 57397f187..b4652bd65 100644 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ b/examples/powertools-examples-core/cdk/app/pom.xml @@ -51,13 +51,6 @@ log4j-api ${log4j.version} - - - junit - junit - 4.13.2 - test - @@ -105,6 +98,7 @@ shade + false diff --git a/examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java deleted file mode 100644 index 70dad8d71..000000000 --- a/examples/powertools-examples-core/cdk/app/src/test/java/helloworld/AppTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.amazonaws.xray.AWSXRay; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class AppTest { - - @Before - public void setup() { - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.beginSegment("test"); - } - } - - @After - public void tearDown() { - if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) { - AWSXRay.endSubsegment(); - } - - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.endSegment(); - } - } - - @Test - public void successfulResponse() { - App app = new App(); - APIGatewayProxyResponseEvent result = app.handleRequest(null, null); - assertEquals(result.getStatusCode().intValue(), 200); - assertEquals(result.getHeaders().get("Content-Type"), "application/json"); - String content = result.getBody(); - assertNotNull(content); - assertTrue(content.contains("\"message\"")); - assertTrue(content.contains("\"hello world\"")); - assertTrue(content.contains("\"location\"")); - } -} diff --git a/examples/powertools-examples-core/gradle/build.gradle b/examples/powertools-examples-core/gradle/build.gradle index e7367c246..06aec59e8 100644 --- a/examples/powertools-examples-core/gradle/build.gradle +++ b/examples/powertools-examples-core/gradle/build.gradle @@ -30,6 +30,5 @@ dependencies { aspect 'software.amazon.lambda:powertools-tracing:1.17.0' aspect 'software.amazon.lambda:powertools-logging:1.17.0' aspect 'software.amazon.lambda:powertools-metrics:1.17.0' - testImplementation 'junit:junit:4.13.2' } diff --git a/examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java deleted file mode 100644 index af3ec1275..000000000 --- a/examples/powertools-examples-core/gradle/src/test/java/helloworld/AppTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package helloworld; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -public class AppTest { - @Test - public void successfulResponse() { - App app = new App(); - APIGatewayProxyResponseEvent result = app.handleRequest(null, null); - assertEquals(200, result.getStatusCode().intValue()); - assertEquals("application/json", result.getHeaders().get("Content-Type")); - String content = result.getBody(); - assertNotNull(content); - assertTrue(content.contains("\"message\"")); - assertTrue(content.contains("\"hello world\"")); - assertTrue(content.contains("\"location\"")); - } -} diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index 93c858556..997472344 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -51,13 +51,6 @@ log4j-api ${log4j.version} - - - junit - junit - 4.13.2 - test - @@ -104,6 +97,7 @@ shade + false diff --git a/examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java deleted file mode 100644 index 70dad8d71..000000000 --- a/examples/powertools-examples-core/sam/src/test/java/helloworld/AppTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.amazonaws.xray.AWSXRay; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class AppTest { - - @Before - public void setup() { - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.beginSegment("test"); - } - } - - @After - public void tearDown() { - if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) { - AWSXRay.endSubsegment(); - } - - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.endSegment(); - } - } - - @Test - public void successfulResponse() { - App app = new App(); - APIGatewayProxyResponseEvent result = app.handleRequest(null, null); - assertEquals(result.getStatusCode().intValue(), 200); - assertEquals(result.getHeaders().get("Content-Type"), "application/json"); - String content = result.getBody(); - assertNotNull(content); - assertTrue(content.contains("\"message\"")); - assertTrue(content.contains("\"hello world\"")); - assertTrue(content.contains("\"location\"")); - } -} diff --git a/examples/powertools-examples-core/serverless/pom.xml b/examples/powertools-examples-core/serverless/pom.xml index faa47c591..6fce1d2dd 100644 --- a/examples/powertools-examples-core/serverless/pom.xml +++ b/examples/powertools-examples-core/serverless/pom.xml @@ -51,13 +51,6 @@ log4j-api ${log4j.version} - - - junit - junit - 4.13.2 - test - @@ -105,6 +98,7 @@ shade + false diff --git a/examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java deleted file mode 100644 index 70dad8d71..000000000 --- a/examples/powertools-examples-core/serverless/src/test/java/helloworld/AppTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.amazonaws.xray.AWSXRay; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class AppTest { - - @Before - public void setup() { - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.beginSegment("test"); - } - } - - @After - public void tearDown() { - if (AWSXRay.getCurrentSubsegmentOptional().isPresent()) { - AWSXRay.endSubsegment(); - } - - if (null == System.getenv("LAMBDA_TASK_ROOT")) { - AWSXRay.endSegment(); - } - } - - @Test - public void successfulResponse() { - App app = new App(); - APIGatewayProxyResponseEvent result = app.handleRequest(null, null); - assertEquals(result.getStatusCode().intValue(), 200); - assertEquals(result.getHeaders().get("Content-Type"), "application/json"); - String content = result.getBody(); - assertNotNull(content); - assertTrue(content.contains("\"message\"")); - assertTrue(content.contains("\"hello world\"")); - assertTrue(content.contains("\"location\"")); - } -} diff --git a/examples/powertools-examples-core/terraform/pom.xml b/examples/powertools-examples-core/terraform/pom.xml index 8da2780d8..2a55c31bc 100644 --- a/examples/powertools-examples-core/terraform/pom.xml +++ b/examples/powertools-examples-core/terraform/pom.xml @@ -51,13 +51,6 @@ log4j-api ${log4j.version} - - - junit - junit - 4.13.2 - test - @@ -105,6 +98,7 @@ shade + false diff --git a/examples/powertools-examples-core/terraform/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-core/terraform/src/test/java/helloworld/AppTest.java deleted file mode 100644 index 0ca4f264d..000000000 --- a/examples/powertools-examples-core/terraform/src/test/java/helloworld/AppTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import org.junit.Test; - -public class AppTest { - - @Test - public void successfulResponse() { - App app = new App(); - APIGatewayProxyResponseEvent result = app.handleRequest(null, null); - assertEquals(result.getStatusCode().intValue(), 200); - assertEquals(result.getHeaders().get("Content-Type"), "application/json"); - String content = result.getBody(); - assertNotNull(content); - assertTrue(content.contains("\"message\"")); - assertTrue(content.contains("\"hello world\"")); - assertTrue(content.contains("\"location\"")); - } -} diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index a98645a29..8cda4bfb3 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -64,30 +64,6 @@ log4j-api ${log4j.version} - - - org.mockito - mockito-core - 4.11.0 - test - - - org.junit.jupiter - junit-jupiter-api - 5.9.3 - test - - - com.amazonaws - DynamoDBLocal - 1.22.0 - test - - - com.amazonaws - aws-lambda-java-tests - 1.1.1 - @@ -167,6 +143,7 @@ shade + false diff --git a/examples/powertools-examples-idempotency/src/test/java/helloworld/AppTest.java b/examples/powertools-examples-idempotency/src/test/java/helloworld/AppTest.java deleted file mode 100644 index 7f097906a..000000000 --- a/examples/powertools-examples-idempotency/src/test/java/helloworld/AppTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package helloworld; - -import com.amazonaws.services.dynamodbv2.local.main.ServerRunner; -import com.amazonaws.services.dynamodbv2.local.server.DynamoDBProxyServer; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.amazonaws.services.lambda.runtime.tests.EventLoader; -import java.io.IOException; -import java.net.ServerSocket; -import java.net.URI; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; -import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; -import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.dynamodb.DynamoDbClient; -import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; -import software.amazon.awssdk.services.dynamodb.model.BillingMode; -import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; -import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; -import software.amazon.awssdk.services.dynamodb.model.KeyType; -import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; - -public class AppTest { - private static DynamoDbClient client; - @Mock - private Context context; - private App app; - - @BeforeAll - public static void setupDynamoLocal() { - int port = getFreePort(); - try { - DynamoDBProxyServer dynamoProxy = ServerRunner.createServerFromCommandLineArgs(new String[] { - "-inMemory", - "-port", - Integer.toString(port) - }); - dynamoProxy.start(); - } catch (Exception e) { - throw new RuntimeException(); - } - - client = DynamoDbClient.builder() - .httpClient(UrlConnectionHttpClient.builder().build()) - .region(Region.EU_WEST_1) - .endpointOverride(URI.create("http://localhost:" + port)) - .credentialsProvider(StaticCredentialsProvider.create( - AwsBasicCredentials.create("FAKE", "FAKE"))) - .build(); - - client.createTable(CreateTableRequest.builder() - .tableName("idempotency") - .keySchema(KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("id").build()) - .attributeDefinitions( - AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S).build() - ) - .billingMode(BillingMode.PAY_PER_REQUEST) - .build()); - } - - private static int getFreePort() { - try { - ServerSocket socket = new ServerSocket(0); - int port = socket.getLocalPort(); - socket.close(); - return port; - } catch (IOException ioe) { - throw new RuntimeException(ioe); - } - } - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - app = new App(client); - } - - @Test - public void testApp() { - APIGatewayProxyResponseEvent response = - app.handleRequest(EventLoader.loadApiGatewayRestEvent("event.json"), context); - Assertions.assertNotNull(response); - Assertions.assertTrue(response.getBody().contains("hello world")); - } -} diff --git a/examples/powertools-examples-idempotency/src/test/resources/event.json b/examples/powertools-examples-idempotency/src/test/resources/event.json deleted file mode 100644 index fd7f5ace7..000000000 --- a/examples/powertools-examples-idempotency/src/test/resources/event.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "body": "{\"address\": \"https://checkip.amazonaws.com\"}", - "resource": "/{proxy+}", - "path": "/path/to/resource", - "httpMethod": "POST", - "isBase64Encoded": false, - "queryStringParameters": { - "foo": "bar" - }, - "pathParameters": { - "proxy": "/path/to/resource" - }, - "stageVariables": { - "baz": "qux" - }, - "headers": { - "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", - "Accept-Encoding": "gzip, deflate, sdch", - "Accept-Language": "en-US,en;q=0.8", - "Cache-Control": "max-age=0", - "CloudFront-Forwarded-Proto": "https", - "CloudFront-Is-Desktop-Viewer": "true", - "CloudFront-Is-Mobile-Viewer": "false", - "CloudFront-Is-SmartTV-Viewer": "false", - "CloudFront-Is-Tablet-Viewer": "false", - "CloudFront-Viewer-Country": "US", - "Host": "1234567890.execute-api.us-east-1.amazonaws.com", - "Upgrade-Insecure-Requests": "1", - "User-Agent": "Custom User Agent String", - "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", - "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", - "X-Forwarded-For": "127.0.0.1, 127.0.0.2", - "X-Forwarded-Port": "443", - "X-Forwarded-Proto": "https" - }, - "requestContext": { - "accountId": "123456789012", - "resourceId": "123456", - "stage": "prod", - "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", - "requestTime": "09/Apr/2015:12:34:56 +0000", - "requestTimeEpoch": 1428582896000, - "identity": { - "cognitoIdentityPoolId": null, - "accountId": null, - "cognitoIdentityId": null, - "caller": null, - "accessKey": null, - "sourceIp": "127.0.0.1", - "cognitoAuthenticationType": null, - "cognitoAuthenticationProvider": null, - "userArn": null, - "userAgent": "Custom User Agent String", - "user": null - }, - "path": "/prod/path/to/resource", - "resourcePath": "/{proxy+}", - "httpMethod": "POST", - "apiId": "1234567890", - "protocol": "HTTP/1.1" - } - } - \ No newline at end of file diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index deb9c6ba6..0e07b0cbb 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -33,26 +33,6 @@ aws-lambda-java-events 3.11.3 - - - - org.mockito - mockito-core - 5.1.1 - test - - - org.junit.jupiter - junit-jupiter-api - 5.9.3 - test - - - org.junit.jupiter - junit-jupiter-engine - 5.9.3 - test - diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index eee3e456a..495fe8b77 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -33,36 +33,10 @@ aws-lambda-java-events 3.11.3 - - - - org.mockito - mockito-core - 4.11.0 - test - - - org.junit.jupiter - junit-jupiter-api - 5.9.3 - test - - - org.junit.jupiter - junit-jupiter-engine - 5.9.3 - test - - - org.apache.maven.plugins - maven-surefire-plugin - - 3.1.2 - org.apache.maven.plugins diff --git a/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/APIGatewayRequestDeserializationFunctionTest.java b/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/APIGatewayRequestDeserializationFunctionTest.java deleted file mode 100644 index ec8cdbd33..000000000 --- a/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/APIGatewayRequestDeserializationFunctionTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.demo.serialization; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -class APIGatewayRequestDeserializationFunctionTest { - - @Mock - private Context context; - private APIGatewayRequestDeserializationFunction deserializationFunction; - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - deserializationFunction = new APIGatewayRequestDeserializationFunction(); - } - - @Test - public void shouldReturnOkStatusWithProductId() { - String body = "{\"id\":1234, \"name\":\"product\", \"price\":42}"; - APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent().withBody(body); - - APIGatewayProxyResponseEvent response = deserializationFunction.handleRequest(request, context); - - assertEquals(200, response.getStatusCode()); - assertEquals("Received request for productId: 1234", response.getBody()); - } -} \ No newline at end of file diff --git a/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/SQSEventDeserializationFunctionTest.java b/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/SQSEventDeserializationFunctionTest.java deleted file mode 100644 index b46af3052..000000000 --- a/examples/powertools-examples-serialization/src/test/java/org/demo/serialization/SQSEventDeserializationFunctionTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.demo.serialization; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import java.util.ArrayList; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -class SQSEventDeserializationFunctionTest { - - @Mock - private Context context; - private SQSEventDeserializationFunction deserializationFunction; - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - deserializationFunction = new SQSEventDeserializationFunction(); - } - - @Test - public void shouldReturnNumberOfReceivedMessages() { - SQSEvent.SQSMessage message1 = messageWithBody("{ \"id\": 1234, \"name\": \"product\", \"price\": 42}"); - SQSEvent.SQSMessage message2 = messageWithBody("{ \"id\": 12345, \"name\": \"product5\", \"price\": 45}"); - SQSEvent event = new SQSEvent(); - event.setRecords(new ArrayList() {{ - add(message1); - add(message2); - }}); - - String response = deserializationFunction.handleRequest(event, context); - - assertEquals("Number of received messages: 2", response); - } - - private SQSEvent.SQSMessage messageWithBody(String body) { - SQSEvent.SQSMessage record1 = new SQSEvent.SQSMessage(); - record1.setBody(body); - return record1; - } -} \ No newline at end of file diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 889fe85da..0338fe7d9 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -103,6 +103,7 @@ shade + false diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 29f52b33e..65628f6b2 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -42,36 +42,10 @@ aws-lambda-java-core 1.2.3 - - - - org.mockito - mockito-core - 4.11.0 - test - - - org.junit.jupiter - junit-jupiter-api - 5.9.3 - test - - - org.junit.jupiter - junit-jupiter-engine - 5.9.3 - test - - - org.apache.maven.plugins - maven-surefire-plugin - - 3.1.2 - dev.aspectj aspectj-maven-plugin diff --git a/examples/powertools-examples-validation/src/test/java/org/demo/validation/InboundValidationTest.java b/examples/powertools-examples-validation/src/test/java/org/demo/validation/InboundValidationTest.java deleted file mode 100644 index d5e6de313..000000000 --- a/examples/powertools-examples-validation/src/test/java/org/demo/validation/InboundValidationTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.demo.validation; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import software.amazon.lambda.powertools.validation.ValidationException; - -public class InboundValidationTest { - - @Mock - private Context context; - private InboundValidation inboundValidation; - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - inboundValidation = new InboundValidation(); - } - - @Test - public void shouldReturnOkStatusWhenInputIsValid() { - String body = "{\n" + - " \"id\": 43242,\n" + - " \"name\": \"FooBar XY\",\n" + - " \"price\": 258\n" + - " }"; - APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent().withBody(body); - - APIGatewayProxyResponseEvent response = inboundValidation.handleRequest(request, context); - - assertEquals(200, response.getStatusCode()); - } - - @Test - public void shouldThrowExceptionWhenRequestInInvalid() { - String bodyWithMissedId = "{\n" + - " \"name\": \"FooBar XY\",\n" + - " \"price\": 258\n" + - " }"; - APIGatewayProxyRequestEvent request = new APIGatewayProxyRequestEvent().withBody(bodyWithMissedId); - - assertThrows(ValidationException.class, () -> inboundValidation.handleRequest(request, context)); - } -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 823b09d61..e1a0c5a6c 100644 --- a/pom.xml +++ b/pom.xml @@ -263,18 +263,6 @@ 3.13.0 test - - org.mockito - mockito-core - 4.11.0 - test - - - org.mockito - mockito-inline - 4.11.0 - test - org.aspectj aspectjweaver @@ -286,6 +274,12 @@ assertj-core 3.24.2 test + + + net.bytebuddy + byte-buddy + + org.skyscreamer @@ -544,6 +538,62 @@ + + olderThanJdk11 + + (,11) + + + + 4.11.0 + + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.mockito + mockito-inline + ${mockito.version} + test + + + + + newerThanJdk11 + + [11,) + + + 5.6.0 + + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + true + + + + + + newerThanJdk8 diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 27bb33a42..0c59ce497 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -56,16 +56,6 @@ aws-lambda-java-tests test - - org.mockito - mockito-core - test - - - org.mockito - mockito-inline - test - \ No newline at end of file diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 1347d95a3..f6cd822a6 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -97,11 +97,6 @@ junit-jupiter-params test - - org.mockito - mockito-core - test - org.assertj assertj-core diff --git a/powertools-core/pom.xml b/powertools-core/pom.xml index a5460031d..b848e9f79 100644 --- a/powertools-core/pom.xml +++ b/powertools-core/pom.xml @@ -86,11 +86,6 @@ commons-lang3 test - - org.mockito - mockito-core - test - org.aspectj aspectjweaver @@ -101,11 +96,6 @@ assertj-core test - - org.mockito - mockito-inline - test - @@ -122,5 +112,4 @@ - \ No newline at end of file diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index e89df47f7..9dfde1bd1 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -107,16 +107,6 @@ junit-pioneer test - - org.mockito - mockito-core - test - - - org.mockito - mockito-inline - test - org.apache.commons commons-lang3 diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index aed8cc2e4..8fdae2139 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -118,16 +118,6 @@ junit-pioneer test - - org.mockito - mockito-core - test - - - org.mockito - mockito-inline - test - org.apache.commons commons-lang3 diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 26ad8c243..c31448e30 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -104,16 +104,6 @@ commons-lang3 test - - org.mockito - mockito-core - test - - - org.mockito - mockito-inline - test - org.aspectj aspectjweaver diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index cb3acf110..eff7296c8 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -104,16 +104,6 @@ commons-lang3 test - - org.mockito - mockito-core - test - - - org.mockito - mockito-inline - test - org.aspectj aspectjweaver diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index f99a3d3cd..808232ab1 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -120,16 +120,6 @@ junit-jupiter-engine test - - org.mockito - mockito-core - test - - - org.mockito - mockito-inline - test - org.apache.commons commons-lang3 diff --git a/powertools-sqs/pom.xml b/powertools-sqs/pom.xml index f824f409d..c4b2b54f0 100644 --- a/powertools-sqs/pom.xml +++ b/powertools-sqs/pom.xml @@ -115,11 +115,6 @@ commons-lang3 test - - org.mockito - mockito-core - test - org.aspectj aspectjweaver diff --git a/powertools-test-suite/pom.xml b/powertools-test-suite/pom.xml index 55e713ec0..34e80b06e 100644 --- a/powertools-test-suite/pom.xml +++ b/powertools-test-suite/pom.xml @@ -100,11 +100,6 @@ commons-lang3 test - - org.mockito - mockito-core - test - org.aspectj aspectjweaver diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index d2f14c3e0..d98a97e2a 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -105,16 +105,6 @@ commons-lang3 test - - org.mockito - mockito-core - test - - - org.mockito - mockito-inline - test - org.aspectj aspectjweaver diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 606f02139..24de0ba2a 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -111,11 +111,6 @@ commons-lang3 test - - org.mockito - mockito-core - test - org.aspectj aspectjweaver From 5f26c7683eb1b5ec182837f3b14df8fad2886645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Tue, 24 Oct 2023 13:28:00 +0200 Subject: [PATCH 083/577] chore: add missing projects and improve workflow (#1487) --- .github/workflows/pr_build.yml | 53 ++++++++++++++++------------- .github/workflows/run-e2e-tests.yml | 12 ++++--- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 04f35c63b..c316c0073 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -6,18 +6,21 @@ on: - main - v2 paths: + - 'powertools-batch/**' - 'powertools-cloudformation/**' - - 'powertools-core/**' - - 'powertools-serialization/**' + - 'powertools-core/**' # not in v2 + - 'powertools-common/**' # v2 only + - 'powertools-e2e-tests/**' + - 'powertools-idempotency/**' + - 'powertools-large-messages/**' - 'powertools-logging/**' - - 'powertools-sqs/**' + - 'powertools-metrics/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' + - 'powertools-sqs/**' # not in v2 + - 'powertools-test-suite/**' # not in v2 - 'powertools-tracing/**' - 'powertools-validation/**' - - 'powertools-idempotency/**' - - 'powertools-parameters/**' - - 'powertools-metrics/**' - - 'powertools-test-suite/**' - - 'powertools-e2e-tests/**' - 'examples/**' - 'pom.xml' - 'examples/pom.xml' @@ -26,18 +29,20 @@ on: branches: - main paths: + - 'powertools-batch/**' - 'powertools-cloudformation/**' - 'powertools-core/**' - - 'powertools-serialization/**' + - 'powertools-e2e-tests/**' + - 'powertools-idempotency/**' + - 'powertools-large-messages/**' - 'powertools-logging/**' + - 'powertools-metrics/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' - 'powertools-sqs/**' + - 'powertools-test-suite/**' - 'powertools-tracing/**' - 'powertools-validation/**' - - 'powertools-idempotency/**' - - 'powertools-parameters/**' - - 'powertools-metrics/**' - - 'powertools-test-suite/**' - - 'powertools-e2e-tests/**' - 'examples/**' - 'pom.xml' - 'examples/pom.xml' @@ -48,7 +53,7 @@ jobs: strategy: max-parallel: 5 matrix: - java: [8, 11, 15, 16, 17, 18, 19, 20, 21 ] + java: [8, 11, 17, 21, 15, 16, 18, 19, 20] name: Java ${{ matrix.java }} env: JAVA: ${{ matrix.java }} @@ -68,26 +73,26 @@ jobs: run: mvn -B install --file pom.xml - name: Build Gradle Example - Java if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 - run: | - cd examples/powertools-examples-core/gradle - ./gradlew build + working-directory: examples/powertools-examples-core/gradle + run: ./gradlew build - name: Build Gradle Example - Kotlin - run: | - cd examples/powertools-examples-core/kotlin - ./gradlew build + if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 + working-directory: examples/powertools-examples-core/kotlin + run: ./gradlew build - name: Setup Terraform if: ${{ matrix.java == '11' }} uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 #v2.0.3 - name: Setup AWS credentials + if: ${{ matrix.java == '11' }} uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} aws-region: ${{ env.AWS_REGION }} - name: Terraform validate + working-directory: examples/powertools-examples-core/terraform if: ${{ matrix.java == '11' }} run: | terraform -version - cd examples/powertools-examples-core/terraform terraform init -backend=false terraform validate terraform plan @@ -95,17 +100,17 @@ jobs: if: ${{ matrix.java == '11' }} uses: terraform-linters/setup-tflint@a5a1af8c6551fb10c53f1cd4ba62359f1973746f # v3.1.1 - name: Terraform lint + working-directory: examples/powertools-examples-core/terraform if: ${{ matrix.java == '11' }} run: | tflint --version - cd examples/powertools-examples-core/terraform tflint --init tflint -f compact - name: Upload coverage to Codecov uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 if: ${{ matrix.java == '11' }} # publish results once with: - files: ./powertools-cloudformation/target/site/jacoco/jacoco.xml,./powertools-core/target/site/jacoco/jacoco.xml,./powertools-idempotency/target/site/jacoco/jacoco.xml,./powertools-logging/target/site/jacoco/jacoco.xml,./powertools-metrics/target/site/jacoco/jacoco.xml,./powertools-parameters/target/site/jacoco/jacoco.xml,./powertools-serialization/target/site/jacoco/jacoco.xml,./powertools-sqs/target/site/jacoco/jacoco.xml,./powertools-tracing/target/site/jacoco/jacoco.xml,./powertools-validation/target/site/jacoco/jacoco.xml + files: ./powertools-cloudformation/target/site/jacoco/jacoco.xml,./powertools-core/target/site/jacoco/jacoco.xml,./powertools-idempotency/target/site/jacoco/jacoco.xml,./powertools-logging/target/site/jacoco/jacoco.xml,./powertools-metrics/target/site/jacoco/jacoco.xml,./powertools-parameters/target/site/jacoco/jacoco.xml,./powertools-serialization/target/site/jacoco/jacoco.xml,./powertools-sqs/target/site/jacoco/jacoco.xml,./powertools-tracing/target/site/jacoco/jacoco.xml,./powertools-validation/target/site/jacoco/jacoco.xml,./powertools-large-messages/target/site/jacoco/jacoco.xml,./powertools-batch/target/site/jacoco/jacoco.xml savepr: runs-on: ubuntu-latest name: Save PR number if running on PR by dependabot diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index c4a8c6fb2..a2a1b9aec 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -9,14 +9,16 @@ on: - v2 paths: # add other modules when there are under e2e tests - 'powertools-e2e-tests/**' + - 'powertools-batch/**' - 'powertools-core/**' - - 'powertools-serialization/**' - - 'powertools-logging/**' - - 'powertools-tracing/**' + - 'powertools-common/**' - 'powertools-idempotency/**' - - 'powertools-parameters/**' + - 'powertools-large-message/**' + - 'powertools-logging/**' - 'powertools-metrics/**' - - 'powertools-large-messages/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' + - 'powertools-tracing/**' - 'pom.xml' - '.github/workflows/**' From cd0f3dc1b00f5c4a34138febe9e7dc0cae9ea4f9 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Tue, 24 Oct 2023 16:18:23 +0200 Subject: [PATCH 084/577] docs(customer-reference): add Vertex Pharmaceuticals as a customer reference (#1486) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2afb40e5d..900395554 100644 --- a/README.md +++ b/README.md @@ -205,6 +205,7 @@ The following companies, among others, use Powertools: * [Capital One](https://www.capitalone.com/) * [CPQi (Exadel Financial Services)](https://cpqi.com/) * [Europace AG](https://europace.de/) +* [Vertex Pharmaceuticals](https://www.vrtx.com/) ## Credits From a3d2c9b7d0b3b1bbd430d73bd2d5c8a50f036452 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Tue, 24 Oct 2023 16:41:44 +0200 Subject: [PATCH 085/577] Merge cleanup: fix some missing changes --- .github/workflows/pr_build.yml | 2 +- examples/README.md | 10 +++++----- .../kotlin/build.gradle.kts | 6 +++--- .../terraform/pom.xml | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 0f749a4a0..b22dd80bc 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -73,7 +73,7 @@ jobs: run: ./gradlew build - name: Build Gradle Example - Kotlin if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 - working-directory: examples/powertools-examples-core/kotlin + working-directory: examples/powertools-examples-core-utilities/kotlin run: ./gradlew build - name: Setup Terraform if: ${{ matrix.java == '11' }} diff --git a/examples/README.md b/examples/README.md index 6dbe00185..48df52df8 100644 --- a/examples/README.md +++ b/examples/README.md @@ -6,11 +6,11 @@ Each example can be copied from its subdirectory and used independently of the r ## Examples * [powertools-examples-core](powertools-examples-core) - Demonstrates the core logging, tracing, and metrics modules with different build tools and languages - * [CDK](./powertools-examples-core/cdk) - * [Gradle](./powertools-examples-core/gradle) - * [SAM](./powertools-examples-core/sam) - * [Serverless](./powertools-examples-core/serverless) - * [Kotlin](./powertools-examples-core/kotlin) + * [CDK](./powertools-examples-core-utilities/cdk) + * [Gradle](./powertools-examples-core-utilities/gradle) + * [SAM](./powertools-examples-core-utilities/sam) + * [Serverless](./powertools-examples-core-utilities/serverless) + * [Kotlin](./powertools-examples-core-utilities/kotlin) * [powertools-examples-idempotency](powertools-examples-idempotency) - An idempotent HTTP API * [powertools-examples-parameters](powertools-examples-parameters) - Uses the parameters module to provide runtime parameters to a function * [powertools-examples-serialization](powertools-examples-serialization) - Uses the serialization module to serialize and deserialize API Gateway & SQS payloads diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index fc363c1b9..29a29b0c4 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -14,9 +14,9 @@ dependencies { implementation("com.fasterxml.jackson.core:jackson-databind:2.13.2.2") implementation("com.amazonaws:aws-lambda-java-events:3.11.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2") - aspect("software.amazon.lambda:powertools-tracing:1.18.0-SNAPSHOT") - aspect("software.amazon.lambda:powertools-logging:1.18.0-SNAPSHOT") - aspect("software.amazon.lambda:powertools-metrics:1.18.0-SNAPSHOT") + aspect("software.amazon.lambda:powertools-tracing:2.0.0-SNAPSHOT") + aspect("software.amazon.lambda:powertools-logging:2.0.0-SNAPSHOT") + aspect("software.amazon.lambda:powertools-metrics:2.0.0-SNAPSHOT") testImplementation("junit:junit:4.13.2") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") } diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 2a55c31bc..538a6da8f 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 2.0.0-SNAPSHOT powertools-examples-core-terraform jar From 327846f699f5a1bf2df12791dd6414b8dbbc6853 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Tue, 24 Oct 2023 16:55:58 +0200 Subject: [PATCH 086/577] Merge fixes - readme link and terraform build --- examples/README.md | 2 +- examples/pom.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/README.md b/examples/README.md index 48df52df8..aa8457def 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,7 +5,7 @@ Each example can be copied from its subdirectory and used independently of the r ## Examples -* [powertools-examples-core](powertools-examples-core) - Demonstrates the core logging, tracing, and metrics modules with different build tools and languages +* [powertools-examples-core-utilities](powertools-examples-core-utilities) - Demonstrates the core logging, tracing, and metrics modules with different build tools and languages * [CDK](./powertools-examples-core-utilities/cdk) * [Gradle](./powertools-examples-core-utilities/gradle) * [SAM](./powertools-examples-core-utilities/sam) diff --git a/examples/pom.xml b/examples/pom.xml index be52778da..3526be2a4 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -33,6 +33,7 @@ powertools-examples-core-utilities/cdk/app powertools-examples-core-utilities/cdk/infra powertools-examples-core-utilities/serverless + powertools-examples-core-utilities/terraform powertools-examples-idempotency powertools-examples-parameters powertools-examples-serialization From cfe069f61161c26e85d570c7b15a1d44b5949c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Tue, 24 Oct 2023 17:18:04 +0200 Subject: [PATCH 087/577] enforce our version of jackson-databind in serialization module (#1472) --- powertools-serialization/pom.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index b1f228df7..e5c4087fe 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -67,6 +67,10 @@ org.apache.logging.log4j log4j-slf4j2-impl + + com.fasterxml.jackson.core + jackson-databind + From 6e334199976f004e0d4ab115e1bc1eb35fd13a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Thu, 26 Oct 2023 11:12:43 +0200 Subject: [PATCH 088/577] chore: artifacts size on good branches (#1493) --- .github/workflows/pr_artifacts_size.yml | 23 ++++++++++++------- .../powertools-examples-idempotency/pom.xml | 7 ------ powertools-idempotency/pom.xml | 7 ------ 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/.github/workflows/pr_artifacts_size.yml b/.github/workflows/pr_artifacts_size.yml index cbacd78da..f37f83a8d 100644 --- a/.github/workflows/pr_artifacts_size.yml +++ b/.github/workflows/pr_artifacts_size.yml @@ -3,19 +3,26 @@ name: Artifacts Size on: pull_request: branches: - - master + - main + - v2 paths: + - 'powertools-batch/**' - 'powertools-cloudformation/**' - - 'powertools-core/**' - - 'powertools-serialization/**' + - 'powertools-core/**' # not in v2 + - 'powertools-common/**' # v2 only + - 'powertools-e2e-tests/**' + - 'powertools-idempotency/**' + - 'powertools-large-messages/**' - 'powertools-logging/**' - - 'powertools-sqs/**' + - 'powertools-metrics/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' + - 'powertools-sqs/**' # not in v2 + - 'powertools-test-suite/**' # not in v2 - 'powertools-tracing/**' - 'powertools-validation/**' - - 'powertools-parameters/**' - - 'powertools-idempotency/**' - - 'powertools-metrics/**' - 'pom.xml' + - '.github/workflows/pr_artifacts_size.yml' jobs: codecheck: runs-on: ubuntu-latest @@ -27,7 +34,7 @@ jobs: distribution: 'corretto' java-version: 11 - name: Build with Maven - run: mvn clean package --file pom.xml -DskipTests + run: mvn clean package --file pom.xml -DskipTests artifact:buildinfo - name: Get artifacts size & build report id: artifacts-size-report run: | diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 8cda4bfb3..4b8eba9c9 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -244,11 +244,4 @@ - - - dynamodb-local-oregon - DynamoDB Local Release Repository - https://s3.eu-central-1.amazonaws.com/dynamodb-local-frankfurt/release - - diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 9dfde1bd1..8b3459dee 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -189,11 +189,4 @@ - - - dynamodb-local-oregon - DynamoDB Local Release Repository - https://s3.eu-central-1.amazonaws.com/dynamodb-local-frankfurt/release - - \ No newline at end of file From 62ccaf94fb23cd0843f35e922b4c57a2d7267965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Thu, 26 Oct 2023 22:26:29 +0200 Subject: [PATCH 089/577] chore(v2): clean examples (#1495) --- .../cdk/app/pom.xml | 9 +- .../sam/pom.xml | 138 +++++++++--------- .../serverless/pom.xml | 9 +- .../terraform/pom.xml | 79 +++------- 4 files changed, 86 insertions(+), 149 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 2d8e3b371..be8c9ca67 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -2,13 +2,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 + Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) with CDK software.amazon.lambda.examples 1.17.0 powertools-examples-core-utilities-cdk jar - Powertools for AWS Lambda (Java) library Examples - Core 2.20.0 @@ -58,13 +58,6 @@ aspectjrt ${aspectj.version} - - - junit - junit - 4.13.2 - test - diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 130fb814d..a88150f4b 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -56,81 +56,75 @@ aspectjrt ${aspectj.version} - - - junit - junit - 4.13.2 - test - - - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.5.0 - - - package - - shade - - - - - - - - - - - org.apache.logging.log4j - log4j-transform-maven-shade-plugin-extensions - 0.1.0 - - - - + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.0 + + + package + + shade + + + false + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - From 0a30d8e9e6cfa117e998509883233ebf411263c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Wed, 8 Nov 2023 11:06:35 +0100 Subject: [PATCH 090/577] Update CONTRIBUTING.md --- CONTRIBUTING.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8db303737..c4330cf8e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,8 +55,7 @@ We strongly recommend installing the CheckStyle-IDEA plugin and apply the provid 2. After installing the plugin, open the preferences (`⌘,` on macOS, or `Ctrl+Alt+S` on Windows/Linux) and search for _Code Style_. Click on the gear icon near the scheme and import checkstyle configuration. Click on "Apply" and "OK". ![](docs/media/intellij_checkstyle_1.png) -3. Select the code you've created (module, package, class) and reformat code: `⌘⌥L` (macOS), or `Ctrl+Alt+L` (Windows/Linux): -![](docs/media/intellij_checkstyle_2.png) +3. Select the code you've created (module, package, class) and reformat code: `⌘⌥L` (macOS), or `Ctrl+Alt+L` (Windows/Linux). 4. Apply the reformat, optimize imports, rearrange and cleanup to your code and only to java files: ![](docs/media/intellij_checkstyle_3.png) From 7918d9a862cdaa30dbb93b51232216e31f79f5c3 Mon Sep 17 00:00:00 2001 From: Michele Ricciardi Date: Wed, 8 Nov 2023 16:35:51 +0100 Subject: [PATCH 091/577] fix: get trace id from system property when env var is not set (#1503) * fix: check if XRAY Trace ID is present in System property * chore: remove erroneous extra char in tests --- .../core/internal/LambdaConstants.java | 1 + .../core/internal/LambdaHandlerProcessor.java | 8 +++- .../core/internal/SystemWrapper.java | 4 ++ .../amazon/lambda/powertools/LoggingE2ET.java | 2 + .../internal/LambdaLoggingAspectTest.java | 21 ++++++++- .../powertools/metrics/MetricsLoggerTest.java | 44 +++++++++++++++++-- .../internal/LambdaMetricsAspectTest.java | 6 +-- 7 files changed, 77 insertions(+), 9 deletions(-) diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java index d0f94260b..e64e334c5 100644 --- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java +++ b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaConstants.java @@ -24,6 +24,7 @@ public class LambdaConstants { @Deprecated public static final String ON_DEMAND = "on-demand"; public static final String X_AMZN_TRACE_ID = "_X_AMZN_TRACE_ID"; + public static final String XRAY_TRACE_HEADER = "com.amazonaws.xray.traceHeader"; public static final String AWS_SAM_LOCAL = "AWS_SAM_LOCAL"; public static final String ROOT_EQUALS = "Root="; public static final String POWERTOOLS_SERVICE_NAME = "POWERTOOLS_SERVICE_NAME"; diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java index e9e220e41..91c93c3f3 100644 --- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java +++ b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java @@ -16,6 +16,7 @@ import static java.util.Optional.empty; import static java.util.Optional.of; +import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getProperty; import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; import com.amazonaws.services.lambda.runtime.Context; @@ -93,7 +94,12 @@ public static boolean isSamLocal() { } public static Optional getXrayTraceId() { - final String X_AMZN_TRACE_ID = getenv(LambdaConstants.X_AMZN_TRACE_ID); + String X_AMZN_TRACE_ID = getenv(LambdaConstants.X_AMZN_TRACE_ID); + // For the Java Lambda 17+ runtime, the Trace ID is set as a System Property + if (X_AMZN_TRACE_ID == null) { + X_AMZN_TRACE_ID = getProperty(LambdaConstants.XRAY_TRACE_HEADER); + } + if (X_AMZN_TRACE_ID != null) { return of(X_AMZN_TRACE_ID.split(";")[0].replace(LambdaConstants.ROOT_EQUALS, "")); } diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java index 30f72232f..99046ffec 100644 --- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java +++ b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/SystemWrapper.java @@ -21,4 +21,8 @@ private SystemWrapper() { public static String getenv(String name) { return System.getenv(name); } + + public static String getProperty(String name) { + return System.getProperty(name); + } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java index f958970d8..b060879d3 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java @@ -46,6 +46,7 @@ public class LoggingE2ET { public static void setup() { infrastructure = Infrastructure.builder() .testName(LoggingE2ET.class.getSimpleName()) + .tracing(true) .pathToFunction("logging") .environmentVariables( Stream.of(new String[][] { @@ -83,6 +84,7 @@ public void test_logInfoWithAdditionalKeys() throws JsonProcessingException { assertThat(jsonNode.get("message").asText()).isEqualTo("New Order"); assertThat(jsonNode.get("orderId").asText()).isEqualTo(orderId); assertThat(jsonNode.get("coldStart").asBoolean()).isTrue(); + assertThat(jsonNode.get("xray_trace_id").asText()).isNotBlank(); assertThat(jsonNode.get("function_request_id").asText()).isEqualTo(invocationResult1.getRequestId()); // second call should not be cold start diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index b78710586..6952fe755 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.openMocks; import static org.skyscreamer.jsonassert.JSONAssert.assertEquals; +import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getProperty; import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; import com.amazonaws.services.lambda.runtime.Context; @@ -245,13 +246,31 @@ void shouldLogServiceNameWhenEnvVarSet() throws IllegalAccessException { .containsEntry("service", "testService"); } + @Test + void shouldLogxRayTraceIdSystemPropertySet() { + String xRayTraceId = "1-5759e988-bd862e3fe1be46a994272793"; + + try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { + mocked.when(() -> getenv("_X_AMZN_TRACE_ID")) + .thenReturn(null); + mocked.when(() -> getProperty("com.amazonaws.xray.traceHeader")) + .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); + + requestHandler.handleRequest(new Object(), context); + + assertThat(ThreadContext.getImmutableContext()) + .hasSize(EXPECTED_CONTEXT_SIZE + 1) + .containsEntry("xray_trace_id", xRayTraceId); + } + } + @Test void shouldLogxRayTraceIdEnvVarSet() { String xRayTraceId = "1-5759e988-bd862e3fe1be46a994272793"; try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { mocked.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); + .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); requestHandler.handleRequest(new Object(), context); diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java index 7f234a4d6..16a068849 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNullPointerException; import static org.mockito.Mockito.mockStatic; +import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getProperty; import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; import com.fasterxml.jackson.core.JsonProcessingException; @@ -66,7 +67,7 @@ void singleMetricsCaptureUtilityWithDefaultDimension() { software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); + .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); MetricsUtils.defaultDimensions(DimensionSet.of("Service", "Booking")); @@ -96,7 +97,7 @@ void singleMetricsCaptureUtility() { software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); + .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, "test", metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); @@ -123,7 +124,7 @@ void singleMetricsCaptureUtilityWithDefaultNameSpace() { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); + .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); @@ -165,6 +166,41 @@ void shouldThrowExceptionWhenDefaultDimensionIsNull() { .withMessage("Null dimension set not allowed"); } + @Test + void shouldUseTraceIdFromSystemPropertyIfEnvVarNotPresent() { + try (MockedStatic mocked = mockStatic(SystemWrapper.class); + MockedStatic internalWrapper = mockStatic( + software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { + mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); + mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName"); + internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) + .thenReturn(null); + internalWrapper.when(() -> getProperty("com.amazonaws.xray.traceHeader")) + .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); + + MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, + metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("Dimension1", "Value1") + .containsKey("_aws") + .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); + + Map aws = (Map) logAsJson.get("_aws"); + + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=GlobalName"); + }); + } + } + private void testLogger(Consumer> methodToTest) { try (MockedStatic mocked = mockStatic(SystemWrapper.class); MockedStatic internalWrapper = mockStatic( @@ -172,7 +208,7 @@ private void testLogger(Consumer> methodToTest) { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); + .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); methodToTest.accept(metricsLogger -> { diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java index eaddfa75d..0a735c75e 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java @@ -91,7 +91,7 @@ public void metricsWithoutColdStart() { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); + .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); MetricsUtils.defaultDimensions(null); requestHandler = new PowertoolsMetricsEnabledHandler(); @@ -135,7 +135,7 @@ public void metricsWithDefaultDimensionSpecified() { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); + .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); requestHandler = new PowertoolsMetricsEnabledDefaultDimensionHandler(); @@ -179,7 +179,7 @@ public void metricsWithDefaultNoDimensionSpecified() { mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""); + .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); requestHandler = new PowertoolsMetricsEnabledDefaultNoDimensionHandler(); From 3afb1d2e5a548eb3fea3bbe4728fa3708ec61106 Mon Sep 17 00:00:00 2001 From: jdoherty Date: Wed, 8 Nov 2023 16:40:20 +0000 Subject: [PATCH 092/577] removing dynamodb local from examples (#1507) --- examples/powertools-examples-idempotency/pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 99eb5dc9f..901074ddb 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -83,12 +83,6 @@ 5.9.3 test - - com.amazonaws - DynamoDBLocal - 1.22.0 - test - com.amazonaws aws-lambda-java-tests From 0f3e8960d5fab2f658e5e855e7bd979c9d77d17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Wed, 8 Nov 2023 17:52:08 +0100 Subject: [PATCH 093/577] fix #1500 (#1506) --- .../powertools/metrics/MetricsUtils.java | 8 +++-- .../powertools/metrics/MetricsLoggerTest.java | 31 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java index 09517d46e..7891b22ec 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java @@ -178,8 +178,12 @@ private static void captureRequestAndTraceId(MetricsLogger metricsLogger) { private static String defaultNameSpace() { MetricsContext context = MetricsLoggerHelper.metricsContext(); - return "aws-embedded-metrics".equals(context.getNamespace()) ? - SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE") : context.getNamespace(); + if ("aws-embedded-metrics".equals(context.getNamespace())) { + String namespace = SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE"); + return namespace != null ? namespace : "aws-embedded-metrics"; + } else { + return context.getNamespace(); + } } private static Optional awsRequestId() { diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java index 16a068849..ce9d63cfd 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java @@ -112,6 +112,37 @@ void singleMetricsCaptureUtility() { .containsEntry("Dimension1", "Value1") .containsKey("_aws") .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); + + Map aws = (Map) logAsJson.get("_aws"); + + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=test"); + }); + } + } + + @Test + void singleMetricsCaptureUtilityWithNullNamespace() { + try (MockedStatic mocked = mockStatic(SystemWrapper.class); + MockedStatic internalWrapper = mockStatic( + software.amazon.lambda.powertools.core.internal.SystemWrapper.class)) { + mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); + // POWERTOOLS_METRICS_NAMESPACE is not defined + + MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, + metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + + Map aws = (Map) logAsJson.get("_aws"); + + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=aws-embedded-metrics"); }); } } From de547d02754216c06812d73d80159d55be8007e3 Mon Sep 17 00:00:00 2001 From: Alexey Soshin Date: Tue, 14 Nov 2023 14:27:38 +0000 Subject: [PATCH 094/577] feat: Add support for POWERTOOLS_LOGGER_LOG_EVENT (#1510) --- docs/core/logging.md | 4 +- docs/index.md | 2 + .../core/internal/LambdaHandlerProcessor.java | 7 ++ .../logging/internal/LambdaLoggingAspect.java | 14 ++- .../handlers/PowerToolLogEventDisabled.java | 28 +++++ .../internal/LambdaLoggingAspectTest.java | 119 +++++++++++------- 6 files changed, 127 insertions(+), 47 deletions(-) create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventDisabled.java diff --git a/docs/core/logging.md b/docs/core/logging.md index 2df9a4529..fd74db3d2 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -217,9 +217,7 @@ Key | Type | Example | Description ## Capturing context Lambda info -You can enrich your structured logs with key Lambda context information via `logEvent` annotation parameter. -You can also explicitly log any incoming event using `logEvent` param. Refer [Override default object mapper](#override-default-object-mapper) -to customise what is logged. +When debugging in non-production environments, you can instruct Logger to log the incoming event with `@Logger(logEvent = true)` or via `POWERTOOLS_LOGGER_LOG_EVENT=true` environment variable. !!! warning Log event is disabled by default to prevent sensitive info being logged. diff --git a/docs/index.md b/docs/index.md index 6af4c5e8d..92589be7c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -285,5 +285,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl | **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics) | | **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logging) | | **POWERTOOLS_LOG_LEVEL** | Sets logging level | [Logging](./core/logging) | +| **POWERTOOLS_LOGGER_LOG_EVENT** | Enables/Disables whether to log the incoming event when using the aspect | [Logging](./core/logging) | | **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Enables/Disables tracing mode to capture method response | [Tracing](./core/tracing) | | **POWERTOOLS_TRACER_CAPTURE_ERROR** | Enables/Disables tracing mode to capture method error | [Tracing](./core/tracing) | + diff --git a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java index 91c93c3f3..d4e18dddc 100644 --- a/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java +++ b/powertools-core/src/main/java/software/amazon/lambda/powertools/core/internal/LambdaHandlerProcessor.java @@ -47,6 +47,13 @@ public static boolean isHandlerMethod(final ProceedingJoinPoint pjp) { return placedOnRequestHandler(pjp) || placedOnStreamHandler(pjp); } + /** + * The class needs to implement RequestHandler interface + * The function needs to have exactly two arguments + * The second argument needs to be of type com.amazonaws.services.lambda.runtime.Context + * @param pjp + * @return + */ public static boolean placedOnRequestHandler(final ProceedingJoinPoint pjp) { return RequestHandler.class.isAssignableFrom(pjp.getSignature().getDeclaringType()) && pjp.getArgs().length == 2 diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java index 4a98735af..ff556d89a 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java @@ -33,6 +33,7 @@ import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -42,6 +43,7 @@ import java.util.Map; import java.util.Optional; import java.util.Random; + import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -65,6 +67,7 @@ public final class LambdaLoggingAspect { private static final String LOG_LEVEL = System.getenv("POWERTOOLS_LOG_LEVEL"); private static final String SAMPLING_RATE = System.getenv("POWERTOOLS_LOGGER_SAMPLE_RATE"); + private static Boolean LOG_EVENT; private static Level LEVEL_AT_INITIALISATION; @@ -74,6 +77,13 @@ public final class LambdaLoggingAspect { } LEVEL_AT_INITIALISATION = LOG.getLevel(); + + String logEvent = System.getenv("POWERTOOLS_LOGGER_LOG_EVENT"); + if (logEvent != null) { + LOG_EVENT = Boolean.parseBoolean(logEvent); + } else { + LOG_EVENT = false; + } } private static void resetLogLevels(Level logLevel) { @@ -104,7 +114,9 @@ public Object around(ProceedingJoinPoint pjp, getXrayTraceId().ifPresent(xRayTraceId -> appendKey("xray_trace_id", xRayTraceId)); - if (logging.logEvent()) { + // Check that the environment variable was enabled explicitly + // Or that the handler was annotated with @Logging(logEvent = true) + if (LOG_EVENT || logging.logEvent()) { proceedArgs = logEvent(pjp); } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventDisabled.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventDisabled.java new file mode 100644 index 000000000..77103e450 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventDisabled.java @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowerToolLogEventDisabled implements RequestHandler { + + @Logging(logEvent = false) + @Override + public Object handleRequest(Object input, Context context) { + return null; + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index 6952fe755..75cf22aa5 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -14,19 +14,6 @@ package software.amazon.lambda.powertools.logging.internal; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonList; -import static java.util.stream.Collectors.joining; -import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; -import static org.skyscreamer.jsonassert.JSONAssert.assertEquals; -import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getProperty; -import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; - import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; @@ -37,24 +24,10 @@ import com.amazonaws.services.lambda.runtime.tests.annotations.Event; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.channels.FileChannel; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.ThreadContext; import org.json.JSONException; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -62,18 +35,33 @@ import org.mockito.MockedStatic; import software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.core.internal.SystemWrapper; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayHttpApiCorrelationId; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayRestApiCorrelationId; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabled; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabledForStream; -import software.amazon.lambda.powertools.logging.handlers.PowerToolDisabled; -import software.amazon.lambda.powertools.logging.handlers.PowerToolDisabledForStream; -import software.amazon.lambda.powertools.logging.handlers.PowerToolLogEventEnabled; -import software.amazon.lambda.powertools.logging.handlers.PowerToolLogEventEnabledForStream; -import software.amazon.lambda.powertools.logging.handlers.PowerToolLogEventEnabledWithCustomMapper; -import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId; -import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabledWithClearState; -import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventBridgeCorrelationId; +import software.amazon.lambda.powertools.logging.handlers.*; + +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.channels.FileChannel; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonList; +import static java.util.stream.Collectors.joining; +import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.openMocks; +import static org.skyscreamer.jsonassert.JSONAssert.assertEquals; +import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getProperty; +import static software.amazon.lambda.powertools.core.internal.SystemWrapper.getenv; class LambdaLoggingAspectTest { @@ -116,7 +104,7 @@ void shouldSetLambdaContextWhenEnabled() { void shouldSetLambdaContextForStreamHandlerWhenEnabled() throws IOException { requestStreamHandler = new PowerLogToolEnabledForStream(); - requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), + requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), context); assertThat(ThreadContext.getImmutableContext()) @@ -132,14 +120,14 @@ void shouldSetLambdaContextForStreamHandlerWhenEnabled() throws IOException { @Test void shouldSetColdStartFlag() throws IOException { - requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), + requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), context); assertThat(ThreadContext.getImmutableContext()) .hasSize(EXPECTED_CONTEXT_SIZE) .containsEntry("coldStart", "true"); - requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), + requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), context); assertThat(ThreadContext.getImmutableContext()) @@ -195,6 +183,51 @@ void shouldLogEventForHandler() throws IOException, JSONException { assertEquals(expectEvent, event, false); } + /** + * If POWERTOOLS_LOGGER_LOG_EVENT was set to true, the handler should log, despite @Logging(logEvent=false) + * + * @throws IOException + */ + @Test + void shouldLogEventForHandlerWhenEnvVariableSetToTrue() throws IOException, IllegalAccessException, JSONException { + try { + writeStaticField(LambdaLoggingAspect.class, "LOG_EVENT", Boolean.TRUE, true); + + requestHandler = new PowerToolLogEventDisabled(); + S3EventNotification s3EventNotification = s3EventNotification(); + + requestHandler.handleRequest(s3EventNotification, context); + + Map log = parseToMap(Files.lines(Paths.get("target/logfile.json")).collect(joining())); + + String event = (String) log.get("message"); + + String expectEvent = new BufferedReader( + new InputStreamReader(this.getClass().getResourceAsStream("/s3EventNotification.json"))) + .lines().collect(joining("\n")); + + assertEquals(expectEvent, event, false); + } finally { + writeStaticField(LambdaLoggingAspect.class, "LOG_EVENT", Boolean.FALSE, true); + } + } + + /** + * If POWERTOOLS_LOGGER_LOG_EVENT was set to false and @Logging(logEvent=false), the handler shouldn't log + * + * @throws IOException + */ + @Test + void shouldNotLogEventForHandlerWhenEnvVariableSetToFalse() throws IOException { + requestHandler = new PowerToolLogEventDisabled(); + S3EventNotification s3EventNotification = s3EventNotification(); + + requestHandler.handleRequest(s3EventNotification, context); + + Assertions.assertEquals(0, + Files.lines(Paths.get("target/logfile.json")).collect(joining()).length()); + } + @Test void shouldLogEventForHandlerWithOverriddenObjectMapper() throws IOException, JSONException { RequestHandler handler = new PowerToolLogEventEnabledWithCustomMapper(); From 30c8d33d0d663ec0d6512cfbcea49e2e68aff0c9 Mon Sep 17 00:00:00 2001 From: jdoherty Date: Tue, 14 Nov 2023 14:29:35 +0000 Subject: [PATCH 095/577] chore: Addition of Warn Message If Invalid Annotation Key While Tracing #1511 (#1512) --- .../powertools/tracing/TracingUtils.java | 21 +++++++++++++++++++ .../powertools/tracing/TracingUtilsTest.java | 21 +++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java index 9fb021548..47c4e7422 100644 --- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java +++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/TracingUtils.java @@ -21,12 +21,15 @@ import com.amazonaws.xray.entities.Subsegment; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.function.Consumer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A class of helper functions to add additional functionality and ease * of use. */ public final class TracingUtils { + private static final Logger LOG = LoggerFactory.getLogger(TracingUtils.class); private static ObjectMapper objectMapper; /** @@ -36,6 +39,10 @@ public final class TracingUtils { * @param value the value of the annotation */ public static void putAnnotation(String key, String value) { + if (!isValidAnnotationKey(key)) { + LOG.warn("Ignoring annotation with unsupported characters in key: {}", key); + return; + } AWSXRay.getCurrentSubsegmentOptional() .ifPresent(segment -> segment.putAnnotation(key, value)); } @@ -47,10 +54,24 @@ public static void putAnnotation(String key, String value) { * @param value the value of the annotation */ public static void putAnnotation(String key, Number value) { + if (!isValidAnnotationKey(key)) { + LOG.warn("Ignoring annotation with unsupported characters in key: {}", key); + return; + } AWSXRay.getCurrentSubsegmentOptional() .ifPresent(segment -> segment.putAnnotation(key, value)); } + /** + Make sure that the annotation key is valid according to + the documentation. + + Annotation keys that are added that are invalid are ignored by x-ray. + **/ + private static boolean isValidAnnotationKey(String key) { + return key.matches("^[a-zA-Z0-9_]+$"); + } + /** * Put an annotation to the current subsegment with a Boolean value. * diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java index 78283fbc2..01f25f37a 100644 --- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java +++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java @@ -28,7 +28,6 @@ import org.junit.jupiter.api.Test; class TracingUtilsTest { - @BeforeEach void setUp() { AWSXRay.beginSegment("test"); @@ -123,6 +122,24 @@ void shouldInvokeCodeBlockWrappedWithinSubsegment() { }); } + @Test + void shouldNotAddAnnotationIfInvalidCharacterInKey() { + AWSXRay.beginSubsegment("subSegment"); + String inputKey = "stringKey with spaces"; + TracingUtils.putAnnotation(inputKey, "val"); + AWSXRay.getCurrentSubsegmentOptional() + .ifPresent(segment -> assertThat(segment.getAnnotations()).size().isEqualTo(0)); + } + + @Test + void shouldAddAnnotationIfValidCharactersInKey() { + AWSXRay.beginSubsegment("subSegment"); + String inputKey = "validKey"; + TracingUtils.putAnnotation(inputKey, "val"); + AWSXRay.getCurrentSubsegmentOptional() + .ifPresent(segment -> assertThat(segment.getAnnotations()).size().isEqualTo(1)); + } + @Test void shouldInvokeCodeBlockWrappedWithinNamespacedSubsegment() { Context test = mock(Context.class); @@ -221,4 +238,4 @@ void shouldInvokeCodeBlockWrappedWithinNamespacedEntitySubsegment() throws Inter .containsEntry("key", "val"); }); } -} \ No newline at end of file +} From 6b8fe49dddf33c8d63b1346a365b3e7cfdff4f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Thu, 16 Nov 2023 13:23:18 +0100 Subject: [PATCH 096/577] feat: ALC (#1514) * handle AWS_LAMBDA_LOG configuration * ALC documentation + code review * update doc --- docs/core/logging.md | 44 ++++- powertools-logging/pom.xml | 10 ++ .../logging/internal/LambdaLoggingAspect.java | 19 +- .../internal/LambdaTimestampResolver.java | 169 ++++++++++++++++++ .../LambdaTimestampResolverFactory.java | 49 +++++ .../logging/internal/LoggingConstants.java | 27 +++ .../src/main/resources/LambdaJsonLayout.json | 2 +- .../core/layout/LambdaJsonLayoutTest.java | 31 +++- 8 files changed, 344 insertions(+), 7 deletions(-) create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolver.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolverFactory.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java diff --git a/docs/core/logging.md b/docs/core/logging.md index fd74db3d2..0391ae7b4 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -263,7 +263,7 @@ When debugging in non-production environments, you can instruct Logger to log th } ``` -### Customising fields in logs +### Customising fields in logs - Utility by default emits `timestamp` field in the logs in format `yyyy-MM-dd'T'HH:mm:ss.SSSZz` and in system default timezone. If you need to customize format and timezone, you can do so by configuring `log4j2.component.properties` and configuring properties as shown in example below: @@ -596,6 +596,48 @@ via `samplingRate` attribute on annotation. POWERTOOLS_LOGGER_SAMPLE_RATE: 0.5 ``` +## AWS Lambda Advanced Logging Controls +With AWS [Lambda Advanced Logging Controls (ALC)](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced), you can control the output format of your logs as either `TEXT` or `JSON` and specify the minimum accepted log level for your application. +Regardless of the output format setting in Lambda, Powertools for AWS Lambda will always output JSON formatted logging messages. + +When you have this feature enabled, log messages that don’t meet the configured log level are discarded by Lambda. +For example, if you set the minimum log level to `WARN`, you will only receive `WARN` and `ERROR` messages in your AWS CloudWatch Logs, all other log levels will be discarded by Lambda. + +```mermaid +sequenceDiagram + participant Lambda service + participant Lambda function + participant Application Logger + + Note over Lambda service: AWS_LAMBDA_LOG_LEVEL="WARN" + Lambda service->>Lambda function: Invoke (event) + Lambda function->>Lambda function: Calls handler + Lambda function->>Application Logger: logger.warn("Something happened") + Lambda function-->>Application Logger: logger.debug("Something happened") + Lambda function-->>Application Logger: logger.info("Something happened") + + Lambda service->>Lambda service: DROP INFO and DEBUG logs + + Lambda service->>CloudWatch Logs: Ingest error logs +``` + +Logger will automatically listen for the `AWS_LAMBDA_LOG_FORMAT` and `AWS_LAMBDA_LOG_LEVEL` environment variables, and change behaviour if they’re found to ensure as much compatibility as possible. + +### Priority of log level settings in Powertools for AWS Lambda + +When the Advanced Logging Controls feature is enabled, we are unable to increase the minimum log level below the `AWS_LAMBDA_LOG_LEVEL` environment variable value, see [AWS Lambda service documentation](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-log-level) for more details. + +We prioritise log level settings in this order: + +1. `AWS_LAMBDA_LOG_LEVEL` environment variable +2. `POWERTOOLS_LOG_LEVEL` environment variable + +In the event you have set `POWERTOOLS_LOG_LEVEL` to a level lower than the ACL setting, Powertools for AWS Lambda will output a warning log message informing you that your messages will be discarded by Lambda. + +### Timestamp format + +When the Advanced Logging Controls feature is enabled, Powertools for AWS Lambda must comply with the timestamp format required by AWS Lambda, which is [RFC3339](https://www.rfc-editor.org/rfc/rfc3339). +In this case the format will be `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'`. ## Upgrade to JsonTemplateLayout from deprecated LambdaJsonLayout configuration in log4j2.xml diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index c31448e30..e4767893b 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -137,6 +137,16 @@ org.apache.maven.plugins maven-checkstyle-plugin + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + JSON + + + \ No newline at end of file diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java index ff556d89a..da770ccdb 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java @@ -28,6 +28,7 @@ import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKey; import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKeys; import static software.amazon.lambda.powertools.logging.LoggingUtils.objectMapper; +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.LAMBDA_LOG_LEVEL; import com.amazonaws.services.lambda.runtime.Context; import com.fasterxml.jackson.core.JsonPointer; @@ -63,17 +64,27 @@ @DeclarePrecedence("*, software.amazon.lambda.powertools.logging.internal.LambdaLoggingAspect") public final class LambdaLoggingAspect { private static final Logger LOG = LogManager.getLogger(LambdaLoggingAspect.class); - private static final Random SAMPLER = new Random(); + private static final String POWERTOOLS_LOG_LEVEL = System.getenv("POWERTOOLS_LOG_LEVEL"); - private static final String LOG_LEVEL = System.getenv("POWERTOOLS_LOG_LEVEL"); + private static final Random SAMPLER = new Random(); private static final String SAMPLING_RATE = System.getenv("POWERTOOLS_LOGGER_SAMPLE_RATE"); private static Boolean LOG_EVENT; private static Level LEVEL_AT_INITIALISATION; static { - if (null != LOG_LEVEL) { - resetLogLevels(Level.getLevel(LOG_LEVEL)); + if (POWERTOOLS_LOG_LEVEL != null) { + Level powertoolsLevel = Level.getLevel(POWERTOOLS_LOG_LEVEL); + if (LAMBDA_LOG_LEVEL != null) { + Level lambdaLevel = Level.getLevel(LAMBDA_LOG_LEVEL); + if (powertoolsLevel.intLevel() > lambdaLevel.intLevel()) { + LOG.warn("Current log level ({}) does not match AWS Lambda Advanced Logging Controls minimum log level ({}). This can lead to data loss, consider adjusting them.", + POWERTOOLS_LOG_LEVEL, LAMBDA_LOG_LEVEL); + } + } + resetLogLevels(powertoolsLevel); + } else if (LAMBDA_LOG_LEVEL != null) { + resetLogLevels(Level.getLevel(LAMBDA_LOG_LEVEL)); } LEVEL_AT_INITIALISATION = LOG.getLevel(); diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolver.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolver.java new file mode 100644 index 000000000..500b36c95 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolver.java @@ -0,0 +1,169 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.LAMBDA_LOG_FORMAT; +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.LOG_DATE_RFC3339_FORMAT; + +import java.util.Locale; +import java.util.TimeZone; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.time.MutableInstant; +import org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults; +import org.apache.logging.log4j.layout.template.json.resolver.EventResolver; +import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverConfig; +import org.apache.logging.log4j.layout.template.json.util.InstantFormatter; +import org.apache.logging.log4j.layout.template.json.util.JsonWriter; + +/** + * Default timestamp used by log4j is not RFC3339, which is used by Lambda internally to filter logs. + * When `AWS_LAMBDA_LOG_FORMAT` is set to JSON (i.e. using Lambda logging configuration), we should use the appropriate pattern, + * otherwise logs with invalid date format are considered as INFO. + * Inspired from org.apache.logging.log4j.layout.template.json.resolver.TimestampResolver + * + * TODO: remove in v2 an replace with the good pattern in LambdaJsonLayout.json + */ +public class LambdaTimestampResolver implements EventResolver { + + private final EventResolver internalResolver; + + public LambdaTimestampResolver(final TemplateResolverConfig config) { + final PatternResolverContext patternResolverContext = + PatternResolverContext.fromConfig(config); + internalResolver = new PatternResolver(patternResolverContext); + } + + @Override + public void resolve(LogEvent value, JsonWriter jsonWriter) { + internalResolver.resolve(value, jsonWriter); + } + + static String getName() { + return "lambda-timestamp"; + } + + private static final class PatternResolverContext { + + public static final String PATTERN = "pattern"; + private final InstantFormatter formatter; + + private final StringBuilder lastFormattedInstantBuffer = new StringBuilder(); + + private final MutableInstant lastFormattedInstant = new MutableInstant(); + + private PatternResolverContext( + final String pattern, + final TimeZone timeZone, + final Locale locale) { + this.formatter = InstantFormatter + .newBuilder() + .setPattern(pattern) + .setTimeZone(timeZone) + .setLocale(locale) + .build(); + lastFormattedInstant.initFromEpochSecond(-1, 0); + } + + private static PatternResolverContext fromConfig( + final TemplateResolverConfig config) { + final String pattern = readPattern(config); + final TimeZone timeZone = readTimeZone(config); + final Locale locale = config.getLocale(new String[]{PATTERN, "locale"}); + return new PatternResolverContext(pattern, timeZone, locale); + } + + private static String readPattern(final TemplateResolverConfig config) { + final String format = config.getString(new String[]{PATTERN, "format"}); + return format != null + ? format + : getLambdaTimestampFormatOrDefault(); + } + + private static String getLambdaTimestampFormatOrDefault() { + return "JSON".equals(LAMBDA_LOG_FORMAT) ? LOG_DATE_RFC3339_FORMAT : + JsonTemplateLayoutDefaults.getTimestampFormatPattern(); + } + + private static TimeZone readTimeZone(final TemplateResolverConfig config) { + final String timeZoneId = config.getString(new String[]{PATTERN, "timeZone"}); + if (timeZoneId == null) { + return JsonTemplateLayoutDefaults.getTimeZone(); + } + boolean found = false; + for (final String availableTimeZone : TimeZone.getAvailableIDs()) { + if (availableTimeZone.equalsIgnoreCase(timeZoneId)) { + found = true; + break; + } + } + if (!found) { + throw new IllegalArgumentException( + "invalid timestamp time zone: " + config); + } + return TimeZone.getTimeZone(timeZoneId); + } + + } + + private static final class PatternResolver implements EventResolver { + + private final PatternResolverContext patternResolverContext; + + private PatternResolver(final PatternResolverContext patternResolverContext) { + this.patternResolverContext = patternResolverContext; + } + + @Override + public synchronized void resolve( + final LogEvent logEvent, + final JsonWriter jsonWriter) { + + // Format timestamp if it doesn't match the last cached one. + final boolean instantMatching = patternResolverContext.formatter.isInstantMatching( + patternResolverContext.lastFormattedInstant, + logEvent.getInstant()); + if (!instantMatching) { + + // Format the timestamp. + patternResolverContext.lastFormattedInstantBuffer.setLength(0); + patternResolverContext.lastFormattedInstant.initFrom(logEvent.getInstant()); + patternResolverContext.formatter.format( + patternResolverContext.lastFormattedInstant, + patternResolverContext.lastFormattedInstantBuffer); + + // Write the formatted timestamp. + final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder(); + final int startIndex = jsonWriterStringBuilder.length(); + jsonWriter.writeString(patternResolverContext.lastFormattedInstantBuffer); + + // Cache the written value. + patternResolverContext.lastFormattedInstantBuffer.setLength(0); + patternResolverContext.lastFormattedInstantBuffer.append( + jsonWriterStringBuilder, + startIndex, + jsonWriterStringBuilder.length()); + + } + + // Write the cached formatted timestamp. + else { + jsonWriter.writeRawString( + patternResolverContext.lastFormattedInstantBuffer); + } + + } + + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolverFactory.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolverFactory.java new file mode 100644 index 000000000..2022c6d4a --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolverFactory.java @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext; +import org.apache.logging.log4j.layout.template.json.resolver.EventResolverFactory; +import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver; +import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverConfig; +import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverFactory; + +@Plugin(name = "LambdaTimestampResolverFactory", category = TemplateResolverFactory.CATEGORY) +public final class LambdaTimestampResolverFactory implements EventResolverFactory { + + private static final LambdaTimestampResolverFactory INSTANCE = new LambdaTimestampResolverFactory(); + + private LambdaTimestampResolverFactory() { + } + + @PluginFactory + public static LambdaTimestampResolverFactory getInstance() { + return INSTANCE; + } + + @Override + public String getName() { + return LambdaTimestampResolver.getName(); + } + + @Override + public TemplateResolver create(EventResolverContext context, + TemplateResolverConfig config) { + return new LambdaTimestampResolver(config); + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java new file mode 100644 index 000000000..e58ca4109 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +public class LoggingConstants { + public static final String LAMBDA_LOG_LEVEL = System.getenv("AWS_LAMBDA_LOG_LEVEL"); + + public static final String LAMBDA_LOG_FORMAT = System.getenv("AWS_LAMBDA_LOG_FORMAT"); + + public static final String LOG_DATE_RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + + private LoggingConstants() { + // constants + } +} diff --git a/powertools-logging/src/main/resources/LambdaJsonLayout.json b/powertools-logging/src/main/resources/LambdaJsonLayout.json index dfc1fc78f..da3385032 100644 --- a/powertools-logging/src/main/resources/LambdaJsonLayout.json +++ b/powertools-logging/src/main/resources/LambdaJsonLayout.json @@ -1,6 +1,6 @@ { "timestamp": { - "$resolver": "timestamp" + "$resolver": "lambda-timestamp" }, "instant": { "epochSecond": { diff --git a/powertools-logging/src/test/java/org/apache/logging/log4j/core/layout/LambdaJsonLayoutTest.java b/powertools-logging/src/test/java/org/apache/logging/log4j/core/layout/LambdaJsonLayoutTest.java index 9b0c6165a..95fb9c47f 100644 --- a/powertools-logging/src/test/java/org/apache/logging/log4j/core/layout/LambdaJsonLayoutTest.java +++ b/powertools-logging/src/test/java/org/apache/logging/log4j/core/layout/LambdaJsonLayoutTest.java @@ -16,6 +16,7 @@ import static java.util.Collections.emptyMap; import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; +import static org.assertj.core.api.Assertions.as; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.mockito.Mockito.when; @@ -32,8 +33,12 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.format.ResolverStyle; import java.util.Map; import org.apache.logging.log4j.Level; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; @@ -42,7 +47,6 @@ import software.amazon.lambda.powertools.logging.internal.LambdaLoggingAspect; class LambdaJsonLayoutTest { - private RequestHandler handler = new PowerLogToolEnabled(); @Mock @@ -73,6 +77,31 @@ void shouldLogInStructuredFormat() throws IOException { .containsKey("service")); } + @Test + void shouldLogWithRFC3339TimestampFormat_WhenLambdaLoggingIsJSON() throws Exception { + // Given: AWS_LAMBDA_LOG_FORMAT=JSON defined in pom.xml + + // When + handler.handleRequest("test", context); + + // Then + assertThat(Files.lines(Paths.get("target/logfile.json"))) + .hasSize(1) + .allSatisfy(line -> assertThat(parseToMap(line)) + .extracting("timestamp", as(InstanceOfAssertFactories.STRING)) + .satisfies(s -> assertThat(hasDateFormat(s, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")).isTrue())); + } + + private boolean hasDateFormat(String timestamp, String format) { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format).withResolverStyle(ResolverStyle.STRICT); + try { + dtf.parse(timestamp); + return true; + } catch (DateTimeParseException e) { + return false; + } + } + @Test void shouldModifyLogLevelBasedOnEnvVariable() throws IllegalAccessException, IOException, NoSuchMethodException, InvocationTargetException { From 877ab51c10e19db78a06ee703121ac749342d043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Thu, 16 Nov 2023 14:36:51 +0100 Subject: [PATCH 097/577] chore:Prep release 1.18.0 (#1515) * chore:prep release 1.18.0 * update version * update version in kotlin example * maven local repo in gradle example * update changelog --------- Co-authored-by: scottgerring --- CHANGELOG.md | 31 +++++++++++++++++++ README.md | 8 ++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- .../pom.xml | 2 +- .../powertools-examples-core/cdk/app/pom.xml | 2 +- .../cdk/infra/pom.xml | 2 +- .../gradle/build.gradle | 7 +++-- .../kotlin/build.gradle.kts | 6 ++-- examples/powertools-examples-core/sam/pom.xml | 2 +- .../serverless/pom.xml | 2 +- .../terraform/pom.xml | 2 +- .../powertools-examples-idempotency/pom.xml | 2 +- .../powertools-examples-parameters/pom.xml | 2 +- .../powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- .../powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-core/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-sqs/pom.xml | 2 +- powertools-test-suite/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 34 files changed, 72 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbb90ce3f..4b9f664fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,37 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo ## [Unreleased] +## [1.18.0] - 2023-11-16 + +### Added + +* feat: add support for [Lambda Advanced Logging Controls (ALC)](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced) (#1514) by @jeromevdl +* feat: Add support for POWERTOOLS_LOGGER_LOG_EVENT (#1510) by @AlexeySoshin + +### Maintenance + +* fix: json schema 403 error (#1457) by @jeromevdl +* fix: array jmespath fail in idempotency module (#1420) by @jeromevdl +* chore: java21 support in our build (#1488) by @jeromevdl +* chore: Addition of Warn Message If Invalid Annotation Key While Tracing #1511 (#1512) by @jdoherty +* fix: null namespace should fallback to default namespace (#1506) by @jeromevdl +* fix: get trace id from system property when env var is not set (#1503) by @mriccia +* chore: artifacts size on good branches (#1493) by @jeromevdl +* fix: enforce jackson databind version (#1472) by @jeromevdl +* chore: add missing projects and improve workflow (#1487) by @jeromevdl +* chore: Reporting size of the jars in GitHub comments (#1196) by @jeromevdl +* Deps: Bump third party dependencies to the latest versions. + +### Documentation + +* docs(customer-reference): add Vertex Pharmaceuticals as a customer reference (#1486) by @scottgerring +* docs: Adding Kotlin example. (#1454) by @jasoniharris +* docs: Terraform example (#1478) by @skal111 +* docs: Add Serveless Framework example (#1363) by @AlexeySoshin +* docs: Fix link to SQS large message migration guide (#1422) by @scottgerring +* docs(logging): correct log example keys (#1411) by @walmsles +* docs: Update gradle configuration readme (#1359) by @scottgerring + ## [1.17.0] - 2023-08-21 ### Added diff --git a/README.md b/README.md index 900395554..63ba35cc6 100644 --- a/README.md +++ b/README.md @@ -20,17 +20,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your software.amazon.lambda powertools-tracing - 1.17.0 + 1.18.0 software.amazon.lambda powertools-logging - 1.17.0 + 1.18.0 software.amazon.lambda powertools-metrics - 1.17.0 + 1.18.0 ... @@ -190,7 +190,7 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam ## Examples -See the latest release of the **[examples](https://github.com/aws-powertools/powertools-lambda-java/tree/v1.17.0/examples)** for example projects showcasing usage of different utilities. +See the latest release of the **[examples](https://github.com/aws-powertools/powertools-lambda-java/tree/v1.18.0/examples)** for example projects showcasing usage of different utilities. Have a demo project to contribute which showcase usage of different utilities from powertools? We are happy to accept it [here](CONTRIBUTING.md#security-issue-notifications). diff --git a/examples/pom.xml b/examples/pom.xml index 900f095f8..428c74af8 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-examples - 1.18.0-SNAPSHOT + 1.18.0 pom Powertools for AWS Lambda (Java) library Examples diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 99d3a97cc..af3655b9a 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 1.18.0 powertools-examples-batch jar Powertools for AWS Lambda (Java) library Examples - Batch diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index c195cd262..2df1ce9f6 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 1.18.0 powertools-examples-cloudformation jar diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml index b4652bd65..9d9435ac3 100644 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ b/examples/powertools-examples-core/cdk/app/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.16.1 + 1.17.0 powertools-examples-core-cdk jar diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index 216bf35d4..fd3cd313b 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -4,7 +4,7 @@ 4.0.0 software.amazon.lambda.examples cdk - 1.18.0-SNAPSHOT + 1.18.0 UTF-8 2.100.0 diff --git a/examples/powertools-examples-core/gradle/build.gradle b/examples/powertools-examples-core/gradle/build.gradle index 06aec59e8..0d6b0eee8 100644 --- a/examples/powertools-examples-core/gradle/build.gradle +++ b/examples/powertools-examples-core/gradle/build.gradle @@ -18,6 +18,7 @@ compileJava { } repositories { + mavenLocal() mavenCentral() } @@ -27,8 +28,8 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' - aspect 'software.amazon.lambda:powertools-tracing:1.17.0' - aspect 'software.amazon.lambda:powertools-logging:1.17.0' - aspect 'software.amazon.lambda:powertools-metrics:1.17.0' + aspect 'software.amazon.lambda:powertools-tracing:1.18.0' + aspect 'software.amazon.lambda:powertools-logging:1.18.0' + aspect 'software.amazon.lambda:powertools-metrics:1.18.0' } diff --git a/examples/powertools-examples-core/kotlin/build.gradle.kts b/examples/powertools-examples-core/kotlin/build.gradle.kts index fc363c1b9..f95d1099d 100644 --- a/examples/powertools-examples-core/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core/kotlin/build.gradle.kts @@ -14,9 +14,9 @@ dependencies { implementation("com.fasterxml.jackson.core:jackson-databind:2.13.2.2") implementation("com.amazonaws:aws-lambda-java-events:3.11.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2") - aspect("software.amazon.lambda:powertools-tracing:1.18.0-SNAPSHOT") - aspect("software.amazon.lambda:powertools-logging:1.18.0-SNAPSHOT") - aspect("software.amazon.lambda:powertools-metrics:1.18.0-SNAPSHOT") + aspect("software.amazon.lambda:powertools-tracing:1.18.0") + aspect("software.amazon.lambda:powertools-logging:1.18.0") + aspect("software.amazon.lambda:powertools-metrics:1.18.0") testImplementation("junit:junit:4.13.2") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") } diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index 997472344..adb5e13eb 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 1.18.0 powertools-examples-core-sam jar diff --git a/examples/powertools-examples-core/serverless/pom.xml b/examples/powertools-examples-core/serverless/pom.xml index 6fce1d2dd..36c7e7280 100644 --- a/examples/powertools-examples-core/serverless/pom.xml +++ b/examples/powertools-examples-core/serverless/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 1.18.0 powertools-examples-core-serverless jar diff --git a/examples/powertools-examples-core/terraform/pom.xml b/examples/powertools-examples-core/terraform/pom.xml index 2a55c31bc..532675717 100644 --- a/examples/powertools-examples-core/terraform/pom.xml +++ b/examples/powertools-examples-core/terraform/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 1.18.0 powertools-examples-core-terraform jar diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 4b8eba9c9..5e79debf4 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 1.18.0 powertools-examples-idempotency jar Powertools for AWS Lambda (Java) library Examples - Idempotency diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 0e07b0cbb..495d6c59c 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 1.18.0 powertools-examples-parameters jar Powertools for AWS Lambda (Java) library Examples - Parameters diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 495fe8b77..e54c84315 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 1.18.0 powertools-examples-serialization jar Powertools for AWS Lambda (Java) library Examples - Serialization diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 0338fe7d9..9d0b3f2a8 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 1.18.0 powertools-examples-sqs jar Powertools for AWS Lambda (Java) library Examples - SQS diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 65628f6b2..3cb4264c0 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.18.0-SNAPSHOT + 1.18.0 powertools-examples-validation jar Powertools for AWS Lambda (Java) library Examples - Validation diff --git a/mkdocs.yml b/mkdocs.yml index 0f9c065a7..a271c1260 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -88,7 +88,7 @@ extra_javascript: extra: powertools: - version: 1.17.0 # to update after each release (we do not want snapshot version here) + version: 1.18.0 # to update after each release (we do not want snapshot version here) repo_url: https://github.com/aws-powertools/powertools-lambda-java edit_uri: edit/main/docs diff --git a/pom.xml b/pom.xml index e1a0c5a6c..76b59d747 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-parent - 1.18.0-SNAPSHOT + 1.18.0 pom Powertools for AWS Lambda (Java) library Parent diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 0c59ce497..cedbcf317 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 1.18.0-SNAPSHOT + 1.18.0 A suite of utilities that makes batch message processing using AWS Lambda easier. diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index f6cd822a6..660f6e34a 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 Powertools for AWS Lambda (Java)library Cloudformation diff --git a/powertools-core/pom.xml b/powertools-core/pom.xml index b848e9f79..0d82530a0 100644 --- a/powertools-core/pom.xml +++ b/powertools-core/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 Powertools for AWS Lambda (Java) library Core diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 6507e3104..995aeb1c7 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -10,7 +10,7 @@ Fake handlers that use Powertools for AWS Lambda (Java). - 1.18.0-SNAPSHOT + 1.18.0 UTF-8 1.8 1.8 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 84760eac8..d2aeaed66 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 powertools-e2e-tests diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 8b3459dee..fe85d74fd 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-parent - 1.18.0-SNAPSHOT + 1.18.0 powertools-idempotency diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 8fdae2139..2d5540c54 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ software.amazon.lambda powertools-parent - 1.18.0-SNAPSHOT + 1.18.0 powertools-large-messages diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index e4767893b..6fd4ce89f 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 Powertools for AWS Lambda (Java) library Logging diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index eff7296c8..677e18ed7 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 Powertools for AWS Lambda (Java) library Metrics diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 808232ab1..0e86a0a06 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 powertools-parameters diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index e5c4087fe..06b828923 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 powertools-serialization diff --git a/powertools-sqs/pom.xml b/powertools-sqs/pom.xml index c4b2b54f0..e14ec59b5 100644 --- a/powertools-sqs/pom.xml +++ b/powertools-sqs/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 Powertools for AWS Lambda (Java) library SQS diff --git a/powertools-test-suite/pom.xml b/powertools-test-suite/pom.xml index 34e80b06e..a6e84c4ac 100644 --- a/powertools-test-suite/pom.xml +++ b/powertools-test-suite/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 Powertools for AWS Lambda (Java) library Test Suite diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index d98a97e2a..f16bedd2f 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 Powertools for AWS Lambda (Java) library Tracing diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 24de0ba2a..a372e4740 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0-SNAPSHOT + 1.18.0 Powertools for AWS Lambda (Java) validation library From 2602ea7a058d6f644d36bb81e0eabd1ce15ae0fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:44:08 +0100 Subject: [PATCH 098/577] chore: update version to next snapshot: 1-19.0-SNAPSHOT (#1516) * update version to next snapshot: 1-19.0-SNAPSHOT * update version to next snapshot: 1-19.0-SNAPSHOT * update version to next snapshot: 1-19.0-SNAPSHOT * building only for LTS --- .github/workflows/pr_build.yml | 2 +- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core/cdk/infra/pom.xml | 2 +- examples/powertools-examples-core/gradle/build.gradle | 6 +++--- examples/powertools-examples-core/kotlin/build.gradle.kts | 6 +++--- examples/powertools-examples-core/sam/pom.xml | 2 +- examples/powertools-examples-core/serverless/pom.xml | 2 +- examples/powertools-examples-core/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-core/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-sqs/pom.xml | 2 +- powertools-test-suite/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 31 files changed, 35 insertions(+), 35 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index c316c0073..3cf3a5425 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -53,7 +53,7 @@ jobs: strategy: max-parallel: 5 matrix: - java: [8, 11, 17, 21, 15, 16, 18, 19, 20] + java: [8, 11, 17, 21] name: Java ${{ matrix.java }} env: JAVA: ${{ matrix.java }} diff --git a/examples/pom.xml b/examples/pom.xml index 428c74af8..5c423f251 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-examples - 1.18.0 + 1.19.0-SNAPSHOT pom Powertools for AWS Lambda (Java) library Examples diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index af3655b9a..c8f829997 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0 + 1.19.0-SNAPSHOT powertools-examples-batch jar Powertools for AWS Lambda (Java) library Examples - Batch diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 2df1ce9f6..54d6b50ef 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0 + 1.19.0-SNAPSHOT powertools-examples-cloudformation jar diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index fd3cd313b..e2a1d6b9a 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -4,7 +4,7 @@ 4.0.0 software.amazon.lambda.examples cdk - 1.18.0 + 1.19.0-SNAPSHOT UTF-8 2.100.0 diff --git a/examples/powertools-examples-core/gradle/build.gradle b/examples/powertools-examples-core/gradle/build.gradle index 0d6b0eee8..520b689cb 100644 --- a/examples/powertools-examples-core/gradle/build.gradle +++ b/examples/powertools-examples-core/gradle/build.gradle @@ -28,8 +28,8 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' - aspect 'software.amazon.lambda:powertools-tracing:1.18.0' - aspect 'software.amazon.lambda:powertools-logging:1.18.0' - aspect 'software.amazon.lambda:powertools-metrics:1.18.0' + aspect 'software.amazon.lambda:powertools-tracing:1.19.0-SNAPSHOT' + aspect 'software.amazon.lambda:powertools-logging:1.19.0-SNAPSHOT' + aspect 'software.amazon.lambda:powertools-metrics:1.19.0-SNAPSHOT' } diff --git a/examples/powertools-examples-core/kotlin/build.gradle.kts b/examples/powertools-examples-core/kotlin/build.gradle.kts index f95d1099d..4a167f225 100644 --- a/examples/powertools-examples-core/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core/kotlin/build.gradle.kts @@ -14,9 +14,9 @@ dependencies { implementation("com.fasterxml.jackson.core:jackson-databind:2.13.2.2") implementation("com.amazonaws:aws-lambda-java-events:3.11.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2") - aspect("software.amazon.lambda:powertools-tracing:1.18.0") - aspect("software.amazon.lambda:powertools-logging:1.18.0") - aspect("software.amazon.lambda:powertools-metrics:1.18.0") + aspect("software.amazon.lambda:powertools-tracing:1.19.0-SNAPSHOT") + aspect("software.amazon.lambda:powertools-logging:1.19.0-SNAPSHOT") + aspect("software.amazon.lambda:powertools-metrics:1.19.0-SNAPSHOT") testImplementation("junit:junit:4.13.2") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") } diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index adb5e13eb..16f82ebd6 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0 + 1.19.0-SNAPSHOT powertools-examples-core-sam jar diff --git a/examples/powertools-examples-core/serverless/pom.xml b/examples/powertools-examples-core/serverless/pom.xml index 36c7e7280..f8d9ab684 100644 --- a/examples/powertools-examples-core/serverless/pom.xml +++ b/examples/powertools-examples-core/serverless/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0 + 1.19.0-SNAPSHOT powertools-examples-core-serverless jar diff --git a/examples/powertools-examples-core/terraform/pom.xml b/examples/powertools-examples-core/terraform/pom.xml index 532675717..eef73207e 100644 --- a/examples/powertools-examples-core/terraform/pom.xml +++ b/examples/powertools-examples-core/terraform/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0 + 1.19.0-SNAPSHOT powertools-examples-core-terraform jar diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 5e79debf4..bf4c041bf 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ 4.0.0 software.amazon.lambda.examples - 1.18.0 + 1.19.0-SNAPSHOT powertools-examples-idempotency jar Powertools for AWS Lambda (Java) library Examples - Idempotency diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 495d6c59c..2aa813ff4 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.18.0 + 1.19.0-SNAPSHOT powertools-examples-parameters jar Powertools for AWS Lambda (Java) library Examples - Parameters diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index e54c84315..4f2b8ffda 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.18.0 + 1.19.0-SNAPSHOT powertools-examples-serialization jar Powertools for AWS Lambda (Java) library Examples - Serialization diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 9d0b3f2a8..a6737bfed 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.18.0 + 1.19.0-SNAPSHOT powertools-examples-sqs jar Powertools for AWS Lambda (Java) library Examples - SQS diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 3cb4264c0..42d484ed1 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 1.18.0 + 1.19.0-SNAPSHOT powertools-examples-validation jar Powertools for AWS Lambda (Java) library Examples - Validation diff --git a/pom.xml b/pom.xml index 76b59d747..0ac62cbda 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-parent - 1.18.0 + 1.19.0-SNAPSHOT pom Powertools for AWS Lambda (Java) library Parent diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index cedbcf317..fabaeba30 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 1.18.0 + 1.19.0-SNAPSHOT A suite of utilities that makes batch message processing using AWS Lambda easier. diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 660f6e34a..54c104468 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT Powertools for AWS Lambda (Java)library Cloudformation diff --git a/powertools-core/pom.xml b/powertools-core/pom.xml index 0d82530a0..041950cf5 100644 --- a/powertools-core/pom.xml +++ b/powertools-core/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT Powertools for AWS Lambda (Java) library Core diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 995aeb1c7..502b14eb3 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -10,7 +10,7 @@ Fake handlers that use Powertools for AWS Lambda (Java). - 1.18.0 + 1.19.0-SNAPSHOT UTF-8 1.8 1.8 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index d2aeaed66..05c544641 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT powertools-e2e-tests diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index fe85d74fd..94aceebfc 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-parent - 1.18.0 + 1.19.0-SNAPSHOT powertools-idempotency diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 2d5540c54..04e46dc6e 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ software.amazon.lambda powertools-parent - 1.18.0 + 1.19.0-SNAPSHOT powertools-large-messages diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 6fd4ce89f..78c36f41a 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT Powertools for AWS Lambda (Java) library Logging diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 677e18ed7..53df4cf57 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT Powertools for AWS Lambda (Java) library Metrics diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 0e86a0a06..788ac9438 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT powertools-parameters diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 06b828923..70280a0b8 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT powertools-serialization diff --git a/powertools-sqs/pom.xml b/powertools-sqs/pom.xml index e14ec59b5..d65458d5e 100644 --- a/powertools-sqs/pom.xml +++ b/powertools-sqs/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT Powertools for AWS Lambda (Java) library SQS diff --git a/powertools-test-suite/pom.xml b/powertools-test-suite/pom.xml index a6e84c4ac..50e473ad1 100644 --- a/powertools-test-suite/pom.xml +++ b/powertools-test-suite/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT Powertools for AWS Lambda (Java) library Test Suite diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index f16bedd2f..26bc0aa16 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT Powertools for AWS Lambda (Java) library Tracing diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index a372e4740..11ad1398f 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 1.18.0 + 1.19.0-SNAPSHOT Powertools for AWS Lambda (Java) validation library From 0c9b9ab9a542e581a06faf41deac0f1acc053378 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Fri, 17 Nov 2023 13:46:53 +0100 Subject: [PATCH 099/577] Add some more margin to the test pause (#1518) --- .../amazon/lambda/powertools/LargeMessageIdempotentE2ET.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageIdempotentE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageIdempotentE2ET.java index e8ee3ca5c..ef342ea13 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageIdempotentE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageIdempotentE2ET.java @@ -107,7 +107,7 @@ public static void tearDown() { @Test public void test_ttlNotExpired_doesNotInsertInDDB_ttlExpired_insertInDDB() throws InterruptedException, IOException { - int waitMs = 10000; + int waitMs = 15000; // GIVEN InputStream inputStream = this.getClass().getResourceAsStream("/large_sqs_message.txt"); From 76cd36306633489b1e1651e1fb281b267922f2e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Fri, 17 Nov 2023 15:00:23 +0100 Subject: [PATCH 100/577] test: e2e tests with java 21 (#1517) * e2e tests with java 21 * Run Java21 tests using the Java17 compiler * Run all of the E2E tests in parallel, not just the first 3 * Try again * . * Let's try again * Add some comment on Java21 to the repo * Add caveat about lambda runtimes * Clean up wording a little --------- Co-authored-by: Scott Gerring --- .github/workflows/run-e2e-tests.yml | 15 ++++++--- README.md | 8 +++++ docs/index.md | 10 +++++- powertools-e2e-tests/pom.xml | 2 +- .../powertools/testutils/Infrastructure.java | 32 ++++++++++++------- .../powertools/testutils/JavaRuntime.java | 3 +- 6 files changed, 51 insertions(+), 19 deletions(-) diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index a2a1b9aec..9e71f56af 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -32,13 +32,19 @@ jobs: e2e: runs-on: ubuntu-latest strategy: - max-parallel: 3 + max-parallel: 4 matrix: - java: [ 8, 11, 17 ] + java: [ 8, 11, 17, 21 ] name: End-to-end tests java${{ matrix.java }} env: - JAVA_VERSION: ${{ matrix.java }} AWS_DEFAULT_REGION: eu-west-1 + + # If matrix.version is 21, use 17, otherwise use matrix.version + # This is because AspectJ does not yet support weaving with Java21; we want + # to test the Java21 runtime, but we can't yet use the JDK21 compiler. + # https://github.com/eclipse-aspectj/aspectj/issues/260#issuecomment-1815920274 + JAVA_VERSION: ${{ (matrix.java == 21 && '17') || matrix.java }} + JAVA_LAMBDA_RUNTIME_VERSION: ${{ matrix.java }} permissions: id-token: write # needed to interact with GitHub's OIDC Token endpoint. contents: read @@ -48,7 +54,8 @@ jobs: uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'corretto' - java-version: ${{ matrix.java }} + # See comment above on JAVA_VERSION env var + java-version: ${{ (matrix.java == 21 && '17') || matrix.java }} cache: maven - name: Setup AWS credentials uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 diff --git a/README.md b/README.md index 63ba35cc6..bdf779bfb 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,14 @@ Powertools for AWS Lambda (Java) is a developer toolkit to implement Serverless **[📜Documentation](https://docs.powertools.aws.dev/lambda-java/)** | **[Feature request](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=)** | **[🐛Bug Report](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=bug%2C+triage&template=bug_report.md&title=)** | **[Detailed blog post](https://aws.amazon.com/blogs/opensource/simplifying-serverless-best-practices-with-aws-lambda-powertools-java/)** +### Java Compatibility +Powertools for AWS Lambda (Java) supports all Java version from 8 up to 21 as well as the +[corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). + +AspectJ does not yet support Java 21 [[1]](https://github.com/eclipse-aspectj/aspectj/issues/260), [[2]](https://github.com/eclipse-aspectj/aspectj/blob/master/docs/dist/doc/JavaVersionCompatibility.md). +If you need to use aspects - either Powertools features leveraging aspects or other libraries - you should use the JDK 17 compiler and target either the Java 17 or Java 21 +Lambda runtimes. + ### Installation Powertools for AWS Lambda (Java) is available in Maven Central. You can use your favourite dependency management tool to install it diff --git a/docs/index.md b/docs/index.md index 92589be7c..b1b55e2d6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,10 +11,18 @@ Powertools for AWS Lambda (Java) is a suite of utilities for AWS Lambda Function Powertools for AWS Lambda is also available for [Python](https://docs.powertools.aws.dev/lambda/python/latest/){target="_blank"}, [TypeScript](https://docs.powertools.aws.dev/lambda/typescript/latest/){target="_blank"}, and [.NET](https://docs.powertools.aws.dev/lambda/dotnet/){target="_blank"} -!!! tip "Looking for a quick run through of the core utilities?" +???+ tip "Looking for a quick run through of the core utilities?" Check out [this detailed blog post](https://aws.amazon.com/blogs/opensource/simplifying-serverless-best-practices-with-aws-lambda-powertools-java/) with a practical example. To dive deeper, the [Powertools for AWS Lambda (Java) workshop](https://catalog.us-east-1.prod.workshops.aws/workshops/a7011c82-e4af-4a52-80fa-fcd61f1dacd9/en-US/introduction) is a great next step. +???+ tip "Java Compatability" + Powertools for AWS Lambda (Java) supports all Java version from 8 up to 21 as well as the + [corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). + + AspectJ does not yet support Java 21 [[1]](https://github.com/eclipse-aspectj/aspectj/issues/260), [[2]](https://github.com/eclipse-aspectj/aspectj/blob/master/docs/dist/doc/JavaVersionCompatibility.md). + If you need to use aspects - either Powertools features leveraging aspects or other libraries - you should use the JDK 17 compiler and target either the Java 17 or Java 21 + Lambda runtimes. + ## Tenets This project separates core utilities that will be available in other runtimes vs general utilities that might not be available across all runtimes. diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 05c544641..8a0b65f32 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ 1.8 1.8 10.3.0 - 2.100.0 + 2.109.0 diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java index b1fab2883..11ee24b05 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java @@ -114,6 +114,7 @@ public class Infrastructure { private final String queue; private final String kinesisStream; private final String largeMessagesBucket; + private final JavaRuntime lambdaRuntimeVersion; private String ddbStreamsTableName; private String functionName; private Object cfnTemplate; @@ -124,6 +125,7 @@ private Infrastructure(Builder builder) { this.tracing = builder.tracing; this.envVar = builder.environmentVariables; this.runtime = builder.runtime; + this.lambdaRuntimeVersion = builder.lambdaRuntimeVersion; this.timeout = builder.timeoutInSeconds; this.pathToFunction = builder.pathToFunction; this.idempotencyTable = builder.idemPotencyTable; @@ -204,6 +206,7 @@ public void destroy() { private Stack createStackWithLambda() { boolean createTableForAsyncTests = false; Stack stack = new Stack(app, stackName); + List packagingInstruction = Arrays.asList( "/bin/sh", "-c", @@ -247,7 +250,7 @@ private Stack createStackWithLambda() { .handler("software.amazon.lambda.powertools.e2e.Function::handleRequest") .memorySize(1024) .timeout(Duration.seconds(timeout)) - .runtime(runtime.getCdkRuntime()) + .runtime(lambdaRuntimeVersion.getCdkRuntime()) .environment(envVar) .tracing(tracing ? Tracing.ACTIVE : Tracing.DISABLED) .build(); @@ -504,29 +507,34 @@ public static class Builder { private String queue; private String kinesisStream; private String ddbStreamsTableName; + private JavaRuntime lambdaRuntimeVersion; private Builder() { - getJavaRuntime(); + runtime = mapRuntimeVersion("JAVA_VERSION"); + lambdaRuntimeVersion = mapRuntimeVersion("JAVA_LAMBDA_RUNTIME_VERSION"); } - /** - * Retrieve the java runtime to use for the lambda function. - */ - private void getJavaRuntime() { - String javaVersion = System.getenv("JAVA_VERSION"); // must be set in GitHub actions + + + private JavaRuntime mapRuntimeVersion(String environmentVariableName) { + String javaVersion = System.getenv(environmentVariableName); // must be set in GitHub actions + JavaRuntime ret = null; if (javaVersion == null) { - throw new IllegalArgumentException("JAVA_VERSION is not set"); + throw new IllegalArgumentException("JAVA_LAMBDA_RUNTIME_VERSION is not set"); } if (javaVersion.startsWith("8")) { - runtime = JavaRuntime.JAVA8AL2; + ret = JavaRuntime.JAVA8AL2; } else if (javaVersion.startsWith("11")) { - runtime = JavaRuntime.JAVA11; + ret = JavaRuntime.JAVA11; } else if (javaVersion.startsWith("17")) { - runtime = JavaRuntime.JAVA17; + ret = JavaRuntime.JAVA17; + } else if (javaVersion.startsWith("21")) { + ret = JavaRuntime.JAVA21; } else { throw new IllegalArgumentException("Unsupported Java version " + javaVersion); } - LOG.debug("Java Version set to {}, using runtime {}", javaVersion, runtime.getRuntime()); + LOG.debug("Java Version set to {}, using runtime variable {}", ret, javaVersion); + return ret; } public Infrastructure build() { diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java index c50fcab84..c75682949 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java @@ -20,7 +20,8 @@ public enum JavaRuntime { JAVA8("java8", Runtime.JAVA_8, "1.8"), JAVA8AL2("java8.al2", Runtime.JAVA_8_CORRETTO, "1.8"), JAVA11("java11", Runtime.JAVA_11, "11"), - JAVA17("java17", Runtime.JAVA_17, "17"); + JAVA17("java17", Runtime.JAVA_17, "17"), + JAVA21("java21", Runtime.JAVA_21, "21"); private final String runtime; private final Runtime cdkRuntime; From ff4ee6890d2bc3ee1328c7c182185dc473a5a44b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Mon, 20 Nov 2023 07:46:09 +0100 Subject: [PATCH 101/577] update doc for ALC (#1520) --- docs/core/logging.md | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/docs/core/logging.md b/docs/core/logging.md index 0391ae7b4..70781b1b2 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -596,12 +596,18 @@ via `samplingRate` attribute on annotation. POWERTOOLS_LOGGER_SAMPLE_RATE: 0.5 ``` -## AWS Lambda Advanced Logging Controls -With AWS [Lambda Advanced Logging Controls (ALC)](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced), you can control the output format of your logs as either `TEXT` or `JSON` and specify the minimum accepted log level for your application. -Regardless of the output format setting in Lambda, Powertools for AWS Lambda will always output JSON formatted logging messages. +## AWS Lambda Advanced Logging Controls (ALC) -When you have this feature enabled, log messages that don’t meet the configured log level are discarded by Lambda. -For example, if you set the minimum log level to `WARN`, you will only receive `WARN` and `ERROR` messages in your AWS CloudWatch Logs, all other log levels will be discarded by Lambda. +!!!question "When is it useful?" + When you want to set a logging policy to drop informational or verbose logs for one or all AWS Lambda functions, regardless of runtime and logger used. + + +With [AWS Lambda Advanced Logging Controls (ALC)](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced){target="_blank"}, you can enforce a minimum log level that Lambda will accept from your application code. + +When enabled, you should keep `Logger` and ALC log level in sync to avoid data loss. + +Here's a sequence diagram to demonstrate how ALC will drop both `INFO` and `DEBUG` logs emitted from `Logger`, when ALC log level is stricter than `Logger`. + ```mermaid sequenceDiagram @@ -610,29 +616,29 @@ sequenceDiagram participant Application Logger Note over Lambda service: AWS_LAMBDA_LOG_LEVEL="WARN" + Note over Application Logger: POWERTOOLS_LOG_LEVEL="DEBUG" + Lambda service->>Lambda function: Invoke (event) Lambda function->>Lambda function: Calls handler - Lambda function->>Application Logger: logger.warn("Something happened") + Lambda function->>Application Logger: logger.error("Something happened") Lambda function-->>Application Logger: logger.debug("Something happened") Lambda function-->>Application Logger: logger.info("Something happened") - - Lambda service->>Lambda service: DROP INFO and DEBUG logs - + Lambda service--xLambda service: DROP INFO and DEBUG logs Lambda service->>CloudWatch Logs: Ingest error logs ``` -Logger will automatically listen for the `AWS_LAMBDA_LOG_FORMAT` and `AWS_LAMBDA_LOG_LEVEL` environment variables, and change behaviour if they’re found to ensure as much compatibility as possible. - ### Priority of log level settings in Powertools for AWS Lambda -When the Advanced Logging Controls feature is enabled, we are unable to increase the minimum log level below the `AWS_LAMBDA_LOG_LEVEL` environment variable value, see [AWS Lambda service documentation](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-log-level) for more details. - We prioritise log level settings in this order: 1. `AWS_LAMBDA_LOG_LEVEL` environment variable 2. `POWERTOOLS_LOG_LEVEL` environment variable -In the event you have set `POWERTOOLS_LOG_LEVEL` to a level lower than the ACL setting, Powertools for AWS Lambda will output a warning log message informing you that your messages will be discarded by Lambda. +If you set `Logger` level lower than ALC, we will emit a warning informing you that your messages will be discarded by Lambda. + +> **NOTE** +> +> With ALC enabled, we are unable to increase the minimum log level below the `AWS_LAMBDA_LOG_LEVEL` environment variable value, see [AWS Lambda service documentation](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-log-level){target="_blank"} for more details. ### Timestamp format From 8e4173a086158a539d3ab040f0a0d274807c00eb Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 20 Nov 2023 10:19:30 +0100 Subject: [PATCH 102/577] chore: Testing java21 aspectj pre-release (#1519) * e2e tests with java 21 * use aspectj 1.9.21-SNAPSHOT * Fix log4j2.xml missing in logging test for java21 * rollback double runtime * remove comment * keep aspectj 1.9.7 in parent for java8 compatibility * use M1 instead of snapshot * update documentation for aspectj * update documentation for aspectj --------- Co-authored-by: Jerome Van Der Linden --- README.md | 39 ++++-- docs/index.md | 43 ++++-- pom.xml | 3 +- powertools-e2e-tests/handlers/logging/pom.xml | 4 + powertools-e2e-tests/handlers/pom.xml | 126 +++++++----------- .../powertools/testutils/Infrastructure.java | 9 +- 6 files changed, 122 insertions(+), 102 deletions(-) diff --git a/README.md b/README.md index bdf779bfb..dbe8eb2fe 100644 --- a/README.md +++ b/README.md @@ -9,19 +9,11 @@ Powertools for AWS Lambda (Java) is a developer toolkit to implement Serverless **[📜Documentation](https://docs.powertools.aws.dev/lambda-java/)** | **[Feature request](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=)** | **[🐛Bug Report](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=bug%2C+triage&template=bug_report.md&title=)** | **[Detailed blog post](https://aws.amazon.com/blogs/opensource/simplifying-serverless-best-practices-with-aws-lambda-powertools-java/)** -### Java Compatibility -Powertools for AWS Lambda (Java) supports all Java version from 8 up to 21 as well as the -[corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). - -AspectJ does not yet support Java 21 [[1]](https://github.com/eclipse-aspectj/aspectj/issues/260), [[2]](https://github.com/eclipse-aspectj/aspectj/blob/master/docs/dist/doc/JavaVersionCompatibility.md). -If you need to use aspects - either Powertools features leveraging aspects or other libraries - you should use the JDK 17 compiler and target either the Java 17 or Java 21 -Lambda runtimes. - -### Installation +## Installation Powertools for AWS Lambda (Java) is available in Maven Central. You can use your favourite dependency management tool to install it -#### Maven: +### Maven: ```xml ... @@ -196,6 +188,33 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam ``` +### Java Compatibility +Powertools for AWS Lambda (Java) supports all Java version from 8 up to 21 as well as the +[corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). +For the modules that provide annotations, Powertools for AWS Lambda (Java) leverages the **aspectj** library. +You may need to add the good version of `aspectjrt` to your dependencies based on the JDK used for building your function: + +```xml + + org.aspectj + aspectjrt + 1.9.?? + +``` + +

+ JDK - aspectj dependency matrix + +| JDK version | aspectj version | +|-------------|-----------------| +| `1.8` | `1.9.7` | +| `11-17` | `1.9.20.1` | +| `21` | `1.9.21` | + +More info [here](https://github.com/aws-powertools/powertools-lambda-java/pull/1519/files#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R191). + +
+ ## Examples See the latest release of the **[examples](https://github.com/aws-powertools/powertools-lambda-java/tree/v1.18.0/examples)** for example projects showcasing usage of different utilities. diff --git a/docs/index.md b/docs/index.md index b1b55e2d6..884e02476 100644 --- a/docs/index.md +++ b/docs/index.md @@ -15,14 +15,6 @@ Powertools for AWS Lambda (Java) is a suite of utilities for AWS Lambda Function Check out [this detailed blog post](https://aws.amazon.com/blogs/opensource/simplifying-serverless-best-practices-with-aws-lambda-powertools-java/) with a practical example. To dive deeper, the [Powertools for AWS Lambda (Java) workshop](https://catalog.us-east-1.prod.workshops.aws/workshops/a7011c82-e4af-4a52-80fa-fcd61f1dacd9/en-US/introduction) is a great next step. -???+ tip "Java Compatability" - Powertools for AWS Lambda (Java) supports all Java version from 8 up to 21 as well as the - [corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). - - AspectJ does not yet support Java 21 [[1]](https://github.com/eclipse-aspectj/aspectj/issues/260), [[2]](https://github.com/eclipse-aspectj/aspectj/blob/master/docs/dist/doc/JavaVersionCompatibility.md). - If you need to use aspects - either Powertools features leveraging aspects or other libraries - you should use the JDK 17 compiler and target either the Java 17 or Java 21 - Lambda runtimes. - ## Tenets This project separates core utilities that will be available in other runtimes vs general utilities that might not be available across all runtimes. @@ -282,6 +274,41 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl Under the hood, `org.codehaus.mojo:aspectj-maven-plugin` is based on AspectJ 1.9.7, while `dev.aspectj:aspectj-maven-plugin` is based on AspectJ 1.9.8, compiled for Java 11+. +### Java Compatibility +Powertools for AWS Lambda (Java) supports all Java version from 8 up to 21 as well as the +[corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). + +For the following modules, Powertools for AWS Lambda (Java) leverages the **aspectj** library to provide annotations: +- Logging +- Metrics +- Tracing +- Parameters +- Idempotency +- Validation +- Large messages + + +You may need to add the good version of `aspectjrt` to your dependencies based on the jdk used for building your function: + +```xml + + org.aspectj + aspectjrt + 1.9.?? + +``` + +Use the following [dependency matrix](https://github.com/eclipse-aspectj/aspectj/blob/master/docs/dist/doc/JavaVersionCompatibility.md) between this library and the JDK: + +| JDK version | aspectj version | +|-------------|-----------------| +| `1.8` | `1.9.7` | +| `11-17` | `1.9.20.1` | +| `21` | `1.9.21` | + +_Note: 1.9.21 is not yet available and Java 21 not yet officially supported by aspectj, but you can already use the `1.9.21.M1`_ + + ## Environment variables !!! info diff --git a/pom.xml b/pom.xml index 0ac62cbda..3c30dc260 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,6 @@ 1.8 2.20.0 2.15.3 - 1.9.7 2.21.0 2.14.0 2.1.3 @@ -84,6 +83,7 @@ 3.11.3 1.1.2 3.11.0 + 1.9.7 1.13.1 3.1.2 0.8.10 @@ -516,6 +516,7 @@ + jdk16 diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml index 4b613f2bf..61ec6b414 100644 --- a/powertools-e2e-tests/handlers/logging/pom.xml +++ b/powertools-e2e-tests/handlers/logging/pom.xml @@ -17,6 +17,10 @@ software.amazon.lambda powertools-logging + + org.aspectj + aspectjrt + com.amazonaws aws-lambda-java-events diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 502b14eb3..a9096477b 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -42,7 +42,11 @@ pom import - + + org.aspectj + aspectjrt + ${aspectj.version} + software.amazon.lambda powertools-logging @@ -143,96 +147,66 @@ false + + dev.aspectj + aspectj-maven-plugin + ${aspectj.plugin.version} + + true + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + ignore + ${project.build.sourceEncoding} + + + + + compile + test-compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + - jdk8 + jdk8to16 - (,11) + [1.8,16] 1.9.7 - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - ignore - ${project.build.sourceEncoding} - - - - process-sources - - compile - test-compile - - - - - - - org.aspectj - aspectjtools - ${aspectj.version} - - - - - - - jdk11plus + jdk17to20 - [11,) + [17,20] - - - - - dev.aspectj - aspectj-maven-plugin - ${aspectj.plugin.version} - - ${maven.compiler.source} - ${maven.compiler.target} - ${maven.compiler.target} - ignore - ${project.build.sourceEncoding} - - - - process-sources - - compile - test-compile - - - - - - - + + 1.9.20.1 + + + + jdk21 + + [21,) + + + 1.9.21.M1 + diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java index 11ee24b05..28a0f2bb4 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java @@ -114,7 +114,6 @@ public class Infrastructure { private final String queue; private final String kinesisStream; private final String largeMessagesBucket; - private final JavaRuntime lambdaRuntimeVersion; private String ddbStreamsTableName; private String functionName; private Object cfnTemplate; @@ -125,7 +124,6 @@ private Infrastructure(Builder builder) { this.tracing = builder.tracing; this.envVar = builder.environmentVariables; this.runtime = builder.runtime; - this.lambdaRuntimeVersion = builder.lambdaRuntimeVersion; this.timeout = builder.timeoutInSeconds; this.pathToFunction = builder.pathToFunction; this.idempotencyTable = builder.idemPotencyTable; @@ -213,7 +211,6 @@ private Stack createStackWithLambda() { "cd " + pathToFunction + " && timeout -s SIGKILL 5m mvn clean install -ff " + " -Dmaven.test.skip=true " + - " -Dmaven.resources.skip=true " + " -Dmaven.compiler.source=" + runtime.getMvnProperty() + " -Dmaven.compiler.target=" + runtime.getMvnProperty() + " && cp /asset-input/" + pathToFunction + "/target/function.jar /asset-output/" @@ -250,7 +247,7 @@ private Stack createStackWithLambda() { .handler("software.amazon.lambda.powertools.e2e.Function::handleRequest") .memorySize(1024) .timeout(Duration.seconds(timeout)) - .runtime(lambdaRuntimeVersion.getCdkRuntime()) + .runtime(runtime.getCdkRuntime()) .environment(envVar) .tracing(tracing ? Tracing.ACTIVE : Tracing.DISABLED) .build(); @@ -507,11 +504,9 @@ public static class Builder { private String queue; private String kinesisStream; private String ddbStreamsTableName; - private JavaRuntime lambdaRuntimeVersion; private Builder() { runtime = mapRuntimeVersion("JAVA_VERSION"); - lambdaRuntimeVersion = mapRuntimeVersion("JAVA_LAMBDA_RUNTIME_VERSION"); } @@ -520,7 +515,7 @@ private JavaRuntime mapRuntimeVersion(String environmentVariableName) { String javaVersion = System.getenv(environmentVariableName); // must be set in GitHub actions JavaRuntime ret = null; if (javaVersion == null) { - throw new IllegalArgumentException("JAVA_LAMBDA_RUNTIME_VERSION is not set"); + throw new IllegalArgumentException(environmentVariableName + " is not set"); } if (javaVersion.startsWith("8")) { ret = JavaRuntime.JAVA8AL2; From 26730af1a93b962220efe8cf3a4b426e63095804 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Tue, 21 Nov 2023 16:47:06 +0100 Subject: [PATCH 103/577] Fix POM --- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 520b689cb..e85936350 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -28,8 +28,8 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' - aspect 'software.amazon.lambda:powertools-tracing:1.19.0-SNAPSHOT' - aspect 'software.amazon.lambda:powertools-logging:1.19.0-SNAPSHOT' - aspect 'software.amazon.lambda:powertools-metrics:1.19.0-SNAPSHOT' + aspect 'software.amazon.lambda:powertools-tracing:2.0.0-SNAPSHOT' + aspect 'software.amazon.lambda:powertools-logging:2.0.0-SNAPSHOT' + aspect 'software.amazon.lambda:powertools-metrics:2.0.0-SNAPSHOT' } From 628a2ca93223df2b2962d1bc122f32a6f572b382 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Wed, 22 Nov 2023 09:07:00 +0100 Subject: [PATCH 104/577] chore: Remove build cruft --- .github/workflows/run-e2e-tests.yml | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 9e71f56af..626268214 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -38,13 +38,7 @@ jobs: name: End-to-end tests java${{ matrix.java }} env: AWS_DEFAULT_REGION: eu-west-1 - - # If matrix.version is 21, use 17, otherwise use matrix.version - # This is because AspectJ does not yet support weaving with Java21; we want - # to test the Java21 runtime, but we can't yet use the JDK21 compiler. - # https://github.com/eclipse-aspectj/aspectj/issues/260#issuecomment-1815920274 - JAVA_VERSION: ${{ (matrix.java == 21 && '17') || matrix.java }} - JAVA_LAMBDA_RUNTIME_VERSION: ${{ matrix.java }} + JAVA_VERSION: ${{ matrix.java }} permissions: id-token: write # needed to interact with GitHub's OIDC Token endpoint. contents: read @@ -54,8 +48,7 @@ jobs: uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'corretto' - # See comment above on JAVA_VERSION env var - java-version: ${{ (matrix.java == 21 && '17') || matrix.java }} + java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 From 6141243f6c530c73669d318032fe07b28c36d26b Mon Sep 17 00:00:00 2001 From: jdoherty Date: Fri, 1 Dec 2023 09:31:57 +0000 Subject: [PATCH 105/577] chore: remove Java 8 from v2 examples (#1531) * Remove Java 8 issue #1466 * reverting pom to java 8 as change should only apply to examples * updated workflow to not build examples in java 8 workflow * updated syntax of workflow * excluding examples from spotbugs check for java 8 build * updated github actions workflow * updated workflows to have a comma seperated list of examples modules when java 8 to exclude * updating build syntax for non java 8 * updating gradle config for Java 11+ * updating the java version on spotbugs to 11 --- .github/workflows/pr_build.yml | 8 ++++-- .github/workflows/spotbugs.yml | 2 +- examples/README.md | 2 -- examples/powertools-examples-batch/pom.xml | 25 ++----------------- .../README.md | 11 +++++++- .../pom.xml | 24 ++---------------- .../cdk/app/pom.xml | 24 ++---------------- .../cdk/infra/pom.xml | 4 +-- .../gradle/README.md | 2 +- .../gradle/build.gradle | 8 +++--- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../gradle/template.yaml | 4 +-- .../kotlin/README.md | 2 +- .../kotlin/build.gradle.kts | 21 +++------------- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../sam/pom.xml | 24 ++---------------- .../serverless/pom.xml | 25 +++---------------- .../terraform/pom.xml | 24 ++---------------- .../powertools-examples-idempotency/pom.xml | 24 ++---------------- .../powertools-examples-parameters/pom.xml | 24 ++---------------- .../powertools-examples-serialization/pom.xml | 12 ++------- .../powertools-examples-validation/README.md | 2 +- 22 files changed, 53 insertions(+), 223 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index eb3cc053d..e86f49753 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -66,13 +66,17 @@ jobs: java-version: ${{ matrix.java }} cache: 'maven' - name: Build with Maven + if: ${{ matrix.java == '8' }} # If 8 exclude the examples directory + run: mvn -B install --file pom.xml -pl '!software.amazon.lambda.examples:powertools-examples-idempotency,!software.amazon.lambda.examples:powertools-examples-batch,!software.amazon.lambda.examples:powertools-examples-cloudformation,!software.amazon.lambda.examples:powertools-examples-core-utilities-cdk,!software.amazon.lambda.examples:powertools-examples-core-utilities-sam,!software.amazon.lambda.examples:powertools-examples-core-utilities-serverless,!software.amazon.lambda.examples:powertools-examples-core-utilities-terraform,!software.amazon.lambda.examples:powertools-examples-parameters,!software.amazon.lambda.examples:powertools-examples-serialization,!software.amazon.lambda.examples:powertools-examples-validation,!software.amazon.lambda.examples:cdk,!software.amazon.lambda:powertools-examples' + - name: Build with Maven + if: ${{ matrix.java != '8' }} # If not 8 don't exclude the examples directory run: mvn -B install --file pom.xml - name: Build Gradle Example - Java - if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 + if: ${{ matrix.java != '8' }} working-directory: examples/powertools-examples-core-utilities/gradle run: ./gradlew build - name: Build Gradle Example - Kotlin - if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 + if: ${{ matrix.java != '8' }} working-directory: examples/powertools-examples-core-utilities/kotlin run: ./gradlew build - name: Setup Terraform diff --git a/.github/workflows/spotbugs.yml b/.github/workflows/spotbugs.yml index d314107fa..f0d50d8c5 100644 --- a/.github/workflows/spotbugs.yml +++ b/.github/workflows/spotbugs.yml @@ -28,7 +28,7 @@ jobs: uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'corretto' - java-version: 8 + java-version: 11 # https://github.com/jwgmeligmeyling/spotbugs-github-action/issues/6 # https://github.blog/2020-08-03-github-actions-improvements-for-fork-and-pull-request-workflows/ # Avoid complexity of git action with publishing report. Just build with spotbugs profile. diff --git a/examples/README.md b/examples/README.md index aa8457def..2e34513db 100644 --- a/examples/README.md +++ b/examples/README.md @@ -63,8 +63,6 @@ If you're not using SAM, you can look for examples for other tools under [powert You can find more examples in the https://github.com/aws/aws-sam-cli-app-templates project: -* [Java 8 + Maven](https://github.com/aws/aws-sam-cli-app-templates/tree/master/java8/hello-pt-maven) -* [Java 8 on Amazon Linux 2 + Maven](https://github.com/aws/aws-sam-cli-app-templates/tree/master/java8.al2/hello-pt-maven) * [Java 11 + Maven](https://github.com/aws/aws-sam-cli-app-templates/tree/master/java11/hello-pt-maven) * [Java 17 + Maven](https://github.com/aws/aws-sam-cli-app-templates/tree/master/java17/hello-pt-maven) * [Java 17 + Gradle](https://github.com/aws/aws-sam-cli-app-templates/tree/master/java17/hello-pt-gradle) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index a5115aeeb..36660bc96 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -12,8 +12,8 @@ 2.20.0 - 1.8 - 1.8 + 11 + 11 1.9.20 2.21.1 @@ -143,25 +143,4 @@ - - - - - jdk8 - - (,11) - - - 1.9.7 - - - \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/README.md b/examples/powertools-examples-cloudformation/README.md index 4b53ff0aa..f0a15f1cd 100644 --- a/examples/powertools-examples-cloudformation/README.md +++ b/examples/powertools-examples-cloudformation/README.md @@ -2,18 +2,27 @@ This project contains an example of Lambda function using the CloudFormation module of Powertools for AWS Lambda in Java. For more information on this module, please refer to the [documentation](https://awslabs.github.io/aws-lambda-powertools-java/utilities/custom_resources/). +In this example you pass in a bucket name as a parameter and upon CloudFormation events a call is made to a lambda. That lambda attempts to create the bucket on CREATE events, create a new bucket if the name changes with an UPDATE event and delete the bucket upon DELETE events. + ## Deploy the sample application This sample can be used either with the Serverless Application Model (SAM) or with CDK. ### Deploy with SAM CLI To deploy it using the SAM CLI, check out the instructions for getting started in [the examples directory](../README.md) +Run the following in your shell: + +```bash +cd infra/sam +sam build +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-20230718 +``` ### Deploy with CDK To use CDK you need the following tools. * CDK - [Install CDK](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) -* Java 8 - [Install Java 8](https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/downloads-list.html) +* Java 11 - [Install Java 11](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/downloads-list.html) * Maven - [Install Maven](https://maven.apache.org/install.html) * Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index d179fbe2e..864ea5fe6 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -11,8 +11,8 @@ 2.20.0 - 1.8 - 1.8 + 11 + 11 1.2.3 3.11.3 2.21.0 @@ -169,24 +169,4 @@ - - - - jdk8 - - (,11) - - - 1.9.7 - - - diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index be8c9ca67..822e87633 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -12,8 +12,8 @@ 2.20.0 - 1.8 - 1.8 + 11 + 11 1.9.20 @@ -138,24 +138,4 @@ - - - - jdk8 - - (,11) - - - 1.9.7 - - - diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index d2b05b122..053bd239c 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -18,8 +18,8 @@ maven-compiler-plugin 3.11.0 - 1.8 - 1.8 + 11 + 11 diff --git a/examples/powertools-examples-core-utilities/gradle/README.md b/examples/powertools-examples-core-utilities/gradle/README.md index c7c798d5d..adc7fe635 100644 --- a/examples/powertools-examples-core-utilities/gradle/README.md +++ b/examples/powertools-examples-core-utilities/gradle/README.md @@ -1,7 +1,7 @@ # Powertools for AWS Lambda (Java) - Core Utilities Example with Gradle This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) with -[Gradle](https://gradle.org/) running the build. This example is configured for Java 1.8 only; in order to use a newer version, check out the Gradle +[Gradle](https://gradle.org/) running the build. This example is configured for Java 11 only; in order to use a newer version, check out the Gradle configuration guide [in the main project README](../../../README.md). You can also use `sam init` to create a new Gradle-powered Powertools application - choose to use the **AWS Quick Start Templates**, diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index e85936350..03971c406 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -1,16 +1,16 @@ plugins { id 'java' - id "io.freefair.aspectj.post-compile-weaving" version "6.6.3" + id "io.freefair.aspectj.post-compile-weaving" version "8.2.2" } wrapper { - gradleVersion = "7.6.1" + gradleVersion = "8.5" } compileJava { - sourceCompatibility = "1.8" - targetCompatibility = "1.8" + sourceCompatibility = "11" + targetCompatibility = "11" ajc { enabled = true diff --git a/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.properties b/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.properties index 0d23ac00c..1af9e0930 100644 --- a/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.properties +++ b/examples/powertools-examples-core-utilities/gradle/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/examples/powertools-examples-core-utilities/gradle/template.yaml b/examples/powertools-examples-core-utilities/gradle/template.yaml index a717c2998..1a1572fca 100644 --- a/examples/powertools-examples-core-utilities/gradle/template.yaml +++ b/examples/powertools-examples-core-utilities/gradle/template.yaml @@ -26,7 +26,7 @@ Resources: Properties: CodeUri: . Handler: helloworld.App::handleRequest - Runtime: java8 + Runtime: java11 MemorySize: 512 Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object Variables: @@ -43,7 +43,7 @@ Resources: Properties: CodeUri: . Handler: helloworld.AppStream::handleRequest - Runtime: java8 + Runtime: java11 MemorySize: 512 Tracing: Active Environment: diff --git a/examples/powertools-examples-core-utilities/kotlin/README.md b/examples/powertools-examples-core-utilities/kotlin/README.md index da9ec5b52..422e12742 100644 --- a/examples/powertools-examples-core-utilities/kotlin/README.md +++ b/examples/powertools-examples-core-utilities/kotlin/README.md @@ -1,7 +1,7 @@ # Powertools for AWS Lambda (Kotlin) - Core Utilities Example This project demonstrates the Lambda for Powertools Kotlin module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) with -[Gradle](https://gradle.org/) running the build. This example is configured for Java 1.8 only; in order to use a newer version, check out the Gradle +[Gradle](https://gradle.org/) running the build. This example is configured for Java 11 only; in order to use a newer version, check out the Gradle configuration guide [in the main project README](../../../README.md). You can also use `sam init` to create a new Gradle-powered Powertools application - choose to use the **AWS Quick Start Templates**, diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 29a29b0c4..1c16db0db 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("io.freefair.aspectj.post-compile-weaving") version "6.6.3" + id("io.freefair.aspectj.post-compile-weaving") version "8.2.2" kotlin("jvm") version "1.9.10" } @@ -21,19 +21,6 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") } -tasks.compileKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} - -tasks.compileTestKotlin { - kotlinOptions { - jvmTarget = "1.8" - } -} - -// If using JDK 11 or higher, use the following instead: -//kotlin { -// jvmToolchain(11) -//} \ No newline at end of file +kotlin { + jvmToolchain(11) +} \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/kotlin/gradle/wrapper/gradle-wrapper.properties b/examples/powertools-examples-core-utilities/kotlin/gradle/wrapper/gradle-wrapper.properties index 0d23ac00c..1af9e0930 100644 --- a/examples/powertools-examples-core-utilities/kotlin/gradle/wrapper/gradle-wrapper.properties +++ b/examples/powertools-examples-core-utilities/kotlin/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index a88150f4b..3ddecc5e4 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -10,8 +10,8 @@ 2.20.0 - 1.8 - 1.8 + 11 + 11 1.9.20 @@ -126,24 +126,4 @@ - - - - jdk8 - - (,11) - - - 1.9.7 - - - diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index c92d0b653..7ebfdfc00 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -10,8 +10,8 @@ 2.20.0 - 1.8 - 1.8 + 11 + 11 1.9.20 @@ -59,6 +59,7 @@
+ helloworld-lambda dev.aspectj @@ -126,24 +127,4 @@ - - - - jdk8 - - (,11) - - - 1.9.7 - - - diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index d74ce7085..f508d9d3d 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -10,8 +10,8 @@ 2.20.0 - 1.8 - 1.8 + 11 + 11 1.9.20 @@ -145,24 +145,4 @@ - - - - jdk8 - - (,11) - - - 1.9.7 - - - diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 901074ddb..b7fd3d832 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -24,8 +24,8 @@ 2.20.0 - 1.8 - 1.8 + 11 + 11 1.9.20 @@ -198,24 +198,4 @@ - - - - jdk8 - - (,11) - - - 1.9.7 - - - diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index cffab7a65..7a4af628c 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -8,8 +8,8 @@ Powertools for AWS Lambda (Java) library Examples - Parameters - 1.8 - 1.8 + 11 + 11 1.9.20 @@ -108,24 +108,4 @@ - - - - jdk8 - - (,11) - - - 1.9.7 - - - diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 5d7036497..468c7d161 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -8,8 +8,8 @@ Powertools for AWS Lambda (Java) library Examples - Serialization - 1.8 - 1.8 + 11 + 11 @@ -37,14 +37,6 @@ - - - org.apache.maven.plugins - maven-deploy-plugin - - true - - org.apache.maven.plugins diff --git a/examples/powertools-examples-validation/README.md b/examples/powertools-examples-validation/README.md index 3f6790b0c..2f2028301 100644 --- a/examples/powertools-examples-validation/README.md +++ b/examples/powertools-examples-validation/README.md @@ -15,7 +15,7 @@ started with SAM in [the examples directory](../README.md) To test the validation, we can POST a JSON object shaped like our schema: ```bash - curl -X POST https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/hello/ -H "Content-Type: application/json" -d '{"address": "https://checkip.amazonaws.com"}' + curl -X POST https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/hello/ -H "Content-Type: application/json" -d '{"id": 123,"name":"The Hitchhikers Guide to the Galaxy","price":10.99}' ``` If we break the schema - for instance, by removing one of the compulsory fields, From 412118dc1def72f4c128e042cd3f23277c976e3a Mon Sep 17 00:00:00 2001 From: skal111 Date: Fri, 1 Dec 2023 16:59:52 +0000 Subject: [PATCH 106/577] feat(v2): Validation failures return 400s (#1489) --- docs/utilities/validation.md | 5 +- powertools-e2e-tests/handlers/pom.xml | 6 + .../handlers/validation-alb-event/pom.xml | 60 +++++++ .../lambda/powertools/e2e/Function.java | 36 ++++ .../src/main/resources/log4j2.xml | 16 ++ .../resources/validation/inbound_schema.json | 32 ++++ .../resources/validation/outbound_schema.json | 32 ++++ .../handlers/validation-apigw-event/pom.xml | 60 +++++++ .../lambda/powertools/e2e/Function.java | 33 ++++ .../src/main/resources/log4j2.xml | 16 ++ .../resources/validation/inbound_schema.json | 32 ++++ .../resources/validation/outbound_schema.json | 32 ++++ .../lambda/powertools/ValidationALBE2ET.java | 104 ++++++++++++ .../powertools/ValidationApiGWE2ET.java | 107 ++++++++++++ .../validation/invalid_alb_in_event.json | 28 +++ .../validation/invalid_alb_out_event.json | 28 +++ .../validation/invalid_api_gw_in_event.json | 62 +++++++ .../validation/invalid_api_gw_out_event.json | 62 +++++++ .../validation/valid_alb_in_out_event.json | 28 +++ .../validation/valid_api_gw_in_out_event.json | 62 +++++++ .../validation/internal/ValidationAspect.java | 131 ++++++++++++--- ...aV7APIGatewayProxyRequestEventHandler.java | 34 ++++ ...java => GenericSchemaV7StringHandler.java} | 5 +- ...nInboundAPIGatewayV2HTTPEventHandler.java} | 11 +- ...andledResponseEventsArgumentsProvider.java | 64 +++++++ .../ResponseEventsArgumentsProvider.java | 7 +- .../internal/ValidationAspectTest.java | 159 ++++++++++++++---- 27 files changed, 1176 insertions(+), 76 deletions(-) create mode 100644 powertools-e2e-tests/handlers/validation-alb-event/pom.xml create mode 100644 powertools-e2e-tests/handlers/validation-alb-event/src/main/java/software/amazon/lambda/powertools/e2e/Function.java create mode 100644 powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/log4j2.xml create mode 100644 powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/validation/inbound_schema.json create mode 100644 powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/validation/outbound_schema.json create mode 100644 powertools-e2e-tests/handlers/validation-apigw-event/pom.xml create mode 100644 powertools-e2e-tests/handlers/validation-apigw-event/src/main/java/software/amazon/lambda/powertools/e2e/Function.java create mode 100644 powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/log4j2.xml create mode 100644 powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/validation/inbound_schema.json create mode 100644 powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/validation/outbound_schema.json create mode 100644 powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java create mode 100644 powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java create mode 100644 powertools-e2e-tests/src/test/resources/validation/invalid_alb_in_event.json create mode 100644 powertools-e2e-tests/src/test/resources/validation/invalid_alb_out_event.json create mode 100644 powertools-e2e-tests/src/test/resources/validation/invalid_api_gw_in_event.json create mode 100644 powertools-e2e-tests/src/test/resources/validation/invalid_api_gw_out_event.json create mode 100644 powertools-e2e-tests/src/test/resources/validation/valid_alb_in_out_event.json create mode 100644 powertools-e2e-tests/src/test/resources/validation/valid_api_gw_in_out_event.json create mode 100644 powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7APIGatewayProxyRequestEventHandler.java rename powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/{GenericSchemaV7Handler.java => GenericSchemaV7StringHandler.java} (92%) rename powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/{ValidationInboundStringHandler.java => ValidationInboundAPIGatewayV2HTTPEventHandler.java} (87%) create mode 100644 powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/HandledResponseEventsArgumentsProvider.java diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index 928ffb6c8..dfd97e0d4 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -156,7 +156,10 @@ We support JSON schema version 4, 6, 7 and 201909 (from [jmespath-jackson librar `@Validation` annotation is used to validate either inbound events or functions' response. -It will fail fast with `ValidationException` if an event or response doesn't conform with given JSON Schema. +It will fail fast if an event or response doesn't conform with given JSON Schema. For most type of events a `ValidationException` will be thrown. +For API gateway events associated with REST APIs and HTTP APIs - `APIGatewayProxyRequestEvent` and `APIGatewayV2HTTPEvent` - the `@Validation` +annotation will build and return a custom 400 / "Bad Request" response, with a body containing the validation errors. This saves you from having +to catch the validation exception and map it back to a meaningful user error yourself. While it is easier to specify a json schema file in the classpath (using the notation `"classpath:/path/to/schema.json"`), you can also provide a JSON String containing the schema. diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 1bda3caa5..7c1208470 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -32,6 +32,7 @@ metrics idempotency parameters + validation @@ -83,6 +84,11 @@ powertools-batch ${lambda.powertools.version} + + software.amazon.lambda + powertools-validation + ${lambda.powertools.version} + com.amazonaws aws-lambda-java-core diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml new file mode 100644 index 000000000..31570fe4e --- /dev/null +++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml @@ -0,0 +1,60 @@ + + 4.0.0 + + + software.amazon.lambda + e2e-test-handlers-parent + 1.0.0 + + + e2e-test-handler-validation-alb-event + jar + A Lambda function using Powertools for AWS Lambda (Java) validation + + + + software.amazon.lambda + powertools-validation + + + com.amazonaws + aws-lambda-java-events + + + org.aspectj + aspectjrt + + + + + + + dev.aspectj + aspectj-maven-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-validation + + + + + + + compile + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + + diff --git a/powertools-e2e-tests/handlers/validation-alb-event/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/validation-alb-event/src/main/java/software/amazon/lambda/powertools/e2e/Function.java new file mode 100644 index 000000000..d221ee153 --- /dev/null +++ b/powertools-e2e-tests/handlers/validation-alb-event/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -0,0 +1,36 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; +import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerResponseEvent; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; + +import software.amazon.lambda.powertools.validation.Validation; + +public class Function + implements RequestHandler { + @Validation(inboundSchema = "classpath:/validation/inbound_schema.json", outboundSchema = "classpath:/validation/outbound_schema.json") + public ApplicationLoadBalancerResponseEvent handleRequest(ApplicationLoadBalancerRequestEvent input, + Context context) { + ApplicationLoadBalancerResponseEvent response = new ApplicationLoadBalancerResponseEvent(); + response.setBody(input.getBody()); + response.setStatusCode(200); + response.setIsBase64Encoded(false); + return response; + } +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/log4j2.xml b/powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/log4j2.xml new file mode 100644 index 000000000..8925f70b9 --- /dev/null +++ b/powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/validation/inbound_schema.json b/powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/validation/inbound_schema.json new file mode 100644 index 000000000..3665879eb --- /dev/null +++ b/powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/validation/inbound_schema.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "http://example.com/product.json", + "type": "object", + "title": "Product schema", + "description": "JSON schema to validate Products", + "default": {}, + "examples": [ + { + "id": 43242, + "name": "FooBar XY", + "price": 258 + } + ], + "required": [ + "price" + ], + "properties": { + "price": { + "$id": "#/properties/price", + "type": "number", + "title": "Price of the product", + "description": "Positive price of the product", + "default": 0, + "exclusiveMinimum": 0, + "examples": [ + 258.99 + ] + } + }, + "additionalProperties": true +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/validation/outbound_schema.json b/powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/validation/outbound_schema.json new file mode 100644 index 000000000..b1f14d025 --- /dev/null +++ b/powertools-e2e-tests/handlers/validation-alb-event/src/main/resources/validation/outbound_schema.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "http://example.com/product.json", + "type": "object", + "title": "Product schema", + "description": "JSON schema to validate Products", + "default": {}, + "examples": [ + { + "id": 43242, + "name": "FooBar XY", + "price": 258 + } + ], + "required": [ + "price" + ], + "properties": { + "price": { + "$id": "#/properties/price", + "type": "number", + "title": "Price of the product", + "description": "Positive price of the product", + "default": 0, + "exclusiveMaximum": 1000, + "examples": [ + 258.99 + ] + } + }, + "additionalProperties": true +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml new file mode 100644 index 000000000..9129abc7d --- /dev/null +++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml @@ -0,0 +1,60 @@ + + 4.0.0 + + + software.amazon.lambda + e2e-test-handlers-parent + 1.0.0 + + + e2e-test-handler-validation-apigw-event + jar + A Lambda function using Powertools for AWS Lambda (Java) validation + + + + software.amazon.lambda + powertools-validation + + + com.amazonaws + aws-lambda-java-events + + + org.aspectj + aspectjrt + + + + + + + dev.aspectj + aspectj-maven-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-validation + + + + + + + compile + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + + diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/validation-apigw-event/src/main/java/software/amazon/lambda/powertools/e2e/Function.java new file mode 100644 index 000000000..5ac8951d8 --- /dev/null +++ b/powertools-e2e-tests/handlers/validation-apigw-event/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -0,0 +1,33 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + +import software.amazon.lambda.powertools.validation.Validation; + +public class Function implements RequestHandler { + @Validation(inboundSchema = "classpath:/validation/inbound_schema.json", outboundSchema = "classpath:/validation/outbound_schema.json") + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent(); + response.setBody(input.getBody()); + response.setStatusCode(200); + response.setIsBase64Encoded(false); + return response; + } +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/log4j2.xml b/powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/log4j2.xml new file mode 100644 index 000000000..8925f70b9 --- /dev/null +++ b/powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/validation/inbound_schema.json b/powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/validation/inbound_schema.json new file mode 100644 index 000000000..3665879eb --- /dev/null +++ b/powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/validation/inbound_schema.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "http://example.com/product.json", + "type": "object", + "title": "Product schema", + "description": "JSON schema to validate Products", + "default": {}, + "examples": [ + { + "id": 43242, + "name": "FooBar XY", + "price": 258 + } + ], + "required": [ + "price" + ], + "properties": { + "price": { + "$id": "#/properties/price", + "type": "number", + "title": "Price of the product", + "description": "Positive price of the product", + "default": 0, + "exclusiveMinimum": 0, + "examples": [ + 258.99 + ] + } + }, + "additionalProperties": true +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/validation/outbound_schema.json b/powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/validation/outbound_schema.json new file mode 100644 index 000000000..b1f14d025 --- /dev/null +++ b/powertools-e2e-tests/handlers/validation-apigw-event/src/main/resources/validation/outbound_schema.json @@ -0,0 +1,32 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "$id": "http://example.com/product.json", + "type": "object", + "title": "Product schema", + "description": "JSON schema to validate Products", + "default": {}, + "examples": [ + { + "id": 43242, + "name": "FooBar XY", + "price": 258 + } + ], + "required": [ + "price" + ], + "properties": { + "price": { + "$id": "#/properties/price", + "type": "number", + "title": "Price of the product", + "description": "Positive price of the product", + "default": 0, + "exclusiveMaximum": 1000, + "examples": [ + 258.99 + ] + } + }, + "additionalProperties": true +} \ No newline at end of file diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java new file mode 100644 index 000000000..324c77a34 --- /dev/null +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java @@ -0,0 +1,104 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT; +import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.testutils.Infrastructure; +import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; + +class ValidationALBE2ET { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private static Infrastructure infrastructure; + private static String functionName; + + @BeforeAll + @Timeout(value = 5, unit = TimeUnit.MINUTES) + public static void setup() { + infrastructure = Infrastructure.builder().testName(ValidationALBE2ET.class.getSimpleName()) + .pathToFunction("validation-alb-event").build(); + Map outputs = infrastructure.deploy(); + functionName = outputs.get(FUNCTION_NAME_OUTPUT); + } + + @AfterAll + public static void tearDown() { + if (infrastructure != null) { + infrastructure.destroy(); + } + } + + @Test + void test_validInboundSQSEvent() throws IOException { + InputStream inputStream = this.getClass().getResourceAsStream("/validation/valid_alb_in_out_event.json"); + String validEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, validEvent); + + // THEN + // invocation should pass validation and return 200 + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(200); + assertThat(validJsonNode.get("body").asText()).isEqualTo("{\"price\": 150}"); + } + + @Test + void test_invalidInboundSQSEvent() throws IOException { + InputStream inputStream = this.getClass().getResourceAsStream("/validation/invalid_alb_in_event.json"); + String invalidEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); + + // THEN + // invocation should fail inbound validation and return an error message + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("errorMessage").asText()).contains("$.price: is missing but it is required"); + } + + @Test + void test_invalidOutboundSQSEvent() throws IOException { + InputStream inputStream = this.getClass().getResourceAsStream("/validation/invalid_alb_out_event.json"); + String invalidEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); + + // THEN + // invocation should fail outbound validation and return 400 + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("errorMessage").asText()).contains("$.price: must have an exclusive maximum value of 1000"); + } +} diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java new file mode 100644 index 000000000..af7c7d87c --- /dev/null +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java @@ -0,0 +1,107 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools; + +import static org.assertj.core.api.Assertions.assertThat; +import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT; +import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.testutils.Infrastructure; +import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; + +class ValidationApiGWE2ET { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private static Infrastructure infrastructure; + private static String functionName; + + @BeforeAll + @Timeout(value = 5, unit = TimeUnit.MINUTES) + public static void setup() { + infrastructure = Infrastructure.builder().testName(ValidationApiGWE2ET.class.getSimpleName()) + .pathToFunction("validation-apigw-event").build(); + Map outputs = infrastructure.deploy(); + functionName = outputs.get(FUNCTION_NAME_OUTPUT); + } + + @AfterAll + public static void tearDown() { + if (infrastructure != null) { + infrastructure.destroy(); + } + } + + @Test + void test_validInboundApiGWEvent() throws IOException { + InputStream inputStream = this.getClass().getResourceAsStream("/validation/valid_api_gw_in_out_event.json"); + String validEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, validEvent); + + // THEN + // invocation should pass validation and return 200 + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(200); + assertThat(validJsonNode.get("body").asText()).isEqualTo("{\"price\": 150}"); + } + + @Test + void test_invalidInboundApiGWEvent() throws IOException { + InputStream inputStream = this.getClass().getResourceAsStream("/validation/invalid_api_gw_in_event.json"); + String invalidEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); + + // THEN + // invocation should fail inbound validation and return 400 + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(400); + assertThat(validJsonNode.get("body").asText()).contains("$.price: is missing but it is required"); + } + + @Test + void test_invalidOutboundApiGWEvent() throws IOException { + InputStream inputStream = this.getClass().getResourceAsStream("/validation/invalid_api_gw_out_event.json"); + String invalidEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); + + // THEN + // invocation should fail outbound validation and return 400 + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(400); + assertThat(validJsonNode.get("body").asText()) + .contains("$.price: must have an exclusive maximum value of 1000"); + } +} diff --git a/powertools-e2e-tests/src/test/resources/validation/invalid_alb_in_event.json b/powertools-e2e-tests/src/test/resources/validation/invalid_alb_in_event.json new file mode 100644 index 000000000..ebad834d8 --- /dev/null +++ b/powertools-e2e-tests/src/test/resources/validation/invalid_alb_in_event.json @@ -0,0 +1,28 @@ +{ + "requestContext": { + "elb": { + "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a" + } + }, + "httpMethod": "POST", + "path": "/path/to/resource", + "queryStringParameters": { + "query": "1234ABCD" + }, + "headers": { + "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", + "accept-encoding": "gzip", + "accept-language": "en-US,en;q=0.9", + "connection": "keep-alive", + "host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com", + "upgrade-insecure-requests": "1", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", + "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476", + "x-forwarded-for": "72.12.164.125", + "x-forwarded-port": "80", + "x-forwarded-proto": "http", + "x-imforwards": "20" + }, + "body": "{\"message\": \"Lambda rocks\"}", + "isBase64Encoded": true +} \ No newline at end of file diff --git a/powertools-e2e-tests/src/test/resources/validation/invalid_alb_out_event.json b/powertools-e2e-tests/src/test/resources/validation/invalid_alb_out_event.json new file mode 100644 index 000000000..1b1961063 --- /dev/null +++ b/powertools-e2e-tests/src/test/resources/validation/invalid_alb_out_event.json @@ -0,0 +1,28 @@ +{ + "requestContext": { + "elb": { + "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a" + } + }, + "httpMethod": "POST", + "path": "/path/to/resource", + "queryStringParameters": { + "query": "1234ABCD" + }, + "headers": { + "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", + "accept-encoding": "gzip", + "accept-language": "en-US,en;q=0.9", + "connection": "keep-alive", + "host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com", + "upgrade-insecure-requests": "1", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", + "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476", + "x-forwarded-for": "72.12.164.125", + "x-forwarded-port": "80", + "x-forwarded-proto": "http", + "x-imforwards": "20" + }, + "body": "{\"price\": 50000}", + "isBase64Encoded": true +} \ No newline at end of file diff --git a/powertools-e2e-tests/src/test/resources/validation/invalid_api_gw_in_event.json b/powertools-e2e-tests/src/test/resources/validation/invalid_api_gw_in_event.json new file mode 100644 index 000000000..014ef9f05 --- /dev/null +++ b/powertools-e2e-tests/src/test/resources/validation/invalid_api_gw_in_event.json @@ -0,0 +1,62 @@ +{ + "body": "{\"message\": \"Lambda rocks\"}", + "resource": "/{proxy+}", + "path": "/path/to/resource", + "httpMethod": "POST", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/path/to/resource", + "resourcePath": "/{proxy+}", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } +} \ No newline at end of file diff --git a/powertools-e2e-tests/src/test/resources/validation/invalid_api_gw_out_event.json b/powertools-e2e-tests/src/test/resources/validation/invalid_api_gw_out_event.json new file mode 100644 index 000000000..b7ef1780c --- /dev/null +++ b/powertools-e2e-tests/src/test/resources/validation/invalid_api_gw_out_event.json @@ -0,0 +1,62 @@ +{ + "body": "{\"price\": 50000}", + "resource": "/{proxy+}", + "path": "/path/to/resource", + "httpMethod": "POST", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/path/to/resource", + "resourcePath": "/{proxy+}", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } +} \ No newline at end of file diff --git a/powertools-e2e-tests/src/test/resources/validation/valid_alb_in_out_event.json b/powertools-e2e-tests/src/test/resources/validation/valid_alb_in_out_event.json new file mode 100644 index 000000000..35560f109 --- /dev/null +++ b/powertools-e2e-tests/src/test/resources/validation/valid_alb_in_out_event.json @@ -0,0 +1,28 @@ +{ + "requestContext": { + "elb": { + "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a" + } + }, + "httpMethod": "POST", + "path": "/path/to/resource", + "queryStringParameters": { + "query": "1234ABCD" + }, + "headers": { + "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", + "accept-encoding": "gzip", + "accept-language": "en-US,en;q=0.9", + "connection": "keep-alive", + "host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com", + "upgrade-insecure-requests": "1", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", + "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476", + "x-forwarded-for": "72.12.164.125", + "x-forwarded-port": "80", + "x-forwarded-proto": "http", + "x-imforwards": "20" + }, + "body": "{\"price\": 150}", + "isBase64Encoded": true +} \ No newline at end of file diff --git a/powertools-e2e-tests/src/test/resources/validation/valid_api_gw_in_out_event.json b/powertools-e2e-tests/src/test/resources/validation/valid_api_gw_in_out_event.json new file mode 100644 index 000000000..8cb8ea27a --- /dev/null +++ b/powertools-e2e-tests/src/test/resources/validation/valid_api_gw_in_out_event.json @@ -0,0 +1,62 @@ +{ + "body": "{\"price\": 150}", + "resource": "/{proxy+}", + "path": "/path/to/resource", + "httpMethod": "POST", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/path/to/resource", + "resourcePath": "/{proxy+}", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } +} \ No newline at end of file diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java index 0d71104f3..978be16de 100644 --- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java @@ -22,6 +22,10 @@ import static software.amazon.lambda.powertools.validation.ValidationUtils.getJsonSchema; import static software.amazon.lambda.powertools.validation.ValidationUtils.validate; +import java.util.Collections; +import java.util.List; +import java.util.Map; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; @@ -51,6 +55,7 @@ import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.validation.Validation; import software.amazon.lambda.powertools.validation.ValidationConfig; +import software.amazon.lambda.powertools.validation.ValidationException; /** * Aspect for {@link Validation} annotation @@ -73,6 +78,11 @@ public Object around(ProceedingJoinPoint pjp, if (validation.schemaVersion() != V201909) { ValidationConfig.get().setSchemaVersion(validation.schemaVersion()); } + + // we need this result object to be null at this point as validation of API events, if + // it fails, will catch the ValidationException and generate a 400 API response. This response + // will be stored in the result object to prevent executing the lambda + Object result = null; if (placedOnRequestHandler(pjp)) { validationNeeded = true; @@ -85,10 +95,10 @@ public Object around(ProceedingJoinPoint pjp, validate(obj, inboundJsonSchema, validation.envelope()); } else if (obj instanceof APIGatewayProxyRequestEvent) { APIGatewayProxyRequestEvent event = (APIGatewayProxyRequestEvent) obj; - validate(event.getBody(), inboundJsonSchema); + result = validateAPIGatewayProxyBody(event.getBody(), inboundJsonSchema, null, null); } else if (obj instanceof APIGatewayV2HTTPEvent) { APIGatewayV2HTTPEvent event = (APIGatewayV2HTTPEvent) obj; - validate(event.getBody(), inboundJsonSchema); + result = validateAPIGatewayV2HTTPBody(event.getBody(), inboundJsonSchema, null, null); } else if (obj instanceof SNSEvent) { SNSEvent event = (SNSEvent) obj; event.getRecords().forEach(record -> validate(record.getSNS().getMessage(), inboundJsonSchema)); @@ -140,33 +150,100 @@ record -> validate(decode(record.getData()), inboundJsonSchema))); } } - Object result = pjp.proceed(proceedArgs); - - if (validationNeeded && !validation.outboundSchema().isEmpty()) { - JsonSchema outboundJsonSchema = getJsonSchema(validation.outboundSchema(), true); - - if (result instanceof APIGatewayProxyResponseEvent) { - APIGatewayProxyResponseEvent response = (APIGatewayProxyResponseEvent) result; - validate(response.getBody(), outboundJsonSchema); - } else if (result instanceof APIGatewayV2HTTPResponse) { - APIGatewayV2HTTPResponse response = (APIGatewayV2HTTPResponse) result; - validate(response.getBody(), outboundJsonSchema); - } else if (result instanceof APIGatewayV2WebSocketResponse) { - APIGatewayV2WebSocketResponse response = (APIGatewayV2WebSocketResponse) result; - validate(response.getBody(), outboundJsonSchema); - } else if (result instanceof ApplicationLoadBalancerResponseEvent) { - ApplicationLoadBalancerResponseEvent response = (ApplicationLoadBalancerResponseEvent) result; - validate(response.getBody(), outboundJsonSchema); - } else if (result instanceof KinesisAnalyticsInputPreprocessingResponse) { - KinesisAnalyticsInputPreprocessingResponse response = - (KinesisAnalyticsInputPreprocessingResponse) result; - response.getRecords().forEach(record -> validate(decode(record.getData()), outboundJsonSchema)); - } else { - LOG.warn("Unhandled response type {}, please use the 'envelope' parameter to specify what to validate", - result.getClass().getName()); - } + // don't execute the lambda if result was set by previous validation step + // in that case result should already hold a response with validation information + if (result != null) { + LOG.error("Incoming API event's body failed inbound schema validation."); } + else { + result = pjp.proceed(proceedArgs); + + if (validationNeeded && !validation.outboundSchema().isEmpty()) { + JsonSchema outboundJsonSchema = getJsonSchema(validation.outboundSchema(), true); + + Object overridenResponse = null; + // The normal behavior of @Validation is to throw an exception if response's validation fails. + // but in the case of APIGatewayProxyResponseEvent and APIGatewayV2HTTPResponse we want to return + // a 400 response with the validation errors instead of throwing an exception. + if (result instanceof APIGatewayProxyResponseEvent) { + APIGatewayProxyResponseEvent response = (APIGatewayProxyResponseEvent) result; + overridenResponse = validateAPIGatewayProxyBody(response.getBody(), outboundJsonSchema, response.getHeaders(), + response.getMultiValueHeaders()); + } else if (result instanceof APIGatewayV2HTTPResponse) { + APIGatewayV2HTTPResponse response = (APIGatewayV2HTTPResponse) result; + overridenResponse = validateAPIGatewayV2HTTPBody(response.getBody(), outboundJsonSchema, response.getHeaders(), + response.getMultiValueHeaders()); + // all type of below responses will throw an exception if validation fails + } else if (result instanceof APIGatewayV2WebSocketResponse) { + APIGatewayV2WebSocketResponse response = (APIGatewayV2WebSocketResponse) result; + validate(response.getBody(), outboundJsonSchema); + } else if (result instanceof ApplicationLoadBalancerResponseEvent) { + ApplicationLoadBalancerResponseEvent response = (ApplicationLoadBalancerResponseEvent) result; + validate(response.getBody(), outboundJsonSchema); + } else if (result instanceof KinesisAnalyticsInputPreprocessingResponse) { + KinesisAnalyticsInputPreprocessingResponse response = + (KinesisAnalyticsInputPreprocessingResponse) result; + response.getRecords().forEach(record -> validate(decode(record.getData()), outboundJsonSchema)); + } else { + LOG.warn("Unhandled response type {}, please use the 'envelope' parameter to specify what to validate", + result.getClass().getName()); + } + + if (overridenResponse != null) { + result = overridenResponse; + LOG.error("API response failed outbound schema validation."); + } + } + } return result; } + + /** + * Validates the given body against the provided JsonSchema. If validation fails the ValidationException + * will be catched and transformed to a 400, bad request, API response + * @param body body of the event to validate + * @param inboundJsonSchema validation schema + * @return null if validation passed, or a 400 response object otherwise + */ + private APIGatewayProxyResponseEvent validateAPIGatewayProxyBody(final String body, final JsonSchema jsonSchema, + final Map headers, Map> multivalueHeaders) { + APIGatewayProxyResponseEvent result = null; + try { + validate(body, jsonSchema); + } catch (ValidationException e) { + LOG.error("There were validation errors: {}", e.getMessage()); + result = new APIGatewayProxyResponseEvent(); + result.setBody(e.getMessage()); + result.setHeaders(headers == null ? Collections.emptyMap() : headers); + result.setMultiValueHeaders(multivalueHeaders == null ? Collections.emptyMap() : multivalueHeaders); + result.setStatusCode(400); + result.setIsBase64Encoded(false); + } + return result; + } + + /** + * Validates the given body against the provided JsonSchema. If validation fails the ValidationException + * will be catched and transformed to a 400, bad request, API response + * @param body body of the event to validate + * @param inboundJsonSchema validation schema + * @return null if validation passed, or a 400 response object otherwise + */ + private APIGatewayV2HTTPResponse validateAPIGatewayV2HTTPBody(final String body, final JsonSchema jsonSchema, + final Map headers, Map> multivalueHeaders) { + APIGatewayV2HTTPResponse result = null; + try { + validate(body, jsonSchema); + } catch (ValidationException e) { + LOG.error("There were validation errors: {}", e.getMessage()); + result = new APIGatewayV2HTTPResponse(); + result.setBody(e.getMessage()); + result.setHeaders(headers == null ? Collections.emptyMap() : headers); + result.setMultiValueHeaders(multivalueHeaders == null ? Collections.emptyMap() : multivalueHeaders); + result.setStatusCode(400); + result.setIsBase64Encoded(false); + } + return result; + } } diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7APIGatewayProxyRequestEventHandler.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7APIGatewayProxyRequestEventHandler.java new file mode 100644 index 000000000..74e8605a5 --- /dev/null +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7APIGatewayProxyRequestEventHandler.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.validation.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + +import software.amazon.lambda.powertools.validation.Validation; + +public class GenericSchemaV7APIGatewayProxyRequestEventHandler implements RequestHandler { + + @Validation(inboundSchema = "classpath:/schema_v7.json") + @Override + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent(); + response.setBody("valid-test"); + response.setStatusCode(200); + return response; + } +} \ No newline at end of file diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7Handler.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7StringHandler.java similarity index 92% rename from powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7Handler.java rename to powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7StringHandler.java index 5b8343d1b..ab0645f29 100644 --- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7Handler.java +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/GenericSchemaV7StringHandler.java @@ -16,13 +16,14 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; + import software.amazon.lambda.powertools.validation.Validation; -public class GenericSchemaV7Handler implements RequestHandler { +public class GenericSchemaV7StringHandler implements RequestHandler { @Validation(inboundSchema = "classpath:/schema_v7.json") @Override public String handleRequest(T input, Context context) { return "OK"; } -} +} \ No newline at end of file diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/ValidationInboundStringHandler.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/ValidationInboundAPIGatewayV2HTTPEventHandler.java similarity index 87% rename from powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/ValidationInboundStringHandler.java rename to powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/ValidationInboundAPIGatewayV2HTTPEventHandler.java index fd5692884..b8c67b1eb 100644 --- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/ValidationInboundStringHandler.java +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/ValidationInboundAPIGatewayV2HTTPEventHandler.java @@ -17,10 +17,12 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPResponse; + import software.amazon.lambda.powertools.validation.Validation; -public class ValidationInboundStringHandler implements RequestHandler { +public class ValidationInboundAPIGatewayV2HTTPEventHandler implements RequestHandler { private static final String schema = "{\n" + " \"$schema\": \"http://json-schema.org/draft-07/schema\",\n" + @@ -80,7 +82,10 @@ public class ValidationInboundStringHandler implements RequestHandler provideArguments(ExtensionContext context) { + + String body = "{id"; + + Map headers = new HashMap<>(); + headers.put("header1", "value1,value2,value3"); + Map> headersList = new HashMap<>(); + List headerValues = new ArrayList<>(); + headerValues.add("value1"); + headerValues.add("value2"); + headerValues.add("value3"); + headersList.put("header1", headerValues); + + final APIGatewayProxyResponseEvent apiGWProxyResponseEvent = new APIGatewayProxyResponseEvent() + .withBody(body) + .withHeaders(headers) + .withMultiValueHeaders(headersList); + + APIGatewayV2HTTPResponse apiGWV2HTTPResponse = new APIGatewayV2HTTPResponse(); + apiGWV2HTTPResponse.setBody(body); + apiGWV2HTTPResponse.setHeaders(headers); + apiGWV2HTTPResponse.setMultiValueHeaders(headersList); + + return Stream.of(apiGWProxyResponseEvent, apiGWV2HTTPResponse).map(Arguments::of); + } +} diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ResponseEventsArgumentsProvider.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ResponseEventsArgumentsProvider.java index b634d6f8c..74803a05a 100644 --- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ResponseEventsArgumentsProvider.java +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ResponseEventsArgumentsProvider.java @@ -35,11 +35,6 @@ public Stream provideArguments(ExtensionContext context) { String body = "{id"; - final APIGatewayProxyResponseEvent apiGWProxyResponseEvent = new APIGatewayProxyResponseEvent().withBody(body); - - APIGatewayV2HTTPResponse apiGWV2HTTPResponse = new APIGatewayV2HTTPResponse(); - apiGWV2HTTPResponse.setBody(body); - APIGatewayV2WebSocketResponse apiGWV2WebSocketResponse = new APIGatewayV2WebSocketResponse(); apiGWV2WebSocketResponse.setBody(body); @@ -53,7 +48,7 @@ public Stream provideArguments(ExtensionContext context) { KinesisAnalyticsInputPreprocessingResponse.Result.Ok, buffer)); kaipResponse.setRecords(records); - return Stream.of(apiGWProxyResponseEvent, apiGWV2HTTPResponse, apiGWV2WebSocketResponse, albResponseEvent, + return Stream.of(apiGWV2WebSocketResponse, albResponseEvent, kaipResponse).map(Arguments::of); } } diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java index c8d5e7ade..1708ebeeb 100644 --- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java @@ -17,11 +17,31 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.when; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsSource; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPResponse; import com.amazonaws.services.lambda.runtime.events.ActiveMQEvent; @@ -40,25 +60,15 @@ import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer; import com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers; import com.networknt.schema.SpecVersion; -import java.io.IOException; -import java.util.stream.Stream; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.Signature; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.ArgumentsSource; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; + import software.amazon.lambda.powertools.validation.Validation; import software.amazon.lambda.powertools.validation.ValidationConfig; import software.amazon.lambda.powertools.validation.ValidationException; -import software.amazon.lambda.powertools.validation.handlers.GenericSchemaV7Handler; +import software.amazon.lambda.powertools.validation.handlers.GenericSchemaV7APIGatewayProxyRequestEventHandler; +import software.amazon.lambda.powertools.validation.handlers.GenericSchemaV7StringHandler; import software.amazon.lambda.powertools.validation.handlers.SQSWithCustomEnvelopeHandler; import software.amazon.lambda.powertools.validation.handlers.SQSWithWrongEnvelopeHandler; -import software.amazon.lambda.powertools.validation.handlers.ValidationInboundStringHandler; +import software.amazon.lambda.powertools.validation.handlers.ValidationInboundAPIGatewayV2HTTPEventHandler; import software.amazon.lambda.powertools.validation.model.MyCustomEvent; @@ -99,7 +109,7 @@ void setUp() { @ParameterizedTest @ArgumentsSource(ResponseEventsArgumentsProvider.class) - public void testValidateOutboundJsonSchema(Object object) throws Throwable { + void testValidateOutboundJsonSchemaWithExceptions(Object object) throws Throwable { when(validation.schemaVersion()).thenReturn(SpecVersion.VersionFlag.V7); when(pjp.getSignature()).thenReturn(signature); when(pjp.getSignature().getDeclaringType()).thenReturn(RequestHandler.class); @@ -114,6 +124,47 @@ public void testValidateOutboundJsonSchema(Object object) throws Throwable { validationAspect.around(pjp, validation); }); } + + @ParameterizedTest + @ArgumentsSource(HandledResponseEventsArgumentsProvider.class) + void testValidateOutboundJsonSchemaWithHandledExceptions(Object object) throws Throwable { + when(validation.schemaVersion()).thenReturn(SpecVersion.VersionFlag.V7); + when(pjp.getSignature()).thenReturn(signature); + when(pjp.getSignature().getDeclaringType()).thenReturn(RequestHandler.class); + Object[] args = {new Object(), context}; + when(pjp.getArgs()).thenReturn(args); + when(pjp.proceed(args)).thenReturn(object); + when(validation.inboundSchema()).thenReturn(""); + when(validation.outboundSchema()).thenReturn("classpath:/schema_v7.json"); + + Object response = validationAspect.around(pjp, validation); + assertThat(response).isInstanceOfAny(APIGatewayProxyResponseEvent.class, APIGatewayV2HTTPResponse.class); + + List headerValues = new ArrayList<>(); + headerValues.add("value1"); + headerValues.add("value2"); + headerValues.add("value3"); + + if (response instanceof APIGatewayProxyResponseEvent) { + assertThat(response).isInstanceOfSatisfying(APIGatewayProxyResponseEvent.class, t -> { + assertThat(t.getStatusCode()).isEqualTo(400); + assertThat(t.getBody()).isNotBlank(); + assertThat(t.getIsBase64Encoded()).isFalse(); + assertThat(t.getHeaders()).containsEntry("header1", "value1,value2,value3"); + assertThat(t.getMultiValueHeaders()).containsEntry("header1", headerValues); + }); + } else if (response instanceof APIGatewayV2HTTPResponse) { + assertThat(response).isInstanceOfSatisfying(APIGatewayV2HTTPResponse.class, t -> { + assertThat(t.getStatusCode()).isEqualTo(400); + assertThat(t.getBody()).isNotBlank(); + assertThat(t.getIsBase64Encoded()).isFalse(); + assertThat(t.getHeaders()).containsEntry("header1", "value1,value2,value3"); + assertThat(t.getMultiValueHeaders()).containsEntry("header1", headerValues); + }); + } else { + fail(); + } + } @Test public void testValidateOutboundJsonSchema_APIGWV2() throws Throwable { @@ -137,50 +188,84 @@ public void testValidateOutboundJsonSchema_APIGWV2() throws Throwable { @Test public void validate_inputOK_schemaInClasspath_shouldValidate() { - GenericSchemaV7Handler handler = new GenericSchemaV7Handler(); + GenericSchemaV7APIGatewayProxyRequestEventHandler handler = new GenericSchemaV7APIGatewayProxyRequestEventHandler(); APIGatewayProxyRequestEvent event = new APIGatewayProxyRequestEvent(); event.setBody("{" + " \"id\": 1," + " \"name\": \"Lampshade\"," + " \"price\": 42" + "}"); - assertThat(handler.handleRequest(event, context)).isEqualTo("OK"); + + + APIGatewayProxyResponseEvent response = handler.handleRequest(event, context); + assertThat(response.getBody()).isEqualTo("valid-test"); + assertThat(response.getStatusCode()).isEqualTo(200); + } @Test public void validate_inputKO_schemaInClasspath_shouldThrowValidationException() { - GenericSchemaV7Handler handler = new GenericSchemaV7Handler(); + GenericSchemaV7APIGatewayProxyRequestEventHandler handler = new GenericSchemaV7APIGatewayProxyRequestEventHandler(); + + Map headers = new HashMap<>(); + headers.put("header1", "value1"); + Map> headersList = new HashMap<>(); + List headerValues = new ArrayList<>(); + headerValues.add("value1"); + headersList.put("header1", headerValues); + APIGatewayProxyRequestEvent event = new APIGatewayProxyRequestEvent(); event.setBody("{" + - " \"id\": 1," + - " \"name\": \"Lampshade\"," + - " \"price\": -2" + - "}"); + " \"id\": 1," + + " \"name\": \"Lampshade\"," + + " \"price\": -2" + + "}"); + event.setHeaders(headers); + event.setMultiValueHeaders(headersList); + // price is negative - assertThatExceptionOfType(ValidationException.class).isThrownBy(() -> handler.handleRequest(event, context)); + APIGatewayProxyResponseEvent response = handler.handleRequest(event, context); + assertThat(response.getBody()).isNotBlank(); + assertThat(response.getStatusCode()).isEqualTo(400); + assertThat(response.getHeaders()).isEmpty(); + assertThat(response.getMultiValueHeaders()).isEmpty(); } @Test public void validate_inputOK_schemaInString_shouldValidate() { - ValidationInboundStringHandler handler = new ValidationInboundStringHandler(); + ValidationInboundAPIGatewayV2HTTPEventHandler handler = new ValidationInboundAPIGatewayV2HTTPEventHandler(); APIGatewayV2HTTPEvent event = new APIGatewayV2HTTPEvent(); event.setBody("{" + - " \"id\": 1," + - " \"name\": \"Lampshade\"," + - " \"price\": 42" + - "}"); - assertThat(handler.handleRequest(event, context)).isEqualTo("OK"); + " \"id\": 1," + + " \"name\": \"Lampshade\"," + + " \"price\": 42" + + "}"); + + APIGatewayV2HTTPResponse response = handler.handleRequest(event, context); + assertThat(response.getBody()).isEqualTo("valid-test"); + assertThat(response.getStatusCode()).isEqualTo(200); } + @Test public void validate_inputKO_schemaInString_shouldThrowValidationException() { - ValidationInboundStringHandler handler = new ValidationInboundStringHandler(); + ValidationInboundAPIGatewayV2HTTPEventHandler handler = new ValidationInboundAPIGatewayV2HTTPEventHandler(); + + Map headers = new HashMap<>(); + headers.put("header1", "value1"); + APIGatewayV2HTTPEvent event = new APIGatewayV2HTTPEvent(); event.setBody("{" + - " \"id\": 1," + - " \"name\": \"Lampshade\"" + - "}"); - assertThatExceptionOfType(ValidationException.class).isThrownBy(() -> handler.handleRequest(event, context)); + " \"id\": 1," + + " \"name\": \"Lampshade\"" + + "}"); + event.setHeaders(headers); + + APIGatewayV2HTTPResponse response = handler.handleRequest(event, context); + assertThat(response.getBody()).isNotBlank(); + assertThat(response.getStatusCode()).isEqualTo(400); + assertThat(response.getHeaders()).isEmpty(); + assertThat(response.getMultiValueHeaders()).isEmpty(); } @Test @@ -189,7 +274,7 @@ public void validate_SQS() { LambdaEventSerializers.serializerFor(SQSEvent.class, ClassLoader.getSystemClassLoader()); SQSEvent event = pojoSerializer.fromJson(this.getClass().getResourceAsStream("/sqs.json")); - GenericSchemaV7Handler handler = new GenericSchemaV7Handler(); + GenericSchemaV7StringHandler handler = new GenericSchemaV7StringHandler<>(); assertThat(handler.handleRequest(event, context)).isEqualTo("OK"); } @@ -219,7 +304,7 @@ public void validate_Kinesis() { LambdaEventSerializers.serializerFor(KinesisEvent.class, ClassLoader.getSystemClassLoader()); KinesisEvent event = pojoSerializer.fromJson(this.getClass().getResourceAsStream("/kinesis.json")); - GenericSchemaV7Handler handler = new GenericSchemaV7Handler(); + GenericSchemaV7StringHandler handler = new GenericSchemaV7StringHandler<>(); assertThat(handler.handleRequest(event, context)).isEqualTo("OK"); } @@ -229,7 +314,7 @@ public void validateEEvent(String jsonResource, Class eventClass) throws IOExcep Object event = ValidationConfig.get().getObjectMapper() .readValue(this.getClass().getResourceAsStream(jsonResource), eventClass); - GenericSchemaV7Handler handler = new GenericSchemaV7Handler(); + GenericSchemaV7StringHandler handler = new GenericSchemaV7StringHandler<>(); assertThat(handler.handleRequest(event, context)).isEqualTo("OK"); } } From 00d04c3bd31b434b88a9a79732744a2511ff3932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Fri, 1 Dec 2023 21:07:51 +0100 Subject: [PATCH 107/577] chore: fix end 2 end build (#1534) * different build on java8 * do not build example for artifact size --- .github/workflows/pr_artifacts_size.yml | 2 +- .github/workflows/run-e2e-tests.yml | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_artifacts_size.yml b/.github/workflows/pr_artifacts_size.yml index f37f83a8d..1d905af01 100644 --- a/.github/workflows/pr_artifacts_size.yml +++ b/.github/workflows/pr_artifacts_size.yml @@ -34,7 +34,7 @@ jobs: distribution: 'corretto' java-version: 11 - name: Build with Maven - run: mvn clean package --file pom.xml -DskipTests artifact:buildinfo + run: mvn clean package --file pom.xml -DskipTests artifact:buildinfo -pl '!software.amazon.lambda.examples:powertools-examples-idempotency,!software.amazon.lambda.examples:powertools-examples-batch,!software.amazon.lambda.examples:powertools-examples-cloudformation,!software.amazon.lambda.examples:powertools-examples-core-utilities-cdk,!software.amazon.lambda.examples:powertools-examples-core-utilities-sam,!software.amazon.lambda.examples:powertools-examples-core-utilities-serverless,!software.amazon.lambda.examples:powertools-examples-core-utilities-terraform,!software.amazon.lambda.examples:powertools-examples-parameters,!software.amazon.lambda.examples:powertools-examples-serialization,!software.amazon.lambda.examples:powertools-examples-validation,!software.amazon.lambda.examples:cdk,!software.amazon.lambda:powertools-examples' - name: Get artifacts size & build report id: artifacts-size-report run: | diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 60048abdc..5c7bc0b71 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -56,5 +56,12 @@ jobs: with: role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} aws-region: ${{ env.AWS_DEFAULT_REGION }} + + - name: Build with Maven Java 8 + if: ${{ matrix.java == '8' }} # If 8 exclude the examples directory + run: mvn -DskipTests install --file pom.xml -pl '!software.amazon.lambda.examples:powertools-examples-idempotency,!software.amazon.lambda.examples:powertools-examples-batch,!software.amazon.lambda.examples:powertools-examples-cloudformation,!software.amazon.lambda.examples:powertools-examples-core-utilities-cdk,!software.amazon.lambda.examples:powertools-examples-core-utilities-sam,!software.amazon.lambda.examples:powertools-examples-core-utilities-serverless,!software.amazon.lambda.examples:powertools-examples-core-utilities-terraform,!software.amazon.lambda.examples:powertools-examples-parameters,!software.amazon.lambda.examples:powertools-examples-serialization,!software.amazon.lambda.examples:powertools-examples-validation,!software.amazon.lambda.examples:cdk,!software.amazon.lambda:powertools-examples' + - name: Build with Maven + if: ${{ matrix.java != '8' }} # If not 8 don't exclude the examples directory + run: mvn -DskipTests install --file pom.xml - name: Run e2e test with Maven - run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml \ No newline at end of file + run: mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml \ No newline at end of file From 03024bec2805cb1b86b51c35e1d8e43998091ff4 Mon Sep 17 00:00:00 2001 From: Jason Harris Date: Tue, 5 Dec 2023 08:33:19 +0000 Subject: [PATCH 108/577] docs: HelloWorldStreamFunction in examples fails with sam (#1532) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Setting up Kotlin environment. Converting test to Kotlin. * Deploying via SAM successfully. * Added Kotlin example. * Removing unused Gradle build file. * Adding SAM template so can be used as an existing project and Java target compatibility * Adding SAM template so can be used as an existing project * Updating guidance to use SAM for build and deploy * Restructuring separate Java and Kotlin examples. * Updating core examples readme to represent new structure for Java and Kotlin examples. * Refactoring application code for efficiency, updating build to cover tests too and is more idiomatic and readme to be more descriptive * Updating to fix trailing \n * Updating guidance to be more specific for examples * Adopting new mechanism for specifying jvm target. * accommodating new project structure * Fixing link typo after refactoring * Setting up Kotlin environment. Converting test to Kotlin. * Deploying via SAM successfully. * Added Kotlin example. * Removing unused Gradle build file. * Adding SAM template so can be used as an existing project and Java target compatibility * Adding SAM template so can be used as an existing project * Updating guidance to use SAM for build and deploy * Restructuring separate Java and Kotlin examples. * Updating core examples readme to represent new structure for Java and Kotlin examples. * Refactoring application code for efficiency, updating build to cover tests too and is more idiomatic and readme to be more descriptive * Updating to fix trailing \n * Updating guidance to be more specific for examples * Adopting new mechanism for specifying jvm target. * accommodating new project structure * Fixing link typo after refactoring * Flattening structure back to original to make merging easier for v2 * Adding build for Kotlin Gradle * Adding build for Kotlin Gradle - Restructuring Java examples to v1 approach * Correcting paths * Adding SNAPSHOT support and local capability for Maven. Testing using Java 1.8 * Reviewed and updated against PR comments. * Un-commenting examples * Adding validation step for IaC SAM * Adding Terraform for Java projects IaC validator and linter * Adding additional projects for SAM validation and matrix approach * Refactoring stream function to process input logging example with a Lambda Function URL instead of APIGW. * Demonstrating Java streaming response * Refactoring stream function to process input logging example to return * Update CONTRIBUTING.md * fix: get trace id from system property when env var is not set (#1503) * fix: check if XRAY Trace ID is present in System property * chore: remove erroneous extra char in tests * fix #1500 (#1506) * feat: Add support for POWERTOOLS_LOGGER_LOG_EVENT (#1510) * chore: Addition of Warn Message If Invalid Annotation Key While Tracing #1511 (#1512) * feat: ALC (#1514) * handle AWS_LAMBDA_LOG configuration * ALC documentation + code review * update doc * chore:Prep release 1.18.0 (#1515) * chore:prep release 1.18.0 * update version * update version in kotlin example * maven local repo in gradle example * update changelog --------- Co-authored-by: scottgerring * chore: update version to next snapshot: 1-19.0-SNAPSHOT (#1516) * update version to next snapshot: 1-19.0-SNAPSHOT * update version to next snapshot: 1-19.0-SNAPSHOT * update version to next snapshot: 1-19.0-SNAPSHOT * building only for LTS * Add some more margin to the test pause (#1518) * test: e2e tests with java 21 (#1517) * e2e tests with java 21 * Run Java21 tests using the Java17 compiler * Run all of the E2E tests in parallel, not just the first 3 * Try again * . * Let's try again * Add some comment on Java21 to the repo * Add caveat about lambda runtimes * Clean up wording a little --------- Co-authored-by: Scott Gerring * update doc for ALC (#1520) * chore: Testing java21 aspectj pre-release (#1519) * e2e tests with java 21 * use aspectj 1.9.21-SNAPSHOT * Fix log4j2.xml missing in logging test for java21 * rollback double runtime * remove comment * keep aspectj 1.9.7 in parent for java8 compatibility * use M1 instead of snapshot * update documentation for aspectj * update documentation for aspectj --------- Co-authored-by: Jerome Van Der Linden * chore: Remove build cruft * Adding context for using RequestStreamHandler * removing pr_lint * Update examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java Clarify usage of RequestStreamHandler. Co-authored-by: Alexey Soshin --------- Co-authored-by: Jason Harris Co-authored-by: Scott Gerring Co-authored-by: Jason Harris Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> Co-authored-by: Michele Ricciardi Co-authored-by: Alexey Soshin Co-authored-by: jdoherty Co-authored-by: Scott Gerring Co-authored-by: Jerome Van Der Linden --- .../src/main/java/helloworld/AppStream.java | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java index 401ef8c48..94806cc38 100644 --- a/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java +++ b/examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java @@ -17,22 +17,43 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import com.fasterxml.jackson.databind.ObjectMapper; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.Map; +import java.nio.charset.StandardCharsets; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.metrics.Metrics; +import java.io.InputStreamReader; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; + public class AppStream implements RequestStreamHandler { private static final ObjectMapper mapper = new ObjectMapper(); + private final static Logger log = LogManager.getLogger(AppStream.class); @Override @Logging(logEvent = true) @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - Map map = mapper.readValue(input, Map.class); + // RequestStreamHandler can be used instead of RequestHandler for cases when you'd like to deserialize request body or serialize response body yourself, instead of allowing that to happen automatically + // Note that you still need to return a proper JSON for API Gateway to handle + // See Lambda Response format for examples: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html + public void handleRequest(InputStream input, OutputStream output, Context context) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); + PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8)))) { - System.out.println(map.size()); + log.info("Received: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(reader))); + + writer.write("{\"body\": \"" + System.currentTimeMillis() + "\"} "); + } catch (IOException e) { + log.error("Something has gone wrong: ", e); + } } } + From 04d692a54b29a8dd40301153ba938c937ff0a3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:39:47 +0100 Subject: [PATCH 109/577] deps: bump aspectj to 1.9.21 for jdk21 (#1536) --- docs/index.md | 3 --- powertools-e2e-tests/handlers/pom.xml | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/index.md b/docs/index.md index 884e02476..06c9beb6d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -306,9 +306,6 @@ Use the following [dependency matrix](https://github.com/eclipse-aspectj/aspectj | `11-17` | `1.9.20.1` | | `21` | `1.9.21` | -_Note: 1.9.21 is not yet available and Java 21 not yet officially supported by aspectj, but you can already use the `1.9.21.M1`_ - - ## Environment variables !!! info diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index a9096477b..799ed465e 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -205,7 +205,7 @@ [21,) - 1.9.21.M1 + 1.9.21 From 6b0fe5a19eda5be0c8d4890f1f39faf8a61453cd Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 11 Dec 2023 14:13:16 +0100 Subject: [PATCH 110/577] chore(v2): Split parameters module up by parameter provider (#1403) --- docs/utilities/parameters.md | 693 +++++++++--------- .../powertools-examples-parameters/pom.xml | 8 +- .../demo/parameters/ParametersFunction.java | 25 +- mkdocs.yml | 2 +- pom.xml | 34 +- powertools-e2e-tests/handlers/batch/pom.xml | 2 +- .../handlers/idempotency/pom.xml | 2 +- .../handlers/largemessage/pom.xml | 2 +- .../handlers/largemessage_idempotent/pom.xml | 2 +- powertools-e2e-tests/handlers/logging/pom.xml | 2 +- powertools-e2e-tests/handlers/metrics/pom.xml | 4 +- .../handlers/parameters/pom.xml | 6 +- .../lambda/powertools/e2e/Function.java | 10 +- powertools-e2e-tests/handlers/pom.xml | 10 +- powertools-e2e-tests/handlers/tracing/pom.xml | 2 +- .../handlers/validation-alb-event/pom.xml | 2 +- .../handlers/validation-apigw-event/pom.xml | 2 +- powertools-parameters/pom.xml | 62 +- .../powertools-parameters-appconfig/pom.xml | 85 +++ .../parameters/appconfig/AppConfigParam.java | 57 ++ .../appconfig/AppConfigParametersAspect.java | 54 ++ .../appconfig}/AppConfigProvider.java | 120 +-- .../appconfig/AppConfigProviderBuilder.java | 124 ++++ .../appconfig/AppConfigParamAspectTest.java | 55 ++ .../appconfig}/AppConfigProviderTest.java | 16 +- .../powertools-parameters-dynamodb/pom.xml | 85 +++ .../parameters/dynamodb/DynamoDbParam.java} | 34 +- .../dynamodb/DynamoDbParamAspect.java | 51 ++ .../parameters/dynamodb/DynamoDbProvider.java | 121 +++ .../dynamodb/DynamoDbProviderBuilder.java | 113 +++ .../DynamoDbProviderSchemaException.java | 2 +- .../dynamodb/DynamoDbParamAspectTest.java | 55 ++ .../dynamodb}/DynamoDbProviderE2ETest.java | 4 +- .../dynamodb}/DynamoDbProviderTest.java | 15 +- .../powertools-parameters-secrets/pom.xml | 85 +++ .../parameters/secrets/SecretsParam.java | 46 ++ .../secrets/SecretsParamAspect.java | 48 ++ .../parameters/secrets/SecretsProvider.java | 115 +++ .../secrets/SecretsProviderBuilder.java | 101 +++ .../secrets/SecretsParamAspectTest.java | 49 ++ .../secrets}/SecretsProviderTest.java | 26 +- .../powertools-parameters-ssm/pom.xml | 85 +++ .../powertools/parameters/ssm/SSMParam.java | 47 ++ .../parameters/ssm/SSMParamAspect.java | 49 ++ .../parameters/ssm}/SSMProvider.java | 140 +--- .../parameters/ssm/SSMProviderBuilder.java | 98 +++ .../parameters/ssm/SSMParamAspectTest.java | 52 ++ .../parameters/ssm}/SSMProviderTest.java | 40 +- .../powertools-parameters-tests/pom.xml | 67 ++ .../parameters/BaseProviderTest.java | 47 +- .../ParamProvidersIntegrationTest.java} | 43 +- .../parameters/cache/CacheManagerTest.java | 0 .../parameters/cache/DataStoreTest.java | 0 .../parameters/internal/AnotherObject.java | 0 .../parameters/internal/CustomProvider.java | 2 +- .../transform/Base64TransformerTest.java | 0 .../transform/JsonTransformerTest.java | 0 .../transform/ObjectToDeserialize.java | 0 .../transform/TransformationManagerTest.java | 0 powertools-parameters/spotbugs-exclude.xml | 82 +++ .../parameters/BaseParamAspect.java | 57 ++ .../powertools/parameters/BaseProvider.java | 26 +- .../parameters/DynamoDbProvider.java | 213 ------ .../powertools/parameters/ParamManager.java | 194 ----- .../parameters/SecretsProvider.java | 226 ------ .../internal/LambdaParametersAspect.java | 56 -- .../parameters/ParamManagerTest.java | 118 --- .../internal/LambdaParametersAspectTest.java | 105 --- spotbugs-exclude.xml | 50 +- 69 files changed, 2363 insertions(+), 1765 deletions(-) create mode 100644 powertools-parameters/powertools-parameters-appconfig/pom.xml create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java rename powertools-parameters/{src/main/java/software/amazon/lambda/powertools/parameters => powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig}/AppConfigProvider.java (52%) create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java rename powertools-parameters/{src/test/java/software/amazon/lambda/powertools/parameters => powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig}/AppConfigProviderTest.java (95%) create mode 100644 powertools-parameters/powertools-parameters-dynamodb/pom.xml rename powertools-parameters/{src/main/java/software/amazon/lambda/powertools/parameters/Param.java => powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java} (52%) create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java rename powertools-parameters/{src/main/java/software/amazon/lambda/powertools/parameters => powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb}/exception/DynamoDbProviderSchemaException.java (92%) create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java rename powertools-parameters/{src/test/java/software/amazon/lambda/powertools/parameters => powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb}/DynamoDbProviderE2ETest.java (96%) rename powertools-parameters/{src/test/java/software/amazon/lambda/powertools/parameters => powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb}/DynamoDbProviderTest.java (94%) create mode 100644 powertools-parameters/powertools-parameters-secrets/pom.xml create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java create mode 100644 powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java rename powertools-parameters/{src/test/java/software/amazon/lambda/powertools/parameters => powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets}/SecretsProviderTest.java (81%) create mode 100644 powertools-parameters/powertools-parameters-ssm/pom.xml create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java rename powertools-parameters/{src/main/java/software/amazon/lambda/powertools/parameters => powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm}/SSMProvider.java (60%) create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java create mode 100644 powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java rename powertools-parameters/{src/test/java/software/amazon/lambda/powertools/parameters => powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm}/SSMProviderTest.java (84%) create mode 100644 powertools-parameters/powertools-parameters-tests/pom.xml rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java (91%) rename powertools-parameters/{src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java => powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java} (81%) rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java (100%) rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java (100%) rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java (100%) rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java (97%) rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java (100%) rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java (100%) rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java (100%) rename powertools-parameters/{ => powertools-parameters-tests}/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java (100%) create mode 100644 powertools-parameters/spotbugs-exclude.xml create mode 100644 powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java delete mode 100644 powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java delete mode 100644 powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java delete mode 100644 powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java delete mode 100644 powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java delete mode 100644 powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java delete mode 100644 powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index 85d30d77e..f72c7704e 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -4,29 +4,46 @@ description: Utility --- -The parameters utility provides a way to retrieve parameter values from +The parameters utilities provide a way to retrieve parameter values from [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html), -[AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), or [Amazon DynamoDB](https://aws.amazon.com/dynamodb/). -It also provides a base class to create your parameter provider implementation. +[AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), [Amazon DynamoDB](https://aws.amazon.com/dynamodb/), +or [AWS AppConfig](https://aws.amazon.com/systems-manager/features/appconfig/). + +## Key features -**Key features** - -* Retrieve one or multiple parameters from the underlying provider +* Retrieve one or multiple parameters from an underlying provider in a standard way * Cache parameter values for a given amount of time (defaults to 5 seconds) * Transform parameter values from JSON or base 64 encoded strings ## Install -Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. +In order to provide lightweight dependencies, each parameters module is available as its own +package: + +* **Secrets Manager** - `powertools-parameters-secrets` +* **SSM Parameter Store** - `powertools-parameters-ssm` +* **Amazon DynamoDB** -`powertools-parameters-dynamodb` +* **AWS AppConfig** - `powertools-parameters-appconfig` + +You can easily mix and match parameter providers within the same project for different needs. + +Depending on which Java version you are using, you configuration will differ. Note that you must also provide +the concrete parameters module you want to use below - see the TODOs! === "Maven Java 11+" - ```xml hl_lines="3-7 16 18 24-27" + ```xml hl_lines="4-12 17 24 30-34" ... software.amazon.lambda - powertools-parameters - {{ powertools.version }} + + + powertools-parameters-secrets + powertools-parameters-ssm + powertools-parameters-dynamodb + powertools-parameters-appconfig + + {{ powertools.version }} ... @@ -44,9 +61,10 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl 11 11 + software.amazon.lambda - powertools-parameters + powertools-parameters-secrets @@ -65,13 +83,19 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl === "Maven Java 1.8" - ```xml hl_lines="3-7 16 18 24-27" + ```xml hl_lines="4-12 17 24 30-34" ... software.amazon.lambda - powertools-parameters - {{ powertools.version }} + + + powertools-parameters-secrets + powertools-parameters-ssm + powertools-parameters-dynamodb + powertools-parameters-appconfig + + {{ powertools.version }} ... @@ -89,9 +113,10 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl 1.8 1.8 + software.amazon.lambda - powertools-parameters + powertools-parameters-secrets @@ -110,7 +135,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl === "Gradle Java 11+" - ```groovy hl_lines="3 11" + ```groovy hl_lines="3 11 12" plugins { id 'java' id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' @@ -121,7 +146,8 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl } dependencies { - aspect 'software.amazon.lambda:powertools-parameters:{{ powertools.version }}' + // TODO! Provide the parameters module you want to use here + aspect 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}' } sourceCompatibility = 11 // or higher @@ -130,7 +156,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl === "Gradle Java 1.8" - ```groovy hl_lines="3 11" + ```groovy hl_lines="3 11 12" plugins { id 'java' id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' @@ -140,8 +166,9 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl mavenCentral() } + // TODO! Provide an aspectLibrary for each of the parameters module(s) you want to use here dependencies { - aspect 'software.amazon.lambda:powertools-parameters:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}' } sourceCompatibility = 1.8 @@ -152,63 +179,78 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl This utility requires additional permissions to work as expected. See the table below: -Provider | Function/Method | IAM Permission -------------------------------------------------- |----------------------------------------------------------------------| --------------------------------------------------------------------------------- -SSM Parameter Store | `SSMProvider.get(String)` `SSMProvider.get(String, Class)` | `ssm:GetParameter` -SSM Parameter Store | `SSMProvider.getMultiple(String)` | `ssm:GetParametersByPath` -Secrets Manager | `SecretsProvider.get(String)` `SecretsProvider.get(String, Class)` | `secretsmanager:GetSecretValue` -DynamoDB | `DynamoDBProvider.get(String)` `DynamoDBProvider.getMultiple(string)` | `dynamodb:GetItem` `dynamoDB:Query` +| Provider | Function/Method | IAM Permission | +|-----------|-------------------------------------------------------------------------|---------------------------------------------------------------------------| +| SSM | `SSMProvider.get(String)` `SSMProvider.get(String, Class)` | `ssm:GetParameter` | +| SSM | `SSMProvider.getMultiple(String)` | `ssm:GetParametersByPath` | +| SSM | If using `withDecryption(true)` | You must add an additional permission `kms:Decrypt` | +| Secrets | `SecretsProvider.get(String)` `SecretsProvider.get(String, Class)` | `secretsmanager:GetSecretValue` | +| DynamoDB | `DynamoDBProvider.get(String)` `DynamoDBProvider.getMultiple(string)` | `dynamodb:GetItem` `dynamoDB:Query` | +| AppConfig | `AppConfigProvider.get(String)` `AppConfigProvider.getMultiple(string)` | `appconfig:StartConfigurationSession`, `appConfig:GetLatestConfiguration` | -## SSM Parameter Store +## Retrieving Parameters +You can retrieve parameters either using annotations or by using the `xParamProvider` class for each parameter +provider directly. The latter is useful if you need to configure the underlying SDK client, for example to use +a different region or credentials, the former is simpler to use. -You can retrieve a single parameter using SSMProvider.get() and pass the key of the parameter. -For multiple parameters, you can use SSMProvider.getMultiple() and pass the path to retrieve them all. +## Built-in provider classes -Alternatively, you can retrieve an instance of a provider and configure its underlying SDK client, -in order to get data from other regions or use specific credentials. +This section describes the built-in provider classes for each parameter store, providing +examples showing how to inject parameters using annotations, and how to use the provider +interface. In cases where a provider supports extra features, these will also be described. -=== "SSMProvider" +### Secrets Manager - ```java hl_lines="6" - import software.amazon.lambda.powertools.parameters.SSMProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; +=== "Secrets Manager: @SecretsParam" - public class AppWithSSM implements RequestHandler { - // Get an instance of the SSM Provider - SSMProvider ssmProvider = ParamManager.getSsmProvider(); - - // Retrieve a single parameter - String value = ssmProvider.get("/my/parameter"); - - // Retrieve multiple parameters from a path prefix - // This returns a Map with the parameter name as key - Map values = ssmProvider.getMultiple("/my/path/prefix"); + ```java hl_lines="8 9" + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import software.amazon.lambda.powertools.parameters.secrets.SecretsParam; + public class ParametersFunction implements RequestHandler { + + // Annotation-style injection from secrets manager + @SecretsParam(key = "/powertools-java/userpwd") + String secretParam; + + public string handleRequest(String request, Context context) { + // ... do something with the secretParam here + return "something"; + } } ``` -=== "SSMProvider with a custom client" +=== "Secrets Manager: SecretsProvider" - ```java hl_lines="5 7" - import software.amazon.lambda.powertools.parameters.SSMProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; + ```java hl_lines="12-15 19" + import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; + + import com.amazonaws.services.lambda.runtime.Context; + import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; + import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider; + import com.amazonaws.services.lambda.runtime.RequestHandler; - public class AppWithSSM implements RequestHandler { - SsmClient client = SsmClient.builder().region(Region.EU_CENTRAL_1).build(); - // Get an instance of the SSM Provider - SSMProvider ssmProvider = ParamManager.getSsmProvider(client); + public class RequestHandlerWithParams implements RequestHandler { - // Retrieve a single parameter - String value = ssmProvider.get("/my/parameter"); + // Get an instance of the SecretsProvider. We can provide a custom client here if we want, + // for instance to use a particular region. + SecretsProvider secretsProvider = SecretsProvider + .builder() + .withClient(SecretsManagerClient.builder().build()) + .build(); - // Retrieve multiple parameters from a path prefix - // This returns a Map with the parameter name as key - Map values = ssmProvider.getMultiple("/my/path/prefix"); + public String handleRequest(String input, Context context) { + // Retrieve a single secret + String value = secretsProvider.get("/my/secret"); + // ... do something with the secretParam here + return "something"; + } } ``` -### Additional arguments +### SSM Parameter Store The AWS Systems Manager Parameter Store provider supports two additional arguments for the `get()` and `getMultiple()` methods: @@ -217,9 +259,59 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen | **withDecryption()** | `False` | Will automatically decrypt the parameter. | | **recursive()** | `False` | For `getMultiple()` only, will fetch all parameter values recursively based on a path prefix. | -**Example:** -=== "AppWithSSM.java" +=== "SSM Parameter Store: @SSMParam" + + ```java hl_lines="8 9" + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import software.amazon.lambda.powertools.parameters.ssm.SSMParam; + + public class ParametersFunction implements RequestHandler { + + // Annotation-style injection from SSM Parameter Store + @SSMParam(key = "/powertools-java/param") + String ssmParam; + + public string handleRequest(String request, Context context) { + return ssmParam; // Request handler simply returns our configuration value + } + } + ``` + +=== "SSM Parameter Store: SSMProvider" + + ```java hl_lines="12-15 19-20 22" + import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import software.amazon.awssdk.services.ssm.SsmClient; + import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; + + public class RequestHandlerWithParams implements RequestHandler { + + // Get an instance of the SSMProvider. We can provide a custom client here if we want, + // for instance to use a particular region. + SSMProvider ssmProvider = SSMProvider + .builder() + .withClient(SsmClient.builder().build()) + .build(); + + public String handleRequest(String input, Context context) { + // Retrieve a single param + String value = ssmProvider + .get("/my/secret"); + // We might instead want to retrieve multiple parameters at once, returning a Map of key/value pairs + // .getMultiple("/my/secret/path"); + + // Return the result + return value; + } + } + ``` + +=== "SSM Parameter Store: Additional Options" ```java hl_lines="9 12" import software.amazon.lambda.powertools.parameters.SSMProvider; @@ -238,183 +330,159 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen } ``` -## Secrets Manager +### DynamoDB -For secrets stored in Secrets Manager, use `getSecretsProvider`. +=== "DynamoDB: @DyanmoDbParam" -Alternatively, you can retrieve an instance of a provider and configure its underlying SDK client, -in order to get data from other regions or use specific credentials. + ```java hl_lines="8 9" + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDBParam; + public class ParametersFunction implements RequestHandler { -=== "SecretsProvider" + // Annotation-style injection from DynamoDB + @DynamoDbParam(table = "my-test-tablename", key = "myKey") + String ddbParam; - ```java hl_lines="9" - import software.amazon.lambda.powertools.parameters.SecretsProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; - - public class AppWithSecrets implements RequestHandler { - // Get an instance of the Secrets Provider - SecretsProvider secretsProvider = ParamManager.getSecretsProvider(); - - // Retrieve a single secret - String value = secretsProvider.get("/my/secret"); - + public string handleRequest(String request, Context context) { + return ddbParam; // Request handler simply returns our configuration value + } } ``` -=== "SecretsProvider with a custom client" +=== "DynamoDB: DynamoDbProvider" - ```java hl_lines="5 7" - import software.amazon.lambda.powertools.parameters.SecretsProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; + ```java hl_lines="12-15 19-20 22" + import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import software.amazon.awssdk.services.dynamodb.DynamoDbClient; + import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProvider; - public class AppWithSecrets implements RequestHandler { - SecretsManagerClient client = SecretsManagerClient.builder().region(Region.EU_CENTRAL_1).build(); - // Get an instance of the Secrets Provider - SecretsProvider secretsProvider = ParamManager.getSecretsProvider(client); + public class RequestHandlerWithParams implements RequestHandler { - // Retrieve a single secret - String value = secretsProvider.get("/my/secret"); + // Get an instance of the DynamoDbProvider. We can provide a custom client here if we want, + // for instance to use a particular region. + DynamoDbProvider ddbProvider = DynamoDbProvider + .builder() + .withClient(DynamoDbClient.builder().build()) + .build(); + public String handleRequest(String input, Context context) { + // Retrieve a single param + String value = ddbProvider + .get("/my/secret"); + // We might instead want to retrieve multiple values at once, returning a Map of key/value pairs + // .getMultiple("my-partition-key-value"); + + // Return the result + return value; + } } ``` -## DynamoDB -To get secrets stored in DynamoDB, use `getDynamoDbProvider`, providing the name of the table that -contains the secrets. As with the other providers, an overloaded methods allows you to retrieve -a `DynamoDbProvider` providing a client if you need to configure it yourself. +### AppConfig -=== "DynamoDbProvider" +=== "AppConfig: @AppConfigParam" - ```java hl_lines="6 9" - import software.amazon.lambda.powertools.parameters.DynamoDbProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; + ```java hl_lines="8 9" + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import software.amazon.lambda.powertools.parameters.appconfig.AppConfigParam; - public class AppWithDynamoDbParameters implements RequestHandler { - // Get an instance of the DynamoDbProvider - DynamoDbProvider ddbProvider = ParamManager.getDynamoDbProvider("my-parameters-table"); + public class ParametersFunction implements RequestHandler { - // Retrieve a single parameter - String value = ddbProvider.get("my-key"); - } - ``` - -=== "DynamoDbProvider with a custom client" + // Annotation-style injection from AppConfig + @AppConfigParam(application = "my-app", environment = "my-env", key = "myKey") + String appConfigParam; - ```java hl_lines="9 10 11 12 15 18" - import software.amazon.lambda.powertools.parameters.DynamoDbProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; - import software.amazon.awssdk.services.dynamodb.DynamoDbClient; - import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; - import software.amazon.awssdk.regions.Region; - - public class AppWithDynamoDbParameters implements RequestHandler { - // Get a DynamoDB Client with an explicit region - DynamoDbClient ddbClient = DynamoDbClient.builder() - .httpClientBuilder(UrlConnectionHttpClient.builder()) - .region(Region.EU_CENTRAL_2) - .build(); - - // Get an instance of the DynamoDbProvider - DynamoDbProvider provider = ParamManager.getDynamoDbProvider(ddbClient, "test-table"); - - // Retrieve a single parameter - String value = ddbProvider.get("my-key"); - } + public string handleRequest(String request, Context context) { + return appConfigParam; // Request handler simply returns our configuration value + } + } ``` -## AppConfig -To get parameters stored in AppConfig, use `getAppConfigProvider`, providing the application and environment -name to retrieve configuration from. As with the other providers, an overloaded method allows you to retrieve -an `AppConfigProvider` providing a client if you need to configure it yourself. - -=== "AppConfigProvider" +=== "AppConfig: AppConfigProvider" - ```java hl_lines="6 9" - import software.amazon.lambda.powertools.parameters.AppConfigProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; - - public class AppWitAppConfigParameters implements RequestHandler { - // Get an instance of the AppConfigProvider - AppConfigProvider appConfigProvider = ParamManager.getAppConfigProvider("my-environment", "my-app"); + ```java hl_lines="12-15 19-20" + import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; - // Retrieve a single parameter - String value = appConfigProvider.get("my-key"); - } - ``` - -=== "AppConfigProvider with a custom client" - - ```java hl_lines="9 10 11 12 15 18" - import software.amazon.lambda.powertools.parameters.AppConfigProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; - import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; - import software.amazon.awssdk.regions.Region; - - public class AppWithDynamoDbParameters implements RequestHandler { - // Get an AppConfig Client with an explicit region - AppConfigDataClient appConfigDataClient = AppConfigDataClient.builder() - .httpClientBuilder(UrlConnectionHttpClient.builder()) - .region(Region.EU_CENTRAL_2) - .build(); + import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider; - // Get an instance of the DynamoDbProvider - AppConfigProvider appConfigProvider = ParamManager.getAppConfigProvider(appConfigDataClient, "my-environment", "my-app"); + public class RequestHandlerWithParams implements RequestHandler { + + // Get an instance of the AppConfigProvider. We can provide a custom client here if we want, + // for instance to use a particular region. + AppConfigProvider appConfigProvider = AppConfigProvider + .builder() + .withClient(AppConfigDataClient.builder().build()) + .build(); - // Retrieve a single parameter - String value = appConfigProvider.get("my-key"); - } + public String handleRequest(String input, Context context) { + // Retrieve a single param + String value = appConfigProvider + .get("/my/secret"); + + // Return the result + return value; + } + } ``` - ## Advanced configuration ### Caching +Each provider uses the `CacheManager` to cache parameter values. When a value is retrieved using from the provider, a +custom cache duration can be provided using `withMaxAge(duration, unit)`. -By default, all parameters and their corresponding values are cached for 5 seconds. - -You can customize this default value using `defaultMaxAge`. You can also customize this value for each parameter using -`withMaxAge`. - -=== "Provider with default Max age" - - ```java hl_lines="9" - import software.amazon.lambda.powertools.parameters.SecretsProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; +If this is not specified, the default value set on the `CacheManager` itself will be used. This default can be customized +by calling `setDefaultExpirationTime(duration, unit)` on the `CacheManager`. - public class AppWithSecrets implements RequestHandler { - // Get an instance of the Secrets Provider - SecretsProvider secretsProvider = ParamManager.getSecretsProvider() - .defaultMaxAge(10, ChronoUnit.SECONDS); +=== "Customize Cache" - String value = secretsProvider.get("/my/secret"); + ```java hl_lines="9 10 14 19 22-25" + import java.time.Duration; + import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider; + import software.amazon.lambda.powertools.parameters.cache.CacheManager; - } - ``` - -=== "Provider with age for each param" - - ```java hl_lines="8" - import software.amazon.lambda.powertools.parameters.SecretsProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; - - public class AppWithSecrets implements RequestHandler { - SecretsManagerClient client = SecretsManagerClient.builder().region(Region.EU_CENTRAL_1).build(); + public class CustomizeCache { - SecretsProvider secretsProvider = ParamManager.getSecretsProvider(client); - - String value = secretsProvider.withMaxAge(10, ChronoUnit.SECONDS).get("/my/secret"); + public void CustomizeCache() { + + CacheManager cacheManager = new CacheManager(); + cacheManager.setDefaultExpirationTime(Duration.ofSeconds(10)); + AppConfigProvider paramProvider = AppConfigProvider + .builder() + .withCacheManager(cacheManager) + .withClient(AppConfigDataClient.builder().build()) + .build(); + + // Will use the default specified above - 10 seconds + String myParam1 = paramProvider.get("myParam1"); + + // Will override the default above + String myParam2 = paramProvider + .withMaxAge(20, ChronoUnit.SECONDS) + .get("myParam2"); + + return myParam2; + } } ``` + ### Transform values Parameter values can be transformed using ```withTransformation(transformerClass)```. -Base64 and JSON transformations are provided. For more complex transformation, you need to specify how to deserialize- +Base64 and JSON transformations are provided. For more complex transformation, you need to specify how to deserialize. -!!! warning "`SSMProvider.getMultiple()` does not support transformation and will return simple Strings." +!!! warning "`getMultiple()` does not support transformation and will return simple Strings." === "Base64 Transformation" ```java @@ -431,14 +499,16 @@ Base64 and JSON transformations are provided. For more complex transformation, y .get("/my/parameter/json", MyObj.class); ``` -## Write your own Transformer + + +#### Create your own Transformer You can write your own transformer, by implementing the `Transformer` interface and the `applyTransformation()` method. For example, if you wish to deserialize XML into an object. === "XmlTransformer.java" - ```java hl_lines="1" + ```java public class XmlTransformer implements Transformer { private final XmlMapper mapper = new XmlMapper(); @@ -470,172 +540,141 @@ To simplify the use of the library, you can chain all method calls before a get. ```java ssmProvider - .defaultMaxAge(10, SECONDS) // will set 10 seconds as the default cache TTL .withMaxAge(1, MINUTES) // will set the cache TTL for this value at 1 minute .withTransformation(json) // json is a static import from Transformer.json .withDecryption() // enable decryption of the parameter value .get("/my/param", MyObj.class); // finally get the value - ``` - -## Create your own provider -You can create your own custom parameter store provider by inheriting the ```BaseProvider``` class and implementing the -```String getValue(String key)``` method to retrieve data from your underlying store. All transformation and caching logic is handled by the get() methods in the base class. +### Create your own Provider +You can create your own custom parameter store provider by implementing a handful of classes: -=== "Example implementation using S3 as a custom parameter" +=== "CustomProvider.java" ```java - public class S3Provider extends BaseProvider { - - private final S3Client client; - private String bucket; - - S3Provider(CacheManager cacheManager) { - this(cacheManager, S3Client.create()); - } - - S3Provider(CacheManager cacheManager, S3Client client) { - super(cacheManager); - this.client = client; + import java.util.Map; + import software.amazon.lambda.powertools.parameters.BaseProvider; + import software.amazon.lambda.powertools.parameters.cache.CacheManager; + import software.amazon.lambda.powertools.parameters.transform.TransformationManager; + + /** + * Our custom parameter provider itself. This does the heavy lifting of retrieving + * parameters from whatever our underlying parameter store might be. + **/ + public class CustomProvider extends BaseProvider { + + public CustomProvider(CacheManager cacheManager, TransformationManager transformationManager) { + super(cacheManager, transformationManager); } - - public S3Provider withBucket(String bucket) { - this.bucket = bucket; - return this; + + public CustomProviderBuilder builder() { + return new CustomProviderBuilder(); } @Override protected String getValue(String key) { - if (bucket == null) { - throw new IllegalStateException("A bucket must be specified, using withBucket() method"); - } - - GetObjectRequest request = GetObjectRequest.builder().bucket(bucket).key(key).build(); - ResponseBytes response = client.getObject(request, ResponseTransformer.toBytes()); - return response.asUtf8String(); + throw new RuntimeException("TODO - return a single value"); } @Override protected Map getMultipleValues(String path) { - if (bucket == null) { - throw new IllegalStateException("A bucket must be specified, using withBucket() method"); - } - - ListObjectsV2Request listRequest = ListObjectsV2Request.builder().bucket(bucket).prefix(path).build(); - List s3Objects = client.listObjectsV2(listRequest).contents(); - - Map result = new HashMap<>(); - s3Objects.forEach(s3Object -> { - result.put(s3Object.key(), getValue(s3Object.key())); - }); - - return result; + throw new RuntimeException("TODO - Optional - return multiple values"); } - - @Override - protected void resetToDefaults() { - super.resetToDefaults(); - bucket = null; - } - } ``` -=== "Using custom parameter store" - - ```java hl_lines="3" - S3Provider provider = new S3Provider(ParamManager.getCacheManager()); - - provider.setTransformationManager(ParamManager.getTransformationManager()); - - String value = provider.withBucket("myBucket").get("myKey"); - ``` - -## Annotation - -You can make use of the annotation `@Param` to inject a parameter value in a variable. +=== "CustomProviderBuilder.java" -By default, it will use `SSMProvider` to retrieve the value from AWS System Manager Parameter Store. -You could specify a different provider as long as it extends `BaseProvider` and/or a `Transformer`. + ```java + /** + * Provides a builder-style interface to configure our @{link CustomProvider}. + **/ + public class CustomProviderBuilder { + private CacheManager cacheManager; + private TransformationManager transformationManager; + + /** + * Create a {@link CustomProvider} instance. + * + * @return a {@link CustomProvider} + */ + public CustomProvider build() { + if (cacheManager == null) { + cacheManager = new CacheManager(); + } + return new CustomProvider(cacheManager, transformationManager); + } -=== "Param Annotation" + /** + * Provide a CacheManager to the {@link CustomProvider} + * + * @param cacheManager the manager that will handle the cache of parameters + * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) + */ + public CustomProviderBuilder withCacheManager(CacheManager cacheManager) { + this.cacheManager = cacheManager; + return this; + } - ```java hl_lines="3" - public class AppWithAnnotation implements RequestHandler { - - @Param(key = "/my/parameter/json") - ObjectToDeserialize value; - + /** + * Provide a transformationManager to the {@link CustomProvider} + * + * @param transformationManager the manager that will handle transformation of parameters + * @return the builder to chain calls (eg.
builder.withTransformationManager().build()
) + */ + public CustomProviderBuilder withTransformationManager(TransformationManager transformationManager) { + this.transformationManager = transformationManager; + return this; + } } ``` -=== "Custom Provider Usage" - - ```java hl_lines="3" - public class AppWithAnnotation implements RequestHandler { - - @Param(key = "/my/parameter/json" provider = SecretsProvider.class, transformer = JsonTransformer.class) - ObjectToDeserialize value; - +=== "CustomProviderParam.java" + + ```java + import java.lang.annotation.ElementType; + import java.lang.annotation.Retention; + import java.lang.annotation.RetentionPolicy; + import java.lang.annotation.Target; + import software.amazon.lambda.powertools.parameters.transform.Transformer; + + /** + * Aspect to inject a parameter from our custom provider. Note that if you + * want to implement a provider _without_ an Aspect and field injection, you can + * skip implementing both this and the {@link CustomProviderAspect} class. + **/ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public @interface CustomProviderParam { + // The parameter key + String key(); + + // The transformer to use + Class transformer() default Transformer.class; } ``` - In this case ```SecretsProvider``` will be used to retrieve a raw value that is then trasformed into the target Object by using ```JsonTransformer```. - To show the convenience of the annotation compare the following two code snippets. - - -### Install +=== "CustomProviderAspect.java" -If you want to use the ```@Param``` annotation in your project add configuration to compile-time weave (CTW) the powertools-parameters aspects into your project. - -=== "Maven" + ```java - ```xml - - - ... - - dev.aspectj - aspectj-maven-plugin - 1.13.1 - - ... - - ... - - software.amazon.lambda - powertools-parameters - - - - - - - compile - - - - - ... - - - ``` + /** + * Aspect to inject a parameter from our custom provider where the {@link CustomProviderParam} + * annotation is used. + **/ + @Aspect + public class CustomProviderAspect extends BaseParamAspect { -=== "Gradle" - - ```groovy - plugins{ - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.3.0' - } - - repositories { - mavenCentral() - } + @Pointcut("get(* *) && @annotation(ddbConfigParam)") + public void getParam(CustomProviderParam customConfigParam) { + } + + @Around("getParam(customConfigParam)") + public Object injectParam(final ProceedingJoinPoint joinPoint, final CustomProviderParam customConfigParam) { + BaseProvider provider = CustomProvider.builder().build(); - dependencies { - ... - aspect 'software.amazon.lambda:powertools-parameters:{{ powertools.version }}' - implementation 'org.aspectj:aspectjrt:1.9.19' + return getAndTransform(customConfigParam.key(), ddbConfigParam.transformer(), provider, + (FieldSignature) joinPoint.getSignature()); + } + } ``` \ No newline at end of file diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 7a4af628c..8d7fbd4f4 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -21,9 +21,15 @@ software.amazon.lambda - powertools-parameters + powertools-parameters-ssm ${project.version} + + software.amazon.lambda + powertools-parameters-secrets + ${project.version} + + com.amazonaws aws-lambda-java-core diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java index 5b691cfd9..9a1d3636b 100644 --- a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java +++ b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java @@ -31,17 +31,30 @@ import java.util.stream.Collectors; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import software.amazon.lambda.powertools.parameters.ParamManager; -import software.amazon.lambda.powertools.parameters.SSMProvider; -import software.amazon.lambda.powertools.parameters.SecretsProvider; +import software.amazon.lambda.powertools.parameters.secrets.SecretsParam; +import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider; +import software.amazon.lambda.powertools.parameters.ssm.SSMParam; +import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; public class ParametersFunction implements RequestHandler { private final static Logger log = LogManager.getLogger(ParametersFunction.class); - SSMProvider ssmProvider = ParamManager.getSsmProvider(); - SecretsProvider secretsProvider = ParamManager.getSecretsProvider(); + // Annotation-style injection from secrets manager + @SecretsParam(key = "/powertools-java/userpwd") + String secretParamInjected; - String simpleValue = ssmProvider.defaultMaxAge(30, SECONDS).get("/powertools-java/sample/simplekey"); + // Annotation-style injection from Systems Manager + @SSMParam(key = "/powertools-java/sample/simplekey") + String ssmParamInjected; + + SSMProvider ssmProvider = SSMProvider + .builder() + .build(); + SecretsProvider secretsProvider = SecretsProvider + .builder() + .build(); + + String simpleValue = ssmProvider.withMaxAge(30, SECONDS).get("/powertools-java/sample/simplekey"); String listValue = ssmProvider.withMaxAge(60, SECONDS).get("/powertools-java/sample/keylist"); MyObject jsonObj = ssmProvider.withTransformation(json).get("/powertools-java/sample/keyjson", MyObject.class); Map allValues = ssmProvider.getMultiple("/powertools-java/sample"); diff --git a/mkdocs.yml b/mkdocs.yml index a8569f664..b7f793e18 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -85,7 +85,7 @@ extra_javascript: extra: powertools: - version: 1.18.0 # to update after each release (we do not want snapshot version here) + version: 2.0.0 # to update after each release (we do not want snapshot version here) repo_url: https://github.com/aws-powertools/powertools-lambda-java edit_uri: edit/main/docs diff --git a/pom.xml b/pom.xml index cad72dee1..1d35a990f 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,11 @@ powertools-e2e-tests powertools-batch examples + powertools-parameters/powertools-parameters-ssm + powertools-parameters/powertools-parameters-secrets + powertools-parameters/powertools-parameters-dynamodb + powertools-parameters/powertools-parameters-appconfig + powertools-parameters/powertools-parameters-tests @@ -600,35 +605,6 @@ - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.3.0 - - checkstyle.xml - UTF-8 - true - true - false - - - - - - com.puppycrawl.tools - checkstyle - 10.12.3 - - - - - - check - - - - diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index aee9bf3dd..8740dcb0b 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT e2e-test-handler-batch diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index 22b6a1c53..a0e6bd4fc 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT e2e-test-handler-idempotency diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index 8302624ef..277e76fc1 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT e2e-test-handler-largemessage diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index 1fe9092ef..d887341c5 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT e2e-test-handler-large-msg-idempotent diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml index 05e91d8e3..222c5ab2e 100644 --- a/powertools-e2e-tests/handlers/logging/pom.xml +++ b/powertools-e2e-tests/handlers/logging/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT e2e-test-handler-logging diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 2f3cabd16..68059e67e 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -5,12 +5,12 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT e2e-test-handler-metrics jar - A Lambda function using Powertools for AWS Lambda (Java) Parameters + A Lambda function using Powertools for AWS Lambda (Java) Metrics diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index 4d5330da0..328d30485 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -5,12 +5,12 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT e2e-test-handler-parameters jar - A Lambda function using powertools logging + A Lambda function using powertools parameters @@ -19,7 +19,7 @@ software.amazon.lambda - powertools-parameters + powertools-parameters-appconfig com.amazonaws diff --git a/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index 3a83a1b05..1e151825e 100644 --- a/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/parameters/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -17,14 +17,18 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.parameters.AppConfigProvider; -import software.amazon.lambda.powertools.parameters.ParamManager; +import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider; public class Function implements RequestHandler { @Logging public String handleRequest(Input input, Context context) { - AppConfigProvider provider = ParamManager.getAppConfigProvider(input.getEnvironment(), input.getApp()); + AppConfigProvider provider = AppConfigProvider.builder() + .withApplication(input.getApp()) + .withEnvironment(input.getEnvironment()) + .build(); + + //(input.getEnvironment(), input.getApp()); return provider.get(input.getKey()); } diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 7c1208470..2c73de977 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -4,7 +4,7 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT pom Handlers for End-to-End tests Fake handlers that use Powertools for AWS Lambda (Java). @@ -27,12 +27,16 @@ + batch + largemessage + largemessage_idempotent logging tracing metrics idempotency parameters - validation + validation-alb-event + validation-apigw-event @@ -71,7 +75,7 @@ software.amazon.lambda - powertools-parameters + powertools-parameters-appconfig ${lambda.powertools.version} diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index b9240c356..b96fcef0a 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT e2e-test-handler-tracing diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml index 31570fe4e..be50094c1 100644 --- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT e2e-test-handler-validation-alb-event diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml index 9129abc7d..f204a8a9f 100644 --- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 1.0.0 + 2.0.0-SNAPSHOT e2e-test-handler-validation-apigw-event diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index eb73962e1..1bc662457 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -28,77 +28,17 @@ Powertools for AWS Lambda (Java) library Parameters - - Set of utilities to retrieve parameters from Secrets Manager or SSM Parameter Store - - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - + Set of utilities to retrieve parameters - common interface software.amazon.lambda powertools-common - - software.amazon.awssdk - ssm - - - software.amazon.awssdk - apache-client - - - software.amazon.awssdk - netty-nio-client - - - - - software.amazon.awssdk - secretsmanager - - - software.amazon.awssdk - apache-client - - - software.amazon.awssdk - netty-nio-client - - - software.amazon.awssdk url-connection-client - - software.amazon.awssdk - dynamodb - - - software.amazon.awssdk - appconfigdata - com.fasterxml.jackson.core diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml new file mode 100644 index 000000000..3a3018c7c --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + + software.amazon.lambda + powertools-parent + 2.0.0-SNAPSHOT + ../../pom.xml + + + powertools-parameters-appconfig + Powertools for AWS Lambda (Java) library Parameters - AppConfig + AppConfig implementation for the Parameters module + + + + software.amazon.lambda + powertools-parameters + ${project.version} + + + + software.amazon.awssdk + appconfigdata + + + software.amazon.awssdk + apache-client + + + software.amazon.awssdk + netty-nio-client + + + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.apache.commons + commons-lang3 + test + + + org.assertj + assertj-core + test + + + org.aspectj + aspectjweaver + test + + + + + + + maven-surefire-plugin + 3.1.2 + + + eu-central-1 + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + \ No newline at end of file diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java new file mode 100644 index 000000000..eb959be76 --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParam.java @@ -0,0 +1,57 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.appconfig; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import software.amazon.lambda.powertools.parameters.transform.Transformer; + +/** + * Use this annotation to inject AWS AppConfig parameters into fields in your application. You + * can also use {@code AppConfigProviderBuilder} to obtain AppConfig values directly, rather than + * injecting them implicitly. + * Both {@code environment} and {@code application} fields are necessary. + * + * @see AppConfigProviderBuilder + * @see Powertools for AWS Lambda (Java) parameters documentation + * + *
+ * @AppConfigParam(key = "my-param", environment = "my-env", application = "my-app")
+ * String appConfigParam;
+ * 
+ */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface AppConfigParam { + String key(); + + /** + * Mandatory. Provide an environment to the {@link AppConfigProvider} + */ + String environment(); + + /** + * Mandatory. Provide an application to the {@link AppConfigProvider} + */ + String application(); + + /** + * Optional Provide a Transformer to transform the returned parameter values. + */ + Class transformer() default Transformer.class; +} diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java new file mode 100644 index 000000000..7ab4cf23e --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParametersAspect.java @@ -0,0 +1,54 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.appconfig; + +import java.util.function.BiFunction; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.FieldSignature; +import software.amazon.lambda.powertools.parameters.BaseParamAspect; + +/** + * Provides the AppConfig parameter aspect. This aspect is responsible for injecting + * parameters from AWS AppConfig into fields annotated with @AppConfigParam. See the + * README and Powertools for Lambda (Java) documentation for information on using this feature. + */ +@Aspect +public class AppConfigParametersAspect extends BaseParamAspect { + + private static BiFunction providerBuilder = + (String env, String app) -> AppConfigProvider.builder() + .withEnvironment(env) + .withApplication(app) + .build(); + + + @Pointcut("get(* *) && @annotation(appConfigParamAnnotation)") + public void getParam(AppConfigParam appConfigParamAnnotation) { + } + + @Around("getParam(appConfigParamAnnotation)") + public Object injectParam(final ProceedingJoinPoint joinPoint, final AppConfigParam appConfigParamAnnotation) { + + AppConfigProvider provider = providerBuilder.apply + (appConfigParamAnnotation.environment(), appConfigParamAnnotation.application()); + + return getAndTransform(appConfigParamAnnotation.key(), appConfigParamAnnotation.transformer(), provider, + (FieldSignature) joinPoint.getSignature()); + } + +} diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java similarity index 52% rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java rename to powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java index 5a1e575dd..5fd272c9b 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/AppConfigProvider.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java @@ -12,20 +12,16 @@ * */ -package software.amazon.lambda.powertools.parameters; +package software.amazon.lambda.powertools.parameters.appconfig; import java.util.HashMap; import java.util.Map; -import software.amazon.awssdk.core.SdkSystemSetting; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; -import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationRequest; import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationResponse; import software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionRequest; -import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.parameters.BaseProvider; +import software.amazon.lambda.powertools.parameters.ParamProvider; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; @@ -50,8 +46,9 @@ public class AppConfigProvider extends BaseProvider { private final String environment; private final HashMap establishedSessions = new HashMap<>(); - AppConfigProvider(CacheManager cacheManager, AppConfigDataClient client, String environment, String application) { - super(cacheManager); + AppConfigProvider(CacheManager cacheManager, TransformationManager transformationManager, + AppConfigDataClient client, String environment, String application) { + super(cacheManager, transformationManager); this.client = client; this.application = application; this.environment = environment; @@ -60,12 +57,13 @@ public class AppConfigProvider extends BaseProvider { /** * Create a builder that can be used to configure and create a {@link AppConfigProvider}. * - * @return a new instance of {@link AppConfigProvider.Builder} + * @return a new instance of {@link AppConfigProviderBuilder} */ - public static AppConfigProvider.Builder builder() { - return new AppConfigProvider.Builder(); + public static AppConfigProviderBuilder builder() { + return new AppConfigProviderBuilder(); } + /** * Retrieve the parameter value from the AppConfig parameter store.
* @@ -128,102 +126,4 @@ private EstablishedSession(String nextSessionToken, String value) { } } - static class Builder { - private AppConfigDataClient client; - private CacheManager cacheManager; - private TransformationManager transformationManager; - private String environment; - private String application; - - /** - * Create a {@link AppConfigProvider} instance. - * - * @return a {@link AppConfigProvider} - */ - public AppConfigProvider build() { - if (cacheManager == null) { - throw new IllegalStateException("No CacheManager provided; please provide one"); - } - if (environment == null) { - throw new IllegalStateException("No environment provided; please provide one"); - } - if (application == null) { - throw new IllegalStateException("No application provided; please provide one"); - } - - // Create a AppConfigDataClient if we haven't been given one - if (client == null) { - client = AppConfigDataClient.builder() - .httpClientBuilder(UrlConnectionHttpClient.builder()) - .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, - UserAgentConfigurator.getUserAgent(PARAMETERS)).build()) - .build(); - } - - AppConfigProvider provider = new AppConfigProvider(cacheManager, client, environment, application); - - if (transformationManager != null) { - provider.setTransformationManager(transformationManager); - } - return provider; - } - - /** - * Set custom {@link AppConfigProvider} to pass to the {@link AppConfigDataClient}.
- * Use it if you want to customize the region or any other part of the client. - * - * @param client Custom client - * @return the builder to chain calls (eg.
builder.withClient().build()
) - */ - public AppConfigProvider.Builder withClient(AppConfigDataClient client) { - this.client = client; - return this; - } - - /** - * Mandatory. Provide an environment to the {@link AppConfigProvider} - * - * @param environment the AppConfig environment - * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) - */ - public AppConfigProvider.Builder withEnvironment(String environment) { - this.environment = environment; - return this; - } - - /** - * Mandatory. Provide an application to the {@link AppConfigProvider} - * - * @param application the application to pull configuration from - * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) - */ - public AppConfigProvider.Builder withApplication(String application) { - this.application = application; - return this; - } - - /** - * Mandatory. Provide a CacheManager to the {@link AppConfigProvider} - * - * @param cacheManager the manager that will handle the cache of parameters - * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) - */ - public AppConfigProvider.Builder withCacheManager(CacheManager cacheManager) { - this.cacheManager = cacheManager; - return this; - } - - /** - * Provide a transformationManager to the {@link AppConfigProvider} - * - * @param transformationManager the manager that will handle transformation of parameters - * @return the builder to chain calls (eg.
builder.withTransformationManager().build()
) - */ - public AppConfigProvider.Builder withTransformationManager(TransformationManager transformationManager) { - this.transformationManager = transformationManager; - return this; - } - } } diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java new file mode 100644 index 000000000..dadacb843 --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java @@ -0,0 +1,124 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.appconfig; + +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.parameters.BaseProvider; +import software.amazon.lambda.powertools.parameters.ParamProvider; +import software.amazon.lambda.powertools.parameters.cache.CacheManager; +import software.amazon.lambda.powertools.parameters.transform.TransformationManager; + +/** + * Implements a {@link ParamProvider} on top of the AppConfig service. AppConfig provides + */ +public class AppConfigProviderBuilder { + private AppConfigDataClient client; + private CacheManager cacheManager; + private TransformationManager transformationManager; + private String environment; + private String application; + + /** + * Create a {@link AppConfigProvider} instance. + * + * @return a {@link AppConfigProvider} + */ + public AppConfigProvider build() { + if (cacheManager == null) { + cacheManager = new CacheManager(); + } + if (environment == null) { + throw new IllegalStateException("No environment provided; please provide one"); + } + if (application == null) { + throw new IllegalStateException("No application provided; please provide one"); + } + + // Create a AppConfigDataClient if we haven't been given one + if (client == null) { + client = AppConfigDataClient.builder() + .httpClientBuilder(UrlConnectionHttpClient.builder()) + .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, + UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build()) + .build(); + } + + return new AppConfigProvider(cacheManager, transformationManager, client, environment, application); + } + + /** + * Set custom {@link AppConfigDataClient} to pass to the {@link AppConfigProvider}.
+ * Use it if you want to customize the region or any other part of the client. + * + * @param client Custom client + * @return the builder to chain calls (eg.
builder.withClient().build()
) + */ + public AppConfigProviderBuilder withClient(AppConfigDataClient client) { + this.client = client; + return this; + } + + /** + * Mandatory. Provide an environment to the {@link AppConfigProvider} + * + * @param environment the AppConfig environment + * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) + */ + public AppConfigProviderBuilder withEnvironment(String environment) { + this.environment = environment; + return this; + } + + /** + * Mandatory. Provide an application to the {@link AppConfigProvider} + * + * @param application the application to pull configuration from + * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) + */ + public AppConfigProviderBuilder withApplication(String application) { + this.application = application; + return this; + } + + /** + * Provide a CacheManager to the {@link AppConfigProvider} + * + * @param cacheManager the manager that will handle the cache of parameters + * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) + */ + public AppConfigProviderBuilder withCacheManager(CacheManager cacheManager) { + this.cacheManager = cacheManager; + return this; + } + + /** + * Provide a transformationManager to the {@link AppConfigProvider} + * + * @param transformationManager the manager that will handle transformation of parameters + * @return the builder to chain calls (eg.
builder.withTransformationManager().build()
) + */ + public AppConfigProviderBuilder withTransformationManager(TransformationManager transformationManager) { + this.transformationManager = transformationManager; + return this; + } +} diff --git a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java new file mode 100644 index 000000000..f50e88ec5 --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.appconfig; + +import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.function.BiFunction; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class AppConfigParamAspectTest { + + @Test + public void parameterInjectedByProvider() throws Exception { + // Setup our aspect to return a mocked AppConfigProvider + String environment = "myEnvironment"; + String appName = "myApp"; + String key = "myKey"; + String value = "myValue"; + AppConfigProvider provider = Mockito.mock(AppConfigProvider.class); + BiFunction providerBuilder = (String env, String app) -> { + if (env.equals(environment) && app.equals(appName)) { + return provider; + } + throw new RuntimeException("Whoops! Asked for an app/env that we weren't configured for"); + }; + writeStaticField(AppConfigParametersAspect.class, "providerBuilder", providerBuilder, true); + + // Setup our mocked AppConfigProvider to return a value for our test data + Mockito.when(provider.get(key)).thenReturn(value); + + // Create an instance of a class and let the AppConfigParametersAspect inject it + MyInjectedClass obj = new MyInjectedClass(); + assertThat(obj.myParameter).isEqualTo(value); + } + + class MyInjectedClass { + @AppConfigParam(application = "myApp", environment = "myEnvironment", key = "myKey") + public String myParameter; + } + +} diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java similarity index 95% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java rename to powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java index f467dca72..ded568e8d 100644 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/AppConfigProviderTest.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java @@ -12,11 +12,11 @@ * */ -package software.amazon.lambda.powertools.parameters; +package software.amazon.lambda.powertools.parameters.appconfig; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatRuntimeException; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.MockitoAnnotations.openMocks; import org.junit.jupiter.api.BeforeEach; @@ -193,18 +193,6 @@ public void getMultipleValuesThrowsException() { .withMessage("Retrieving multiple parameter values is not supported with the AWS App Config Provider"); } - @Test - public void testAppConfigProviderBuilderMissingCacheManager_throwsException() { - - // Act & Assert - assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder() - .withEnvironment(environmentName) - .withApplication(applicationName) - .withClient(client) - .build()) - .withMessage("No CacheManager provided; please provide one"); - } - @Test public void testAppConfigProviderBuilderMissingEnvironment_throwsException() { diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml new file mode 100644 index 000000000..ad32bdff8 --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + + software.amazon.lambda + powertools-parent + 2.0.0-SNAPSHOT + ../../pom.xml + + + powertools-parameters-dynamodb + Powertools for AWS Lambda (Java) library Parameters - DynamoDB + DynamoDB implementation for the Parameters module + + + + software.amazon.lambda + powertools-parameters + ${project.version} + + + + software.amazon.awssdk + dynamodb + + + software.amazon.awssdk + apache-client + + + software.amazon.awssdk + netty-nio-client + + + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.apache.commons + commons-lang3 + test + + + org.assertj + assertj-core + test + + + org.aspectj + aspectjweaver + test + + + + + + + maven-surefire-plugin + 3.1.2 + + + eu-central-1 + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + \ No newline at end of file diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java similarity index 52% rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java rename to powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java index 7ffb0310c..946786cb4 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/Param.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParam.java @@ -12,7 +12,7 @@ * */ -package software.amazon.lambda.powertools.parameters; +package software.amazon.lambda.powertools.parameters.dynamodb; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -21,25 +21,31 @@ import software.amazon.lambda.powertools.parameters.transform.Transformer; /** - * {@code Param} is used to signal that the annotated field should be - * populated with a value retrieved from a parameter store through a {@link ParamProvider}. + * Inject a parameter from the DynamoDB Parameter Store into a field. You can also use + * {@code DynamoDbProviderBuilder} to obtain DynamoDB values directly, rather than injecting them implicitly. * - *

By default {@code Param} use {@link SSMProvider} as parameter provider. This can be overridden specifying - * the annotation variable {@code Param(provider = )}.
- * The library provide a provider for AWS System Manager Parameters Store ({@link SSMProvider}) and a provider - * for AWS Secrets Manager ({@link SecretsProvider}). - * The user can implement a custom provider by extending the abstract class {@link BaseProvider}.

- * - *

If the parameter value requires transformation before being assigned to the annotated field - * users can specify a {@link Transformer} - *

+ * Usage: + *
+ * @DynamoDbParam(key = "my-param", table = "my-table")
+ * String myParameter;
+ * 
*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) -public @interface Param { +public @interface DynamoDbParam { + /** + * Mandatory. Partition key from the DynamoDB table + */ String key(); - Class provider() default SSMProvider.class; + /** + * Mandatory. Table name for the DynamoDB table + * @return + */ + String table(); + /** + * Optional Provide a Transformer to transform the returned parameter values. + */ Class transformer() default Transformer.class; } diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java new file mode 100644 index 000000000..1aa022cbd --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspect.java @@ -0,0 +1,51 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.dynamodb; + +import java.util.function.Function; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.FieldSignature; +import software.amazon.lambda.powertools.parameters.BaseParamAspect; +import software.amazon.lambda.powertools.parameters.BaseProvider; + +/** + * Provides the Amazon DynamoDB parameter aspect. This aspect is responsible for injecting + * parameters from DynamoDB into fields annotated with @DynamoDbParam. See the + * README and Powertools for Lambda (Java) documentation for information on using this feature. + */ +@Aspect +public class DynamoDbParamAspect extends BaseParamAspect { + + private static Function providerBuilder = + (String table) -> DynamoDbProvider.builder() + .withTable(table) + .build(); + + @Pointcut("get(* *) && @annotation(ddbConfigParam)") + public void getParam(DynamoDbParam ddbConfigParam) { + } + + @Around("getParam(ddbConfigParam)") + public Object injectParam(final ProceedingJoinPoint joinPoint, final DynamoDbParam ddbConfigParam) { + + BaseProvider provider = providerBuilder.apply(ddbConfigParam.table()); + return getAndTransform(ddbConfigParam.key(), ddbConfigParam.transformer(), provider, + (FieldSignature) joinPoint.getSignature()); + } + +} diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java new file mode 100644 index 000000000..4a1476e38 --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProvider.java @@ -0,0 +1,121 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.dynamodb; + +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; +import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; +import software.amazon.awssdk.services.dynamodb.model.QueryRequest; +import software.amazon.awssdk.services.dynamodb.model.QueryResponse; +import software.amazon.lambda.powertools.parameters.BaseProvider; +import software.amazon.lambda.powertools.parameters.ParamProvider; +import software.amazon.lambda.powertools.parameters.cache.CacheManager; +import software.amazon.lambda.powertools.parameters.dynamodb.exception.DynamoDbProviderSchemaException; +import software.amazon.lambda.powertools.parameters.transform.TransformationManager; + +/** + * Implements a {@link ParamProvider} on top of Amazon DynamoDB. The schema of the table + * is described in the Powertools for AWS Lambda (Java) documentation. + * + * @see Parameters provider documentation + */ +public class DynamoDbProvider extends BaseProvider { + + private final DynamoDbClient client; + private final String tableName; + + DynamoDbProvider(CacheManager cacheManager, TransformationManager transformationManager, DynamoDbClient client, + String tableName) { + super(cacheManager, transformationManager); + this.client = client; + this.tableName = tableName; + } + + /** + * Create a builder that can be used to configure and create a {@link DynamoDbProvider}. + * + * @return a new instance of {@link DynamoDbProviderBuilder} + */ + public static DynamoDbProviderBuilder builder() { + return new DynamoDbProviderBuilder(); + } + + /** + * Return a single value from the DynamoDB parameter provider. + * + * @param key key of the parameter + * @return The value, if it exists, null if it doesn't. Throws if the row exists but doesn't match the schema. + */ + @Override + protected String getValue(String key) { + GetItemResponse resp = client.getItem(GetItemRequest.builder() + .tableName(tableName) + .key(Collections.singletonMap("id", AttributeValue.fromS(key))) + .attributesToGet("value") + .build()); + + // If we have an item at the key, we should be able to get a 'val' out of it. If not it's + // exceptional. + // If we don't have an item at the key, we should return null. + if (resp.hasItem() && !resp.item().values().isEmpty()) { + if (!resp.item().containsKey("value")) { + throw new DynamoDbProviderSchemaException("Missing 'value': " + resp.item()); + } + return resp.item().get("value").s(); + } + + return null; + } + + /** + * Returns multiple values from the DynamoDB parameter provider. + * + * @param path Parameter store path + * @return All values matching the given path, and an empty map if none do. Throws if any records exist that don't match the schema. + */ + @Override + protected Map getMultipleValues(String path) { + + QueryResponse resp = client.query(QueryRequest.builder() + .tableName(tableName) + .keyConditionExpression("id = :v_id") + .expressionAttributeValues(Collections.singletonMap(":v_id", AttributeValue.fromS(path))) + .build()); + + return resp + .items() + .stream() + .peek((i) -> + { + if (!i.containsKey("sk")) { + throw new DynamoDbProviderSchemaException("Missing 'sk': " + i); + } + if (!i.containsKey("value")) { + throw new DynamoDbProviderSchemaException("Missing 'value': " + i); + } + }) + .collect( + Collectors.toMap( + (i) -> i.get("sk").s(), + (i) -> i.get("value").s())); + + + } + +} diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java new file mode 100644 index 000000000..6b6610ba1 --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java @@ -0,0 +1,113 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.dynamodb; + +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.parameters.BaseProvider; +import software.amazon.lambda.powertools.parameters.ParamProvider; +import software.amazon.lambda.powertools.parameters.cache.CacheManager; +import software.amazon.lambda.powertools.parameters.transform.TransformationManager; + +/** + * Implements a {@link ParamProvider} on top of the DynamoDB service. DynamoDB provides + */ +public class DynamoDbProviderBuilder { + private DynamoDbClient client; + private String table; + private CacheManager cacheManager; + private TransformationManager transformationManager; + + static DynamoDbClient createClient() { + return DynamoDbClient.builder() + .httpClientBuilder(UrlConnectionHttpClient.builder()) + .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, + UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build()) + .build(); + } + + /** + * Create a {@link DynamoDbProvider} instance. + * + * @return a {@link DynamoDbProvider} + */ + public DynamoDbProvider build() { + if (cacheManager == null) { + cacheManager = new CacheManager(); + } + if (table == null) { + throw new IllegalStateException("No DynamoDB table name provided; please provide one"); + } + DynamoDbProvider provider; + if (client == null) { + client = createClient(); + } + provider = new DynamoDbProvider(cacheManager, transformationManager, client, table); + + return provider; + } + + /** + * Set custom {@link DynamoDbClient} to pass to the {@link DynamoDbClient}.
+ * Use it if you want to customize the region or any other part of the client. + * + * @param client Custom client + * @return the builder to chain calls (eg.
builder.withClient().build()
) + */ + public DynamoDbProviderBuilder withClient(DynamoDbClient client) { + this.client = client; + return this; + } + + /** + * Provide a CacheManager to the {@link DynamoDbProvider} + * + * @param cacheManager the manager that will handle the cache of parameters + * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) + */ + public DynamoDbProviderBuilder withCacheManager(CacheManager cacheManager) { + this.cacheManager = cacheManager; + return this; + } + + /** + * Mandatory. Provide a DynamoDB table to the {@link DynamoDbProvider} + * + * @param table the table that parameters will be retrieved from. + * @return the builder to chain calls (eg.
builder.withTable().build()
) + */ + public DynamoDbProviderBuilder withTable(String table) { + this.table = table; + return this; + } + + /** + * Provide a transformationManager to the {@link DynamoDbProvider} + * + * @param transformationManager the manager that will handle transformation of parameters + * @return the builder to chain calls (eg.
builder.withTransformationManager().build()
) + */ + public DynamoDbProviderBuilder withTransformationManager(TransformationManager transformationManager) { + this.transformationManager = transformationManager; + return this; + } +} diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/exception/DynamoDbProviderSchemaException.java similarity index 92% rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java rename to powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/exception/DynamoDbProviderSchemaException.java index 77df6e3d3..4a22dbc99 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/exception/DynamoDbProviderSchemaException.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/exception/DynamoDbProviderSchemaException.java @@ -12,7 +12,7 @@ * */ -package software.amazon.lambda.powertools.parameters.exception; +package software.amazon.lambda.powertools.parameters.dynamodb.exception; /** * Thrown when the DynamoDbProvider comes across parameter data that diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java new file mode 100644 index 000000000..07e93a7c1 --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java @@ -0,0 +1,55 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.dynamodb; + +import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.function.Function; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class DynamoDbParamAspectTest { + + @Test + public void parameterInjectedByProvider() throws Exception { + // Setup our aspect to return a mocked DynamoDbProvider + String tableName = "my-test-tablename"; + String key = "myKey"; + String value = "myValue"; + DynamoDbProvider provider = Mockito.mock(DynamoDbProvider.class); + + Function providerBuilder = (String table) -> { + if (table.equals(tableName)) { + return provider; + } + throw new RuntimeException("Whoops! Asked for an app/env that we weren't configured for"); + }; + writeStaticField(DynamoDbParamAspect.class, "providerBuilder", providerBuilder, true); + + // Setup our mocked DynamoDbProvider to return a value for our test data + Mockito.when(provider.get(key)).thenReturn(value); + + // Create an instance of a class and let the AppConfigParametersAspect inject it + MyInjectedClass obj = new MyInjectedClass(); + assertThat(obj.myParameter).isEqualTo(value); + } + + class MyInjectedClass { + @DynamoDbParam(table = "my-test-tablename", key = "myKey") + public String myParameter; + } + +} diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java similarity index 96% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java rename to powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java index 18212b45c..2695938d8 100644 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderE2ETest.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java @@ -12,7 +12,7 @@ * */ -package software.amazon.lambda.powertools.parameters; +package software.amazon.lambda.powertools.parameters.dynamodb; import static org.assertj.core.api.Assertions.assertThat; @@ -104,7 +104,7 @@ public void TestGetValues() { } private DynamoDbProvider makeProvider(String tableName) { - return new DynamoDbProvider(new CacheManager(), DynamoDbClient.builder() + return new DynamoDbProvider(new CacheManager(), null, DynamoDbClient.builder() .httpClientBuilder(UrlConnectionHttpClient.builder()).build(), tableName); } diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java similarity index 94% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java rename to powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java index 2cf84dad4..68bfd7cdb 100644 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/DynamoDbProviderTest.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java @@ -12,7 +12,7 @@ * */ -package software.amazon.lambda.powertools.parameters; +package software.amazon.lambda.powertools.parameters.dynamodb; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; @@ -35,7 +35,7 @@ import software.amazon.awssdk.services.dynamodb.model.QueryRequest; import software.amazon.awssdk.services.dynamodb.model.QueryResponse; import software.amazon.lambda.powertools.parameters.cache.CacheManager; -import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException; +import software.amazon.lambda.powertools.parameters.dynamodb.exception.DynamoDbProviderSchemaException; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; public class DynamoDbProviderTest { @@ -55,7 +55,7 @@ public class DynamoDbProviderTest { public void init() { openMocks(this); CacheManager cacheManager = new CacheManager(); - provider = new DynamoDbProvider(cacheManager, client, tableName); + provider = new DynamoDbProvider(cacheManager, transformationManager, client, tableName); } @@ -217,15 +217,6 @@ public void getValuesWithMalformedRowThrows() { }); } - @Test - public void testDynamoDBBuilderMissingCacheManager_throwsException() { - - // Act & Assert - assertThatIllegalStateException().isThrownBy(() -> DynamoDbProvider.builder() - .withTable("table") - .build()); - } - @Test public void testDynamoDBBuilderMissingTable_throwsException() { diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml new file mode 100644 index 000000000..6c4501ca3 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + + software.amazon.lambda + powertools-parent + 2.0.0-SNAPSHOT + ../../pom.xml + + + powertools-parameters-secrets + Powertools for AWS Lambda (Java) library Parameters - Secrets Manager + Secrets Manager implementation for the Parameters module + + + + software.amazon.lambda + powertools-parameters + ${project.version} + + + + software.amazon.awssdk + secretsmanager + + + software.amazon.awssdk + apache-client + + + software.amazon.awssdk + netty-nio-client + + + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.apache.commons + commons-lang3 + test + + + org.assertj + assertj-core + test + + + org.aspectj + aspectjweaver + test + + + + + + + maven-surefire-plugin + 3.1.2 + + + eu-central-1 + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + \ No newline at end of file diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java new file mode 100644 index 000000000..f9c110c49 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParam.java @@ -0,0 +1,46 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.secrets; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import software.amazon.lambda.powertools.parameters.transform.Transformer; + +/** + * Inject a parameter from the Secrets Manager into a field. You can also use + * {@code SecretsProviderBuilder} to obtain Secrets Manager values directly, rather than + * injecting them implicitly. + * + *
+ * @SecretsParam(key = "my-secret")
+ * String mySecret;
+ * 
+ */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface SecretsParam { + /** + * Mandatory. key from the secrets manager store. + * @return + */ + String key(); + + /** + * Optional. a transfer to apply to the value + */ + Class transformer() default Transformer.class; +} diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java new file mode 100644 index 000000000..748c88cc9 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspect.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.secrets; + +import java.util.function.Supplier; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.FieldSignature; +import software.amazon.lambda.powertools.parameters.BaseParamAspect; + +/** + * Provides the Secrets parameter aspect. This aspect is responsible for injecting + * parameters from AWS Secrets Manager into fields annotated with @SecretsParam. See the + * README and Powertools for Lambda (Java) documentation for information on using this feature. + */ +@Aspect +public class SecretsParamAspect extends BaseParamAspect { + + private static Supplier providerBuilder = () -> SecretsProvider.builder() + .build(); + + @Pointcut("get(* *) && @annotation(secretsParam)") + public void getParam(SecretsParam secretsParam) { + } + + @Around("getParam(secretsParam)") + public Object injectParam(final ProceedingJoinPoint joinPoint, final SecretsParam secretsParam) { + + SecretsProvider provider = providerBuilder.get(); + return getAndTransform(secretsParam.key(), secretsParam.transformer(), provider, + (FieldSignature) joinPoint.getSignature()); + } + +} diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java new file mode 100644 index 000000000..9087c1ad6 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProvider.java @@ -0,0 +1,115 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.secrets; + +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.util.Base64; +import java.util.Map; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; +import software.amazon.lambda.powertools.parameters.BaseProvider; +import software.amazon.lambda.powertools.parameters.cache.CacheManager; +import software.amazon.lambda.powertools.parameters.transform.TransformationManager; + +/** + * AWS Secrets Manager Parameter Provider

+ * + * Samples: + *
+ *     SecretsProvider provider = SecretsProvider.builder().build();
+ *
+ *     String value = provider.get("key");
+ *     System.out.println(value);
+ *     >>> "value"
+ *
+ *     // Get a value and cache it for 30 seconds (all others values will now be cached for 30 seconds)
+ *     String value = provider.defaultMaxAge(30, ChronoUnit.SECONDS).get("key");
+ *
+ *     // Get a value and cache it for 1 minute (all others values are cached for 5 seconds by default)
+ *     String value = provider.withMaxAge(1, ChronoUnit.MINUTES).get("key");
+ *
+ *     // Get a base64 encoded value, decoded into a String, and store it in the cache
+ *     String value = provider.withTransformation(Transformer.base64).get("key");
+ *
+ *     // Get a json value, transform it into an Object, and store it in the cache
+ *     TargetObject = provider.withTransformation(Transformer.json).get("key", TargetObject.class);
+ * 
+ */ +public class SecretsProvider extends BaseProvider { + + private final SecretsManagerClient client; + + /** + * Use the {@link SecretsProviderBuilder} to create an instance! + * + * @param client custom client you would like to use. + */ + SecretsProvider(CacheManager cacheManager, TransformationManager transformationManager, + SecretsManagerClient client) { + super(cacheManager, transformationManager); + this.client = client; + } + + /** + * Create a builder that can be used to configure and create a {@link SecretsProvider}. + * + * @return a new instance of {@link SecretsProviderBuilder} + */ + public static SecretsProviderBuilder builder() { + return new SecretsProviderBuilder(); + } + + /** + * Create a SecretsProvider with all default settings. + */ + public static SecretsProvider create() { + return new SecretsProviderBuilder().build(); + } + + /** + * Retrieve the parameter value from the AWS Secrets Manager. + * + * @param key key of the parameter + * @return the value of the parameter identified by the key + */ + @Override + protected String getValue(String key) { + GetSecretValueRequest request = GetSecretValueRequest.builder().secretId(key).build(); + + String secretValue = client.getSecretValue(request).secretString(); + if (secretValue == null) { + secretValue = + new String(Base64.getDecoder().decode(client.getSecretValue(request).secretBinary().asByteArray()), + UTF_8); + } + return secretValue; + } + + /** + * @throws UnsupportedOperationException as it is not possible to get multiple values simultaneously from Secrets Manager + */ + @Override + protected Map getMultipleValues(String path) { + throw new UnsupportedOperationException("Impossible to get multiple values from AWS Secrets Manager"); + } + + + // For test purpose only + SecretsManagerClient getClient() { + return client; + } + +} diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java new file mode 100644 index 000000000..125425200 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java @@ -0,0 +1,101 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.secrets; + +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.parameters.BaseProvider; +import software.amazon.lambda.powertools.parameters.ParamProvider; +import software.amazon.lambda.powertools.parameters.cache.CacheManager; +import software.amazon.lambda.powertools.parameters.transform.TransformationManager; + +/** + * Implements a {@link ParamProvider} on top of the SecretsManager service. SecretsManager provides + */ +public class SecretsProviderBuilder { + + private SecretsManagerClient client; + private CacheManager cacheManager; + private TransformationManager transformationManager; + + private static SecretsManagerClient createClient() { + return SecretsManagerClient.builder() + .httpClientBuilder(UrlConnectionHttpClient.builder()) + .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, + UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build()) + .build(); + } + + /** + * Create a {@link SecretsProvider} instance. + * + * @return a {@link SecretsProvider} + */ + public SecretsProvider build() { + if (cacheManager == null) { + // TODO - what should we do with this + cacheManager = new CacheManager(); + } + SecretsProvider provider; + if (client == null) { + client = createClient(); + } + + provider = new SecretsProvider(cacheManager, transformationManager, client); + + return provider; + } + + /** + * Set custom {@link SecretsManagerClient} to pass to the {@link SecretsProvider}.
+ * Use it if you want to customize the region or any other part of the client. + * + * @param client Custom client + * @return the builder to chain calls (eg.
builder.withClient().build()
) + */ + public SecretsProviderBuilder withClient(SecretsManagerClient client) { + this.client = client; + return this; + } + + /** + * Provide a CacheManager to the {@link SecretsProvider} + * + * @param cacheManager the manager that will handle the cache of parameters + * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) + */ + public SecretsProviderBuilder withCacheManager(CacheManager cacheManager) { + this.cacheManager = cacheManager; + return this; + } + + /** + * Provide a transformationManager to the {@link SecretsProvider} + * + * @param transformationManager the manager that will handle transformation of parameters + * @return the builder to chain calls (eg.
builder.withTransformationManager().build()
) + */ + public SecretsProviderBuilder withTransformationManager(TransformationManager transformationManager) { + this.transformationManager = transformationManager; + return this; + } +} diff --git a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java new file mode 100644 index 000000000..7aa0f0872 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.secrets; + +import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.function.Supplier; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class SecretsParamAspectTest { + + @Test + public void parameterInjectedByProvider() throws Exception { + // Setup our aspect to return a mocked SecretsProvider + String key = "myKey"; + String value = "mySecretValue"; + SecretsProvider provider = Mockito.mock(SecretsProvider.class); + + Supplier providerBuilder = () -> provider; + writeStaticField(SecretsParamAspect.class, "providerBuilder", providerBuilder, true); + + // Setup our mocked SecretsProvider to return a value for our test data + Mockito.when(provider.get(key)).thenReturn(value); + + // Create an instance of a class and let the SecretsParamAspect inject it + MyInjectedClass obj = new MyInjectedClass(); + assertThat(obj.mySecret).isEqualTo(value); + } + + class MyInjectedClass { + @SecretsParam(key = "myKey") + public String mySecret; + } + +} diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java similarity index 81% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java rename to powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java index f4f2d9bee..21173cad1 100644 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SecretsProviderTest.java +++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java @@ -12,12 +12,11 @@ * */ -package software.amazon.lambda.powertools.parameters; +package software.amazon.lambda.powertools.parameters.secrets; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatRuntimeException; -import static org.mockito.MockitoAnnotations.openMocks; +import static org.junit.jupiter.api.Assertions.assertNotNull; import java.time.temporal.ChronoUnit; import java.util.Base64; @@ -27,6 +26,7 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; @@ -51,9 +51,9 @@ public class SecretsProviderTest { @BeforeEach public void init() { - openMocks(this); + MockitoAnnotations.openMocks(this); cacheManager = new CacheManager(); - provider = new SecretsProvider(cacheManager, client); + provider = new SecretsProvider(cacheManager, transformationManager, client); } @Test @@ -62,7 +62,6 @@ public void getValue() { String expectedValue = "Value1"; GetSecretValueResponse response = GetSecretValueResponse.builder().secretString(expectedValue).build(); Mockito.when(client.getSecretValue(paramCaptor.capture())).thenReturn(response); - provider.defaultMaxAge(1, ChronoUnit.DAYS); provider.withMaxAge(2, ChronoUnit.DAYS); String value = provider.getValue(key); @@ -96,13 +95,14 @@ public void getMultipleValuesThrowsException() { } @Test - public void testSecretsProviderBuilderMissingCacheManager_throwsException() { + public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() { - // Act & Assert - assertThatIllegalStateException().isThrownBy(() -> SecretsProvider.builder() - .withClient(client) - .withTransformationManager(transformationManager) - .build()) - .withMessage("No CacheManager provided, please provide one"); + // Act + SecretsProvider secretsProvider = SecretsProvider.builder() + .build(); + + // Assert + assertNotNull(secretsProvider); + assertNotNull(secretsProvider.getClient()); } } diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml new file mode 100644 index 000000000..80276189d --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -0,0 +1,85 @@ + + + 4.0.0 + + + software.amazon.lambda + powertools-parent + 2.0.0-SNAPSHOT + ../../pom.xml + + + powertools-parameters-ssm + Powertools for AWS Lambda (Java) library Parameters - SSM + SSM Parameter Store implementation for the Parameters module + + + + software.amazon.lambda + powertools-parameters + ${project.version} + + + + software.amazon.awssdk + ssm + + + software.amazon.awssdk + apache-client + + + software.amazon.awssdk + netty-nio-client + + + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.apache.commons + commons-lang3 + test + + + org.assertj + assertj-core + test + + + org.aspectj + aspectjweaver + test + + + + + + + maven-surefire-plugin + 3.1.2 + + + eu-central-1 + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + + \ No newline at end of file diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java new file mode 100644 index 000000000..9b1587bb4 --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParam.java @@ -0,0 +1,47 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.ssm; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import software.amazon.lambda.powertools.parameters.transform.Transformer; + +/** + * Inject a parameter from the SSM Parameter Store into a field. You can also use + * {@code SSMProviderBuilder} to obtain SSM values directly, rather than injecting them implicitly. + * + * Usage: + *
+ * @SSMParam(key = "/my/parameter")
+ * String myParameter;
+ * 
+ */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface SSMParam { + /** + * Mandatory. Key from the SSM parameter store + * @return + */ + String key(); + + + /** + * Optional. a transfer to apply to the value + */ + Class transformer() default Transformer.class; +} diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java new file mode 100644 index 000000000..b4d370506 --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspect.java @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.ssm; + +import java.util.function.Supplier; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.FieldSignature; +import software.amazon.lambda.powertools.parameters.BaseParamAspect; + +/** + * Provides the SSM parameter store parameter aspect. This aspect is responsible for injecting + * parameters from SSM Parameter Store into fields annotated with @SSMParam. See the + * README and Powertools for Lambda (Java) documentation for information on using this feature. + */ +@Aspect +public class SSMParamAspect extends BaseParamAspect { + + // This supplier produces a new SSMProvider each time it is called + private static Supplier providerBuilder = () -> SSMProvider.builder() + .build(); + + @Pointcut("get(* *) && @annotation(secretsParam)") + public void getParam(SSMParam secretsParam) { + } + + @Around("getParam(ssmPaam)") + public Object injectParam(final ProceedingJoinPoint joinPoint, final SSMParam ssmPaam) { + + SSMProvider provider = providerBuilder.get(); + return getAndTransform(ssmPaam.key(), ssmPaam.transformer(), provider, + (FieldSignature) joinPoint.getSignature()); + } + +} diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java similarity index 60% rename from powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java rename to powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java index 10bb70c15..c24b08b84 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SSMProvider.java +++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java @@ -12,32 +12,25 @@ * */ -package software.amazon.lambda.powertools.parameters; +package software.amazon.lambda.powertools.parameters.ssm; -import java.time.temporal.ChronoUnit; import java.util.HashMap; import java.util.Map; -import software.amazon.awssdk.core.SdkSystemSetting; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; -import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; -import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.ssm.SsmClient; import software.amazon.awssdk.services.ssm.model.GetParameterRequest; import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest; import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse; import software.amazon.awssdk.utils.StringUtils; -import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.parameters.BaseProvider; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; -import software.amazon.lambda.powertools.parameters.transform.Transformer; /** * AWS System Manager Parameter Store Provider

* * Samples: *
- *     SSMProvider provider = ParamManager.getSsmProvider();
+ *     SSMProvider provider = SSMProvider.builder().build();
  *
  *     String value = provider.get("key");
  *     System.out.println(value);
@@ -80,33 +73,30 @@ public class SSMProvider extends BaseProvider {
      * Constructor with custom {@link SsmClient}. 
* Use when you need to customize region or any other attribute of the client.

*

- * Use the {@link SSMProvider.Builder} to create an instance of it. + * Use the {@link SSMProviderBuilder} to create an instance of it. * - * @param client custom client you would like to use. + * @param client custom client you would like to use. + * @param transformationManager Null, or a transformation manager */ - SSMProvider(CacheManager cacheManager, SsmClient client) { - super(cacheManager); + SSMProvider(CacheManager cacheManager, TransformationManager transformationManager, SsmClient client) { + super(cacheManager, transformationManager); this.client = client; } /** - * Constructor with only a CacheManager
- *

- * Used in {@link ParamManager#createProvider(Class)} + * Create a builder that can be used to configure and create a {@link SSMProvider}. * - * @param cacheManager handles the parameter caching + * @return a new instance of {@link SSMProviderBuilder} */ - SSMProvider(CacheManager cacheManager) { - this(cacheManager, Builder.createClient()); + public static SSMProviderBuilder builder() { + return new SSMProviderBuilder(); } /** - * Create a builder that can be used to configure and create a {@link SSMProvider}. - * - * @return a new instance of {@link SSMProvider.Builder} + * Create a SSMProvider with all default settings. */ - public static SSMProvider.Builder builder() { - return new SSMProvider.Builder(); + public static SSMProvider create() { + return new SSMProviderBuilder().build(); } /** @@ -124,33 +114,6 @@ public String getValue(String key) { return client.getParameter(request).parameter().value(); } - /** - * {@inheritDoc} - */ - @Override - public SSMProvider defaultMaxAge(int maxAge, ChronoUnit unit) { - super.defaultMaxAge(maxAge, unit); - return this; - } - - /** - * {@inheritDoc} - */ - @Override - public SSMProvider withMaxAge(int maxAge, ChronoUnit unit) { - super.withMaxAge(maxAge, unit); - return this; - } - - /** - * {@inheritDoc} - */ - @Override - public SSMProvider withTransformation(Class transformerClass) { - super.withTransformation(transformerClass); - return this; - } - /** * Tells System Manager Parameter Store to decrypt the parameter value.
* By default, parameter values are not decrypted.
@@ -210,7 +173,7 @@ private Map getMultipleBis(String path, String nextToken) { res.parameters().forEach(parameter -> { /* Standardize the parameter name - The parameter name returned by SSM will contained the full path. + The parameter name returned by SSM will contain the full path. However, for readability, we should return only the part after the path. */ @@ -242,75 +205,4 @@ SsmClient getClient() { return client; } - static class Builder { - private SsmClient client; - private CacheManager cacheManager; - private TransformationManager transformationManager; - - private static SsmClient createClient() { - return SsmClient.builder() - .httpClientBuilder(UrlConnectionHttpClient.builder()) - .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, - UserAgentConfigurator.getUserAgent(PARAMETERS)).build()) - .build(); - } - - /** - * Create a {@link SSMProvider} instance. - * - * @return a {@link SSMProvider} - */ - public SSMProvider build() { - if (cacheManager == null) { - throw new IllegalStateException("No CacheManager provided, please provide one"); - } - SSMProvider provider; - if (client == null) { - client = createClient(); - } - - provider = new SSMProvider(cacheManager, client); - - if (transformationManager != null) { - provider.setTransformationManager(transformationManager); - } - return provider; - } - - /** - * Set custom {@link SsmClient} to pass to the {@link SSMProvider}.
- * Use it if you want to customize the region or any other part of the client. - * - * @param client Custom client - * @return the builder to chain calls (eg.

builder.withClient().build()
) - */ - public SSMProvider.Builder withClient(SsmClient client) { - this.client = client; - return this; - } - - /** - * Mandatory. Provide a CacheManager to the {@link SSMProvider} - * - * @param cacheManager the manager that will handle the cache of parameters - * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) - */ - public SSMProvider.Builder withCacheManager(CacheManager cacheManager) { - this.cacheManager = cacheManager; - return this; - } - - /** - * Provide a transformationManager to the {@link SSMProvider} - * - * @param transformationManager the manager that will handle transformation of parameters - * @return the builder to chain calls (eg.
builder.withTransformationManager().build()
) - */ - public SSMProvider.Builder withTransformationManager(TransformationManager transformationManager) { - this.transformationManager = transformationManager; - return this; - } - } } diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java new file mode 100644 index 000000000..3b4fff1b3 --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java @@ -0,0 +1,98 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.ssm; + +import software.amazon.awssdk.core.SdkSystemSetting; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.ssm.SsmClient; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; +import software.amazon.lambda.powertools.parameters.BaseProvider; +import software.amazon.lambda.powertools.parameters.cache.CacheManager; +import software.amazon.lambda.powertools.parameters.transform.TransformationManager; + +/** + * Builder for the {@link SSMProvider} + */ +public class SSMProviderBuilder { + private SsmClient client; + private CacheManager cacheManager; + private TransformationManager transformationManager; + + private static SsmClient createClient() { + return SsmClient.builder() + .httpClientBuilder(UrlConnectionHttpClient.builder()) + .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, + UserAgentConfigurator.getUserAgent(BaseProvider.PARAMETERS)).build()) + .build(); + } + + /** + * Create a {@link SSMProvider} instance. + * + * @return a {@link SSMProvider} + */ + public SSMProvider build() { + if (cacheManager == null) { + cacheManager = new CacheManager(); + } + SSMProvider provider; + if (client == null) { + client = createClient(); + } + + provider = new SSMProvider(cacheManager, transformationManager, client); + + return provider; + } + + /** + * Set custom {@link SsmClient} to pass to the {@link SSMProvider}.
+ * Use it if you want to customize the region or any other part of the client. + * + * @param client Custom client + * @return the builder to chain calls (eg.
builder.withClient().build()
) + */ + public SSMProviderBuilder withClient(SsmClient client) { + this.client = client; + return this; + } + + /** + * Provide a CacheManager to the {@link SSMProvider} + * + * @param cacheManager the manager that will handle the cache of parameters + * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) + */ + public SSMProviderBuilder withCacheManager(CacheManager cacheManager) { + this.cacheManager = cacheManager; + return this; + } + + /** + * Provide a transformationManager to the {@link SSMProvider} + * + * @param transformationManager the manager that will handle transformation of parameters + * @return the builder to chain calls (eg.
builder.withTransformationManager().build()
) + */ + public SSMProviderBuilder withTransformationManager(TransformationManager transformationManager) { + this.transformationManager = transformationManager; + return this; + } +} diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java new file mode 100644 index 000000000..e56d20ffa --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters.ssm; + +import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.function.Supplier; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class SSMParamAspectTest { + + // This class tests the SSM Param aspect in the same fashion + // as the tests for the aspects for the other providers. + + @Test + public void parameterInjectedByProvider() throws Exception { + + String key = "myKey"; + String value = "mySecretValue"; + SSMProvider provider = Mockito.mock(SSMProvider.class); + + Supplier providerBuilder = () -> provider; + writeStaticField(SSMParamAspect.class, "providerBuilder", providerBuilder, true); + + // Setup our mocked SSMProvider to return a value for our test data + Mockito.when(provider.get(key)).thenReturn(value); + + // Create an instance of a class and let the SSMParamAspect inject it + MyInjectedClass obj = new MyInjectedClass(); + assertThat(obj.mySecret).isEqualTo(value); + } + + class MyInjectedClass { + @SSMParam(key = "myKey") + public String mySecret; + } + +} diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SSMProviderTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java similarity index 84% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SSMProviderTest.java rename to powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java index 2a4f8f927..b105da438 100644 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/SSMProviderTest.java +++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java @@ -12,16 +12,10 @@ * */ -package software.amazon.lambda.powertools.parameters; +package software.amazon.lambda.powertools.parameters.ssm; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; import java.time.temporal.ChronoUnit; import java.util.ArrayList; @@ -31,8 +25,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; import org.mockito.Captor; import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import software.amazon.awssdk.services.ssm.SsmClient; import software.amazon.awssdk.services.ssm.model.GetParameterRequest; import software.amazon.awssdk.services.ssm.model.GetParameterResponse; @@ -62,9 +59,9 @@ public class SSMProviderTest { @BeforeEach public void init() { - openMocks(this); + MockitoAnnotations.openMocks(this); cacheManager = new CacheManager(); - provider = new SSMProvider(cacheManager, client); + provider = new SSMProvider(cacheManager, null, client); } @Test @@ -100,7 +97,7 @@ public void getMultiple() { parameters.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build()); parameters.add(Parameter.builder().name("/prod/app1/key3").value("foo3").build()); GetParametersByPathResponse response = GetParametersByPathResponse.builder().parameters(parameters).build(); - when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response); + Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response); Map params = provider.getMultiple("/prod/app1"); assertThat(params).contains( @@ -123,7 +120,7 @@ public void getMultipleWithTrailingSlash() { parameters.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build()); parameters.add(Parameter.builder().name("/prod/app1/key3").value("foo3").build()); GetParametersByPathResponse response = GetParametersByPathResponse.builder().parameters(parameters).build(); - when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response); + Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response); Map params = provider.getMultiple("/prod/app1/"); assertThat(params).contains( @@ -146,7 +143,7 @@ public void getMultiple_cached_shouldNotCallSSM() { parameters.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build()); parameters.add(Parameter.builder().name("/prod/app1/key3").value("foo3").build()); GetParametersByPathResponse response = GetParametersByPathResponse.builder().parameters(parameters).build(); - when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response); + Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response); provider.getMultiple("/prod/app1"); @@ -156,7 +153,8 @@ public void getMultiple_cached_shouldNotCallSSM() { provider.get("/prod/app1/key2"); provider.get("/prod/app1/key3"); - verify(client, times(1)).getParametersByPath(any(GetParametersByPathRequest.class)); + Mockito.verify(client, Mockito.times(1)) + .getParametersByPath(ArgumentMatchers.any(GetParametersByPathRequest.class)); } @@ -172,7 +170,7 @@ public void getMultipleWithNextToken() { parameters2.add(Parameter.builder().name("/prod/app1/key3").value("foo3").build()); GetParametersByPathResponse response2 = GetParametersByPathResponse.builder().parameters(parameters2).build(); - when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response1, response2); + Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())).thenReturn(response1, response2); Map params = provider.getMultiple("/prod/app1"); @@ -196,22 +194,10 @@ public void getMultipleWithNextToken() { assertThat(request2.nextToken()).isEqualTo("123abc"); } - @Test - public void testSecretsProviderBuilderMissingCacheManager_throwsException() { - - // Act & Assert - assertThatIllegalStateException().isThrownBy(() -> SSMProvider.builder() - .withClient(client) - .withTransformationManager(transformationManager) - .build()) - .withMessage("No CacheManager provided, please provide one"); - } - private void initMock(String expectedValue) { Parameter parameter = Parameter.builder().value(expectedValue).build(); GetParameterResponse result = GetParameterResponse.builder().parameter(parameter).build(); - when(client.getParameter(paramCaptor.capture())).thenReturn(result); - provider.defaultMaxAge(1, ChronoUnit.DAYS); + Mockito.when(client.getParameter(paramCaptor.capture())).thenReturn(result); provider.withMaxAge(2, ChronoUnit.DAYS); provider.recursive(); } diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml new file mode 100644 index 000000000..d8e9b2a02 --- /dev/null +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + software.amazon.lambda + powertools-parent + 2.0.0-SNAPSHOT + ../../pom.xml + + + powertools-parameters-tests + Powertools parameters tests that cut across all the parameters providers + + + true + + + + + software.amazon.lambda + powertools-parameters-ssm + test + ${project.version} + + + software.amazon.lambda + powertools-parameters-secrets + test + ${project.version} + + + software.amazon.lambda + powertools-parameters-dynamodb + test + ${project.version} + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.apache.commons + commons-lang3 + test + + + org.assertj + assertj-core + test + + + org.aspectj + aspectjweaver + test + + + \ No newline at end of file diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java similarity index 91% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java index edc671e2c..5fa740253 100644 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java @@ -25,6 +25,7 @@ import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; import java.time.Clock; +import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Base64; import java.util.HashMap; @@ -51,9 +52,8 @@ public void setup() { clock = Clock.systemDefaultZone(); cacheManager = new CacheManager(); - provider = new BasicProvider(cacheManager); transformationManager = new TransformationManager(); - provider.setTransformationManager(transformationManager); + provider = new BasicProvider(cacheManager, transformationManager); } @Test @@ -138,7 +138,8 @@ public void get_customTTL_expired_shouldGetValue() { @Test public void get_customDefaultTTL_cached_shouldGetFromCache() { - provider.defaultMaxAge(12, ChronoUnit.MINUTES).get("foobar"); + provider.cacheManager.setDefaultExpirationTime(Duration.of(12, MINUTES)); + provider.get("foobar"); getFromStore = false; provider.setClock(offset(clock, of(10, MINUTES))); @@ -149,7 +150,7 @@ public void get_customDefaultTTL_cached_shouldGetFromCache() { @Test public void get_customDefaultTTL_expired_shouldGetValue() { - provider.defaultMaxAge(2, ChronoUnit.MINUTES).get("barbaz"); + provider.cacheManager.setDefaultExpirationTime(Duration.of(2, MINUTES)); getFromStore = false; provider.setClock(offset(clock, of(3, MINUTES))); @@ -160,9 +161,7 @@ public void get_customDefaultTTL_expired_shouldGetValue() { @Test public void get_customDefaultTTLAndTTL_cached_shouldGetFromCache() { - provider.defaultMaxAge(12, ChronoUnit.MINUTES) - .withMaxAge(5, SECONDS) - .get("foobaz"); + provider.get("foobaz"); getFromStore = false; provider.setClock(offset(clock, of(4, SECONDS))); @@ -173,9 +172,10 @@ public void get_customDefaultTTLAndTTL_cached_shouldGetFromCache() { @Test public void get_customDefaultTTLAndTTL_expired_shouldGetValue() { - provider.defaultMaxAge(2, ChronoUnit.MINUTES) - .withMaxAge(5, SECONDS) - .get("bariton"); + + provider.cacheManager.setDefaultExpirationTime(Duration.ofMinutes(2)); + + provider.withMaxAge(5, SECONDS).get("bariton"); getFromStore = false; provider.setClock(offset(clock, of(6, SECONDS))); @@ -275,8 +275,9 @@ public void getObject_customTTL_expired_shouldGetValue() { public void getObject_customDefaultTTL_cached_shouldGetFromCache() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); - provider.defaultMaxAge(12, ChronoUnit.MINUTES) - .withTransformation(json) + provider.cacheManager.setDefaultExpirationTime(Duration.of(12, MINUTES)); + + provider.withTransformation(json) .get("foo", ObjectToDeserialize.class); getFromStore = false; @@ -290,8 +291,9 @@ public void getObject_customDefaultTTL_cached_shouldGetFromCache() { public void getObject_customDefaultTTL_expired_shouldGetValue() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); - provider.defaultMaxAge(2, ChronoUnit.MINUTES) - .withTransformation(json) + provider.cacheManager.setDefaultExpirationTime(Duration.of(2, MINUTES)); + + provider.withTransformation(json) .get("foo", ObjectToDeserialize.class); getFromStore = false; @@ -305,9 +307,10 @@ public void getObject_customDefaultTTL_expired_shouldGetValue() { public void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); - provider.defaultMaxAge(12, ChronoUnit.MINUTES) + provider.cacheManager.setDefaultExpirationTime(Duration.ofSeconds(5)); + + provider.withTransformation(json) .withMaxAge(5, SECONDS) - .withTransformation(json) .get("foo", ObjectToDeserialize.class); getFromStore = false; @@ -321,8 +324,9 @@ public void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() { public void getObject_customDefaultTTLAndTTL_expired_shouldGetValue() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); - provider.defaultMaxAge(2, ChronoUnit.MINUTES) - .withMaxAge(5, SECONDS) + provider.cacheManager.setDefaultExpirationTime(Duration.ofMinutes(2)); + + provider.withMaxAge(5, SECONDS) .withTransformation(json) .get("foo", ObjectToDeserialize.class); getFromStore = false; @@ -335,7 +339,7 @@ public void getObject_customDefaultTTLAndTTL_expired_shouldGetValue() { @Test public void get_noTransformationManager_shouldThrowException() { - provider.setTransformationManager(null); + provider = new BasicProvider(new CacheManager(), null); assertThatIllegalStateException() .isThrownBy(() -> provider.withTransformation(base64).get("foo")); @@ -343,7 +347,6 @@ public void get_noTransformationManager_shouldThrowException() { @Test public void getObject_noTransformationManager_shouldThrowException() { - provider.setTransformationManager(null); assertThatIllegalStateException() .isThrownBy(() -> provider.get("foo", ObjectToDeserialize.class)); @@ -379,8 +382,8 @@ class BasicProvider extends BaseProvider { private String value = "valueFromStore"; - public BasicProvider(CacheManager cacheManager) { - super(cacheManager); + public BasicProvider(CacheManager cacheManager, TransformationManager transformationManager) { + super(cacheManager, transformationManager); } public void setValue(String value) { diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java similarity index 81% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java index d6fbe66f0..7d790d140 100644 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerIntegrationTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java @@ -14,7 +14,6 @@ package software.amazon.lambda.powertools.parameters; -import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; @@ -25,14 +24,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import org.assertj.core.data.MapEntry; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; @@ -43,8 +40,10 @@ import software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest; import software.amazon.awssdk.services.ssm.model.GetParametersByPathResponse; import software.amazon.awssdk.services.ssm.model.Parameter; +import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider; +import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; -public class ParamManagerIntegrationTest { +public class ParamProvidersIntegrationTest { @Mock SsmClient ssmClient; @@ -59,19 +58,17 @@ public class ParamManagerIntegrationTest { SecretsManagerClient secretsManagerClient; @Captor ArgumentCaptor secretsCaptor; - @Mock - private AppConfigDataClient appConfigDataClient; @BeforeEach public void setup() throws IllegalAccessException { openMocks(this); - - writeStaticField(ParamManager.class, "providers", new ConcurrentHashMap<>(), true); } @Test public void ssmProvider_get() { - SSMProvider ssmProvider = ParamManager.getSsmProvider(ssmClient); + SSMProvider ssmProvider = SSMProvider.builder() + .withClient(ssmClient) + .build(); String expectedValue = "value"; Parameter parameter = Parameter.builder().value(expectedValue).build(); @@ -87,7 +84,9 @@ public void ssmProvider_get() { @Test public void ssmProvider_getMultiple() { - SSMProvider ssmProvider = ParamManager.getSsmProvider(ssmClient); + SSMProvider ssmProvider = SSMProvider.builder() + .withClient(ssmClient) + .build(); List parameters = new ArrayList<>(); parameters.add(Parameter.builder().name("/prod/app1/key1").value("foo1").build()); @@ -112,7 +111,9 @@ public void ssmProvider_getMultiple() { @Test public void secretsProvider_get() { - SecretsProvider secretsProvider = ParamManager.getSecretsProvider(secretsManagerClient); + SecretsProvider secretsProvider = SecretsProvider.builder() + .withClient(secretsManagerClient) + .build(); String expectedValue = "Value1"; GetSecretValueResponse response = GetSecretValueResponse.builder().secretString(expectedValue).build(); @@ -125,24 +126,4 @@ public void secretsProvider_get() { verify(secretsManagerClient, times(1)).getSecretValue(any(GetSecretValueRequest.class)); } - @Test - public void getDynamoDbProvider() { - - // Act - DynamoDbProvider provider = ParamManager.getDynamoDbProvider(ddbClient, "test-table"); - - // Assert - assertThat(provider).isNotNull(); - } - - @Test - public void getAppConfigProvider() { - - // Act - AppConfigProvider provider = ParamManager.getAppConfigProvider(appConfigDataClient, "test-env", "test-app"); - - // Assert - assertThat(provider).isNotNull(); - - } } diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java similarity index 100% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java similarity index 100% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java similarity index 100% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/AnotherObject.java diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java similarity index 97% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java index 2c9db3712..a98d68c22 100644 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/internal/CustomProvider.java @@ -25,7 +25,7 @@ public class CustomProvider extends BaseProvider { private final Map values = new HashMap<>(); public CustomProvider(CacheManager cacheManager) { - super(cacheManager); + super(cacheManager, null); values.put("/simple", "value"); values.put("/base64", Base64.getEncoder().encodeToString("value".getBytes())); values.put("/json", "{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java similarity index 100% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java similarity index 100% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java similarity index 100% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/ObjectToDeserialize.java diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java similarity index 100% rename from powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java rename to powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java diff --git a/powertools-parameters/spotbugs-exclude.xml b/powertools-parameters/spotbugs-exclude.xml new file mode 100644 index 000000000..d48e9bee1 --- /dev/null +++ b/powertools-parameters/spotbugs-exclude.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java new file mode 100644 index 000000000..f7ebdf97a --- /dev/null +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseParamAspect.java @@ -0,0 +1,57 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.parameters; + +import org.aspectj.lang.reflect.FieldSignature; +import software.amazon.lambda.powertools.parameters.transform.Transformer; + +/** + * Provides a common base for all parameter aspects. This lets us group functionality that + * we need to reimplement in each aspect. This class should be extended for each + * additional parameter aspect. + */ +public abstract class BaseParamAspect { + + /** + * Gets the parameter value from the provider and transforms it if necessary. This transformation + * is generic across all parameter providers. + * + * @param key The key of the parameter to get + * @param transformer The transformer to use to transform the parameter value + * @param provider A concrete instance of the parameter provider to retrieve the value from + * @param fieldSignature The signature of the field that the parameter is being injected into + * @return The value of the parameter, transformed if necessary + */ + protected Object getAndTransform(String key, Class transformer, BaseProvider provider, + FieldSignature fieldSignature) { + if (transformer.isInterface()) { + // No transformation + return provider.get(key); + } else { + Class fieldType = fieldSignature.getFieldType(); + if (String.class.isAssignableFrom(fieldType)) { + // Basic transformation + return provider + .withTransformation(transformer) + .get(key); + } else { + // Complex transformation + return provider + .withTransformation(transformer) + .get(key, fieldType); + } + } + } +} diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java index edb82f5ec..bedace28c 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java @@ -34,11 +34,12 @@ public abstract class BaseProvider implements ParamProvider { public static final String PARAMETERS = "parameters"; protected final CacheManager cacheManager; - private TransformationManager transformationManager; + private final TransformationManager transformationManager; private Clock clock; - public BaseProvider(CacheManager cacheManager) { + public BaseProvider(CacheManager cacheManager, TransformationManager transformationManager) { this.cacheManager = cacheManager; + this.transformationManager = transformationManager; } /** @@ -59,25 +60,10 @@ public BaseProvider(CacheManager cacheManager) { */ protected abstract Map getMultipleValues(String path); - /** - * (Optional) Set the default max age for the cache of all parameters. Override the default 5 seconds.
- * If for some parameters, you need to set a different maxAge, use {@link #withMaxAge(int, ChronoUnit)}.
- * Use {@link #withMaxAge(int, ChronoUnit)} after {#defaultMaxAge(int, ChronoUnit)} in the chain. - * - * @param maxAge Maximum time to cache the parameter, before calling the underlying parameter store. - * @param unit Unit of time - * @return the provider itself in order to chain calls (eg.
provider.defaultMaxAge(10, SECONDS).get("key")
). - */ - protected BaseProvider defaultMaxAge(int maxAge, ChronoUnit unit) { - Duration duration = Duration.of(maxAge, unit); - cacheManager.setDefaultExpirationTime(duration); - return this; - } - /** * (Optional) Builder method to call before {@link #get(String)} or {@link #get(String, Class)} * to set cache max age for the parameter to get.

- * The max age is reset to default (either 5 or a custom value set with {@link #defaultMaxAge}) after each get, + * The max age is reset to default (either 5 or a custom value that may be set on the CacheManager) after each get, * so you need to use this method for each parameter to cache with non-default max age.

* * Not Thread Safe: calling this method simultaneously by several threads @@ -225,10 +211,6 @@ protected void resetToDefaults() { } } - protected void setTransformationManager(TransformationManager transformationManager) { - this.transformationManager = transformationManager; - } - /** * For test purpose * diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java deleted file mode 100644 index 363f39d7c..000000000 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/DynamoDbProvider.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.parameters; - -import java.util.Collections; -import java.util.Map; -import java.util.stream.Collectors; -import software.amazon.awssdk.core.SdkSystemSetting; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; -import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.dynamodb.DynamoDbClient; -import software.amazon.awssdk.services.dynamodb.model.AttributeValue; -import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; -import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; -import software.amazon.awssdk.services.dynamodb.model.QueryRequest; -import software.amazon.awssdk.services.dynamodb.model.QueryResponse; -import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; -import software.amazon.lambda.powertools.parameters.cache.CacheManager; -import software.amazon.lambda.powertools.parameters.exception.DynamoDbProviderSchemaException; -import software.amazon.lambda.powertools.parameters.transform.TransformationManager; - -/** - * Implements a {@link ParamProvider} on top of DynamoDB. The schema of the table - * is described in the Powertools for AWS Lambda (Java) documentation. - * - * @see Parameters provider documentation - */ -public class DynamoDbProvider extends BaseProvider { - - private final DynamoDbClient client; - private final String tableName; - - DynamoDbProvider(CacheManager cacheManager, DynamoDbClient client, String tableName) { - super(cacheManager); - this.client = client; - this.tableName = tableName; - } - - DynamoDbProvider(CacheManager cacheManager, String tableName) { - this(cacheManager, Builder.createClient(), tableName); - } - - /** - * Create a builder that can be used to configure and create a {@link DynamoDbProvider}. - * - * @return a new instance of {@link DynamoDbProvider.Builder} - */ - public static DynamoDbProvider.Builder builder() { - return new DynamoDbProvider.Builder(); - } - - /** - * Return a single value from the DynamoDB parameter provider. - * - * @param key key of the parameter - * @return The value, if it exists, null if it doesn't. Throws if the row exists but doesn't match the schema. - */ - @Override - protected String getValue(String key) { - GetItemResponse resp = client.getItem(GetItemRequest.builder() - .tableName(tableName) - .key(Collections.singletonMap("id", AttributeValue.fromS(key))) - .attributesToGet("value") - .build()); - - // If we have an item at the key, we should be able to get a 'val' out of it. If not it's - // exceptional. - // If we don't have an item at the key, we should return null. - if (resp.hasItem() && !resp.item().values().isEmpty()) { - if (!resp.item().containsKey("value")) { - throw new DynamoDbProviderSchemaException("Missing 'value': " + resp.item().toString()); - } - return resp.item().get("value").s(); - } - - return null; - } - - /** - * Returns multiple values from the DynamoDB parameter provider. - * - * @param path Parameter store path - * @return All values matching the given path, and an empty map if none do. Throws if any records exist that don't match the schema. - */ - @Override - protected Map getMultipleValues(String path) { - - QueryResponse resp = client.query(QueryRequest.builder() - .tableName(tableName) - .keyConditionExpression("id = :v_id") - .expressionAttributeValues(Collections.singletonMap(":v_id", AttributeValue.fromS(path))) - .build()); - - return resp - .items() - .stream() - .peek((i) -> - { - if (!i.containsKey("sk")) { - throw new DynamoDbProviderSchemaException("Missing 'sk': " + i.toString()); - } - if (!i.containsKey("value")) { - throw new DynamoDbProviderSchemaException("Missing 'value': " + i.toString()); - } - }) - .collect( - Collectors.toMap( - (i) -> i.get("sk").s(), - (i) -> i.get("value").s())); - - - } - - static class Builder { - private DynamoDbClient client; - private String table; - private CacheManager cacheManager; - private TransformationManager transformationManager; - - private static DynamoDbClient createClient() { - return DynamoDbClient.builder() - .httpClientBuilder(UrlConnectionHttpClient.builder()) - .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, - UserAgentConfigurator.getUserAgent(PARAMETERS)).build()) - .build(); - } - - /** - * Create a {@link DynamoDbProvider} instance. - * - * @return a {@link DynamoDbProvider} - */ - public DynamoDbProvider build() { - if (cacheManager == null) { - throw new IllegalStateException("No CacheManager provided; please provide one"); - } - if (table == null) { - throw new IllegalStateException("No DynamoDB table name provided; please provide one"); - } - DynamoDbProvider provider; - if (client == null) { - client = createClient(); - } - provider = new DynamoDbProvider(cacheManager, client, table); - - if (transformationManager != null) { - provider.setTransformationManager(transformationManager); - } - return provider; - } - - /** - * Set custom {@link DynamoDbClient} to pass to the {@link DynamoDbClient}.
- * Use it if you want to customize the region or any other part of the client. - * - * @param client Custom client - * @return the builder to chain calls (eg.
builder.withClient().build()
) - */ - public DynamoDbProvider.Builder withClient(DynamoDbClient client) { - this.client = client; - return this; - } - - /** - * Mandatory. Provide a CacheManager to the {@link DynamoDbProvider} - * - * @param cacheManager the manager that will handle the cache of parameters - * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) - */ - public DynamoDbProvider.Builder withCacheManager(CacheManager cacheManager) { - this.cacheManager = cacheManager; - return this; - } - - /** - * Mandatory. Provide a DynamoDB table to the {@link DynamoDbProvider} - * - * @param table the table that parameters will be retrieved from. - * @return the builder to chain calls (eg.
builder.withTable().build()
) - */ - public DynamoDbProvider.Builder withTable(String table) { - this.table = table; - return this; - } - - /** - * Provide a transformationManager to the {@link DynamoDbProvider} - * - * @param transformationManager the manager that will handle transformation of parameters - * @return the builder to chain calls (eg.
builder.withTransformationManager().build()
) - */ - public DynamoDbProvider.Builder withTransformationManager(TransformationManager transformationManager) { - this.transformationManager = transformationManager; - return this; - } - } -} diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java deleted file mode 100644 index 6fee0f114..000000000 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/ParamManager.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.parameters; - -import java.lang.reflect.Constructor; -import java.util.concurrent.ConcurrentHashMap; -import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; -import software.amazon.awssdk.services.dynamodb.DynamoDbClient; -import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; -import software.amazon.awssdk.services.ssm.SsmClient; -import software.amazon.lambda.powertools.parameters.cache.CacheManager; -import software.amazon.lambda.powertools.parameters.transform.TransformationManager; - -/** - * Utility class to retrieve instances of parameter providers. - * Each instance is unique (singleton). - */ -public final class ParamManager { - - private static final CacheManager cacheManager = new CacheManager(); - private static final TransformationManager transformationManager = new TransformationManager(); - - // NOTE: For testing purposes `providers` cannot be final - private static ConcurrentHashMap, BaseProvider> providers = new ConcurrentHashMap<>(); - - /** - * Get a concrete implementation of {@link BaseProvider}.
- * You can specify {@link SecretsProvider}, {@link SSMProvider} or create your - * custom provider by extending {@link BaseProvider} if you need to integrate with a different parameter store. - * - * @return a {@link SecretsProvider} - * @deprecated You should not use this method directly but a typed one (getSecretsProvider, getSsmProvider, getDynamoDbProvider, getAppConfigProvider), will be removed in v2 - */ - // TODO in v2: remove public access to this and review how we get providers (it was not designed for DDB and AppConfig in mind initially) - public static T getProvider(Class providerClass) { - if (providerClass == null) { - throw new IllegalStateException("providerClass cannot be null."); - } - if (providerClass == DynamoDbProvider.class || providerClass == AppConfigProvider.class) { - throw new IllegalArgumentException( - providerClass + " cannot be instantiated like this, additional parameters are required"); - } - return (T) providers.computeIfAbsent(providerClass, ParamManager::createProvider); - } - - /** - * Get a {@link SecretsProvider} with default {@link SecretsManagerClient}.
- * If you need to customize the region, or other part of the client, use {@link ParamManager#getSecretsProvider(SecretsManagerClient)} instead. - * - * @return a {@link SecretsProvider} - */ - public static SecretsProvider getSecretsProvider() { - return getProvider(SecretsProvider.class); - } - - /** - * Get a {@link SSMProvider} with default {@link SsmClient}.
- * If you need to customize the region, or other part of the client, use {@link ParamManager#getSsmProvider(SsmClient)} instead. - * - * @return a {@link SSMProvider} - */ - public static SSMProvider getSsmProvider() { - return getProvider(SSMProvider.class); - } - - /** - * Get a {@link DynamoDbProvider} with default {@link DynamoDbClient}
- * If you need to customize the region, or other part of the client, use {@link ParamManager#getDynamoDbProvider(DynamoDbClient, String)} - */ - public static DynamoDbProvider getDynamoDbProvider(String tableName) { - // Because we need a DDB table name to configure our client, we can't use - // ParamManager#getProvider. This means that we need to make sure we do the same stuff - - // set transformation manager and cache manager. - return DynamoDbProvider.builder() - .withCacheManager(cacheManager) - .withTable(tableName) - .withTransformationManager(transformationManager) - .build(); - } - - /** - * Get a {@link AppConfigProvider} with default {@link AppConfigDataClient}.
- * If you need to customize the region, or other part of the client, use {@link ParamManager#getAppConfigProvider(AppConfigDataClient, String, String)} instead. - * - * @return a {@link AppConfigProvider} - */ - public static AppConfigProvider getAppConfigProvider(String environment, String application) { - // Because we need a DDB table name to configure our client, we can't use - // ParamManager#getProvider. This means that we need to make sure we do the same stuff - - // set transformation manager and cache manager. - return AppConfigProvider.builder() - .withCacheManager(cacheManager) - .withTransformationManager(transformationManager) - .withEnvironment(environment) - .withApplication(application) - .build(); - } - - - /** - * Get a {@link SecretsProvider} with your custom {@link SecretsManagerClient}.
- * Use this to configure region or other part of the client. Use {@link ParamManager#getSsmProvider()} if you don't need this customization. - * - * @return a {@link SecretsProvider} - */ - public static SecretsProvider getSecretsProvider(SecretsManagerClient client) { - return (SecretsProvider) providers.computeIfAbsent(SecretsProvider.class, (k) -> SecretsProvider.builder() - .withClient(client) - .withCacheManager(cacheManager) - .withTransformationManager(transformationManager) - .build()); - } - - /** - * Get a {@link SSMProvider} with your custom {@link SsmClient}.
- * Use this to configure region or other part of the client. Use {@link ParamManager#getSsmProvider()} if you don't need this customization. - * - * @return a {@link SSMProvider} - */ - public static SSMProvider getSsmProvider(SsmClient client) { - return (SSMProvider) providers.computeIfAbsent(SSMProvider.class, (k) -> SSMProvider.builder() - .withClient(client) - .withCacheManager(cacheManager) - .withTransformationManager(transformationManager) - .build()); - } - - /** - * Get a {@link DynamoDbProvider} with your custom {@link DynamoDbClient}.
- * Use this to configure region or other part of the client. Use {@link ParamManager#getDynamoDbProvider(String)} )} if you don't need this customization. - * - * @return a {@link DynamoDbProvider} - */ - public static DynamoDbProvider getDynamoDbProvider(DynamoDbClient client, String table) { - return (DynamoDbProvider) providers.computeIfAbsent(DynamoDbProvider.class, (k) -> DynamoDbProvider.builder() - .withClient(client) - .withTable(table) - .withCacheManager(cacheManager) - .withTransformationManager(transformationManager) - .build()); - } - - /** - * Get a {@link AppConfigProvider} with your custom {@link AppConfigDataClient}.
- * Use this to configure region or other part of the client. Use {@link ParamManager#getAppConfigProvider(String, String)} if you don't need this customization. - * - * @return a {@link AppConfigProvider} - */ - public static AppConfigProvider getAppConfigProvider(AppConfigDataClient client, String environment, - String application) { - return (AppConfigProvider) providers.computeIfAbsent(AppConfigProvider.class, (k) -> AppConfigProvider.builder() - .withClient(client) - .withCacheManager(cacheManager) - .withTransformationManager(transformationManager) - .withEnvironment(environment) - .withApplication(application) - .build()); - } - - - public static CacheManager getCacheManager() { - return cacheManager; - } - - public static TransformationManager getTransformationManager() { - return transformationManager; - } - - static T createProvider(Class providerClass) { - try { - Constructor constructor = providerClass.getDeclaredConstructor(CacheManager.class); - T provider = - constructor.newInstance(cacheManager); // FIXME: avoid reflection here as we may have issues (#1280) - provider.setTransformationManager(transformationManager); - return provider; - } catch (ReflectiveOperationException e) { - throw new RuntimeException("Unexpected error occurred. Please raise issue at " + - "https://github.com/aws-powertools/powertools-lambda-java/issues", e); - } - } - -} diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java deleted file mode 100644 index b77f501f2..000000000 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/SecretsProvider.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.parameters; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import java.time.temporal.ChronoUnit; -import java.util.Base64; -import java.util.Map; -import software.amazon.awssdk.core.SdkSystemSetting; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption; -import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; -import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; -import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; -import software.amazon.lambda.powertools.parameters.cache.CacheManager; -import software.amazon.lambda.powertools.parameters.transform.TransformationManager; -import software.amazon.lambda.powertools.parameters.transform.Transformer; - -/** - * AWS Secrets Manager Parameter Provider

- * - * Samples: - *
- *     SecretsProvider provider = ParamManager.getSecretsProvider();
- *
- *     String value = provider.get("key");
- *     System.out.println(value);
- *     >>> "value"
- *
- *     // Get a value and cache it for 30 seconds (all others values will now be cached for 30 seconds)
- *     String value = provider.defaultMaxAge(30, ChronoUnit.SECONDS).get("key");
- *
- *     // Get a value and cache it for 1 minute (all others values are cached for 5 seconds by default)
- *     String value = provider.withMaxAge(1, ChronoUnit.MINUTES).get("key");
- *
- *     // Get a base64 encoded value, decoded into a String, and store it in the cache
- *     String value = provider.withTransformation(Transformer.base64).get("key");
- *
- *     // Get a json value, transform it into an Object, and store it in the cache
- *     TargetObject = provider.withTransformation(Transformer.json).get("key", TargetObject.class);
- * 
- */ -public class SecretsProvider extends BaseProvider { - - private final SecretsManagerClient client; - - /** - * Constructor with custom {@link SecretsManagerClient}.
- * Use when you need to customize region or any other attribute of the client.

- *

- * Use the {@link Builder} to create an instance of it. - * - * @param client custom client you would like to use. - */ - SecretsProvider(CacheManager cacheManager, SecretsManagerClient client) { - super(cacheManager); - this.client = client; - } - - /** - * Constructor with only a CacheManager
- *

- * Used in {@link ParamManager#createProvider(Class)} - * - * @param cacheManager handles the parameter caching - */ - SecretsProvider(CacheManager cacheManager) { - this(cacheManager, Builder.createClient()); - } - - /** - * Create a builder that can be used to configure and create a {@link SecretsProvider}. - * - * @return a new instance of {@link SecretsProvider.Builder} - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Retrieve the parameter value from the AWS Secrets Manager. - * - * @param key key of the parameter - * @return the value of the parameter identified by the key - */ - @Override - protected String getValue(String key) { - GetSecretValueRequest request = GetSecretValueRequest.builder().secretId(key).build(); - - String secretValue = client.getSecretValue(request).secretString(); - if (secretValue == null) { - secretValue = - new String(Base64.getDecoder().decode(client.getSecretValue(request).secretBinary().asByteArray()), - UTF_8); - } - return secretValue; - } - - /** - * @throws UnsupportedOperationException as it is not possible to get multiple values simultaneously from Secrets Manager - */ - @Override - protected Map getMultipleValues(String path) { - throw new UnsupportedOperationException("Impossible to get multiple values from AWS Secrets Manager"); - } - - /** - * {@inheritDoc} - */ - @Override - public SecretsProvider defaultMaxAge(int maxAge, ChronoUnit unit) { - super.defaultMaxAge(maxAge, unit); - return this; - } - - /** - * {@inheritDoc} - */ - @Override - public SecretsProvider withMaxAge(int maxAge, ChronoUnit unit) { - super.withMaxAge(maxAge, unit); - return this; - } - - /** - * {@inheritDoc} - */ - @Override - public SecretsProvider withTransformation(Class transformerClass) { - super.withTransformation(transformerClass); - return this; - } - - // For test purpose only - SecretsManagerClient getClient() { - return client; - } - - static class Builder { - - private SecretsManagerClient client; - private CacheManager cacheManager; - private TransformationManager transformationManager; - - private static SecretsManagerClient createClient() { - return SecretsManagerClient.builder() - .httpClientBuilder(UrlConnectionHttpClient.builder()) - .region(Region.of(System.getenv(SdkSystemSetting.AWS_REGION.environmentVariable()))) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .putAdvancedOption(SdkAdvancedClientOption.USER_AGENT_SUFFIX, - UserAgentConfigurator.getUserAgent(PARAMETERS)).build()) - .build(); - } - - /** - * Create a {@link SecretsProvider} instance. - * - * @return a {@link SecretsProvider} - */ - public SecretsProvider build() { - if (cacheManager == null) { - throw new IllegalStateException("No CacheManager provided, please provide one"); - } - SecretsProvider provider; - if (client == null) { - client = createClient(); - } - - provider = new SecretsProvider(cacheManager, client); - - if (transformationManager != null) { - provider.setTransformationManager(transformationManager); - } - return provider; - } - - /** - * Set custom {@link SecretsManagerClient} to pass to the {@link SecretsProvider}.
- * Use it if you want to customize the region or any other part of the client. - * - * @param client Custom client - * @return the builder to chain calls (eg.

builder.withClient().build()
) - */ - public Builder withClient(SecretsManagerClient client) { - this.client = client; - return this; - } - - /** - * Mandatory. Provide a CacheManager to the {@link SecretsProvider} - * - * @param cacheManager the manager that will handle the cache of parameters - * @return the builder to chain calls (eg.
builder.withCacheManager().build()
) - */ - public Builder withCacheManager(CacheManager cacheManager) { - this.cacheManager = cacheManager; - return this; - } - - /** - * Provide a transformationManager to the {@link SecretsProvider} - * - * @param transformationManager the manager that will handle transformation of parameters - * @return the builder to chain calls (eg.
builder.withTransformationManager().build()
) - */ - public Builder withTransformationManager(TransformationManager transformationManager) { - this.transformationManager = transformationManager; - return this; - } - } -} diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java deleted file mode 100644 index 081af108d..000000000 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspect.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.parameters.internal; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.FieldSignature; -import software.amazon.lambda.powertools.parameters.BaseProvider; -import software.amazon.lambda.powertools.parameters.Param; -import software.amazon.lambda.powertools.parameters.ParamManager; - -@Aspect -public class LambdaParametersAspect { - - @Pointcut("get(* *) && @annotation(paramAnnotation)") - public void getParam(Param paramAnnotation) { - } - - @Around("getParam(paramAnnotation)") - public Object injectParam(final ProceedingJoinPoint joinPoint, final Param paramAnnotation) { - BaseProvider provider = ParamManager.getProvider(paramAnnotation.provider()); - - if (paramAnnotation.transformer().isInterface()) { - // No transformation - return provider.get(paramAnnotation.key()); - } else { - FieldSignature s = (FieldSignature) joinPoint.getSignature(); - if (String.class.isAssignableFrom(s.getFieldType())) { - // Basic transformation - return provider - .withTransformation(paramAnnotation.transformer()) - .get(paramAnnotation.key()); - } else { - // Complex transformation - return provider - .withTransformation(paramAnnotation.transformer()) - .get(paramAnnotation.key(), s.getFieldType()); - } - } - } - -} diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java deleted file mode 100644 index b84fcf743..000000000 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/ParamManagerTest.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.parameters; - -import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.assertj.core.api.Assertions.assertThatRuntimeException; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -import org.junit.jupiter.api.Test; -import software.amazon.lambda.powertools.parameters.cache.CacheManager; -import software.amazon.lambda.powertools.parameters.internal.CustomProvider; -import software.amazon.lambda.powertools.parameters.transform.TransformationManager; - -public class ParamManagerTest { - - @Test - public void testGetCacheManager() { - - // Act - CacheManager cacheManager = ParamManager.getCacheManager(); - - // Assert - assertNotNull(cacheManager); - } - - @Test - public void testGetTransformationManager() { - - // Act - TransformationManager transformationManager = ParamManager.getTransformationManager(); - - // Assert - assertNotNull(transformationManager); - } - - @Test - public void testCreateProvider() { - - // Act - CustomProvider customProvider = ParamManager.createProvider(CustomProvider.class); - - // Assert - assertNotNull(customProvider); - } - - @Test - public void testCreateUninstanciableProvider_throwsException() { - - // Act & Assert - assertThatRuntimeException().isThrownBy(() -> ParamManager.createProvider(BaseProvider.class)); - } - - @Test - public void testGetProviderWithProviderClass() { - - // Act - SecretsProvider secretsProvider = ParamManager.getProvider(SecretsProvider.class); - - // Assert - assertNotNull(secretsProvider); - } - - @Test - public void testGetProviderWithProviderClass_throwsException() { - - // Act & Assert - assertThatIllegalStateException().isThrownBy(() -> ParamManager.getProvider(null)); - } - - @Test - public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() { - - // Act - SecretsProvider secretsProvider = ParamManager.getSecretsProvider(); - - // Assert - assertNotNull(secretsProvider); - assertNotNull(secretsProvider.getClient()); - } - - @Test - public void testGetSSMProvider_withoutParameter_shouldCreateDefaultClient() { - - // Act - SSMProvider ssmProvider = ParamManager.getSsmProvider(); - - // Assert - assertNotNull(ssmProvider); - assertNotNull(ssmProvider.getClient()); - } - - @Test - public void testGetDynamoDBProvider_requireOtherParameters_throwException() { - - // Act & Assert - assertThatIllegalArgumentException().isThrownBy(() -> ParamManager.getProvider(DynamoDbProvider.class)); - } - - @Test - public void testGetAppConfigProvider_requireOtherParameters_throwException() { - - // Act & Assert - assertThatIllegalArgumentException().isThrownBy(() -> ParamManager.getProvider(AppConfigProvider.class)); - } -} diff --git a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java b/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java deleted file mode 100644 index 2c246336b..000000000 --- a/powertools-parameters/src/test/java/software/amazon/lambda/powertools/parameters/internal/LambdaParametersAspectTest.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.parameters.internal; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import software.amazon.lambda.powertools.parameters.Param; -import software.amazon.lambda.powertools.parameters.ParamManager; -import software.amazon.lambda.powertools.parameters.SSMProvider; -import software.amazon.lambda.powertools.parameters.exception.TransformationException; -import software.amazon.lambda.powertools.parameters.transform.Base64Transformer; -import software.amazon.lambda.powertools.parameters.transform.JsonTransformer; -import software.amazon.lambda.powertools.parameters.transform.ObjectToDeserialize; - -public class LambdaParametersAspectTest { - - @Mock - private SSMProvider defaultProvider; - - @Param(key = "/default") - private String defaultValue; - - @Param(key = "/simple", provider = CustomProvider.class) - private String param; - - @Param(key = "/base64", provider = CustomProvider.class, transformer = Base64Transformer.class) - private String basicTransform; - - @Param(key = "/json", provider = CustomProvider.class, transformer = JsonTransformer.class) - private ObjectToDeserialize complexTransform; - - @Param(key = "/json", provider = CustomProvider.class, transformer = JsonTransformer.class) - private AnotherObject wrongTransform; - - @BeforeEach - public void init() { - openMocks(this); - } - - @Test - public void testDefault_ShouldUseSSMProvider() { - try (MockedStatic mocked = mockStatic(ParamManager.class)) { - mocked.when(() -> ParamManager.getProvider(SSMProvider.class)).thenReturn(defaultProvider); - when(defaultProvider.get("/default")).thenReturn("value"); - - assertThat(defaultValue).isEqualTo("value"); - mocked.verify(() -> ParamManager.getProvider(SSMProvider.class), times(1)); - verify(defaultProvider, times(1)).get("/default"); - - mocked.reset(); - } - } - - @Test - public void testSimple() { - assertThat(param).isEqualTo("value"); - } - - @Test - public void testWithBasicTransform() { - assertThat(basicTransform).isEqualTo("value"); - } - - @Test - public void testWithComplexTransform() { - assertThat(complexTransform) - .isInstanceOf(ObjectToDeserialize.class) - .matches( - o -> o.getFoo().equals("Foo") && - o.getBar() == 42 && - o.getBaz() == 123456789); - } - - @Test - public void testWithComplexTransformWrongTargetClass_ShouldThrowException() { - assertThatExceptionOfType(TransformationException.class) - .isThrownBy(() -> - { - AnotherObject obj = wrongTransform; - }); - } - -} diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index eca7e266f..dc22f22b6 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -8,6 +8,40 @@ https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -65,14 +99,6 @@ - - - - - - - - @@ -140,18 +166,10 @@ - - - - - - - - From b139a96b45101830bb44e1854c4e96552cdfbc1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:41:48 +0100 Subject: [PATCH 111/577] feat(v2): new logging module (#1435) --- docs/core/logging.md | 1134 ++++++++++++----- docs/stylesheets/extra.css | 2 +- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 7 +- .../dynamo/DynamoDBStreamBatchHandler.java | 6 +- .../org/demo/batch/dynamo/DynamoDBWriter.java | 6 +- .../batch/kinesis/KinesisBatchHandler.java | 6 +- .../batch/kinesis/KinesisBatchSender.java | 6 +- .../org/demo/batch/sqs/SqsBatchHandler.java | 6 +- .../org/demo/batch/sqs/SqsBatchSender.java | 6 +- .../pom.xml | 25 +- .../src/main/java/helloworld/App.java | 20 +- .../cdk/app/pom.xml | 4 +- .../cdk/app/src/main/java/helloworld/App.java | 7 +- .../gradle/build.gradle | 3 +- .../gradle/src/main/java/helloworld/App.java | 6 +- .../kotlin/build.gradle.kts | 16 +- .../kotlin/src/main/kotlin/helloworld/App.kt | 5 +- .../src/test/kotlin/helloworld/AppTest.kt | 20 - .../sam/pom.xml | 17 +- .../sam/src/main/java/helloworld/App.java | 6 +- .../serverless/pom.xml | 17 +- .../terraform/pom.xml | 17 +- .../powertools-examples-idempotency/pom.xml | 22 +- .../src/main/java/helloworld/App.java | 6 +- .../powertools-examples-parameters/pom.xml | 6 +- .../demo/parameters/ParametersFunction.java | 6 +- .../powertools-examples-serialization/pom.xml | 4 +- ...GatewayRequestDeserializationFunction.java | 13 +- .../SQSEventDeserializationFunction.java | 6 +- .../powertools-examples-validation/pom.xml | 6 +- pom.xml | 64 +- powertools-batch/pom.xml | 2 +- .../handler/DynamoDbBatchMessageHandler.java | 2 +- .../KinesisStreamsBatchMessageHandler.java | 2 +- .../batch/handler/SqsBatchMessageHandler.java | 4 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 12 +- .../common/internal/LambdaConstants.java | 6 - .../internal/LambdaHandlerProcessor.java | 1 - .../internal/UserAgentConfigurator.java | 6 +- .../internal/LambdaHandlerProcessorTest.java | 3 - powertools-e2e-tests/handlers/batch/pom.xml | 6 +- .../lambda/powertools/e2e/Function.java | 24 +- .../handlers/idempotency/pom.xml | 6 +- .../handlers/largemessage/pom.xml | 6 +- .../handlers/largemessage_idempotent/pom.xml | 6 +- powertools-e2e-tests/handlers/logging/pom.xml | 11 +- .../lambda/powertools/e2e/Function.java | 8 +- .../handlers/parameters/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 13 +- powertools-e2e-tests/pom.xml | 3 +- .../amazon/lambda/powertools/LoggingE2ET.java | 4 +- powertools-idempotency/pom.xml | 11 +- .../powertools/idempotency/Idempotency.java | 2 +- .../handlers/IdempotencyFunction.java | 6 +- powertools-large-messages/pom.xml | 7 +- powertools-logging/pom.xml | 55 +- .../powertools-logging-log4j/pom.xml | 137 ++ .../json/resolver/PowertoolsResolver.java | 286 +++++ .../resolver}/PowertoolsResolverFactory.java | 15 +- .../log4/internal/Log4jLoggingManager.java | 48 + .../src/main/resources/LambdaEcsLayout.json | 89 ++ .../src/main/resources/LambdaJsonLayout.json | 72 ++ ...powertools.logging.internal.LoggingManager | 1 + .../PowerToolsResolverFactoryTest.java | 95 ++ .../PowertoolsMessageResolverTest.java | 115 ++ .../json/resolver/PowertoolsResolverTest.java | 110 ++ .../internal/Log4jLoggingManagerTest.java | 51 + .../handler/PowertoolsJsonMessage.java | 47 + .../handler/PowertoolsLogEnabled.java | 34 + .../test/resources/junit-platform.properties | 17 + .../src/test/resources/log4j2.xml | 24 + .../powertools-logging-logback/pom.xml | 137 ++ .../logging/logback/LambdaEcsEncoder.java | 199 +++ .../logging/logback/LambdaJsonEncoder.java | 208 +++ .../logging/logback/internal/JsonUtils.java | 130 ++ .../logback/internal/LambdaEcsSerializer.java | 187 +++ .../internal/LambdaJsonSerializer.java | 150 +++ .../internal/LogbackLoggingManager.java | 59 + ...powertools.logging.internal.LoggingManager | 1 + .../logging/LogbackLoggingManagerTest.java | 54 + .../internal/LambdaEcsEncoderTest.java | 176 +++ .../internal/LambdaJsonEncoderTest.java | 263 ++++ .../handler/PowertoolsJsonMessage.java | 44 + .../handler/PowertoolsLogEnabled.java | 34 + .../test/resources/junit-platform.properties | 17 + .../src/test/resources/logback-test.xml | 27 + powertools-logging/spotbugs-exclude.xml | 30 + ...Constants.java => CorrelationIdPaths.java} | 14 +- .../lambda/powertools/logging/Logging.java | 37 +- .../powertools/logging/LoggingUtils.java | 56 +- .../internal/AbstractJacksonLayoutCopy.java | 519 -------- .../internal/DefautlLoggingManager.java | 35 + .../logging/internal/JacksonFactoryCopy.java | 133 -- .../logging/internal/LambdaJsonLayout.java | 246 ---- .../logging/internal/LambdaLoggingAspect.java | 372 ++++-- .../internal/LambdaTimestampResolver.java | 169 --- .../LambdaTimestampResolverFactory.java | 49 - .../logging/internal/LoggingConstants.java | 14 +- .../logging/internal/LoggingManager.java | 48 + ...ields.java => PowertoolsLoggedFields.java} | 32 +- .../logging/internal/PowertoolsResolver.java | 66 - .../src/main/resources/LambdaEcsLayout.json | 52 - .../src/main/resources/LambdaJsonLayout.json | 89 -- .../resources/log4j2.component.properties | 2 - .../core/layout/LambdaJsonLayoutTest.java | 173 --- .../java/org/slf4j/test/OutputChoice.java | 77 ++ .../test/java/org/slf4j/test/TestLogger.java | 452 +++++++ .../slf4j/test/TestLoggerConfiguration.java | 204 +++ .../org/slf4j/test/TestLoggerFactory.java | 78 ++ .../org/slf4j/test/TestServiceProvider.java | 76 ++ .../powertools/logging/LoggingUtilsTest.java | 70 +- ...erToolLogEventEnabledWithCustomMapper.java | 63 - .../PowertoolsLogAlbCorrelationId.java | 8 +- ...olsLogApiGatewayHttpApiCorrelationId.java} | 10 +- ...olsLogApiGatewayRestApiCorrelationId.java} | 10 +- .../PowertoolsLogAppSyncCorrelationId.java | 37 + ...tate.java => PowertoolsLogClearState.java} | 17 +- ...sabled.java => PowertoolsLogDisabled.java} | 2 +- ...va => PowertoolsLogDisabledForStream.java} | 2 +- .../handlers/PowertoolsLogEnabled.java | 52 + ...ava => PowertoolsLogEnabledForStream.java} | 2 +- .../logging/handlers/PowertoolsLogError.java | 28 + ...ntEnabled.java => PowertoolsLogEvent.java} | 4 +- ...PowertoolsLogEventBridgeCorrelationId.java | 8 +- ...d.java => PowertoolsLogEventDisabled.java} | 4 +- ....java => PowertoolsLogEventForStream.java} | 8 +- .../handlers/PowertoolsLogResponse.java | 28 + .../PowertoolsLogResponseForStream.java | 35 + ...ava => PowertoolsLogSamplingDisabled.java} | 19 +- ...java => PowertoolsLogSamplingEnabled.java} | 12 +- .../internal/LambdaLoggingAspectTest.java | 709 ++++++++--- .../logging/internal/TestLoggingManager.java | 32 + .../org.slf4j.spi.SLF4JServiceProvider | 1 + ...powertools.logging.internal.LoggingManager | 15 + .../src/test/resources/log4j2.xml | 16 - .../test/resources/s3EventNotification.json | 38 - .../src/test/resources/testlogger.properties | 3 + powertools-metrics/pom.xml | 7 +- powertools-parameters/pom.xml | 7 +- powertools-serialization/pom.xml | 6 +- .../powertools/utilities/JsonConfig.java | 2 +- powertools-tracing/pom.xml | 7 +- powertools-validation/pom.xml | 2 +- .../validation/ValidationConfig.java | 2 +- spotbugs-exclude.xml | 45 +- 147 files changed, 6070 insertions(+), 2778 deletions(-) delete mode 100644 examples/powertools-examples-core-utilities/kotlin/src/test/kotlin/helloworld/AppTest.kt create mode 100644 powertools-logging/powertools-logging-log4j/pom.xml create mode 100644 powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java rename powertools-logging/{src/main/java/software/amazon/lambda/powertools/logging/internal => powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver}/PowertoolsResolverFactory.java (71%) create mode 100644 powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/Log4jLoggingManager.java create mode 100644 powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json create mode 100644 powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json create mode 100644 powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager create mode 100644 powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java create mode 100644 powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsMessageResolverTest.java create mode 100644 powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java create mode 100644 powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/Log4jLoggingManagerTest.java create mode 100644 powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java create mode 100644 powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java create mode 100644 powertools-logging/powertools-logging-log4j/src/test/resources/junit-platform.properties create mode 100644 powertools-logging/powertools-logging-log4j/src/test/resources/log4j2.xml create mode 100644 powertools-logging/powertools-logging-logback/pom.xml create mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java create mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaJsonEncoder.java create mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/JsonUtils.java create mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaEcsSerializer.java create mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaJsonSerializer.java create mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackLoggingManager.java create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/LogbackLoggingManagerTest.java create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java create mode 100644 powertools-logging/powertools-logging-logback/src/test/resources/junit-platform.properties create mode 100644 powertools-logging/powertools-logging-logback/src/test/resources/logback-test.xml create mode 100644 powertools-logging/spotbugs-exclude.xml rename powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/{CorrelationIdPathConstants.java => CorrelationIdPaths.java} (69%) delete mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/AbstractJacksonLayoutCopy.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefautlLoggingManager.java delete mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JacksonFactoryCopy.java delete mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonLayout.java delete mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolver.java delete mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolverFactory.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingManager.java rename powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/{DefaultLambdaFields.java => PowertoolsLoggedFields.java} (59%) delete mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsResolver.java delete mode 100644 powertools-logging/src/main/resources/LambdaEcsLayout.json delete mode 100644 powertools-logging/src/main/resources/LambdaJsonLayout.json delete mode 100644 powertools-logging/src/main/resources/log4j2.component.properties delete mode 100644 powertools-logging/src/test/java/org/apache/logging/log4j/core/layout/LambdaJsonLayoutTest.java create mode 100644 powertools-logging/src/test/java/org/slf4j/test/OutputChoice.java create mode 100644 powertools-logging/src/test/java/org/slf4j/test/TestLogger.java create mode 100644 powertools-logging/src/test/java/org/slf4j/test/TestLoggerConfiguration.java create mode 100644 powertools-logging/src/test/java/org/slf4j/test/TestLoggerFactory.java create mode 100644 powertools-logging/src/test/java/org/slf4j/test/TestServiceProvider.java delete mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventEnabledWithCustomMapper.java rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowerLogToolApiGatewayHttpApiCorrelationId.java => PowertoolsLogApiGatewayHttpApiCorrelationId.java} (78%) rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowerLogToolApiGatewayRestApiCorrelationId.java => PowertoolsLogApiGatewayRestApiCorrelationId.java} (78%) create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogAppSyncCorrelationId.java rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowertoolsLogEnabledWithClearState.java => PowertoolsLogClearState.java} (67%) rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowerToolDisabled.java => PowertoolsLogDisabled.java} (91%) rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowerToolDisabledForStream.java => PowertoolsLogDisabledForStream.java} (92%) create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabled.java rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowerLogToolEnabledForStream.java => PowertoolsLogEnabledForStream.java} (93%) create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogError.java rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowerToolLogEventEnabled.java => PowertoolsLogEvent.java} (92%) rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowerToolLogEventDisabled.java => PowertoolsLogEventDisabled.java} (89%) rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowerToolLogEventEnabledForStream.java => PowertoolsLogEventForStream.java} (80%) create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponse.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponseForStream.java rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowerLogToolEnabled.java => PowertoolsLogSamplingDisabled.java} (68%) rename powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/{PowerLogToolSamplingEnabled.java => PowertoolsLogSamplingEnabled.java} (74%) create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/TestLoggingManager.java create mode 100644 powertools-logging/src/test/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider create mode 100644 powertools-logging/src/test/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager delete mode 100644 powertools-logging/src/test/resources/log4j2.xml delete mode 100644 powertools-logging/src/test/resources/s3EventNotification.json create mode 100644 powertools-logging/src/test/resources/testlogger.properties diff --git a/docs/core/logging.md b/docs/core/logging.md index 70781b1b2..f0fba760a 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -5,24 +5,34 @@ description: Core utility Logging provides an opinionated logger with output structured as JSON. -**Key features** +## Key features -* Capture key fields from Lambda context, cold start and structures logging output as JSON -* Log Lambda event when instructed, disabled by default, can be enabled explicitly via annotation param -* Append additional keys to structured log at any point in time +* Leverages standard logging libraries: [_SLF4J_](https://www.slf4j.org/){target="_blank"} as the API, and [_log4j2_](https://logging.apache.org/log4j/2.x/){target="_blank"} or [_logback_](https://logback.qos.ch/){target="_blank"} for the implementation +* Captures key fields from Lambda context, cold start and structures logging output as JSON +* Optionally logs Lambda request +* Optionally logs Lambda response +* Optionally supports log sampling by including a configurable percentage of DEBUG logs in logging output +* Allows additional keys to be appended to the structured log at any point in time -## Install -Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. +## Getting started -=== "Maven Java 11+" +???+ tip + You can find complete examples in the [project repository](https://github.com/aws-powertools/powertools-lambda-java/tree/v2/examples/powertools-examples-core-utilities){target="_blank"}. - ```xml hl_lines="3-7 16 18 24-27" +### Installation +Depending on preference, you must choose to use either _log4j2_ or _logback_ as your log provider. In both cases you need to configure _aspectj_ +to weave the code and make sure the annotation is processed. + +#### Maven +=== "log4j2" + + ```xml hl_lines="3-7 24-27" ... software.amazon.lambda - powertools-logging + powertools-logging-log4j {{ powertools.version }} ... @@ -60,14 +70,14 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl ``` -=== "Maven Java 1.8" +=== "logback" - ```xml hl_lines="3-7 16 18 24-27" + ```xml hl_lines="3-7 24-27" ... software.amazon.lambda - powertools-logging + powertools-logging-logback {{ powertools.version }} ... @@ -78,13 +88,13 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl ... - org.codehaus.mojo + dev.aspectj aspectj-maven-plugin - 1.14.0 + 1.13.1 - 1.8 - 1.8 - 1.8 + 11 + 11 + 11 software.amazon.lambda @@ -105,7 +115,9 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl ``` -=== "Gradle Java 11+" +#### Gradle + +=== "log4j2" ```groovy hl_lines="3 11" plugins { @@ -118,19 +130,19 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl } dependencies { - aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-logging-log4j:{{ powertools.version }}' } sourceCompatibility = 11 targetCompatibility = 11 ``` -=== "Gradle Java 1.8" +=== "logback" ```groovy hl_lines="3 11" plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' + id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' } repositories { @@ -138,27 +150,61 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl } dependencies { - aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-logging-logback:{{ powertools.version }}' } - sourceCompatibility = 1.8 - targetCompatibility = 1.8 + sourceCompatibility = 11 + targetCompatibility = 11 ``` -## Initialization +### Configuration -Powertools for AWS Lambda (Java) extends the functionality of Log4J. Below is an example `#!xml log4j2.xml` file, with the `JsonTemplateLayout` using `#!json LambdaJsonLayout.json` configured. +#### Main environment variables -!!! info "LambdaJsonLayout is now deprecated" +The logging module requires two settings: - Configuring utiltiy using `` plugin is deprecated now. While utility still supports the old configuration, we strongly recommend upgrading the - `log4j2.xml` configuration to `JsonTemplateLayout` instead. [JsonTemplateLayout](https://logging.apache.org/log4j/2.x/manual/json-template-layout.html) is recommended way of doing structured logging. - - Please follow [this guide](#upgrade-to-jsontemplatelayout-from-deprecated-lambdajsonlayout-configuration-in-log4j2xml) for upgrade steps. +| Environment variable | Setting | Description | +|---------------------------|-------------------|-------------------------------------------------------------------------------------------------------------| +| `POWERTOOLS_LOG_LEVEL` | **Logging level** | Sets how verbose Logger should be. If not set, will use the [Logging configuration](#logging-configuration) | +| `POWERTOOLS_SERVICE_NAME` | **Service** | Sets service key that will be included in all log statements (Default is `service_undefined`) | + +Here is an example using AWS Serverless Application Model (SAM): + +=== "template.yaml" +``` yaml hl_lines="10 11" +Resources: + PaymentFunction: + Type: AWS::Serverless::Function + Properties: + MemorySize: 512 + Timeout: 20 + Runtime: java17 + Environment: + Variables: + POWERTOOLS_LOG_LEVEL: WARN + POWERTOOLS_SERVICE_NAME: payment +``` + +There are some other environment variables which can be set to modify Logging's settings at a global scope: + +| Environment variable | Type | Description | +|---------------------------------|----------|-------------------------------------------------------------------------------------------------------------------------| +| `POWERTOOLS_LOGGER_SAMPLE_RATE` | float | Configure the sampling rate at which `DEBUG` logs should be included. See [sampling rate](#sampling-debug-logs) | +| `POWERTOOLS_LOG_EVENT` | boolean | Specify if the incoming Lambda event should be logged. See [Logging event](#logging-incoming-event) | +| `POWERTOOLS_LOG_RESPONSE` | boolean | Specify if the Lambda response should be logged. See [logging response](#logging-handler-response) | +| `POWERTOOLS_LOG_ERROR` | boolean | Specify if a Lambda uncaught exception should be logged. See [logging exception](#logging-handler-uncaught-exception ) | + +#### Logging configuration + +Powertools for AWS Lambda (Java) simply extends the functionality of the underlying library you choose (_log4j2_ or _logback_). +You can leverage the standard configuration files (_log4j2.xml_ or _logback.xml_): === "log4j2.xml" + With log4j2, we leverage the [`JsonTemplateLayout`](https://logging.apache.org/log4j/2.x/manual/json-template-layout.html){target="_blank"} + to provide structured logging. A default template is provided in powertools ([_LambdaJsonLayout.json_](https://github.com/aws-powertools/powertools-lambda-java/tree/v2/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json){target="_blank"}): + ```xml hl_lines="5" @@ -168,7 +214,7 @@ Powertools for AWS Lambda (Java) extends the functionality of Log4J. Below is an - + @@ -178,152 +224,225 @@ Powertools for AWS Lambda (Java) extends the functionality of Log4J. Below is an ``` -You can also override log level by setting **`POWERTOOLS_LOG_LEVEL`** env var. Here is an example using AWS Serverless Application Model (SAM) +=== "logback.xml" -=== "template.yaml" - ``` yaml hl_lines="9 10" - Resources: - HelloWorldFunction: - Type: AWS::Serverless::Function - Properties: - ... - Runtime: java8 - Environment: - Variables: - POWERTOOLS_LOG_LEVEL: DEBUG - POWERTOOLS_SERVICE_NAME: example + With logback, we leverage a custom [Encoder](https://logback.qos.ch/manual/encoders.html){target="_blank"} + to provide structured logging: + + ```xml hl_lines="4 5" + + + + + + + + + + + + + ``` -You can also explicitly set a service name via **`POWERTOOLS_SERVICE_NAME`** env var. This sets **service** key that will be present across all log statements. +## Log level +Log level is generally configured in the `log4j2.xml` or `logback.xml`. But this level is static and needs a redeployment of the function to be changed. +Powertools for AWS Lambda permits to change this level dynamically thanks to an environment variable `POWERTOOLS_LOG_LEVEL`. -## Standard structured keys +We support the following log levels (SLF4J levels): `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`. +If the level is set to `CRITICAL` (supported in log4j but not logback), we revert it back to `ERROR`. +If the level is set to any other value, we set it to the default value (`INFO`). -Your logs will always include the following keys to your structured logging: +### AWS Lambda Advanced Logging Controls (ALC) -Key | Type | Example | Description -------------------------------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------- -**timestamp** | String | "2020-05-24 18:17:33,774" | Timestamp of actual log statement -**level** | String | "INFO" | Logging level -**coldStart** | Boolean | true| ColdStart value. -**service** | String | "payment" | Service name defined. "service_undefined" will be used if unknown -**samplingRate** | int | 0.1 | Debug logging sampling rate in percentage e.g. 10% in this case -**message** | String | "Collecting payment" | Log statement value. Unserializable JSON values will be casted to string -**functionName**| String | "example-powertools-HelloWorldFunction-1P1Z6B39FLU73" -**functionVersion**| String | "12" -**functionMemorySize**| String | "128" -**functionArn**| String | "arn:aws:lambda:eu-west-1:012345678910:function:example-powertools-HelloWorldFunction-1P1Z6B39FLU73" -**xray_trace_id**| String | "1-5759e988-bd862e3fe1be46a994272793" | X-Ray Trace ID when Lambda function has enabled Tracing -**function_request_id**| String | "899856cb-83d1-40d7-8611-9e78f15f32f4"" | AWS Request ID from lambda context +!!!question "When is it useful?" + When you want to set a logging policy to drop informational or verbose logs for one or all AWS Lambda functions, regardless of runtime and logger used. -## Capturing context Lambda info + +With [AWS Lambda Advanced Logging Controls (ALC)](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced){target="_blank"}, you can enforce a minimum log level that Lambda will accept from your application code. -When debugging in non-production environments, you can instruct Logger to log the incoming event with `@Logger(logEvent = true)` or via `POWERTOOLS_LOGGER_LOG_EVENT=true` environment variable. +When enabled, you should keep Powertools and ALC log level in sync to avoid data loss. -!!! warning - Log event is disabled by default to prevent sensitive info being logged. +Here's a sequence diagram to demonstrate how ALC will drop both `INFO` and `DEBUG` logs emitted from `Logger`, when ALC log level is stricter than `Logger`. + +```mermaid +sequenceDiagram + participant Lambda service + participant Lambda function + participant Application Logger -=== "App.java" + Note over Lambda service: AWS_LAMBDA_LOG_LEVEL="WARN" + Note over Application Logger: POWERTOOLS_LOG_LEVEL="DEBUG" - ```java hl_lines="14" - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - import software.amazon.lambda.powertools.logging.LoggingUtils; + Lambda service->>Lambda function: Invoke (event) + Lambda function->>Lambda function: Calls handler + Lambda function->>Application Logger: logger.error("Something happened") + Lambda function-->>Application Logger: logger.debug("Something happened") + Lambda function-->>Application Logger: logger.info("Something happened") + Lambda service--xLambda service: DROP INFO and DEBUG logs + Lambda service->>CloudWatch Logs: Ingest error logs +``` + +### Priority of log level settings in Powertools for AWS Lambda + +We prioritise log level settings in this order: + +1. `AWS_LAMBDA_LOG_LEVEL` environment variable +2. `POWERTOOLS_LOG_LEVEL` environment variable +3. level defined in the `log4j2.xml` or `logback.xml` files + +If you set Powertools level lower than ALC, we will emit a warning informing you that your messages will be discarded by Lambda. + +> **NOTE** +> +> With ALC enabled, we are unable to increase the minimum log level below the `AWS_LAMBDA_LOG_LEVEL` environment variable value, see [AWS Lambda service documentation](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-log-level){target="_blank"} for more details. + +## Basic Usage + +To use Lambda Powertools for AWS Lambda Logging, use the `@Logging` annotation in your code and the standard _SLF4J_ logger: + +=== "PaymentFunction.java" + + ```java hl_lines="8 10 12 14" + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; - ... - - /** - * Handler for requests to Lambda function. - */ - public class App implements RequestHandler { - - Logger log = LogManager.getLogger(App.class); + // ... other imports + + public class PaymentFunction implements RequestHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); + @Logging public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - ... + LOGGER.info("Collecting payment"); + // ... + LOGGER.debug("order={}, amount={}", order.getId(), order.getAmount()); + // ... } } ``` -=== "AppLogEvent.java" - - ```java hl_lines="8" - /** - * Handler for requests to Lambda function. - */ - public class AppLogEvent implements RequestHandler { +## Standard structured keys + +Your logs will always include the following keys in your structured logging: + +| Key | Type | Example | Description | +|-------------------|--------|-----------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------| +| **timestamp** | String | "2023-12-01T14:49:19.293Z" | Timestamp of actual log statement, by default uses default AWS Lambda timezone (UTC) | +| **level** | String | "INFO" | Logging level (any level supported by _SLF4J_ (i.e. `TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`) | +| **service** | String | "payment" | Service name defined, by default `service_undefined` | +| **sampling_rate** | float | 0.1 | Debug logging sampling rate in percentage e.g. 10% in this case (logged if not 0) | +| **message** | String | "Collecting payment" | Log statement value. Unserializable JSON values will be casted to string | +| **xray_trace_id** | String | "1-5759e988-bd862e3fe1be46a994272793" | X-Ray Trace ID when [Tracing is enabled](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank"} | +| **error** | Map | `{ "name": "InvalidAmountException", "message": "Amount must be superior to 0", "stack": "at..." }` | Eventual exception (e.g. when doing `logger.error("Error", new InvalidAmountException("Amount must be superior to 0"));`) | + +### Log messages as JSON +By default, `message` is logged as a `String` (e.g `"message": "The message"`). When logging JSON content, +you may want to avoid the escaped String (`"message:"{\"key\":\"value\"}"`) for better readability. +You can use `LoggingUtils.logMessagesAsJson(true)` to enable this programmatically. + +=== "PaymentFunction.java" + + ```java hl_lines="14 15 17-20" + import static software.amazon.lambda.powertools.utilities.EventDeserializer.extractDataFrom; + import software.amazon.lambda.powertools.logging.LoggingUtils; + import software.amazon.lambda.powertools.utilities.JsonConfig; + // ... other imports + + public class PaymentFunction implements RequestHandler { - Logger log = LogManager.getLogger(AppLogEvent.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); - @Logging(logEvent = true) + @Logging public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - ... + Order order = extractDataFrom(input).as(Order.class); + + // logged as a String + LOGGER.debug("{}", JsonConfig.get().getObjectMapper().writeValueAsString(order)); + + // Logged as JSON + LoggingUtils.logMessagesAsJson(true); + LOGGER.debug("{}", JsonConfig.get().getObjectMapper().writeValueAsString(order)); + LoggingUtils.logMessagesAsJson(false); + + // ... } } ``` -### Customising fields in logs +=== "Order.java" -- Utility by default emits `timestamp` field in the logs in format `yyyy-MM-dd'T'HH:mm:ss.SSSZz` and in system default timezone. -If you need to customize format and timezone, you can do so by configuring `log4j2.component.properties` and configuring properties as shown in example below: + ```java + public class Order { + private String id; + private Date date; + private Double amount; + } + ``` -=== "log4j2.component.properties" +=== "Example CloudWatch Logs" - ```properties hl_lines="1 2" - log4j.layout.jsonTemplate.timestampFormatPattern=yyyy-MM-dd'T'HH:mm:ss.SSSZz - log4j.layout.jsonTemplate.timeZone=Europe/Oslo + ```json hl_lines="3 9-13" + { + "level": "DEBUG", + "message": "{\"id\":\"435iuh2j3hb4\", \"date\":\"2023-12-01T14:48:59\", \"amount\":435.5}", + "timestamp": "2023-12-01T14:49:19.293Z", + "service": "payment", + } + { + "level": "DEBUG", + "message": { + "id": "435iuh2j3hb4", + "date": "2023-12-01T14:48:59", + "amount":435.5 + }, + "timestamp": "2023-12-01T14:49:19.312Z", + "service": "payment", + } ``` -- Utility also provides sample template for [Elastic Common Schema(ECS)](https://www.elastic.co/guide/en/ecs/current/ecs-reference.html) layout. -The field emitted in logs will follow specs from [ECS](https://www.elastic.co/guide/en/ecs/current/ecs-reference.html) together with field captured by utility as mentioned [above](#standard-structured-keys). +You can also achieve this more broadly for all JSON messages (see advanced configuration for [log4j](#log-messages-as-json_1) & [logback](#log-messages-as-json_2)). - Use `LambdaEcsLayout.json` as `eventTemplateUri` when configuring `JsonTemplateLayout`. +## Additional structured keys -=== "log4j2.xml" +### Logging Lambda context information +The following keys will also be added to all your structured logs (unless [configured otherwise](#more-customization_1)): - ```xml hl_lines="5" - - - - - - - - - - - - - - - - - ``` +| Key | Type | Example | Description | +|--------------------------|---------|----------------------------------------------------------------------------------------|------------------------------------| +| **cold_start** | Boolean | false | ColdStart value | +| **function_name** | String | "example-PaymentFunction-1P1Z6B39FLU73" | Name of the function | +| **function_version** | String | "12" | Version of the function | +| **function_memory_size** | String | "512" | Memory configure for the function | +| **function_arn** | String | "arn:aws:lambda:eu-west-1:012345678910:function:example-PaymentFunction-1P1Z6B39FLU73" | ARN of the function | +| **function_request_id** | String | "899856cb-83d1-40d7-8611-9e78f15f32f4"" | AWS Request ID from lambda context | -## Setting a Correlation ID +### Logging additional keys -You can set a Correlation ID using `correlationIdPath` attribute by passing a [JSON Pointer expression](https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-json-pointer-03){target="_blank"}. +#### Logging a correlation ID -=== "App.java" +You can set a correlation ID using the `correlationIdPath` attribute of the `@Logging`annotation, +by passing a [JMESPath expression](https://jmespath.org/tutorial.html){target="_blank"}, +including our custom [JMESPath Functions](../utilities/serialization.md#built-in-functions). - ```java hl_lines="8" - /** - * Handler for requests to Lambda function. - */ - public class App implements RequestHandler { +=== "AppCorrelationIdPath.java" + + ```java hl_lines="5" + public class AppCorrelationIdPath implements RequestHandler { - Logger log = LogManager.getLogger(App.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AppCorrelationIdPath.class); - @Logging(correlationIdPath = "/headers/my_request_id_header") + @Logging(correlationIdPath = "headers.my_request_id_header") public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - ... - log.info("Collecting payment") - ... + // ... + LOGGER.info("Collecting payment") + // ... } } ``` -=== "Example Event" +=== "Example HTTP Event" ```json hl_lines="3" { @@ -333,42 +452,89 @@ You can set a Correlation ID using `correlationIdPath` attribute by passing a [J } ``` -=== "Example CloudWatch Logs excerpt" +=== "CloudWatch Logs" - ```json hl_lines="11" + ```json hl_lines="6" { "level": "INFO", "message": "Collecting payment", - "timestamp": "2021-05-03 11:47:12,494+0200", + "timestamp": "2023-12-01T14:49:19.293Z", "service": "payment", - "coldStart": true, - "functionName": "test", - "functionMemorySize": 128, - "functionArn": "arn:aws:lambda:eu-west-1:12345678910:function:test", - "function_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", "correlation_id": "correlation_id_value" } ``` -We provide [built-in JSON Pointer expression](https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-json-pointer-03){target="_blank"} -for known event sources, where either a request ID or X-Ray Trace ID are present. -=== "App.java" +**setCorrelationId method** - ```java hl_lines="10" - import software.amazon.lambda.powertools.logging.CorrelationIdPathConstants; +You can also use `LoggingUtils.setCorrelationId()` method to inject it anywhere else in your code. - /** - * Handler for requests to Lambda function. - */ - public class App implements RequestHandler { +=== "AppSetCorrelationId.java" + + ```java hl_lines="8" + public class AppSetCorrelationId implements RequestHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppSetCorrelationId.class); + + @Logging + public String handleRequest(final ScheduledEvent event, final Context context) { + // ... + LoggingUtils.setCorrelationId(event.getId()); + LOGGER.info("Scheduled Event") + // ... + } + } + ``` + +=== "Example Schedule Event" + + ```json hl_lines="2" + { + "id": "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c", + "detail-type": "Scheduled Event", + "source": "aws.events", + "account": "123456789012", + "time": "2023-12-01T14:49:19Z", + "region": "us-east-1", + "resources": [ + "arn:aws:events:us-east-1:123456789012:rule/ExampleRule" + ], + "detail": {} + } + ``` + +=== "CloudWatch Logs with correlation id" + + ```json hl_lines="6" + { + "level": "INFO", + "message": "Scheduled Event", + "timestamp": "2023-12-01T14:49:19.293Z", + "service": "payment", + "correlation_id": "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c" + } + ``` +???+ tip + You can retrieve correlation IDs via `LoggingUtils.getCorrelationId()` method if needed. + +**Known correlation IDs** + +To ease routine tasks like extracting correlation ID from popular event sources, +we provide [built-in JMESPath expressions](#built-in-correlation-id-expressions). + +=== "AppCorrelationId.java" + + ```java hl_lines="1 7" + import software.amazon.lambda.powertools.logging.CorrelationIdPaths; + + public class AppCorrelationId implements RequestHandler { - Logger log = LogManager.getLogger(App.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AppCorrelationId.class); - @Logging(correlationIdPath = CorrelationIdPathConstants.API_GATEWAY_REST) + @Logging(correlationIdPath = CorrelationIdPaths.API_GATEWAY_REST) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - ... - log.info("Collecting payment") - ... + // ... + LOGGER.info("Collecting payment") + // ... } } ``` @@ -377,316 +543,581 @@ for known event sources, where either a request ID or X-Ray Trace ID are present ```json hl_lines="3" { - "requestContext": { - "requestId": "correlation_id_value" - } + "requestContext": { + "requestId": "correlation_id_value" + } } ``` -=== "Example CloudWatch Logs excerpt" +=== "Example CloudWatch Logs" - ```json hl_lines="11" + ```json hl_lines="6" { "level": "INFO", "message": "Collecting payment", - "timestamp": "2021-05-03 11:47:12,494+0200", + "timestamp": "2023-12-01T14:49:19.293Z", "service": "payment", - "coldStart": true, - "functionName": "test", - "functionMemorySize": 128, - "functionArn": "arn:aws:lambda:eu-west-1:12345678910:function:test", - "function_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", "correlation_id": "correlation_id_value" } ``` - -## Appending additional keys -!!! info "Custom keys are persisted across warm invocations" - Always set additional keys as part of your handler to ensure they have the latest value, or explicitly clear them with [`clearState=true`](#clearing-all-state). +#### Custom keys -You can append your own keys to your existing logs via `appendKey`. +???+ warning "Custom keys are persisted across warm invocations" + Always set additional keys as part of your handler method to ensure they have the latest value, or explicitly clear them with [`clearState=true`](#clearing-state). -=== "App.java" +To append an additional key in your logs, you can use the `LoggingUtils.appendKey()` or `LoggingUtils.appendKeys()` for multiple keys: - ```java hl_lines="11 19" - /** - * Handler for requests to Lambda function. - */ - public class App implements RequestHandler { +=== "PaymentFunction.java" + + ```java hl_lines="8 9 15 16" + public class PaymentFunction implements RequestHandler { - Logger log = LogManager.getLogger(App.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AppLogResponse.class); - @Logging(logEvent = true) + @Logging public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - ... - LoggingUtils.appendKey("test", "willBeLogged"); - ... - - ... - Map customKeys = new HashMap<>(); - customKeys.put("test", "value"); - customKeys.put("test1", "value1"); + // ... + LoggingUtils.appendKey("orderId", order.getId()); + LOGGER.info("Collecting payment"); - LoggingUtils.appendKeys(customKeys); - ... + // ... + Map customKeys = new HashMap<>(); + customKeys.put("paymentId", payment.getId()); + customKeys.put("amount", payment.getAmount); + LoggingUtils.appendKeys(customKeys); + LOGGER.info("Payment successful"); } } ``` +=== "Example CloudWatch Logs" + + ```json hl_lines="7 16-18" + { + "level": "INFO", + "message": "Collecting payment", + "service": "payment", + "timestamp": "2023-12-01T14:49:19.293Z", + "xray_trace_id": "1-6569f266-4b0c7f97280dcd8428d3c9b5", + "orderId": "41376" + } + ... + { + "level": "INFO", + "message": "Payment successful", + "service": "payment", + "timestamp": "2023-12-01T14:49:20.118Z", + "xray_trace_id": "1-6569f266-4b0c7f97280dcd8428d3c9b5", + "orderId": "41376", + "paymentId": "3245", + "amount": 345.99 + } + ``` + +???+ tip "Additional keys are based on the MDC" + Mapped Diagnostic Context (MDC) is essentially a Key-Value store. It is supported by the [SLF4J API](https://www.slf4j.org/manual.html#mdc){target="_blank"}, + [logback](https://logback.qos.ch/manual/mdc.html){target="_blank"} and log4j (known as [ThreadContext](https://logging.apache.org/log4j/2.x/manual/thread-context.html){target="_blank"}). + + `LoggingUtils.appendKey("key", "value")` is equivalent to `MDC.put("key", "value")`. + ### Removing additional keys -You can remove any additional key from entry using `LoggingUtils.removeKeys()`. +You can remove any additional key from entry using `LoggingUtils.removeKey()` or `LoggingUtils.removeKeys()` for multiple keys: -=== "App.java" +=== "PaymentFunction.java" ```java hl_lines="19 20" - /** - * Handler for requests to Lambda function. - */ - public class App implements RequestHandler { + public class PaymentFunction implements RequestHandler { - Logger log = LogManager.getLogger(App.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AppLogResponse.class); - @Logging(logEvent = true) + @Logging(logResponse = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - ... - LoggingUtils.appendKey("test", "willBeLogged"); - ... - Map customKeys = new HashMap<>(); - customKeys.put("test1", "value"); - customKeys.put("test2", "value1"); + // ... + LoggingUtils.appendKey("orderId", order.getId()); + LOGGER.info("Collecting payment"); + // ... + Map customKeys = new HashMap<>(); + customKeys.put("paymentId", payment.getId()); + customKeys.put("amount", payment.getAmount); LoggingUtils.appendKeys(customKeys); - ... - LoggingUtils.removeKey("test"); - LoggingUtils.removeKeys("test1", "test2"); - ... + LOGGER.info("Payment successful"); + + // ... + LoggingUtils.removeKey("orderId"); + LoggingUtils.removeKeys("paymentId", "amount"); + + return response; } } ``` -### Clearing all state +=== "Example CloudWatch Logs" + Response is logged (`logResponse=true`) without the additional keys: + + ```json + ... + { + "level": "INFO", + "message": { + "statusCode": 200, + "isBase64Encoded": false, + "body": ..., + "headers": ..., + "multiValueHeaders": ... + }, + "service": "payment", + "timestamp": "2023-12-01T14:49:20.118Z", + "xray_trace_id": "1-6569f266-4b0c7f97280dcd8428d3c9b5" + } + ``` + +???+ tip "Additional keys are based on the MDC" + `LoggingUtils.removeKey("key")` is equivalent to `MDC.remove("key")`. -Logger is commonly initialized in the global scope. Due to [Lambda Execution Context reuse](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html), -this means that custom keys can be persisted across invocations. If you want all custom keys to be deleted, you can use -`clearState=true` attribute on `@Logging` annotation. +#### Clearing state +Logger is commonly initialized in the global scope. Due to [Lambda Execution Context reuse](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html){target="_blank"}, +this means that custom keys can be persisted across invocations. If you want all custom keys to be deleted, you can use +`clearState=true` attribute on the `@Logging` annotation. -=== "App.java" +=== "CreditCardFunction.java" - ```java hl_lines="8 12" - /** - * Handler for requests to Lambda function. - */ - public class App implements RequestHandler { + ```java hl_lines="5 8" + public class CreditCardFunction implements RequestHandler { - Logger log = LogManager.getLogger(App.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CreditCardFunction.class); @Logging(clearState = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - ... - if(input.getHeaders().get("someSpecialHeader")) { - LoggingUtils.appendKey("specialKey", "value"); - } - - log.info("Collecting payment"); - ... + // ... + LoggingUtils.appendKey("cardNumber", card.getId()); + LOGGER.info("Updating card information"); + // ... } } ``` + === "#1 Request" - ```json hl_lines="11" - { - "level": "INFO", - "message": "Collecting payment", - "timestamp": "2021-05-03 11:47:12,494+0200", - "service": "payment", - "coldStart": true, - "functionName": "test", - "functionMemorySize": 128, - "functionArn": "arn:aws:lambda:eu-west-1:12345678910:function:test", - "function_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72", - "specialKey": "value" - } + ```json hl_lines="7" + { + "level": "INFO", + "message": "Updating card information", + "service": "card", + "timestamp": "2023-12-01T14:49:19.293Z", + "xray_trace_id": "1-6569f266-4b0c7f97280dcd8428d3c9b5", + "cardNumber": "6818 8419 9395 5322" + } ``` === "#2 Request" - ```json - { - "level": "INFO", - "message": "Collecting payment", - "timestamp": "2021-05-03 11:47:12,494+0200", - "service": "payment", - "coldStart": true, - "functionName": "test", - "functionMemorySize": 128, - "functionArn": "arn:aws:lambda:eu-west-1:12345678910:function:test", - "function_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72" - } + ```json hl_lines="7" + { + "level": "INFO", + "message": "Updating card information", + "service": "card", + "timestamp": "2023-12-01T14:49:20.213Z", + "xray_trace_id": "2-7a518f43-5e9d2b1f6cfd5e8b3a4e1f9c", + "cardNumber": "7201 6897 6685 3285" + } ``` -## Override default object mapper +???+ tip "Additional keys are based on the MDC" + `clearState` is based on `MDC.clear()`. State clearing is automatically done at the end of the execution of the handler if set to `true`. -You can optionally choose to override default object mapper which is used to serialize lambda function events. You might -want to supply custom object mapper in order to control how serialisation is done, for example, when you want to log only -specific fields from received event due to security. -=== "App.java" +## Logging incoming event - ```java hl_lines="9 10" - /** - * Handler for requests to Lambda function. - */ - public class App implements RequestHandler { +When debugging in non-production environments, you can instruct the `@Logging` annotation to log the incoming event with `logEvent` param or via `POWERTOOLS_LOGGER_LOG_EVENT` env var. + +???+ warning + This is disabled by default to prevent sensitive info being logged + +=== "AppLogEvent.java" + + ```java hl_lines="5" + public class AppLogEvent implements RequestHandler { - Logger log = LogManager.getLogger(App.class); + private static final Logger LOGGER = LoggerFactory.getLogger(AppLogEvent.class); + + @Logging(logEvent = true) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + // ... + } + } + ``` - static { - ObjectMapper objectMapper = new ObjectMapper(); - LoggingUtils.defaultObjectMapper(objectMapper); +???+ note + If you use this on a RequestStreamHandler, Powertools must duplicate input streams in order to log them. + +## Logging handler response + +When debugging in non-production environments, you can instruct the `@Logging` annotation to log the response with `logResponse` param or via `POWERTOOLS_LOGGER_LOG_RESPONSE` env var. + +???+ warning + This is disabled by default to prevent sensitive info being logged + +=== "AppLogResponse.java" + + ```java hl_lines="5" + public class AppLogResponse implements RequestHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppLogResponse.class); + + @Logging(logResponse = true) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + // ... } + } + ``` + +???+ note + If you use this on a RequestStreamHandler, Powertools must duplicate output streams in order to log them. + +## Logging handler uncaught exception +By default, AWS Lambda logs any uncaught exception that might happen in the handler. However, this log is not structured +and does not contain any additional context. You can instruct the `@Logging` annotation to log this kind of exception +with `logError` param or via `POWERTOOLS_LOGGER_LOG_ERROR` env var. + +???+ warning + This is disabled by default to prevent double logging + +=== "AppLogResponse.java" + + ```java hl_lines="5" + public class AppLogError implements RequestHandler { - @Logging(logEvent = true) + private static final Logger LOGGER = LoggerFactory.getLogger(AppLogError.class); + + @Logging(logError = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - ... + // ... } } ``` +# Advanced + ## Sampling debug logs -You can dynamically set a percentage of your logs to **DEBUG** level via env var `POWERTOOLS_LOGGER_SAMPLE_RATE` or -via `samplingRate` attribute on annotation. +You can dynamically set a percentage of your logs to`DEBUG` level to be included in the logger output, regardless of configured log leve, using the`POWERTOOLS_LOGGER_SAMPLE_RATE` environment variable or +via `samplingRate` attribute on the `@Logging` annotation. !!! info Configuration on environment variable is given precedence over sampling rate configuration on annotation, provided it's in valid value range. === "Sampling via annotation attribute" - ```java hl_lines="8" - /** - * Handler for requests to Lambda function. - */ + ```java hl_lines="5" public class App implements RequestHandler { - Logger log = LogManager.getLogger(App.class); + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); @Logging(samplingRate = 0.5) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - ... + // will eventually be logged based on the sampling rate + LOGGER.debug("Handle payment"); } } ``` === "Sampling via environment variable" - ```yaml hl_lines="9" + ```yaml hl_lines="8" Resources: - HelloWorldFunction: - Type: AWS::Serverless::Function - Properties: - ... - Runtime: java8 - Environment: - Variables: - POWERTOOLS_LOGGER_SAMPLE_RATE: 0.5 + PaymentFunction: + Type: AWS::Serverless::Function + Properties: + ... + Environment: + Variables: + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.5 + ``` -## AWS Lambda Advanced Logging Controls (ALC) +## Built-in Correlation ID expressions -!!!question "When is it useful?" - When you want to set a logging policy to drop informational or verbose logs for one or all AWS Lambda functions, regardless of runtime and logger used. +You can use any of the following built-in JMESPath expressions as part of `@Logging(correlationIdPath = ...)`: - -With [AWS Lambda Advanced Logging Controls (ALC)](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced){target="_blank"}, you can enforce a minimum log level that Lambda will accept from your application code. +???+ note "Note: Any object key named with `-` must be escaped" + For example, **`request.headers."x-amzn-trace-id"`**. -When enabled, you should keep `Logger` and ALC log level in sync to avoid data loss. +| Name | Expression | Description | +|-------------------------------|-------------------------------------|---------------------------------| +| **API_GATEWAY_REST** | `"requestContext.requestId"` | API Gateway REST API request ID | +| **API_GATEWAY_HTTP** | `"requestContext.requestId"` | API Gateway HTTP API request ID | +| **APPSYNC_RESOLVER** | `request.headers."x-amzn-trace-id"` | AppSync X-Ray Trace ID | +| **APPLICATION_LOAD_BALANCER** | `headers."x-amzn-trace-id"` | ALB X-Ray Trace ID | +| **EVENT_BRIDGE** | `"id"` | EventBridge Event ID | -Here's a sequence diagram to demonstrate how ALC will drop both `INFO` and `DEBUG` logs emitted from `Logger`, when ALC log level is stricter than `Logger`. - -```mermaid -sequenceDiagram - participant Lambda service - participant Lambda function - participant Application Logger +## Customising fields in logs - Note over Lambda service: AWS_LAMBDA_LOG_LEVEL="WARN" - Note over Application Logger: POWERTOOLS_LOG_LEVEL="DEBUG" +Powertools for AWS Lambda comes with default json structure ([standard fields](#standard-structured-keys) & [lambda context fields](#logging-lambda-context-information)). - Lambda service->>Lambda function: Invoke (event) - Lambda function->>Lambda function: Calls handler - Lambda function->>Application Logger: logger.error("Something happened") - Lambda function-->>Application Logger: logger.debug("Something happened") - Lambda function-->>Application Logger: logger.info("Something happened") - Lambda service--xLambda service: DROP INFO and DEBUG logs - Lambda service->>CloudWatch Logs: Ingest error logs +You can go further and customize which fields you want to keep in your logs or not. The configuration varies according to the underlying logging library. + +### Log4j2 configuration +Log4j2 configuration is done in _log4j2.xml_ and leverages `JsonTemplateLayout`: + +```xml + + + ``` -### Priority of log level settings in Powertools for AWS Lambda +The `JsonTemplateLayout` is automatically configured with the provided template: -We prioritise log level settings in this order: +??? example "LambdaJsonLayout.json" + ```json + { + "level": { + "$resolver": "level", + "field": "name" + }, + "message": { + "$resolver": "powertools", + "field": "message" + }, + "error": { + "message": { + "$resolver": "exception", + "field": "message" + }, + "name": { + "$resolver": "exception", + "field": "className" + }, + "stack": { + "$resolver": "exception", + "field": "stackTrace", + "stackTrace": { + "stringified": true + } + } + }, + "cold_start": { + "$resolver": "powertools", + "field": "cold_start" + }, + "function_arn": { + "$resolver": "powertools", + "field": "function_arn" + }, + "function_memory_size": { + "$resolver": "powertools", + "field": "function_memory_size" + }, + "function_name": { + "$resolver": "powertools", + "field": "function_name" + }, + "function_request_id": { + "$resolver": "powertools", + "field": "function_request_id" + }, + "function_version": { + "$resolver": "powertools", + "field": "function_version" + }, + "sampling_rate": { + "$resolver": "powertools", + "field": "sampling_rate" + }, + "service": { + "$resolver": "powertools", + "field": "service" + }, + "timestamp": { + "$resolver": "timestamp", + "pattern": { + "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" + } + }, + "xray_trace_id": { + "$resolver": "powertools", + "field": "xray_trace_id" + }, + "": { + "$resolver": "powertools" + } + } + ``` -1. `AWS_LAMBDA_LOG_LEVEL` environment variable -2. `POWERTOOLS_LOG_LEVEL` environment variable +You can create your own template and leverage the [PowertoolsResolver](https://github.com/aws-powertools/powertools-lambda-java/tree/v2/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java){target="_blank"} +and any other resolver to log the desired fields with the desired format. Some examples of customization are given below: -If you set `Logger` level lower than ALC, we will emit a warning informing you that your messages will be discarded by Lambda. +#### Log messages as JSON +`message` field is not handled with the standard [`MessageResolver`](https://logging.apache.org/log4j/2.x/manual/json-template-layout.html#event-template-resolver-message){target="_blank"} but by the `PowertoolsResolver`. +With this resolver, you can choose to log all the JSON messages as JSON and not as String. -> **NOTE** -> -> With ALC enabled, we are unable to increase the minimum log level below the `AWS_LAMBDA_LOG_LEVEL` environment variable value, see [AWS Lambda service documentation](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-log-level){target="_blank"} for more details. +=== "my-custom-template.json" -### Timestamp format + ```json + { + "message": { + "$resolver": "powertools", + "field": "message", + "asJson": true + } + } + ``` -When the Advanced Logging Controls feature is enabled, Powertools for AWS Lambda must comply with the timestamp format required by AWS Lambda, which is [RFC3339](https://www.rfc-editor.org/rfc/rfc3339). -In this case the format will be `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'`. +#### Customising date format -## Upgrade to JsonTemplateLayout from deprecated LambdaJsonLayout configuration in log4j2.xml +Utility by default emits `timestamp` field in the logs in format `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` and in system default timezone. +If you need to customize format and timezone, you can update your template.json or by configuring `log4j2.component.properties` as shown in examples below: -Prior to version [1.10.0](https://github.com/aws-powertools/powertools-lambda-java/releases/tag/v1.10.0), only supported way of configuring `log4j2.xml` was via ``. This plugin is -deprecated now and will be removed in future version. Switching to `JsonTemplateLayout` is straight forward. +=== "my-custom-template.json" -Below examples shows deprecated and new configuration of `log4j2.xml`. + ```json + { + "timestamp": { + "$resolver": "timestamp", + "pattern": { + "format": "yyyy-MM-dd HH:mm:ss", + "timeZone": "Europe/Paris", + } + }, + } + ``` -=== "Deprecated configuration of log4j2.xml" +=== "log4j2.component.properties" - ```xml hl_lines="5" - - - - - - - - - - - - - - - - + ```properties hl_lines="1 2" + log4j.layout.jsonTemplate.timestampFormatPattern=yyyy-MM-dd'T'HH:mm:ss.SSSZz + log4j.layout.jsonTemplate.timeZone=Europe/Oslo + ``` + +See [`TimestampResolver` documentation](https://logging.apache.org/log4j/2.x/manual/json-template-layout.html#event-template-resolver-timestamp){target="_blank"} for more details. + +???+ warning "Lambda Advanced Logging Controls date format" + When using the Lambda ALC, you must have a date format compatible with the [RFC3339](https://www.rfc-editor.org/rfc/rfc3339) + +#### More customization +You can also customize how [exceptions are logged](https://logging.apache.org/log4j/2.x/manual/json-template-layout.html#event-template-resolver-exception){target="_blank"}, and much more. +See the [JSON Layout template documentation](https://logging.apache.org/log4j/2.x/manual/json-template-layout.html){target="_blank"} for more details. + +### Logback configuration +Logback configuration is done in _logback.xml_ and the Powertools [`LambdaJsonEncoder`](): + +```xml + + + + +``` + +The `LambdaJsonEncoder` can be customized in different ways: + +#### Log messages as JSON + +With the following configuration, you choose to log all the JSON messages as JSON and not as String (default is `false`): + +```xml + + true + +``` + +#### Customising date format +Utility by default emits `timestamp` field in the logs in format `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` and in system default timezone. +If you need to customize format and timezone, you can change use the following: + +```xml + + yyyy-MM-dd HH:mm:ss + Europe/Paris + +``` + +#### More customization + +- You can use a standard `ThrowableHandlingConverter` to customize the exception format (default is no converter). Example: + +```xml + + + 30 + 2048 + 20 + sun\.reflect\..*\.invoke.* + net\.sf\.cglib\.proxy\.MethodProxy\.invoke + + true + true + + +``` + +- You can choose to add information about threads (default is `false`): + +```xml + + true + +``` + +- You can even choose to remove Powertools information from the logs like function name, arn: + +```xml + + false + +``` + +## Override default object mapper + +You can optionally choose to override default object mapper which is used to serialize lambda function events. You might +want to supply custom object mapper in order to control how serialisation is done, for example, when you want to log only +specific fields from received event due to security. + +=== "App.java" + + ```java hl_lines="6-10" + public class App implements RequestHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + static { + ObjectMapper objectMapper = new ObjectMapper() + .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + LoggingUtils.setObjectMapper(objectMapper); + } + + @Logging(logEvent = true) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + // ... + } + } ``` -=== "New configuration of log4j2.xml" +## Elastic Common Schema (ECS) Support + +Utility also supports [Elastic Common Schema(ECS)](https://www.elastic.co/guide/en/ecs/current/ecs-reference.html){target="_blank"} format. +The field emitted in logs will follow specs from [ECS](https://www.elastic.co/guide/en/ecs/current/ecs-reference.html){target="_blank"} together with field captured by utility as mentioned [above](#standard-structured-keys). + +### Log4j2 configuration + +Use `LambdaEcsLayout.json` as `eventTemplateUri` when configuring `JsonTemplateLayout`. + +=== "log4j2.xml" ```xml hl_lines="5" - + - - - @@ -694,3 +1125,20 @@ Below examples shows deprecated and new configuration of `log4j2.xml`. ``` +### Logback configuration + +Use the `LambdaEcsEncoder` rather than the `LambdaJsonEncoder` when configuring the appender: + +=== "logback.xml" + + ```xml hl_lines="3" + + + + + + + + + + ``` \ No newline at end of file diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index d135d7210..dc08ef51e 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -1,5 +1,5 @@ .md-grid { - max-width: 81vw + max-width: 90vw } .highlight .hll { diff --git a/examples/pom.xml b/examples/pom.xml index 3526be2a4..943cad950 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -23,7 +23,7 @@ 2.0.0-SNAPSHOT pom - Powertools for AWS Lambda (Java) library Examples + Powertools for AWS Lambda (Java) - Examples A suite of examples accompanying for Powertools for AWS Lambda (Java). diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 36660bc96..a1b4c0bbc 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -8,13 +8,12 @@ 2.0.0-SNAPSHOT powertools-examples-batch jar - Powertools for AWS Lambda (Java) library Examples - Batch + Powertools for AWS Lambda (Java) - Examples - Batch - 2.20.0 11 11 - 1.9.20 + 1.9.20.1 2.21.1 @@ -26,7 +25,7 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j ${project.version} diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandler.java index 988c49e86..e3c27c093 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandler.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandler.java @@ -4,14 +4,14 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder; import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; public class DynamoDBStreamBatchHandler implements RequestHandler { - private final static Logger LOGGER = LogManager.getLogger(DynamoDBStreamBatchHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDBStreamBatchHandler.class); private final BatchMessageHandler handler; public DynamoDBStreamBatchHandler() { diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBWriter.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBWriter.java index 953ba8f23..fc1b0747b 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBWriter.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBWriter.java @@ -8,8 +8,8 @@ import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.IntStream; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.demo.batch.model.DdbProduct; import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient; import software.amazon.awssdk.enhanced.dynamodb.TableSchema; @@ -21,7 +21,7 @@ public class DynamoDBWriter implements RequestHandler { - private static final Logger LOGGER = LogManager.getLogger(DynamoDBWriter.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDBWriter.class); private final DynamoDbEnhancedClient enhancedClient; diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java index b188df501..f5d7102b5 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java @@ -4,15 +4,15 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.KinesisEvent; import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.demo.batch.model.Product; import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder; import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; public class KinesisBatchHandler implements RequestHandler { - private final static Logger LOGGER = LogManager.getLogger(KinesisBatchHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(KinesisBatchHandler.class); private final BatchMessageHandler handler; public KinesisBatchHandler() { diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchSender.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchSender.java index 0bc7dc42c..dadead1a2 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchSender.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchSender.java @@ -10,8 +10,8 @@ import java.security.SecureRandom; import java.util.List; import java.util.stream.IntStream; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.demo.batch.model.Product; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; @@ -28,7 +28,7 @@ */ public class KinesisBatchSender implements RequestHandler { - private static final Logger LOGGER = LogManager.getLogger(KinesisBatchSender.class); + private static final Logger LOGGER = LoggerFactory.getLogger(KinesisBatchSender.class); private final KinesisClient kinesisClient; private final SecureRandom random; diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandler.java index bb9d704d3..27689485c 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandler.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandler.java @@ -4,14 +4,14 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.demo.batch.model.Product; import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder; import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; public class SqsBatchHandler implements RequestHandler { - private final static Logger LOGGER = LogManager.getLogger(SqsBatchHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SqsBatchHandler.class); private final BatchMessageHandler handler; public SqsBatchHandler() { diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchSender.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchSender.java index af78bed5a..4050ab98b 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchSender.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchSender.java @@ -10,8 +10,8 @@ import java.security.SecureRandom; import java.util.List; import java.util.stream.IntStream; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.demo.batch.model.Product; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.services.sqs.SqsClient; @@ -27,7 +27,7 @@ */ public class SqsBatchSender implements RequestHandler { - private static final Logger LOGGER = LogManager.getLogger(SqsBatchSender.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SqsBatchSender.class); private final SqsClient sqsClient; private final SecureRandom random; diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 864ea5fe6..bee97e52a 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -7,16 +7,15 @@ powertools-examples-cloudformation jar - Powertools for AWS Lambda (Java) library Examples - CloudFormation + Powertools for AWS Lambda (Java) - Examples - CloudFormation - 2.20.0 11 11 1.2.3 3.11.3 2.21.0 - 1.9.20 + 1.9.20.1 @@ -49,19 +48,9 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j ${project.version} - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - org.aspectj aspectjrt @@ -91,14 +80,6 @@ - - org.apache.logging.log4j - log4j-jcl - ${log4j.version} - - - - diff --git a/examples/powertools-examples-cloudformation/src/main/java/helloworld/App.java b/examples/powertools-examples-cloudformation/src/main/java/helloworld/App.java index 54f13244c..c35ad8fb9 100644 --- a/examples/powertools-examples-cloudformation/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-cloudformation/src/main/java/helloworld/App.java @@ -3,8 +3,8 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; import java.util.Objects; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.core.exception.SdkClientException; import software.amazon.awssdk.core.waiters.WaiterResponse; @@ -24,7 +24,7 @@ */ public class App extends AbstractCustomResourceHandler { - private final static Logger log = LogManager.getLogger(App.class); + private static final Logger log = LoggerFactory.getLogger(App.class); private final S3Client s3Client; public App() { @@ -47,7 +47,7 @@ protected Response create(CloudFormationCustomResourceEvent cloudFormationCustom Objects.requireNonNull(cloudFormationCustomResourceEvent.getResourceProperties().get("BucketName"), "BucketName cannot be null."); - log.info(cloudFormationCustomResourceEvent); + log.info(cloudFormationCustomResourceEvent.toString()); String bucketName = (String) cloudFormationCustomResourceEvent.getResourceProperties().get("BucketName"); log.info("Bucket Name {}", bucketName); try { @@ -57,7 +57,7 @@ protected Response create(CloudFormationCustomResourceEvent cloudFormationCustom return Response.success(bucketName); } catch (AwsServiceException | SdkClientException e) { // In case of error, return a failed response, with the bucketName as the physicalResourceId - log.error(e); + log.error("Unable to create bucket", e); return Response.failed(bucketName); } } @@ -77,7 +77,7 @@ protected Response update(CloudFormationCustomResourceEvent cloudFormationCustom Objects.requireNonNull(cloudFormationCustomResourceEvent.getResourceProperties().get("BucketName"), "BucketName cannot be null."); - log.info(cloudFormationCustomResourceEvent); + log.info(cloudFormationCustomResourceEvent.toString()); // Get the physicalResourceId. physicalResourceId is the value returned to CloudFormation in the Create request, and passed in on subsequent requests (e.g. UPDATE or DELETE) String physicalResourceId = cloudFormationCustomResourceEvent.getPhysicalResourceId(); log.info("Physical Resource ID {}", physicalResourceId); @@ -94,7 +94,7 @@ protected Response update(CloudFormationCustomResourceEvent cloudFormationCustom // Return a successful response with the newBucketName return Response.success(newBucketName); } catch (AwsServiceException | SdkClientException e) { - log.error(e); + log.error("Unable to create bucket", e); return Response.failed(newBucketName); } } else { @@ -120,7 +120,7 @@ protected Response delete(CloudFormationCustomResourceEvent cloudFormationCustom Objects.requireNonNull(cloudFormationCustomResourceEvent.getPhysicalResourceId(), "PhysicalResourceId cannot be null."); - log.info(cloudFormationCustomResourceEvent); + log.info(cloudFormationCustomResourceEvent.toString()); // Get the physicalResourceId. physicalResourceId is the value provided to CloudFormation in the Create request. String bucketName = cloudFormationCustomResourceEvent.getPhysicalResourceId(); log.info("Bucket Name {}", bucketName); @@ -135,7 +135,7 @@ protected Response delete(CloudFormationCustomResourceEvent cloudFormationCustom return Response.success(bucketName); } catch (AwsServiceException | SdkClientException e) { // Return a failed response in case of errors during the bucket deletion - log.error(e); + log.error("Unable to delete bucket", e); return Response.failed(bucketName); } } else { @@ -166,7 +166,7 @@ private void createBucket(String bucketName) { s3Client.createBucket(createBucketRequest); WaiterResponse waiterResponse = waiter.waitUntilBucketExists(HeadBucketRequest.builder().bucket(bucketName).build()); - waiterResponse.matched().response().ifPresent(log::info); + waiterResponse.matched().response().ifPresent(res -> log.info(res.toString())); log.info("Bucket Created {}", bucketName); } } \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 822e87633..f8d340f3b 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) with CDK + Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with CDK software.amazon.lambda.examples @@ -14,7 +14,7 @@ 2.20.0 11 11 - 1.9.20 + 1.9.20.1 diff --git a/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java index 988da2a73..18eea0560 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java @@ -29,8 +29,8 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.cloudwatchlogs.emf.model.DimensionSet; import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; @@ -44,8 +44,7 @@ * Handler for requests to Lambda function. */ public class App implements RequestHandler { - private final static Logger log = LogManager.getLogger(App.class); - + private static final Logger log = LoggerFactory.getLogger(App.class); @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 03971c406..38cf96c1c 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -28,8 +28,9 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' + implementation 'org.aspectj:aspectjrt:1.9.20.1' aspect 'software.amazon.lambda:powertools-tracing:2.0.0-SNAPSHOT' - aspect 'software.amazon.lambda:powertools-logging:2.0.0-SNAPSHOT' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.0.0-SNAPSHOT' aspect 'software.amazon.lambda:powertools-metrics:2.0.0-SNAPSHOT' } diff --git a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java index fccc63b9a..36ef72ae7 100644 --- a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java @@ -29,8 +29,8 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.cloudwatchlogs.emf.model.DimensionSet; import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; @@ -44,7 +44,7 @@ * Handler for requests to Lambda function. */ public class App implements RequestHandler { - private final static Logger log = LogManager.getLogger(App.class); + private static final Logger log = LoggerFactory.getLogger(App.class); @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 1c16db0db..b37ef6d31 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -9,16 +9,16 @@ repositories { } dependencies { - implementation("com.amazonaws:aws-lambda-java-core:1.2.2") - implementation("com.fasterxml.jackson.core:jackson-annotations:2.13.2") - implementation("com.fasterxml.jackson.core:jackson-databind:2.13.2.2") - implementation("com.amazonaws:aws-lambda-java-events:3.11.0") - implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2") + implementation("com.amazonaws:aws-lambda-java-core:1.2.3") + implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.1") + implementation("com.fasterxml.jackson.core:jackson-databind:2.15.3") + implementation("com.amazonaws:aws-lambda-java-events:3.11.3") + implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") + implementation("org.aspectj:aspectjrt:1.9.20.1") aspect("software.amazon.lambda:powertools-tracing:2.0.0-SNAPSHOT") - aspect("software.amazon.lambda:powertools-logging:2.0.0-SNAPSHOT") + aspect("software.amazon.lambda:powertools-logging-log4j:2.0.0-SNAPSHOT") aspect("software.amazon.lambda:powertools-metrics:2.0.0-SNAPSHOT") - testImplementation("junit:junit:4.13.2") - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10") } kotlin { diff --git a/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt b/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt index ed4cf267a..1c925d4f4 100644 --- a/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt +++ b/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt @@ -18,7 +18,8 @@ import com.amazonaws.services.lambda.runtime.RequestHandler import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent import com.amazonaws.xray.entities.Subsegment -import org.apache.logging.log4j.LogManager +import org.slf4j.Logger +import org.slf4j.LoggerFactory import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger import software.amazon.cloudwatchlogs.emf.model.DimensionSet import software.amazon.cloudwatchlogs.emf.model.Unit @@ -92,5 +93,5 @@ class App : RequestHandler 4.0.0 - Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) with SAM + Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM software.amazon.lambda.examples 2.0.0-SNAPSHOT powertools-examples-core-utilities-sam jar - 2.20.0 11 11 - 1.9.20 + 1.9.20.1 @@ -23,7 +22,7 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j ${project.version} @@ -41,16 +40,6 @@ aws-lambda-java-events 3.11.3 - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - org.aspectj aspectjrt diff --git a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java index fccc63b9a..36ef72ae7 100644 --- a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java @@ -29,8 +29,8 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.cloudwatchlogs.emf.model.DimensionSet; import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; @@ -44,7 +44,7 @@ * Handler for requests to Lambda function. */ public class App implements RequestHandler { - private final static Logger log = LogManager.getLogger(App.class); + private static final Logger log = LoggerFactory.getLogger(App.class); @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 7ebfdfc00..32cca9bb4 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -2,17 +2,16 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) with Serverless + Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless software.amazon.lambda.examples 2.0.0-SNAPSHOT powertools-examples-core-utilities-serverless jar - 2.20.0 11 11 - 1.9.20 + 1.9.20.1 @@ -23,7 +22,7 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j ${project.version} @@ -41,16 +40,6 @@ aws-lambda-java-events 3.11.3 - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - org.aspectj aspectjrt diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index f508d9d3d..c6f838619 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -2,17 +2,16 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - Powertools for AWS Lambda (Java) library Examples - Core Utilities (logging, tracing, metrics) with Terraform + Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform software.amazon.lambda.examples 2.0.0-SNAPSHOT powertools-examples-core-utilities-terraform jar - 2.20.0 11 11 - 1.9.20 + 1.9.20.1 @@ -23,7 +22,7 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j ${project.version} @@ -41,16 +40,6 @@ aws-lambda-java-events 3.11.3 - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - org.aspectj aspectjrt diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index b7fd3d832..5a040fec0 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -20,13 +20,12 @@ 2.0.0-SNAPSHOT powertools-examples-idempotency jar - Powertools for AWS Lambda (Java) library Examples - Idempotency + Powertools for AWS Lambda (Java) - Examples - Idempotency - 2.20.0 11 11 - 1.9.20 + 1.9.20.1 @@ -37,7 +36,7 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j ${project.version} @@ -55,16 +54,6 @@ aws-lambda-java-events 3.11.3 - - org.apache.logging.log4j - log4j-core - ${log4j.version} - - - org.apache.logging.log4j - log4j-api - ${log4j.version} - org.aspectj aspectjrt @@ -83,11 +72,6 @@ 5.9.3 test - - com.amazonaws - aws-lambda-java-tests - 1.1.1 - diff --git a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java index 72fa621ad..cf0c0ee31 100644 --- a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java @@ -26,8 +26,8 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.lambda.powertools.idempotency.Idempotency; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; @@ -37,7 +37,7 @@ import software.amazon.lambda.powertools.utilities.JsonConfig; public class App implements RequestHandler { - private final static Logger log = LogManager.getLogger(App.class); + private static final Logger log = LoggerFactory.getLogger(App.class); public App() { this(null); diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 8d7fbd4f4..3630811f3 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -5,18 +5,18 @@ 2.0.0-SNAPSHOT powertools-examples-parameters jar - Powertools for AWS Lambda (Java) library Examples - Parameters + Powertools for AWS Lambda (Java) - Examples - Parameters 11 11 - 1.9.20 + 1.9.20.1 software.amazon.lambda - powertools-logging + powertools-logging-log4j ${project.version} diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java index 9a1d3636b..9c3c422cf 100644 --- a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java +++ b/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java @@ -29,15 +29,15 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.parameters.secrets.SecretsParam; import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider; import software.amazon.lambda.powertools.parameters.ssm.SSMParam; import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; public class ParametersFunction implements RequestHandler { - private final static Logger log = LogManager.getLogger(ParametersFunction.class); + private static final Logger log = LoggerFactory.getLogger(ParametersFunction.class); // Annotation-style injection from secrets manager @SecretsParam(key = "/powertools-java/userpwd") diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 468c7d161..2c8fc951a 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -5,7 +5,7 @@ 2.0.0-SNAPSHOT powertools-examples-serialization jar - Powertools for AWS Lambda (Java) library Examples - Serialization + Powertools for AWS Lambda (Java) - Examples - Serialization 11 @@ -15,7 +15,7 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j ${project.version} diff --git a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java b/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java index e70b37959..3ca75cf4a 100644 --- a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java +++ b/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java @@ -22,18 +22,21 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import java.util.HashMap; import java.util.Map; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class APIGatewayRequestDeserializationFunction implements RequestHandler { - private final static Logger LOGGER = LogManager.getLogger(APIGatewayRequestDeserializationFunction.class); - private static final Map HEADERS = new HashMap() {{ + private static final Logger LOGGER = LoggerFactory.getLogger(APIGatewayRequestDeserializationFunction.class); + private static final Map HEADERS = new HashMap() { + private static final long serialVersionUID = 7074189990115081999L; + { put("Content-Type", "application/json"); put("X-Custom-Header", "application/json"); - }}; + } + }; public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) { diff --git a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java b/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java index 36dbed074..79097e19c 100644 --- a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java +++ b/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java @@ -20,13 +20,13 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import java.util.List; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class SQSEventDeserializationFunction implements RequestHandler { - private final static Logger LOGGER = LogManager.getLogger(SQSEventDeserializationFunction.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SQSEventDeserializationFunction.class); public String handleRequest(SQSEvent event, Context context) { List products = extractDataFrom(event).asListOf(Product.class); diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 2d4ef07a0..ed33568cb 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -19,18 +19,18 @@ 2.0.0-SNAPSHOT powertools-examples-validation jar - Powertools for AWS Lambda (Java) library Examples - Validation + Powertools for AWS Lambda (Java) - Examples - Validation 1.8 1.8 - 1.9.20 + 1.9.20.1 software.amazon.lambda - powertools-logging + powertools-logging-log4j ${project.version} diff --git a/pom.xml b/pom.xml index 1d35a990f..b7227cf8a 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 2.0.0-SNAPSHOT pom - Powertools for AWS Lambda (Java) library Parent + Powertools for AWS Lambda (Java) - Parent A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. @@ -44,6 +44,8 @@ powertools-common powertools-serialization powertools-logging + powertools-logging/powertools-logging-log4j + powertools-logging/powertools-logging-logback powertools-tracing powertools-metrics powertools-parameters @@ -76,7 +78,8 @@ 1.8 1.8 - 2.20.0 + 2.22.0 + 2.0.7 2.15.3 2.21.0 2.14.0 @@ -96,7 +99,8 @@ 3.1.0 5.10.0 1.0.6 - 0.5.1 + 0.6.0 + 1.5.0 @@ -123,6 +127,16 @@ powertools-logging ${project.version} + + software.amazon.lambda + powertools-logging-log4j + ${project.version} + + + software.amazon.lambda + powertools-logging-logback + ${project.version} + software.amazon.lambda powertools-sqs @@ -200,6 +214,11 @@ log4j-core ${log4j.version} + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j.version} + org.apache.logging.log4j log4j-slf4j2-impl @@ -220,6 +239,16 @@ log4j-jcl ${log4j.version} + + co.elastic.logging + logback-ecs-encoder + ${elastic.version} + + + org.slf4j + slf4j-api + ${slf4j.version} + com.amazonaws aws-xray-recorder-sdk-core @@ -519,7 +548,6 @@ - jdk16 @@ -605,6 +633,34 @@ + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.3.0 + + checkstyle.xml + true + true + false + + + + + + com.puppycrawl.tools + checkstyle + 10.12.3 + + + + + + check + + + + diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index d7246b816..eaafdb56e 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -10,7 +10,7 @@ A suite of utilities that makes batch message processing using AWS Lambda easier. - Powertools for AWS Lambda (Java) batch messages + Powertools for AWS Lambda (Java) - Batch messages diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java index aa6eba839..83a8bf7dd 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java @@ -30,7 +30,7 @@ * @see DynamoDB Streams batch failure reporting */ public class DynamoDbBatchMessageHandler implements BatchMessageHandler { - private final static Logger LOGGER = LoggerFactory.getLogger(DynamoDbBatchMessageHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDbBatchMessageHandler.class); private final Consumer successHandler; private final BiConsumer failureHandler; diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java index fe1aaf354..ad1dd302d 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java @@ -34,7 +34,7 @@ * @param The user-defined type of the Kinesis record payload */ public class KinesisStreamsBatchMessageHandler implements BatchMessageHandler { - private final static Logger LOGGER = LoggerFactory.getLogger(KinesisStreamsBatchMessageHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(KinesisStreamsBatchMessageHandler.class); private final BiConsumer rawMessageHandler; private final BiConsumer messageHandler; diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java index b3c416a69..b634f9b62 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java @@ -31,11 +31,11 @@ * @see SQS Batch failure reporting */ public class SqsBatchMessageHandler implements BatchMessageHandler { - private final static Logger LOGGER = LoggerFactory.getLogger(SqsBatchMessageHandler.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SqsBatchMessageHandler.class); // The attribute on an SQS-FIFO message used to record the message group ID // https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#sample-fifo-queues-message-event - private final static String MESSAGE_GROUP_ID_KEY = "MessageGroupId"; + private static final String MESSAGE_GROUP_ID_KEY = "MessageGroupId"; private final Class messageClass; private final BiConsumer messageHandler; diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 0e6763e25..79071d532 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -27,7 +27,7 @@ 2.0.0-SNAPSHOT - Powertools for AWS Lambda (Java) library Cloudformation + Powertools for AWS Lambda (Java) - Cloudformation A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 82e2c1d17..363d2e944 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -27,7 +27,7 @@ 2.0.0-SNAPSHOT - Powertools for AWS Lambda (Java) library Common Internal Utilities + Powertools for AWS Lambda (Java) - Common Internal Utilities Internal utilities shared by the Powertools for AWS Lambda (Java) modules. Do not use directly in your project. https://aws.amazon.com/lambda/ @@ -55,17 +55,17 @@ - com.amazonaws - aws-lambda-java-core + org.slf4j + slf4j-api org.aspectj aspectjrt + provided - org.apache.logging.log4j - log4j-slf4j2-impl - ${log4j.version} + com.amazonaws + aws-lambda-java-core diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java index bdcbdc010..d27ac1aa2 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java @@ -17,12 +17,6 @@ public class LambdaConstants { public static final String LAMBDA_FUNCTION_NAME_ENV = "AWS_LAMBDA_FUNCTION_NAME"; public static final String AWS_REGION_ENV = "AWS_REGION"; - // Also you can use AWS_LAMBDA_INITIALIZATION_TYPE to distinguish between on-demand and SnapStart initialization - // it's not recommended to use this env variable to initialize SDK clients or other resources. - @Deprecated - public static final String AWS_LAMBDA_INITIALIZATION_TYPE = "AWS_LAMBDA_INITIALIZATION_TYPE"; - @Deprecated - public static final String ON_DEMAND = "on-demand"; public static final String X_AMZN_TRACE_ID = "_X_AMZN_TRACE_ID"; public static final String XRAY_TRACE_HEADER = "com.amazonaws.xray.traceHeader"; public static final String AWS_SAM_LOCAL = "AWS_SAM_LOCAL"; diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java index a2830e467..bfacd5204 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java @@ -69,7 +69,6 @@ public static boolean placedOnStreamHandler(final ProceedingJoinPoint pjp) { } public static Context extractContext(final ProceedingJoinPoint pjp) { - if (placedOnRequestHandler(pjp)) { return (Context) pjp.getArgs()[1]; } else if (placedOnStreamHandler(pjp)) { diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java index 585c38c59..8ae10ad62 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java @@ -37,8 +37,8 @@ public class UserAgentConfigurator { public static final String AWS_EXECUTION_ENV = "AWS_EXECUTION_ENV"; private static final Logger LOG = LoggerFactory.getLogger(UserAgentConfigurator.class); private static final String NO_OP = "no-op"; - private static String ptVersion = getProjectVersion(); - private static String userAgentPattern = "PT/" + PT_FEATURE_VARIABLE + "/" + ptVersion + " PTEnv/" + private static final String POWERTOOLS_VERSION = getProjectVersion(); + private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTEnv/" + PT_EXEC_ENV_VARIABLE; private UserAgentConfigurator() { @@ -99,7 +99,7 @@ public static String getUserAgent(String ptFeature) { String awsExecutionEnv = getenv(AWS_EXECUTION_ENV); String ptExecEnv = awsExecutionEnv != null ? awsExecutionEnv : NA; - String userAgent = userAgentPattern.replace(PT_EXEC_ENV_VARIABLE, ptExecEnv); + String userAgent = USER_AGENT_PATTERN.replace(PT_EXEC_ENV_VARIABLE, ptExecEnv); if (ptFeature == null || ptFeature.isEmpty()) { ptFeature = NO_OP; diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index 589aab703..4ad170600 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -31,9 +31,6 @@ import org.aspectj.lang.Signature; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; -import software.amazon.lambda.powertools.common.internal.LambdaConstants; -import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; -import software.amazon.lambda.powertools.common.internal.SystemWrapper; class LambdaHandlerProcessorTest { diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index 8740dcb0b..a36d464ea 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -19,7 +19,7 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j com.amazonaws @@ -29,10 +29,6 @@ com.amazonaws aws-lambda-java-serialization - - org.apache.logging.log4j - log4j-slf4j2-impl - software.amazon.awssdk dynamodb diff --git a/powertools-e2e-tests/handlers/batch/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/batch/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index 64f5a02c2..bfde65bc8 100644 --- a/powertools-e2e-tests/handlers/batch/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/batch/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -14,7 +14,6 @@ package software.amazon.lambda.powertools.e2e; -import com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectMapper; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; @@ -24,41 +23,26 @@ import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer; import com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers; -import com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.JsonNode; - import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.core.util.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder; import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; import software.amazon.lambda.powertools.e2e.model.Product; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.utilities.JsonConfig; - -import javax.management.Attribute; public class Function implements RequestHandler { - private final static Logger LOGGER = LogManager.getLogger(Function.class); + private static final Logger LOGGER = LoggerFactory.getLogger(Function.class); private final BatchMessageHandler sqsHandler; private final BatchMessageHandler kinesisHandler; @@ -139,7 +123,7 @@ public Object createResult(String input, Context context) { SQSEvent event = serializer.fromJson(input); if (event.getRecords().get(0).getEventSource().equals("aws:sqs")) { LOGGER.info("Running for SQS"); - LOGGER.info(event); + LOGGER.info(event.toString()); return sqsHandler.processBatch(event, context); } diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index a0e6bd4fc..da2bbfb80 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -19,11 +19,7 @@ software.amazon.lambda - powertools-logging - - - org.apache.logging.log4j - log4j-slf4j2-impl + powertools-logging-log4j com.amazonaws diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index 277e76fc1..0728404bf 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -23,16 +23,12 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j com.amazonaws aws-lambda-java-events - - org.apache.logging.log4j - log4j-slf4j2-impl - org.aspectj aspectjrt diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index d887341c5..8cb2cb52c 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -23,16 +23,12 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j com.amazonaws aws-lambda-java-events - - org.apache.logging.log4j - log4j-slf4j2-impl - org.aspectj aspectjrt diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml index 222c5ab2e..88feda09b 100644 --- a/powertools-e2e-tests/handlers/logging/pom.xml +++ b/powertools-e2e-tests/handlers/logging/pom.xml @@ -15,7 +15,12 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j + + + org.apache.logging.log4j + log4j-layout-template-json + 2.20.0 org.aspectj @@ -25,10 +30,6 @@ com.amazonaws aws-lambda-java-events - - org.aspectj - aspectjrt - diff --git a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index 62ebabc6e..c2634533d 100644 --- a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -16,18 +16,16 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.logging.LoggingUtils; public class Function implements RequestHandler { - - private static final Logger LOG = LogManager.getLogger(Function.class); + private static final Logger LOG = LoggerFactory.getLogger(Function.class); @Logging public String handleRequest(Input input, Context context) { - LoggingUtils.appendKeys(input.getKeys()); LOG.info(input.getMessage()); diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index 328d30485..2d6a9a06a 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -15,7 +15,7 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j software.amazon.lambda diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 2c73de977..412593da9 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -22,8 +22,7 @@ 1.13.1 3.11.0 2.20.108 - 2.20.0 - 1.9.20 + 1.9.20.1 @@ -33,7 +32,10 @@ logging tracing metrics + batch idempotency + largemessage + largemessage_idempotent parameters validation-alb-event validation-apigw-event @@ -55,7 +57,7 @@ software.amazon.lambda - powertools-logging + powertools-logging-log4j ${lambda.powertools.version} @@ -108,11 +110,6 @@ aws-lambda-java-serialization ${lambda.java.serialization} - - org.apache.logging.log4j - log4j-slf4j2-impl - ${log4j.version} - diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 1f5bd6347..a64e7a354 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -24,7 +24,7 @@ powertools-e2e-tests - Powertools for AWS Lambda (Java)library End-to-end tests + Powertools for AWS Lambda (Java) - End-to-end tests Powertools for AWS Lambda (Java)End-To-End Tests @@ -184,6 +184,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java index b060879d3..f78500c65 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java @@ -83,7 +83,7 @@ public void test_logInfoWithAdditionalKeys() throws JsonProcessingException { JsonNode jsonNode = objectMapper.readTree(functionLogs[0]); assertThat(jsonNode.get("message").asText()).isEqualTo("New Order"); assertThat(jsonNode.get("orderId").asText()).isEqualTo(orderId); - assertThat(jsonNode.get("coldStart").asBoolean()).isTrue(); + assertThat(jsonNode.get("cold_start").asBoolean()).isTrue(); assertThat(jsonNode.get("xray_trace_id").asText()).isNotBlank(); assertThat(jsonNode.get("function_request_id").asText()).isEqualTo(invocationResult1.getRequestId()); @@ -91,6 +91,6 @@ public void test_logInfoWithAdditionalKeys() throws JsonProcessingException { functionLogs = invocationResult2.getLogs().getFunctionLogs(INFO); assertThat(functionLogs).hasSize(1); jsonNode = objectMapper.readTree(functionLogs[0]); - assertThat(jsonNode.get("coldStart").asBoolean()).isFalse(); + assertThat(jsonNode.get("cold_start").asBoolean()).isFalse(); } } diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index f7f44dc99..eda7bd982 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -27,7 +27,7 @@ powertools-idempotency jar - Powertools for AWS Lambda (Java) library Idempotency + Powertools for AWS Lambda (Java) - Idempotency @@ -55,6 +55,11 @@ + + org.aspectj + aspectjrt + provided + software.amazon.lambda powertools-common @@ -86,10 +91,6 @@ url-connection-client ${aws.sdk.version} - - org.aspectj - aspectjrt - diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java index 6da826c45..bd564caf8 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java +++ b/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java @@ -82,7 +82,7 @@ private void setPersistenceStore(BasePersistenceStore persistenceStore) { } private static class Holder { - private final static Idempotency instance = new Idempotency(); + private static final Idempotency instance = new Idempotency(); } public static class Config { diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java index 76c36ae9f..43e191fc2 100644 --- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java +++ b/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java @@ -25,8 +25,8 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.lambda.powertools.idempotency.Idempotency; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; @@ -35,7 +35,7 @@ import software.amazon.lambda.powertools.utilities.JsonConfig; public class IdempotencyFunction implements RequestHandler { - private final static Logger LOG = LogManager.getLogger(IdempotencyFunction.class); + private static final Logger LOG = LoggerFactory.getLogger(IdempotencyFunction.class); public boolean handlerExecuted = false; diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index a56623518..af031ff21 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -29,7 +29,7 @@ powertools-large-messages jar - Powertools for AWS Lambda (Java) library Large messages + Powertools for AWS Lambda (Java) - Large messages GitHub Issues @@ -54,6 +54,11 @@ + + org.aspectj + aspectjrt + provided + software.amazon.lambda powertools-common diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 21a221967..56ca0e62b 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -17,48 +17,26 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - - powertools-logging - jar - powertools-parent software.amazon.lambda 2.0.0-SNAPSHOT - Powertools for AWS Lambda (Java) library Logging - - A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. - - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - + powertools-logging + jar + Powertools for AWS Lambda (Java) - Logging + Set of utility for better logging - common software.amazon.lambda powertools-common + + software.amazon.lambda + powertools-serialization + com.amazonaws aws-lambda-java-core @@ -68,20 +46,13 @@ jackson-databind - org.apache.logging.log4j - log4j-layout-template-json - - - org.apache.logging.log4j - log4j-core + org.slf4j + slf4j-api - org.apache.logging.log4j - log4j-slf4j2-impl - - - org.apache.logging.log4j - log4j-api + org.aspectj + aspectjrt + provided diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml new file mode 100644 index 000000000..df6154560 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -0,0 +1,137 @@ + + + 4.0.0 + + + powertools-parent + software.amazon.lambda + 2.0.0-SNAPSHOT + ../../pom.xml + + + powertools-logging-log4j + jar + Powertools for AWS Lambda (Java) - Logging with Log4j2 + Set of utility for better logging with log4j + + + + software.amazon.lambda + powertools-logging + ${project.version} + + + org.aspectj + aspectjrt + provided + + + org.apache.logging.log4j + log4j-slf4j2-impl + + + org.apache.logging.log4j + log4j-core + + + org.apache.logging.log4j + log4j-layout-template-json + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.apache.commons + commons-lang3 + test + + + org.aspectj + aspectjweaver + test + + + org.assertj + assertj-core + test + + + com.amazonaws + aws-lambda-java-events + test + + + com.amazonaws + aws-lambda-java-tests + test + + + org.skyscreamer + jsonassert + test + + + + + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-logging + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + testLog4j + eu-central-1 + <_X_AMZN_TRACE_ID>Root=1-63441c4a-abcdef012345678912345678 + + + + + + + \ No newline at end of file diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java new file mode 100644 index 000000000..95086a085 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java @@ -0,0 +1,286 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.logging.log4j.layout.template.json.resolver; + +import static java.lang.Boolean.TRUE; +import static software.amazon.lambda.powertools.logging.LoggingUtils.LOG_MESSAGES_AS_JSON; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_NAME; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_REQUEST_ID; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_VERSION; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SAMPLING_RATE; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SERVICE; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.layout.template.json.util.JsonWriter; +import org.apache.logging.log4j.message.Message; +import org.apache.logging.log4j.util.ReadOnlyStringMap; +import software.amazon.lambda.powertools.common.internal.LambdaConstants; +import software.amazon.lambda.powertools.common.internal.SystemWrapper; +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; + +/** + * Custom {@link org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver} + * used by {@link org.apache.logging.log4j.layout.template.json.JsonTemplateLayout} + * to be able to recognize powertools fields in the LambdaJsonLayout.json file. + */ +final class PowertoolsResolver implements EventResolver { + + private static final EventResolver COLD_START_RESOLVER = new EventResolver() { + @Override + public boolean isResolvable(LogEvent logEvent) { + final String coldStart = + logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_COLD_START.getName()); + return null != coldStart; + } + + @Override + public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { + final String coldStart = + logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_COLD_START.getName()); + jsonWriter.writeBoolean(Boolean.parseBoolean(coldStart)); + } + }; + + private static final EventResolver FUNCTION_NAME_RESOLVER = + (final LogEvent logEvent, final JsonWriter jsonWriter) -> { + final String functionName = + logEvent.getContextData().getValue(FUNCTION_NAME.getName()); + jsonWriter.writeString(functionName); + }; + + private static final EventResolver FUNCTION_VERSION_RESOLVER = + (final LogEvent logEvent, final JsonWriter jsonWriter) -> { + final String functionVersion = + logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_VERSION.getName()); + jsonWriter.writeString(functionVersion); + }; + + private static final EventResolver FUNCTION_ARN_RESOLVER = + (final LogEvent logEvent, final JsonWriter jsonWriter) -> { + final String functionArn = + logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_ARN.getName()); + jsonWriter.writeString(functionArn); + }; + + private static final EventResolver FUNCTION_REQ_RESOLVER = + (final LogEvent logEvent, final JsonWriter jsonWriter) -> { + final String functionRequestId = + logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_REQUEST_ID.getName()); + jsonWriter.writeString(functionRequestId); + }; + + private static final EventResolver FUNCTION_MEMORY_RESOLVER = new EventResolver() { + @Override + public boolean isResolvable(LogEvent logEvent) { + final String functionMemory = + logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE.getName()); + return null != functionMemory; + } + + @Override + public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { + final String functionMemory = + logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE.getName()); + jsonWriter.writeNumber(Integer.parseInt(functionMemory)); + } + }; + + private static final EventResolver SAMPLING_RATE_RESOLVER = new EventResolver() { + @Override + public boolean isResolvable(LogEvent logEvent) { + final String samplingRate = + logEvent.getContextData().getValue(PowertoolsLoggedFields.SAMPLING_RATE.getName()); + try { + return (null != samplingRate && Float.parseFloat(samplingRate) > 0.f); + } catch (NumberFormatException nfe) { + return false; + } + } + + @Override + public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { + final String samplingRate = + logEvent.getContextData().getValue(PowertoolsLoggedFields.SAMPLING_RATE.getName()); + jsonWriter.writeNumber(Float.parseFloat(samplingRate)); + } + }; + + private static final EventResolver XRAY_TRACE_RESOLVER = new EventResolver() { + @Override + public boolean isResolvable(LogEvent logEvent) { + final String traceId = + logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_TRACE_ID.getName()); + return null != traceId; + } + + @Override + public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { + final String traceId = + logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_TRACE_ID.getName()); + jsonWriter.writeString(traceId); + } + }; + + private static final EventResolver SERVICE_RESOLVER = + (final LogEvent logEvent, final JsonWriter jsonWriter) -> { + final String service = logEvent.getContextData().getValue(PowertoolsLoggedFields.SERVICE.getName()); + jsonWriter.writeString(service); + }; + + private static final EventResolver REGION_RESOLVER = + (final LogEvent logEvent, final JsonWriter jsonWriter) -> + jsonWriter.writeString(SystemWrapper.getenv(LambdaConstants.AWS_REGION_ENV)); + + public static final String LAMBDA_ARN_REGEX = + "^arn:(aws|aws-us-gov|aws-cn):lambda:[a-zA-Z0-9-]+:\\d{12}:function:[a-zA-Z0-9-_]+(:[a-zA-Z0-9-_]+)?$"; + + private static final EventResolver ACCOUNT_ID_RESOLVER = new EventResolver() { + @Override + public boolean isResolvable(LogEvent logEvent) { + final String arn = logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_ARN.getName()); + return null != arn && !arn.isEmpty() && arn.matches(LAMBDA_ARN_REGEX); + } + + @Override + public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { + final String arn = logEvent.getContextData().getValue(PowertoolsLoggedFields.FUNCTION_ARN.getName()); + jsonWriter.writeString(arn.split(":")[4]); + } + }; + + /** + * Use a custom message resolver to permit to log json string in json format without escaped quotes. + */ + private static final class MessageResolver implements EventResolver { + private final ObjectMapper mapper = new ObjectMapper() + .enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS); + private final boolean logMessagesAsJsonGlobal; + + public MessageResolver(boolean logMessagesAsJson) { + this.logMessagesAsJsonGlobal = logMessagesAsJson; + } + + public boolean isValidJson(String json) { + if (!(json.startsWith("{") || json.startsWith("["))) { + return false; + } + try { + mapper.readTree(json); + } catch (JacksonException e) { + return false; + } + return true; + } + + @Override + public boolean isResolvable(LogEvent logEvent) { + final Message msg = logEvent.getMessage(); + return null != msg && null != msg.getFormattedMessage(); + } + + @Override + public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { + String message = logEvent.getMessage().getFormattedMessage(); + + String logMessagesAsJsonLocal = logEvent.getContextData().getValue(LOG_MESSAGES_AS_JSON); + Boolean logMessagesAsJson = null; + if (logMessagesAsJsonLocal != null) { + logMessagesAsJson = Boolean.parseBoolean(logMessagesAsJsonLocal); + } + + if (((logMessagesAsJsonGlobal && logMessagesAsJson == null) || TRUE.equals(logMessagesAsJson)) + && isValidJson(message)) { + jsonWriter.writeRawString(message); + } else { + jsonWriter.writeString(message); + } + } + } + + private static final EventResolver NON_POWERTOOLS_FIELD_RESOLVER = + (LogEvent logEvent, JsonWriter jsonWriter) -> { + StringBuilder stringBuilder = jsonWriter.getStringBuilder(); + // remove dummy field to kick in powertools resolver + stringBuilder.setLength(stringBuilder.length() - 4); + + // Inject all the context information. + ReadOnlyStringMap contextData = logEvent.getContextData(); + contextData.forEach((key, value) -> { + if (!PowertoolsLoggedFields.stringValues().contains(key) && !LOG_MESSAGES_AS_JSON.equals(key)) { + jsonWriter.writeSeparator(); + jsonWriter.writeString(key); + stringBuilder.append(':'); + jsonWriter.writeValue(value); + } + }); + }; + + private final EventResolver internalResolver; + + private static final Map eventResolverMap = Stream.of(new Object[][] { + { SERVICE.getName(), SERVICE_RESOLVER }, + { FUNCTION_NAME.getName(), FUNCTION_NAME_RESOLVER }, + { FUNCTION_VERSION.getName(), FUNCTION_VERSION_RESOLVER }, + { FUNCTION_ARN.getName(), FUNCTION_ARN_RESOLVER }, + { FUNCTION_MEMORY_SIZE.getName(), FUNCTION_MEMORY_RESOLVER }, + { FUNCTION_REQUEST_ID.getName(), FUNCTION_REQ_RESOLVER }, + { FUNCTION_COLD_START.getName(), COLD_START_RESOLVER }, + { FUNCTION_TRACE_ID.getName(), XRAY_TRACE_RESOLVER }, + { SAMPLING_RATE.getName(), SAMPLING_RATE_RESOLVER }, + { "region", REGION_RESOLVER }, + { "account_id", ACCOUNT_ID_RESOLVER } + }).collect(Collectors.toMap(data -> (String) data[0], data -> (EventResolver) data[1])); + + + PowertoolsResolver(final TemplateResolverConfig config) { + final String fieldName = config.getString("field"); + if (fieldName == null) { + internalResolver = NON_POWERTOOLS_FIELD_RESOLVER; + } else { + boolean logMessagesAsJson = false; + if (config.exists("asJson")) { + logMessagesAsJson = config.getBoolean("asJson"); + } + if ("message".equals(fieldName)) { + internalResolver = new MessageResolver(logMessagesAsJson); + } else { + internalResolver = eventResolverMap.get(fieldName); + } + if (internalResolver == null) { + throw new IllegalArgumentException("unknown field: " + fieldName); + } + } + } + + @Override + public void resolve(LogEvent value, JsonWriter jsonWriter) { + internalResolver.resolve(value, jsonWriter); + } + + @Override + public boolean isResolvable(LogEvent value) { + return value != null && value.getContextData() != null && internalResolver.isResolvable(value); + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsResolverFactory.java b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverFactory.java similarity index 71% rename from powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsResolverFactory.java rename to powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverFactory.java index 7d688f469..297c00691 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsResolverFactory.java +++ b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverFactory.java @@ -12,21 +12,20 @@ * */ -package software.amazon.lambda.powertools.logging.internal; +package org.apache.logging.log4j.layout.template.json.resolver; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.config.plugins.Plugin; import org.apache.logging.log4j.core.config.plugins.PluginFactory; -import org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext; -import org.apache.logging.log4j.layout.template.json.resolver.EventResolverFactory; -import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver; -import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverConfig; -import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverFactory; +/** + * Factory for {@link PowertoolsResolver}. Log4j plugin to process powertools fields in the layout.json + */ @Plugin(name = "PowertoolsResolverFactory", category = TemplateResolverFactory.CATEGORY) public final class PowertoolsResolverFactory implements EventResolverFactory { private static final PowertoolsResolverFactory INSTANCE = new PowertoolsResolverFactory(); + private static final String RESOLVER_NAME = "powertools"; private PowertoolsResolverFactory() { } @@ -38,12 +37,12 @@ public static PowertoolsResolverFactory getInstance() { @Override public String getName() { - return PowertoolsResolver.getName(); + return RESOLVER_NAME; } @Override public TemplateResolver create(EventResolverContext context, TemplateResolverConfig config) { - return new PowertoolsResolver(); + return new PowertoolsResolver(config); } } diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/Log4jLoggingManager.java b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/Log4jLoggingManager.java new file mode 100644 index 000000000..4e57a8e45 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/Log4jLoggingManager.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.log4.internal; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.Configurator; +import org.slf4j.Logger; +import software.amazon.lambda.powertools.logging.internal.LoggingManager; + +/** + * LoggingManager for Log4j2 (see {@link LoggingManager}). + */ +public class Log4jLoggingManager implements LoggingManager { + + /** + * @inheritDoc + */ + @Override + @SuppressWarnings("java:S4792") + public void setLogLevel(org.slf4j.event.Level logLevel) { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configurator.setAllLevels(LogManager.getRootLogger().getName(), Level.getLevel(logLevel.toString())); + ctx.updateLoggers(); + } + + /** + * @inheritDoc + */ + @Override + public org.slf4j.event.Level getLogLevel(Logger logger) { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + return org.slf4j.event.Level.valueOf(ctx.getLogger(logger.getName()).getLevel().toString()); + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json new file mode 100644 index 000000000..19f13f199 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json @@ -0,0 +1,89 @@ +{ + "@timestamp": { + "$resolver": "timestamp", + "pattern": { + "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", + "timeZone": "UTC" + } + }, + "ecs.version": "1.2.0", + "log.level": { + "$resolver": "level", + "field": "name" + }, + "message": { + "$resolver": "message" + }, + "error.type": { + "$resolver": "exception", + "field": "className" + }, + "error.message": { + "$resolver": "exception", + "field": "message" + }, + "error.stack_trace": { + "$resolver": "exception", + "field": "stackTrace", + "stackTrace": { + "stringified": true + } + }, + "service.name": { + "$resolver": "powertools", + "field": "service" + }, + "service.version": { + "$resolver": "powertools", + "field": "function_version" + }, + "log.logger": { + "$resolver": "logger", + "field": "name" + }, + "process.thread.name": { + "$resolver": "thread", + "field": "name" + }, + "cloud.provider" : "aws", + "cloud.service.name" : "lambda", + "cloud.region" : { + "$resolver": "powertools", + "field": "region" + }, + "cloud.account.id" : { + "$resolver": "powertools", + "field": "account_id" + }, + "faas.id": { + "$resolver": "powertools", + "field": "function_arn" + }, + "faas.name": { + "$resolver": "powertools", + "field": "function_name" + }, + "faas.version": { + "$resolver": "powertools", + "field": "function_version" + }, + "faas.memory": { + "$resolver": "powertools", + "field": "function_memory_size" + }, + "faas.execution": { + "$resolver": "powertools", + "field": "function_request_id" + }, + "faas.coldstart": { + "$resolver": "powertools", + "field": "cold_start" + }, + "trace.id": { + "$resolver": "powertools", + "field": "xray_trace_id" + }, + "": { + "$resolver": "powertools" + } +} \ No newline at end of file diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json new file mode 100644 index 000000000..d8d8810f6 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json @@ -0,0 +1,72 @@ +{ + "level": { + "$resolver": "level", + "field": "name" + }, + "message": { + "$resolver": "powertools", + "field": "message" + }, + "error": { + "message": { + "$resolver": "exception", + "field": "message" + }, + "name": { + "$resolver": "exception", + "field": "className" + }, + "stack": { + "$resolver": "exception", + "field": "stackTrace", + "stackTrace": { + "stringified": true + } + } + }, + "cold_start": { + "$resolver": "powertools", + "field": "cold_start" + }, + "function_arn": { + "$resolver": "powertools", + "field": "function_arn" + }, + "function_memory_size": { + "$resolver": "powertools", + "field": "function_memory_size" + }, + "function_name": { + "$resolver": "powertools", + "field": "function_name" + }, + "function_request_id": { + "$resolver": "powertools", + "field": "function_request_id" + }, + "function_version": { + "$resolver": "powertools", + "field": "function_version" + }, + "sampling_rate": { + "$resolver": "powertools", + "field": "sampling_rate" + }, + "service": { + "$resolver": "powertools", + "field": "service" + }, + "timestamp": { + "$resolver": "timestamp", + "pattern": { + "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" + } + }, + "xray_trace_id": { + "$resolver": "powertools", + "field": "xray_trace_id" + }, + "": { + "$resolver": "powertools" + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager new file mode 100644 index 000000000..d444c5525 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager @@ -0,0 +1 @@ +software.amazon.lambda.powertools.logging.log4.internal.Log4jLoggingManager \ No newline at end of file diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java new file mode 100644 index 000000000..4cf798a47 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.logging.log4j.layout.template.json.resolver; + +import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.openMocks; + +import com.amazonaws.services.lambda.runtime.Context; +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.MDC; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled; + +@Order(1) +class PowerToolsResolverFactoryTest { + + @Mock + private Context context; + + @BeforeEach + void setUp() throws IllegalAccessException, IOException { + openMocks(this); + MDC.clear(); + writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); + setupContext(); + // Make sure file is cleaned up before running tests + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // file may not exist on the first launch + } + } + + @AfterEach + void cleanUp() throws IOException{ + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } + + @Test + void shouldLogInJsonFormat() { + PowertoolsLogEnabled handler = new PowertoolsLogEnabled(); + handler.handleRequest("Input", context); + + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains( + "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":\"1\",\"service\":\"testLog4j\",\"timestamp\":") + .contains("\"xray_trace_id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); + } + + @Test + void shouldLogInEcsFormat() { + PowertoolsLogEnabled handler = new PowertoolsLogEnabled(); + handler.handleRequest("Input", context); + + File logFile = new File("target/ecslogfile.json"); + assertThat(contentOf(logFile)).contains( + "\"ecs.version\":\"1.2.0\",\"log.level\":\"DEBUG\",\"message\":\"Test debug event\",\"service.name\":\"testLog4j\",\"service.version\":\"1\",\"log.logger\":\"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled\",\"process.thread.name\":\"main\",\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-central-1\",\"cloud.account.id\":\"012345678910\",\"faas.id\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"faas.name\":\"testFunction\",\"faas.version\":\"1\",\"faas.memory\":1024,\"faas.execution\":\"RequestId\",\"faas.coldstart\":true,\"trace.id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); + } + + private void setupContext() { + when(context.getFunctionName()).thenReturn("testFunction"); + when(context.getInvokedFunctionArn()).thenReturn( + "arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1"); + when(context.getFunctionVersion()).thenReturn("1"); + when(context.getMemoryLimitInMB()).thenReturn(1024); + when(context.getAwsRequestId()).thenReturn("RequestId"); + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsMessageResolverTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsMessageResolverTest.java new file mode 100644 index 000000000..a00b78906 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsMessageResolverTest.java @@ -0,0 +1,115 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.logging.log4j.layout.template.json.resolver; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.openMocks; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Arrays; +import java.util.Collections; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.MDC; +import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsJsonMessage; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled; + +@Order(2) +class PowertoolsMessageResolverTest { + + @Mock + private Context context; + + @BeforeEach + void setUp() throws IOException { + openMocks(this); + MDC.clear(); + setupContext(); + + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } + } + + @AfterEach + void cleanUp() throws IOException { + //Make sure file is cleaned up before running full stack logging regression + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } + + @Test + void shouldLogJsonMessageWithoutEscapedStringsWhenSettingLogAsJson() { + // GIVEN + PowertoolsJsonMessage requestHandler = new PowertoolsJsonMessage(); + SQSEvent.SQSMessage msg = new SQSEvent.SQSMessage(); + msg.setMessageId("1212abcd"); + msg.setBody("plop"); + msg.setEventSource("eb"); + msg.setAwsRegion("eu-west-1"); + SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); + attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); + msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); + + // WHEN + requestHandler.handleRequest(msg, context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("\"message\":{\"messageId\":\"1212abcd\",\"receiptHandle\":null,\"body\":\"plop\",\"md5OfBody\":null,\"md5OfMessageAttributes\":null,\"eventSourceArn\":null,\"eventSource\":\"eb\",\"awsRegion\":\"eu-west-1\",\"attributes\":null,\"messageAttributes\":{\"keyAttribute\":{\"stringValue\":null,\"binaryValue\":null,\"stringListValues\":[\"val1\",\"val2\",\"val3\"],\"binaryListValues\":null,\"dataType\":null}}}") + .contains("\"message\":\"1212abcd\"") + .contains("\"message\":\"{\\\"key\\\":\\\"value\\\"}\"") + .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"") + .doesNotContain(LoggingUtils.LOG_MESSAGES_AS_JSON); + } + + @Test + void shouldLogStringMessageWhenNotJson() { + // GIVEN + PowertoolsLogEnabled requestHandler = new PowertoolsLogEnabled(); + + // WHEN + requestHandler.handleRequest(null, context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("\"message\":\"Test debug event\""); + } + + private void setupContext() { + when(context.getFunctionName()).thenReturn("testFunction"); + when(context.getInvokedFunctionArn()).thenReturn("testArn"); + when(context.getFunctionVersion()).thenReturn("1"); + when(context.getMemoryLimitInMB()).thenReturn(10); + when(context.getAwsRequestId()).thenReturn("RequestId"); + } +} \ No newline at end of file diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java new file mode 100644 index 000000000..1aa98fdef --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java @@ -0,0 +1,110 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.logging.log4j.layout.template.json.resolver; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mockStatic; +import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SAMPLING_RATE; + +import java.util.HashMap; +import java.util.Map; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.apache.logging.log4j.layout.template.json.util.JsonWriter; +import org.apache.logging.log4j.util.SortedArrayStringMap; +import org.apache.logging.log4j.util.StringMap; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.mockito.MockedStatic; +import software.amazon.lambda.powertools.common.internal.SystemWrapper; +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; + +class PowertoolsResolverTest { + + @ParameterizedTest + @EnumSource(value = PowertoolsLoggedFields.class, + mode = EnumSource.Mode.EXCLUDE, + names = {"FUNCTION_MEMORY_SIZE", "SAMPLING_RATE", "FUNCTION_COLD_START", "CORRELATION_ID"}) + void shouldResolveFunctionStringInfo(PowertoolsLoggedFields field) { + String result = resolveField(field.getName(), "value"); + assertThat(result).isEqualTo("\"value\""); + } + + @Test + void shouldResolveMemorySize() { + String result = resolveField(FUNCTION_MEMORY_SIZE.getName(), "42"); + assertThat(result).isEqualTo("42"); + } + + @Test + void shouldResolveSamplingRate() { + String result = resolveField(SAMPLING_RATE.getName(), "0.4"); + assertThat(result).isEqualTo("0.4"); + } + + @Test + void shouldResolveColdStart() { + String result = resolveField(FUNCTION_COLD_START.getName(), "true"); + assertThat(result).isEqualTo("true"); + } + + @Test + void shouldResolveAccountId() { + String result = resolveField(FUNCTION_ARN.getName(), "account_id", "arn:aws:lambda:us-east-2:123456789012:function:my-function"); + assertThat(result).isEqualTo("\"123456789012\""); + } + + @Test + void shouldResolveRegion() { + try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { + mocked.when(() -> getenv("AWS_REGION")) + .thenReturn("eu-central-2"); + + String result = resolveField("region", "dummy, will use the env var"); + assertThat(result).isEqualTo("\"eu-central-2\""); + } + } + + private static String resolveField(String field, String value) { + return resolveField(field, field, value); + } + + private static String resolveField(String data, String field, String value) { + Map configMap = new HashMap<>(); + configMap.put("field", field); + + TemplateResolverConfig config = new TemplateResolverConfig(configMap); + PowertoolsResolver resolver = new PowertoolsResolver(config); + JsonWriter writer = JsonWriter + .newBuilder() + .setMaxStringLength(1000) + .setTruncatedStringSuffix("") + .build(); + + StringMap contextMap = new SortedArrayStringMap(); + contextMap.putValue(data, value); + + Log4jLogEvent logEvent = Log4jLogEvent.newBuilder().setContextData(contextMap).build(); + if (resolver.isResolvable(logEvent)) { + resolver.resolve(logEvent, writer); + } + + return writer.getStringBuilder().toString(); + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/Log4jLoggingManagerTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/Log4jLoggingManagerTest.java new file mode 100644 index 000000000..69e1ee710 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/Log4jLoggingManagerTest.java @@ -0,0 +1,51 @@ +package software.amazon.lambda.powertools.logging.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.slf4j.event.Level.DEBUG; +import static org.slf4j.event.Level.ERROR; +import static org.slf4j.event.Level.WARN; + +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; +import software.amazon.lambda.powertools.logging.log4.internal.Log4jLoggingManager; + +class Log4jLoggingManagerTest { + + private final static Logger LOG = LoggerFactory.getLogger(Log4jLoggingManagerTest.class); + private final static Logger ROOT = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); + + @Test + @Order(1) + void getLogLevel_shouldReturnConfiguredLogLevel() { + // Given log4j2.xml in resources + + // When + Log4jLoggingManager manager = new Log4jLoggingManager(); + Level logLevel = manager.getLogLevel(LOG); + Level rootLevel = manager.getLogLevel(ROOT); + + // Then + assertThat(logLevel).isEqualTo(DEBUG); + assertThat(rootLevel).isEqualTo(WARN); + } + + @Test + @Order(2) + void resetLogLevel() { + // Given log4j2.xml in resources + + // When + Log4jLoggingManager manager = new Log4jLoggingManager(); + manager.setLogLevel(ERROR); + + Level rootLevel = manager.getLogLevel(ROOT); + Level logLevel = manager.getLogLevel(LOG); + + // Then + assertThat(rootLevel).isEqualTo(ERROR); + assertThat(logLevel).isEqualTo(ERROR); + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java new file mode 100644 index 000000000..3d196e5fb --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java @@ -0,0 +1,47 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal.handler; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.utilities.JsonConfig; + +public class PowertoolsJsonMessage implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsJsonMessage.class); + + @Override + @Logging(clearState = true) + public String handleRequest(SQSEvent.SQSMessage input, Context context) { + try { + LoggingUtils.logMessagesAsJson(true); + LOG.debug(JsonConfig.get().getObjectMapper().writeValueAsString(input)); + + LoggingUtils.logMessagesAsJson(false); + LOG.debug("{\"key\":\"value\"}"); + + LOG.debug("{}", input.getMessageId()); + LOG.warn("Message body = {} and id = \"{}\"", input.getBody(), input.getMessageId()); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + return input.getMessageId(); + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java new file mode 100644 index 000000000..faa722756 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal.handler; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; + +public class PowertoolsLogEnabled implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogEnabled.class); + + @Override + @Logging(clearState = true) + public Object handleRequest(Object input, Context context) { + LoggingUtils.appendKey("myKey", "myValue"); + LOG.debug("Test debug event"); + return null; + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/test/resources/junit-platform.properties b/powertools-logging/powertools-logging-log4j/src/test/resources/junit-platform.properties new file mode 100644 index 000000000..80a2481d7 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/resources/junit-platform.properties @@ -0,0 +1,17 @@ +# +# Copyright 2023 Amazon.com, Inc. or its affiliates. +# Licensed under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +# because of LambdaLoggingAspect static initialization of the LoggingManager, we need to +# set an order in the unit tests, especially LambdaLoggingAspectTest needs to be first +junit.jupiter.testclass.order.default=org.junit.jupiter.api.ClassOrderer$OrderAnnotation \ No newline at end of file diff --git a/powertools-logging/powertools-logging-log4j/src/test/resources/log4j2.xml b/powertools-logging/powertools-logging-log4j/src/test/resources/log4j2.xml new file mode 100644 index 000000000..778077bc5 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/resources/log4j2.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + q + + + + + + + + + + \ No newline at end of file diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml new file mode 100644 index 000000000..99fff3ab9 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -0,0 +1,137 @@ + + + 4.0.0 + + powertools-parent + software.amazon.lambda + 2.0.0-SNAPSHOT + ../../pom.xml + + + powertools-logging-logback + Powertools for AWS Lambda (Java) - Logging with LogBack + Set of utility for better logging with logback + + + + software.amazon.lambda + powertools-logging + ${project.version} + + + org.aspectj + aspectjrt + provided + + + ch.qos.logback + logback-classic + + 1.3.4 + provided + + + com.sun.mail + javax.mail + + + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.apache.commons + commons-lang3 + test + + + org.aspectj + aspectjweaver + test + + + org.assertj + assertj-core + test + + + com.amazonaws + aws-lambda-java-events + test + + + com.amazonaws + aws-lambda-java-tests + test + + + org.skyscreamer + jsonassert + test + + + + + + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-logging + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + 3.1.2 + + + testLogback + eu-central-1 + <_X_AMZN_TRACE_ID>Root=1-63441c4a-abcdef012345678912345678 + + + + + + + + \ No newline at end of file diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java new file mode 100644 index 000000000..1fc98ec67 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java @@ -0,0 +1,199 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.logback; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_NAME; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_REQUEST_ID; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_VERSION; + +import ch.qos.logback.classic.pattern.ThrowableHandlingConverter; +import ch.qos.logback.classic.pattern.ThrowableProxyConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.ThrowableProxy; +import ch.qos.logback.core.encoder.EncoderBase; +import java.util.Map; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.logging.logback.internal.LambdaEcsSerializer; + + +/** + * This class will encode the logback event into the format expected by the Elastic Common Schema (ECS) service (for Elasticsearch). + *
+ * Inspired from co.elastic.logging.logback.EcsEncoder, this class doesn't use + * any JSON (de)serialization library (Jackson, Gson, etc.) or Elastic library to avoid the dependency. + *
+ * This encoder also adds cloud information (see doc) + * and Lambda function information (see doc, currently in beta). + */ +public class LambdaEcsEncoder extends EncoderBase { + + protected static final String ECS_VERSION = "1.2.0"; + protected static final String CLOUD_PROVIDER = "aws"; + protected static final String CLOUD_SERVICE = "lambda"; + + private final ThrowableProxyConverter throwableProxyConverter = new ThrowableProxyConverter(); + protected ThrowableHandlingConverter throwableConverter = null; + private boolean includeCloudInfo = true; + private boolean includeFaasInfo = true; + + @Override + public byte[] headerBytes() { + return null; + } + + /** + * Main method of the encoder. Encode a logging event into Json format (with Elastic Search fields) + * + * @param event the logging event + * @return the encoded bytes + */ + @Override + public byte[] encode(ILoggingEvent event) { + final Map mdcPropertyMap = event.getMDCPropertyMap(); + + StringBuilder builder = new StringBuilder(256); + LambdaEcsSerializer.serializeObjectStart(builder); + LambdaEcsSerializer.serializeTimestamp(builder, event.getTimeStamp(), "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "UTC"); + LambdaEcsSerializer.serializeEcsVersion(builder, ECS_VERSION); + LambdaEcsSerializer.serializeLogLevel(builder, event.getLevel()); + LambdaEcsSerializer.serializeFormattedMessage(builder, event.getFormattedMessage()); + IThrowableProxy throwableProxy = event.getThrowableProxy(); + if (throwableProxy != null) { + if (throwableConverter != null) { + LambdaEcsSerializer.serializeException(builder, throwableProxy.getClassName(), + throwableProxy.getMessage(), throwableConverter.convert(event)); + } else if (throwableProxy instanceof ThrowableProxy) { + LambdaEcsSerializer.serializeException(builder, ((ThrowableProxy) throwableProxy).getThrowable()); + } else { + LambdaEcsSerializer.serializeException(builder, throwableProxy.getClassName(), + throwableProxy.getMessage(), throwableProxyConverter.convert(event)); + } + } + LambdaEcsSerializer.serializeServiceName(builder, LambdaHandlerProcessor.serviceName()); + LambdaEcsSerializer.serializeServiceVersion(builder, mdcPropertyMap.get(FUNCTION_VERSION.getName())); + LambdaEcsSerializer.serializeLoggerName(builder, event.getLoggerName()); + LambdaEcsSerializer.serializeThreadName(builder, event.getThreadName()); + String arn = mdcPropertyMap.get(FUNCTION_ARN.getName()); + + if (includeCloudInfo) { + LambdaEcsSerializer.serializeCloudProvider(builder, CLOUD_PROVIDER); + LambdaEcsSerializer.serializeCloudService(builder, CLOUD_SERVICE); + if (arn != null) { + String[] arnParts = arn.split(":"); + LambdaEcsSerializer.serializeCloudRegion(builder, arnParts[3]); + LambdaEcsSerializer.serializeCloudAccountId(builder, arnParts[4]); + } + } + + if (includeFaasInfo) { + LambdaEcsSerializer.serializeFunctionId(builder, arn); + LambdaEcsSerializer.serializeFunctionName(builder, mdcPropertyMap.get(FUNCTION_NAME.getName())); + LambdaEcsSerializer.serializeFunctionVersion(builder, mdcPropertyMap.get(FUNCTION_VERSION.getName())); + LambdaEcsSerializer.serializeFunctionMemory(builder, mdcPropertyMap.get(FUNCTION_MEMORY_SIZE.getName())); + LambdaEcsSerializer.serializeFunctionExecutionId(builder, + mdcPropertyMap.get(FUNCTION_REQUEST_ID.getName())); + LambdaEcsSerializer.serializeColdStart(builder, mdcPropertyMap.get(FUNCTION_COLD_START.getName())); + LambdaEcsSerializer.serializeTraceId(builder, mdcPropertyMap.get(FUNCTION_TRACE_ID.getName())); + } + LambdaEcsSerializer.serializeAdditionalFields(builder, event.getMDCPropertyMap()); + LambdaEcsSerializer.serializeObjectEnd(builder); + return builder.toString().getBytes(UTF_8); + } + + @Override + public byte[] footerBytes() { + return null; + } + + /** + * Specify a throwable converter to format the stacktrace according to your need + * (default is null, no throwableConverter): + *
+ *
{@code
+     *     
+     *         
+     *              30
+     *              2048
+     *              20
+     *              sun\.reflect\..*\.invoke.*
+     *              net\.sf\.cglib\.proxy\.MethodProxy\.invoke
+     *              
+     *              true
+     *              true
+     *         
+     *     
+     * }
+ * + * @param throwableConverter converter for the throwable + */ + public void setThrowableConverter(ThrowableHandlingConverter throwableConverter) { + this.throwableConverter = throwableConverter; + } + + /** + * Specify if cloud information should be logged (default is true): + *
    + *
  • cloud.provider
  • + *
  • cloud.service.name
  • + *
  • cloud.region
  • + *
  • cloud.account.id
  • + *
+ *
+ * We strongly recommend to keep these information. + *
+ *
{@code
+     *     
+     *         false
+     *     
+     * }
+ * + * @param includeCloudInfo if thread information should be logged + */ + public void setIncludeCloudInfo(boolean includeCloudInfo) { + this.includeCloudInfo = includeCloudInfo; + } + + /** + * Specify if Lambda function information should be logged (default is true): + *
    + *
  • faas.id
  • + *
  • faas.name
  • + *
  • faas.version
  • + *
  • faas.memory
  • + *
  • faas.execution
  • + *
  • faas.coldstart
  • + *
  • trace.id
  • + *
+ *
+ * We strongly recommend to keep these information. + *
+ *
{@code
+     *     
+     *         false
+     *     
+     * }
+ * + * @param includeFaasInfo if function information should be logged + */ + public void setIncludeFaasInfo(boolean includeFaasInfo) { + this.includeFaasInfo = includeFaasInfo; + } +} diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaJsonEncoder.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaJsonEncoder.java new file mode 100644 index 000000000..b951e266e --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaJsonEncoder.java @@ -0,0 +1,208 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.logback; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static software.amazon.lambda.powertools.logging.LoggingUtils.LOG_MESSAGES_AS_JSON; + +import ch.qos.logback.classic.pattern.ThrowableHandlingConverter; +import ch.qos.logback.classic.pattern.ThrowableProxyConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.IThrowableProxy; +import ch.qos.logback.classic.spi.ThrowableProxy; +import ch.qos.logback.core.encoder.EncoderBase; +import software.amazon.lambda.powertools.logging.logback.internal.LambdaJsonSerializer; + +/** + * Custom encoder for logback that encodes logs in JSON format. + * It does not use a JSON library but a custom serializer ({@link LambdaJsonSerializer}) + */ +public class LambdaJsonEncoder extends EncoderBase { + + private final ThrowableProxyConverter throwableProxyConverter = new ThrowableProxyConverter(); + protected ThrowableHandlingConverter throwableConverter = null; + protected String timestampFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + protected String timestampFormatTimezoneId = null; + private boolean includeThreadInfo = false; + private boolean includePowertoolsInfo = true; + private boolean logMessagesAsJsonGlobal; + + @Override + public byte[] headerBytes() { + return null; + } + + @Override + public void start() { + super.start(); + throwableProxyConverter.start(); + if (throwableConverter != null) { + throwableConverter.start(); + } + } + + @Override + public byte[] encode(ILoggingEvent event) { + StringBuilder builder = new StringBuilder(256); + LambdaJsonSerializer.serializeObjectStart(builder); + LambdaJsonSerializer.serializeLogLevel(builder, event.getLevel()); + LambdaJsonSerializer.serializeFormattedMessage( + builder, + event.getFormattedMessage(), + logMessagesAsJsonGlobal, + event.getMDCPropertyMap().get(LOG_MESSAGES_AS_JSON)); + IThrowableProxy throwableProxy = event.getThrowableProxy(); + if (throwableProxy != null) { + if (throwableConverter != null) { + LambdaJsonSerializer.serializeException(builder, throwableProxy.getClassName(), + throwableProxy.getMessage(), throwableConverter.convert(event)); + } else if (throwableProxy instanceof ThrowableProxy) { + LambdaJsonSerializer.serializeException(builder, ((ThrowableProxy) throwableProxy).getThrowable()); + } else { + LambdaJsonSerializer.serializeException(builder, throwableProxy.getClassName(), + throwableProxy.getMessage(), throwableProxyConverter.convert(event)); + } + } + LambdaJsonSerializer.serializePowertools(builder, event.getMDCPropertyMap(), includePowertoolsInfo); + if (includeThreadInfo) { + LambdaJsonSerializer.serializeThreadName(builder, event.getThreadName()); + LambdaJsonSerializer.serializeThreadId(builder, String.valueOf(Thread.currentThread().getId())); + LambdaJsonSerializer.serializeThreadPriority(builder, String.valueOf(Thread.currentThread().getPriority())); + } + LambdaJsonSerializer.serializeTimestamp(builder, event.getTimeStamp(), timestampFormat, + timestampFormatTimezoneId); + LambdaJsonSerializer.serializeObjectEnd(builder); + return builder.toString().getBytes(UTF_8); + } + + @Override + public byte[] footerBytes() { + return null; + } + + /** + * Specify the format of the timestamp (default is yyyy-MM-dd'T'HH:mm:ss.SSS'Z'). + * Note that if you use the Lambda Advanced Logging Configuration, you should keep the default format. + *
+ *
{@code
+     *     
+     *         yyyy-MM-dd'T'HH:mm:ss.SSSZz
+     *     
+     * }
+ * + * @param timestampFormat format of the timestamp (compatible with {@link java.text.SimpleDateFormat}) + */ + public void setTimestampFormat(String timestampFormat) { + this.timestampFormat = timestampFormat; + } + + /** + * Specify the format of the time zone id for timestamp (default is null, no timezone): + *
+ *
{@code
+     *     
+     *         Europe/Paris
+     *     
+     * }
+ * + * @param timestampFormatTimezoneId Zone Id (see {@link java.util.TimeZone}) + */ + public void setTimestampFormatTimezoneId(String timestampFormatTimezoneId) { + this.timestampFormatTimezoneId = timestampFormatTimezoneId; + } + + /** + * Specify a throwable converter to format the stacktrace according to your need + * (default is null, no throwableConverter): + *
+ *
{@code
+     *     
+     *         
+     *              30
+     *              2048
+     *              20
+     *              sun\.reflect\..*\.invoke.*
+     *              net\.sf\.cglib\.proxy\.MethodProxy\.invoke
+     *              
+     *              true
+     *              true
+     *         
+     *     
+     * }
+ * + * @param throwableConverter converter for the throwable + */ + public void setThrowableConverter(ThrowableHandlingConverter throwableConverter) { + this.throwableConverter = throwableConverter; + } + + /** + * Specify if thread information should be logged (default is false) + *
+ *
{@code
+     *     
+     *         true
+     *     
+     * }
+ * + * @param includeThreadInfo if thread information should be logged + */ + public void setIncludeThreadInfo(boolean includeThreadInfo) { + this.includeThreadInfo = includeThreadInfo; + } + + /** + * Specify if Lambda function information should be logged (default is true): + *
    + *
  • function_name
  • + *
  • function_version
  • + *
  • function_arn
  • + *
  • function_memory_size
  • + *
  • function_request_id
  • + *
  • cold_start
  • + *
  • xray_trace_id
  • + *
  • sampling_rate
  • + *
  • service
  • + *
+ *
+ * We strongly recommend to keep these information. + *
+ *
{@code
+     *     
+     *         false
+     *     
+     * }
+ * + * @param includePowertoolsInfo if function information should be logged + */ + public void setIncludePowertoolsInfo(boolean includePowertoolsInfo) { + this.includePowertoolsInfo = includePowertoolsInfo; + } + + /** + * Specify if messages should be logged as JSON, without escaping string (default is false): + *
+ *
{@code
+     *     
+     *         true
+     *     
+     * }
+ * + * @param logMessagesAsJson if messages should be looged as JSON (non escaped quotes) + */ + public void setLogMessagesAsJson(boolean logMessagesAsJson) { + this.logMessagesAsJsonGlobal = logMessagesAsJson; + } +} diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/JsonUtils.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/JsonUtils.java new file mode 100644 index 000000000..e604d10c7 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/JsonUtils.java @@ -0,0 +1,130 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.logback.internal; + +/** + * Json tools to serialize attributes manually, to avoid using further dependencies (jackson, gson...) + */ +public class JsonUtils { + + private JsonUtils() { + // static utils + } + + protected static void serializeAttribute(StringBuilder builder, String attr, String value, boolean notBegin) { + if (value != null) { + if (notBegin) { + builder.append(","); + } + builder.append("\"").append(attr).append("\":"); + boolean isString = isString(value); + if (isString) { + builder.append("\""); + } + builder.append(value); + if (isString) { + builder.append("\""); + } + } + } + + protected static void serializeAttribute(StringBuilder builder, String attr, String value) { + serializeAttribute(builder, attr, value, true); + } + + protected static void serializeMessage(StringBuilder builder, String attr, String value, boolean logAsJson) { + builder.append(","); + builder.append("\"").append(attr).append("\":"); + if (logAsJson) { + builder.append(value); // log JSON without quotes + } else { + builder.append("\""); + builder.append(value.replace("\"", "\\\"")); // escape quotes in string + builder.append("\""); + } + } + + + protected static void serializeAttributeAsString(StringBuilder builder, String attr, String value, + boolean notBegin) { + if (value != null) { + if (notBegin) { + builder.append(","); + } + builder.append("\"") + .append(attr) + .append("\":\"") + .append(value) + .append("\""); + } + } + + protected static void serializeAttributeAsString(StringBuilder builder, String attr, String value) { + serializeAttributeAsString(builder, attr, value, true); + } + + /** + * As MDC is a {@code Map}, we need to check the type + * to output numbers and booleans correctly (without quotes) + */ + private static boolean isString(String str) { + if (str == null) { + return true; + } + if ("true".equals(str) || "false".equals(str)) { + return false; // boolean + } + return !isNumeric(str); // number + } + + /** + * Taken from commons-lang3 NumberUtils to avoid include the library + */ + private static boolean isNumeric(final String str) { + if (str == null || str.isEmpty()) { + return false; + } + if (str.charAt(str.length() - 1) == '.') { + return false; + } + if (str.charAt(0) == '-') { + if (str.length() == 1) { + return false; + } + return withDecimalsParsing(str, 1); + } + return withDecimalsParsing(str, 0); + } + + /** + * Taken from commons-lang3 NumberUtils + */ + private static boolean withDecimalsParsing(final String str, final int beginIdx) { + int decimalPoints = 0; + for (int i = beginIdx; i < str.length(); i++) { + final boolean isDecimalPoint = str.charAt(i) == '.'; + if (isDecimalPoint) { + decimalPoints++; + } + if (decimalPoints > 1) { + return false; + } + if (!isDecimalPoint && !Character.isDigit(str.charAt(i))) { + return false; + } + } + return true; + } +} diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaEcsSerializer.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaEcsSerializer.java new file mode 100644 index 000000000..bab1a32fc --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaEcsSerializer.java @@ -0,0 +1,187 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.logback.internal; + +import ch.qos.logback.classic.Level; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.Map; +import java.util.TimeZone; +import java.util.TreeMap; +import java.util.regex.Matcher; +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; + +/** + * This class will serialize the log events in ecs format (ElasticSearch).
+ *

+ * Inspired from the ElasticSearch Serializer co.elastic.logging.EcsJsonSerializer + */ +public class LambdaEcsSerializer { + protected static final String TIMESTAMP_ATTR_NAME = "@timestamp"; + protected static final String ECS_VERSION_ATTR_NAME = "ecs.version"; + protected static final String LOGGER_ATTR_NAME = "log.logger"; + protected static final String LEVEL_ATTR_NAME = "log.level"; + protected static final String SERVICE_NAME_ATTR_NAME = "service.name"; + protected static final String SERVICE_VERSION_ATTR_NAME = "service.version"; + protected static final String SERVICE_ENV_ATTR_NAME = "service.environment"; + protected static final String EVENT_DATASET_ATTR_NAME = "event.dataset"; + protected static final String FORMATTED_MESSAGE_ATTR_NAME = "message"; + protected static final String THREAD_ATTR_NAME = "process.thread.name"; + protected static final String THREAD_ID_ATTR_NAME = "process.thread.id"; + protected static final String EXCEPTION_MSG_ATTR_NAME = "error.message"; + protected static final String EXCEPTION_CLASS_ATTR_NAME = "error.type"; + protected static final String EXCEPTION_STACK_ATTR_NAME = "error.stack_trace"; + protected static final String CLOUD_PROVIDER_ATTR_NAME = "cloud.provider"; + protected static final String CLOUD_REGION_ATTR_NAME = "cloud.region"; + protected static final String CLOUD_ACCOUNT_ATTR_NAME = "cloud.account.id"; + protected static final String CLOUD_SERVICE_ATTR_NAME = "cloud.service.name"; + protected static final String FUNCTION_COLD_START_ATTR_NAME = "faas.coldstart"; + protected static final String FUNCTION_REQUEST_ID_ATTR_NAME = "faas.execution"; + protected static final String FUNCTION_ARN_ATTR_NAME = "faas.id"; + protected static final String FUNCTION_NAME_ATTR_NAME = "faas.name"; + protected static final String FUNCTION_VERSION_ATTR_NAME = "faas.version"; + protected static final String FUNCTION_MEMORY_ATTR_NAME = "faas.memory"; + protected static final String FUNCTION_TRACE_ID_ATTR_NAME = "trace.id"; + + private LambdaEcsSerializer() {} + + public static void serializeObjectStart(StringBuilder builder) { + builder.append('{'); + } + + public static void serializeObjectEnd(StringBuilder builder) { + builder.append("}\n"); + } + + public static void serializeTimestamp(StringBuilder builder, long timestamp, String timestampFormat, + String timestampFormatTimezoneId) { + String formattedTimestamp; + if (timestampFormat == null || timestamp < 0) { + formattedTimestamp = String.valueOf(timestamp); + } else { + Date date = new Date(timestamp); + DateFormat format = new SimpleDateFormat(timestampFormat); + + if (timestampFormatTimezoneId != null) { + TimeZone tz = TimeZone.getTimeZone(timestampFormatTimezoneId); + format.setTimeZone(tz); + } + formattedTimestamp = format.format(date); + } + JsonUtils.serializeAttributeAsString(builder, TIMESTAMP_ATTR_NAME, formattedTimestamp, false); + } + + public static void serializeThreadName(StringBuilder builder, String threadName) { + if (threadName != null) { + JsonUtils.serializeAttributeAsString(builder, THREAD_ATTR_NAME, threadName); + } + } + + public static void serializeLogLevel(StringBuilder builder, Level level) { + JsonUtils.serializeAttributeAsString(builder, LEVEL_ATTR_NAME, level.toString()); + } + + public static void serializeFormattedMessage(StringBuilder builder, String formattedMessage) { + JsonUtils.serializeAttributeAsString(builder, FORMATTED_MESSAGE_ATTR_NAME, + formattedMessage.replace("\"", Matcher.quoteReplacement("\\\""))); + } + + public static void serializeException(StringBuilder builder, String className, String message, String stackTrace) { + JsonUtils.serializeAttributeAsString(builder, EXCEPTION_MSG_ATTR_NAME, message); + JsonUtils.serializeAttributeAsString(builder, EXCEPTION_CLASS_ATTR_NAME, className); + JsonUtils.serializeAttributeAsString(builder, EXCEPTION_STACK_ATTR_NAME, stackTrace); + } + + public static void serializeException(StringBuilder builder, Throwable throwable) { + serializeException(builder, throwable.getClass().getName(), throwable.getMessage(), + Arrays.toString(throwable.getStackTrace())); + } + + public static void serializeThreadId(StringBuilder builder, String threadId) { + JsonUtils.serializeAttributeAsString(builder, THREAD_ID_ATTR_NAME, threadId); + } + + public static void serializeAdditionalFields(StringBuilder builder, Map mdc) { + TreeMap sortedMap = new TreeMap<>(mdc); + + sortedMap.forEach((k, v) -> { + if (!PowertoolsLoggedFields.stringValues().contains(k)) { + JsonUtils.serializeAttributeAsString(builder, k, v); + } + }); + } + + public static void serializeEcsVersion(StringBuilder builder, String ecsVersion) { + JsonUtils.serializeAttributeAsString(builder, ECS_VERSION_ATTR_NAME, ecsVersion); + } + + public static void serializeServiceName(StringBuilder builder, String serviceName) { + JsonUtils.serializeAttributeAsString(builder, SERVICE_NAME_ATTR_NAME, serviceName); + } + + public static void serializeServiceVersion(StringBuilder builder, String serviceVersion) { + JsonUtils.serializeAttributeAsString(builder, SERVICE_VERSION_ATTR_NAME, serviceVersion); + } + + public static void serializeLoggerName(StringBuilder builder, String loggerName) { + JsonUtils.serializeAttributeAsString(builder, LOGGER_ATTR_NAME, loggerName); + } + + public static void serializeCloudProvider(StringBuilder builder, String cloudProvider) { + JsonUtils.serializeAttributeAsString(builder, CLOUD_PROVIDER_ATTR_NAME, cloudProvider); + } + + public static void serializeCloudService(StringBuilder builder, String cloudService) { + JsonUtils.serializeAttributeAsString(builder, CLOUD_SERVICE_ATTR_NAME, cloudService); + } + + public static void serializeCloudRegion(StringBuilder builder, String cloudRegion) { + JsonUtils.serializeAttributeAsString(builder, CLOUD_REGION_ATTR_NAME, cloudRegion); + } + + public static void serializeCloudAccountId(StringBuilder builder, String cloudAccountId) { + JsonUtils.serializeAttributeAsString(builder, CLOUD_ACCOUNT_ATTR_NAME, cloudAccountId); + } + + public static void serializeColdStart(StringBuilder builder, String coldStart) { + JsonUtils.serializeAttributeAsString(builder, FUNCTION_COLD_START_ATTR_NAME, coldStart); + } + + public static void serializeFunctionExecutionId(StringBuilder builder, String requestId) { + JsonUtils.serializeAttributeAsString(builder, FUNCTION_REQUEST_ID_ATTR_NAME, requestId); + } + + public static void serializeFunctionId(StringBuilder builder, String functionArn) { + JsonUtils.serializeAttributeAsString(builder, FUNCTION_ARN_ATTR_NAME, functionArn); + } + + public static void serializeFunctionName(StringBuilder builder, String functionName) { + JsonUtils.serializeAttributeAsString(builder, FUNCTION_NAME_ATTR_NAME, functionName); + } + + public static void serializeFunctionVersion(StringBuilder builder, String functionVersion) { + JsonUtils.serializeAttributeAsString(builder, FUNCTION_VERSION_ATTR_NAME, functionVersion); + } + + public static void serializeFunctionMemory(StringBuilder builder, String functionMemory) { + JsonUtils.serializeAttributeAsString(builder, FUNCTION_MEMORY_ATTR_NAME, functionMemory); + } + + public static void serializeTraceId(StringBuilder builder, String traceId) { + JsonUtils.serializeAttributeAsString(builder, FUNCTION_TRACE_ID_ATTR_NAME, traceId); + } +} diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaJsonSerializer.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaJsonSerializer.java new file mode 100644 index 000000000..7d7b8d0d7 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaJsonSerializer.java @@ -0,0 +1,150 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.logback.internal; + +import static java.lang.Boolean.TRUE; +import static software.amazon.lambda.powertools.logging.LoggingUtils.LOG_MESSAGES_AS_JSON; + +import ch.qos.logback.classic.Level; +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Date; +import java.util.Map; +import java.util.TimeZone; +import java.util.TreeMap; +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; + +/** + * This class will serialize the log events in json.
+ *

+ * Inspired from the ElasticSearch Serializer co.elastic.logging.EcsJsonSerializer + */ +public class LambdaJsonSerializer { + protected static final String TIMESTAMP_ATTR_NAME = "timestamp"; + protected static final String LEVEL_ATTR_NAME = "level"; + protected static final String FORMATTED_MESSAGE_ATTR_NAME = "message"; + protected static final String THREAD_ATTR_NAME = "thread"; + protected static final String THREAD_ID_ATTR_NAME = "thread_id"; + protected static final String THREAD_PRIORITY_ATTR_NAME = "thread_priority"; + protected static final String EXCEPTION_MSG_ATTR_NAME = "message"; + protected static final String EXCEPTION_CLASS_ATTR_NAME = "name"; + protected static final String EXCEPTION_STACK_ATTR_NAME = "stack"; + protected static final String EXCEPTION_ATTR_NAME = "error"; + + private LambdaJsonSerializer() {} + + public static void serializeObjectStart(StringBuilder builder) { + builder.append('{'); + } + + public static void serializeObjectEnd(StringBuilder builder) { + builder.append("}\n"); + } + + public static void serializeTimestamp(StringBuilder builder, long timestamp, String timestampFormat, + String timestampFormatTimezoneId) { + String formattedTimestamp; + if (timestampFormat == null || timestamp < 0) { + formattedTimestamp = String.valueOf(timestamp); + } else { + Date date = new Date(timestamp); + DateFormat format = new SimpleDateFormat(timestampFormat); + + if (timestampFormatTimezoneId != null) { + TimeZone tz = TimeZone.getTimeZone(timestampFormatTimezoneId); + format.setTimeZone(tz); + } + formattedTimestamp = format.format(date); + } + JsonUtils.serializeAttribute(builder, TIMESTAMP_ATTR_NAME, formattedTimestamp); + } + + public static void serializeThreadName(StringBuilder builder, String threadName) { + if (threadName != null) { + JsonUtils.serializeAttribute(builder, THREAD_ATTR_NAME, threadName); + } + } + + public static void serializeLogLevel(StringBuilder builder, Level level) { + JsonUtils.serializeAttribute(builder, LEVEL_ATTR_NAME, level.toString(), false); + } + + public static void serializeFormattedMessage(StringBuilder builder, String message, + boolean logMessagesAsJsonGlobal, String logMessagesAsJsonLocal) { + Boolean logMessagesAsJson = null; + if (logMessagesAsJsonLocal != null) { + logMessagesAsJson = Boolean.parseBoolean(logMessagesAsJsonLocal); + } + + boolean logAsJson = ((logMessagesAsJsonGlobal && logMessagesAsJson == null) || TRUE.equals(logMessagesAsJson)) + && isValidJson(message); + JsonUtils.serializeMessage(builder, FORMATTED_MESSAGE_ATTR_NAME, message, logAsJson); + } + + public static void serializeException(StringBuilder builder, String className, String message, String stackTrace) { + builder.append(",\"").append(EXCEPTION_ATTR_NAME).append("\":{"); + JsonUtils.serializeAttribute(builder, EXCEPTION_MSG_ATTR_NAME, message, false); + JsonUtils.serializeAttribute(builder, EXCEPTION_CLASS_ATTR_NAME, className); + JsonUtils.serializeAttribute(builder, EXCEPTION_STACK_ATTR_NAME, stackTrace); + builder.append("}"); + } + + public static void serializeException(StringBuilder builder, Throwable throwable) { + serializeException(builder, throwable.getClass().getName(), throwable.getMessage(), + Arrays.toString(throwable.getStackTrace())); + } + + public static void serializeThreadId(StringBuilder builder, String threadId) { + JsonUtils.serializeAttribute(builder, THREAD_ID_ATTR_NAME, threadId); + } + + public static void serializeThreadPriority(StringBuilder builder, String threadPriority) { + JsonUtils.serializeAttribute(builder, THREAD_PRIORITY_ATTR_NAME, threadPriority); + } + + public static void serializePowertools(StringBuilder builder, Map mdc, + boolean includePowertoolsInfo) { + TreeMap sortedMap = new TreeMap<>(mdc); + sortedMap.forEach((k, v) -> { + if ((includePowertoolsInfo || !PowertoolsLoggedFields.stringValues().contains(k)) // do not log already logged powertools info + && !(k.equals(PowertoolsLoggedFields.SAMPLING_RATE.getName()) && v.equals("0.0")) // do not log sampling rate when 0 + && !LOG_MESSAGES_AS_JSON.equals(k)) // do not log internal keys + { + JsonUtils.serializeAttribute(builder, k, v); + } + }); + + } + + private static final ObjectMapper mapper = new ObjectMapper() + .enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS); + + private static boolean isValidJson(String str) { + if (!(str.startsWith("{") || str.startsWith("["))) { + return false; + } + try { + mapper.readTree(str); + } catch (JacksonException e) { + return false; + } + return true; + } + +} diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackLoggingManager.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackLoggingManager.java new file mode 100644 index 000000000..86982b444 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackLoggingManager.java @@ -0,0 +1,59 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.logback.internal; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import java.util.List; +import org.slf4j.ILoggerFactory; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.logging.internal.LoggingManager; + +/** + * LoggingManager for Logback (see {@link LoggingManager}). + */ +public class LogbackLoggingManager implements LoggingManager { + + private final LoggerContext loggerContext; + + public LogbackLoggingManager() { + ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory(); + if (!(loggerFactory instanceof LoggerContext)) { + throw new RuntimeException("LoggerFactory does not match required type: " + LoggerContext.class.getName()); + } + loggerContext = (LoggerContext) loggerFactory; + } + + /** + * @inheritDoc + */ + @Override + @SuppressWarnings("java:S4792") + public void setLogLevel(org.slf4j.event.Level logLevel) { + List loggers = loggerContext.getLoggerList(); + for (Logger logger : loggers) { + logger.setLevel(Level.convertAnSLF4JLevel(logLevel)); + } + } + + /** + * @inheritDoc + */ + @Override + public org.slf4j.event.Level getLogLevel(org.slf4j.Logger logger) { + return org.slf4j.event.Level.valueOf(loggerContext.getLogger(logger.getName()).getEffectiveLevel().toString()); + } +} diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager new file mode 100644 index 000000000..958f2e459 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager @@ -0,0 +1 @@ +software.amazon.lambda.powertools.logging.logback.internal.LogbackLoggingManager \ No newline at end of file diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/LogbackLoggingManagerTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/LogbackLoggingManagerTest.java new file mode 100644 index 000000000..214057917 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/LogbackLoggingManagerTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.slf4j.event.Level.DEBUG; +import static org.slf4j.event.Level.ERROR; +import static org.slf4j.event.Level.WARN; + +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; +import software.amazon.lambda.powertools.logging.logback.internal.LogbackLoggingManager; + +class LogbackLoggingManagerTest { + + private static final Logger LOG = LoggerFactory.getLogger(LogbackLoggingManagerTest.class); + private static final Logger ROOT = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); + + @Test + @Order(1) + void getLogLevel_shouldReturnConfiguredLogLevel() { + LogbackLoggingManager manager = new LogbackLoggingManager(); + Level logLevel = manager.getLogLevel(LOG); + assertThat(logLevel).isEqualTo(DEBUG); + + logLevel = manager.getLogLevel(ROOT); + assertThat(logLevel).isEqualTo(WARN); + } + + @Test + @Order(2) + void resetLogLevel() { + LogbackLoggingManager manager = new LogbackLoggingManager(); + manager.setLogLevel(ERROR); + + Level logLevel = manager.getLogLevel(LOG); + assertThat(logLevel).isEqualTo(ERROR); + } +} diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java new file mode 100644 index 000000000..5dcca2fb2 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java @@ -0,0 +1,176 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.openMocks; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.pattern.RootCauseFirstThrowableProxyConverter; +import ch.qos.logback.classic.spi.LoggingEvent; +import com.amazonaws.services.lambda.runtime.Context; +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.charset.StandardCharsets; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.logging.logback.LambdaEcsEncoder; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled; + +@Order(3) +class LambdaEcsEncoderTest { + + private static final Logger logger = (Logger) LoggerFactory.getLogger(LambdaEcsEncoderTest.class.getName()); + + + @Mock + private Context context; + + @BeforeEach + void setUp() throws IllegalAccessException, IOException { + openMocks(this); + MDC.clear(); + writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); + setupContext(); + // Make sure file is cleaned up before running tests + try { + FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // file may not exist on the first launch + } + } + + @AfterEach + void cleanUp() throws IOException{ + FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } + + @Test + void shouldLogInEcsFormat() { + PowertoolsLogEnabled handler = new PowertoolsLogEnabled(); + handler.handleRequest("Input", context); + + File logFile = new File("target/ecslogfile.json"); + assertThat(contentOf(logFile)).contains( + "\"ecs.version\":\"1.2.0\",\"log.level\":\"DEBUG\",\"message\":\"Test debug event\",\"service.name\":\"testLogback\",\"service.version\":\"1\",\"log.logger\":\"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled\",\"process.thread.name\":\"main\",\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-west-1\",\"cloud.account.id\":\"012345678910\",\"faas.id\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"faas.name\":\"testFunction\",\"faas.version\":\"1\",\"faas.memory\":\"1024\",\"faas.execution\":\"RequestId\",\"faas.coldstart\":\"true\",\"trace.id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); + } + + private final LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "message", null, null); + + @Test + void shouldNotLogFunctionInfo() { + // GIVEN + LambdaEcsEncoder encoder = new LambdaEcsEncoder(); + setMDC(); + + // WHEN + byte[] encoded = encoder.encode(loggingEvent); + String result = new String(encoded, StandardCharsets.UTF_8); + + // THEN + assertThat(result).contains("\"faas.id\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"faas.name\":\"testFunction\",\"faas.version\":\"1\",\"faas.memory\":\"1024\",\"faas.execution\":\"RequestId\",\"faas.coldstart\":\"false\""); + + // WHEN (includeFaasInfo = false) + encoder.setIncludeFaasInfo(false); + encoded = encoder.encode(loggingEvent); + result = new String(encoded, StandardCharsets.UTF_8); + + // THEN (no faas info in logs) + assertThat(result).doesNotContain("faas"); + } + + @Test + void shouldNotLogCloudInfo() { + // GIVEN + LambdaEcsEncoder encoder = new LambdaEcsEncoder(); + setMDC(); + + // WHEN + byte[] encoded = encoder.encode(loggingEvent); + String result = new String(encoded, StandardCharsets.UTF_8); + + // THEN + assertThat(result).contains("\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-west-1\",\"cloud.account.id\":\"012345678910\""); + + // WHEN (includeCloudInfo = false) + encoder.setIncludeCloudInfo(false); + encoded = encoder.encode(loggingEvent); + result = new String(encoded, StandardCharsets.UTF_8); + + // THEN (no faas info in logs) + assertThat(result).doesNotContain("cloud"); + } + + @Test + void shouldLogException() { + // GIVEN + LambdaEcsEncoder encoder = new LambdaEcsEncoder(); + encoder.start(); + LoggingEvent errorloggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Error", new IllegalStateException("Unexpected value"), null); + + // WHEN + byte[] encoded = encoder.encode(errorloggingEvent); + String result = new String(encoded, StandardCharsets.UTF_8); + + // THEN + assertThat(result).contains("\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"[software.amazon.lambda.powertools.logging.internal.LambdaEcsEncoderTest.shouldLogException"); + + // WHEN (configure a custom throwableConverter) + encoder = new LambdaEcsEncoder(); + RootCauseFirstThrowableProxyConverter throwableConverter = new RootCauseFirstThrowableProxyConverter(); + encoder.setThrowableConverter(throwableConverter); + encoder.start(); + encoded = encoder.encode(errorloggingEvent); + result = new String(encoded, StandardCharsets.UTF_8); + + // THEN (stack is logged with root cause first) + assertThat(result).contains("\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"java.lang.IllegalStateException: Unexpected value\n"); + } + + private void setMDC() { + MDC.put(PowertoolsLoggedFields.FUNCTION_NAME.getName(), context.getFunctionName()); + MDC.put(PowertoolsLoggedFields.FUNCTION_ARN.getName(), context.getInvokedFunctionArn()); + MDC.put(PowertoolsLoggedFields.FUNCTION_VERSION.getName(), context.getFunctionVersion()); + MDC.put(PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE.getName(), + String.valueOf(context.getMemoryLimitInMB())); + MDC.put(PowertoolsLoggedFields.FUNCTION_REQUEST_ID.getName(), context.getAwsRequestId()); + MDC.put(PowertoolsLoggedFields.FUNCTION_COLD_START.getName(), "false"); + MDC.put(PowertoolsLoggedFields.SAMPLING_RATE.getName(), "0.2"); + MDC.put(PowertoolsLoggedFields.SERVICE.getName(), "Service"); + } + + private void setupContext() { + when(context.getFunctionName()).thenReturn("testFunction"); + when(context.getInvokedFunctionArn()).thenReturn( + "arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1"); + when(context.getFunctionVersion()).thenReturn("1"); + when(context.getMemoryLimitInMB()).thenReturn(1024); + when(context.getAwsRequestId()).thenReturn("RequestId"); + } +} diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java new file mode 100644 index 000000000..dc8ac429b --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -0,0 +1,263 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; +import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.openMocks; +import static software.amazon.lambda.powertools.logging.LoggingUtils.LOG_MESSAGES_AS_JSON; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.pattern.RootCauseFirstThrowableProxyConverter; +import ch.qos.logback.classic.spi.LoggingEvent; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import com.fasterxml.jackson.core.JsonProcessingException; +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.charset.StandardCharsets; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.TimeZone; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsJsonMessage; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled; +import software.amazon.lambda.powertools.utilities.JsonConfig; + +@Order(2) +class LambdaJsonEncoderTest { + private static final Logger logger = (Logger) LoggerFactory.getLogger(LambdaJsonEncoderTest.class.getName()); + + @Mock + private Context context; + + @BeforeAll + private static void init() { + JsonConfig.get().getObjectMapper().setSerializationInclusion(NON_NULL); + } + + @BeforeEach + void setUp() throws IllegalAccessException, IOException { + openMocks(this); + MDC.clear(); + writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); + setupContext(); + // Make sure file is cleaned up before running tests + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // file may not exist on the first launch + } + } + + @AfterEach + void cleanUp() throws IOException{ + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } + + @Test + void shouldLogInJsonFormat() { + // GIVEN + PowertoolsLogEnabled handler = new PowertoolsLogEnabled(); + + // WHEN + handler.handleRequest("Input", context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains( + "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":1,\"myKey\":\"myValue\",\"service\":\"testLogback\",\"xray_trace_id\":\"1-63441c4a-abcdef012345678912345678\",\"timestamp\":"); + } + + @Test + void shouldLogJsonMessageWithoutEscapedStrings() { + // GIVEN + PowertoolsJsonMessage requestHandler = new PowertoolsJsonMessage(); + SQSEvent.SQSMessage msg = new SQSEvent.SQSMessage(); + msg.setMessageId("1212abcd"); + msg.setBody("plop"); + msg.setEventSource("eb"); + msg.setAwsRegion("eu-west-1"); + SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); + attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); + msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); + + // WHEN + requestHandler.handleRequest(msg, context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("\"message\":{\"messageId\":\"1212abcd\",\"body\":\"plop\",\"eventSource\":\"eb\",\"awsRegion\":\"eu-west-1\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}}}") + .contains("\"message\":\"1212abcd\"") + .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"") + .doesNotContain(LOG_MESSAGES_AS_JSON); + } + + private final LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "message", null, null); + + @Test + void shouldNotLogPowertoolsInfo() { + // GIVEN + LambdaJsonEncoder encoder = new LambdaJsonEncoder(); + + MDC.put(PowertoolsLoggedFields.FUNCTION_NAME.getName(), context.getFunctionName()); + MDC.put(PowertoolsLoggedFields.FUNCTION_ARN.getName(), context.getInvokedFunctionArn()); + MDC.put(PowertoolsLoggedFields.FUNCTION_VERSION.getName(), context.getFunctionVersion()); + MDC.put(PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE.getName(), + String.valueOf(context.getMemoryLimitInMB())); + MDC.put(PowertoolsLoggedFields.FUNCTION_REQUEST_ID.getName(), context.getAwsRequestId()); + MDC.put(PowertoolsLoggedFields.FUNCTION_COLD_START.getName(), "false"); + MDC.put(PowertoolsLoggedFields.SAMPLING_RATE.getName(), "0.2"); + MDC.put(PowertoolsLoggedFields.SERVICE.getName(), "Service"); + + // WHEN + byte[] encoded = encoder.encode(loggingEvent); + String result = new String(encoded, StandardCharsets.UTF_8); + + // THEN + assertThat(result).contains("{\"level\":\"INFO\",\"message\":\"message\",\"cold_start\":false,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":1,\"sampling_rate\":0.2,\"service\":\"Service\",\"timestamp\":"); + + // WHEN (powertoolsInfo = false) + encoder.setIncludePowertoolsInfo(false); + encoded = encoder.encode(loggingEvent); + result = new String(encoded, StandardCharsets.UTF_8); + + // THEN (no powertools info in logs) + assertThat(result).doesNotContain("cold_start", "function_arn", "function_memory_size", "function_name", "function_request_id", "function_version", "sampling_rate", "service"); + } + + @Test + void shouldLogMessagesAsJsonWhenEnabledInLogbackConfig() throws JsonProcessingException { + // GIVEN + LambdaJsonEncoder encoder = new LambdaJsonEncoder(); + encoder.setLogMessagesAsJson(true); + + SQSEvent.SQSMessage msg = new SQSEvent.SQSMessage(); + msg.setMessageId("1212abcd"); + msg.setBody("plop"); + msg.setEventSource("eb"); + msg.setAwsRegion("eu-west-1"); + SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); + attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); + msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); + + // WHEN + LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, JsonConfig.get().getObjectMapper().writeValueAsString(msg), null, null); + byte[] encoded = encoder.encode(loggingEvent); + String result = new String(encoded, StandardCharsets.UTF_8); + + // THEN (logged as JSON) + assertThat(result) + .contains("\"message\":{\"messageId\":\"1212abcd\",\"body\":\"plop\",\"eventSource\":\"eb\",\"awsRegion\":\"eu-west-1\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}}}"); + + // WHEN (disabling logging as json) + encoder.setLogMessagesAsJson(false); + encoded = encoder.encode(loggingEvent); + result = new String(encoded, StandardCharsets.UTF_8); + + // THEN (logged as String) + assertThat(result) + .contains("\"message\":\"{\\\"messageId\\\":\\\"1212abcd\\\",\\\"body\\\":\\\"plop\\\",\\\"eventSource\\\":\\\"eb\\\",\\\"awsRegion\\\":\\\"eu-west-1\\\",\\\"messageAttributes\\\":{\\\"keyAttribute\\\":{\\\"stringListValues\\\":[\\\"val1\\\",\\\"val2\\\",\\\"val3\\\"]}}}\""); + } + + @Test + void shouldLogThreadInfo() { + // GIVEN + LambdaJsonEncoder encoder = new LambdaJsonEncoder(); + encoder.setIncludeThreadInfo(true); + + // WHEN + byte[] encoded = encoder.encode(loggingEvent); + String result = new String(encoded, StandardCharsets.UTF_8); + + // THEN + assertThat(result).contains("\"thread\":\"main\",\"thread_id\":1,\"thread_priority\":5"); + } + + @Test + void shouldLogTimestampDifferently() { + // GIVEN + LambdaJsonEncoder encoder = new LambdaJsonEncoder(); + String pattern = "yyyy-MM-dd_HH"; + String timeZone = "Europe/Paris"; + encoder.setTimestampFormat(pattern); + encoder.setTimestampFormatTimezoneId(timeZone); + + // WHEN + Date date = new Date(); + byte[] encoded = encoder.encode(loggingEvent); + String result = new String(encoded, StandardCharsets.UTF_8); + + // THEN + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); + simpleDateFormat.setTimeZone(TimeZone.getTimeZone(timeZone)); + assertThat(result).contains("\"timestamp\":\""+simpleDateFormat.format(date)+"\""); + } + + @Test + void shouldLogException() { + // GIVEN + LambdaJsonEncoder encoder = new LambdaJsonEncoder(); + encoder.start(); + LoggingEvent errorloggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Error", new IllegalStateException("Unexpected value"), null); + + // WHEN + byte[] encoded = encoder.encode(errorloggingEvent); + String result = new String(encoded, StandardCharsets.UTF_8); + + // THEN + assertThat(result).contains("\"message\":\"Error\",\"error\":{\"message\":\"Unexpected value\",\"name\":\"java.lang.IllegalStateException\",\"stack\":\"[software.amazon.lambda.powertools.logging.internal.LambdaJsonEncoderTest.shouldLogException"); + + // WHEN (configure a custom throwableConverter) + encoder = new LambdaJsonEncoder(); + RootCauseFirstThrowableProxyConverter throwableConverter = new RootCauseFirstThrowableProxyConverter(); + encoder.setThrowableConverter(throwableConverter); + encoder.start(); + encoded = encoder.encode(errorloggingEvent); + result = new String(encoded, StandardCharsets.UTF_8); + + // THEN (stack is logged with root cause first) + assertThat(result).contains("\"message\":\"Error\",\"error\":{\"message\":\"Unexpected value\",\"name\":\"java.lang.IllegalStateException\",\"stack\":\"java.lang.IllegalStateException: Unexpected value\n"); + } + + private void setupContext() { + when(context.getFunctionName()).thenReturn("testFunction"); + when(context.getInvokedFunctionArn()).thenReturn( + "arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1"); + when(context.getFunctionVersion()).thenReturn("1"); + when(context.getMemoryLimitInMB()).thenReturn(1024); + when(context.getAwsRequestId()).thenReturn("RequestId"); + } +} diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java new file mode 100644 index 000000000..fdc279319 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java @@ -0,0 +1,44 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal.handler; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.utilities.JsonConfig; + +public class PowertoolsJsonMessage implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsJsonMessage.class); + + @Override + @Logging(clearState = true) + public String handleRequest(SQSEvent.SQSMessage input, Context context) { + try { + LoggingUtils.logMessagesAsJson(true); + LoggingUtils.setCorrelationId(input.getMessageId()); + LOG.debug(JsonConfig.get().getObjectMapper().writeValueAsString(input)); + LOG.debug("{}", input.getMessageId()); + LOG.warn("Message body = {} and id = \"{}\"", input.getBody(), input.getMessageId()); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + return input.getMessageId(); + } +} diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java new file mode 100644 index 000000000..faa722756 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal.handler; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.LoggingUtils; + +public class PowertoolsLogEnabled implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogEnabled.class); + + @Override + @Logging(clearState = true) + public Object handleRequest(Object input, Context context) { + LoggingUtils.appendKey("myKey", "myValue"); + LOG.debug("Test debug event"); + return null; + } +} diff --git a/powertools-logging/powertools-logging-logback/src/test/resources/junit-platform.properties b/powertools-logging/powertools-logging-logback/src/test/resources/junit-platform.properties new file mode 100644 index 000000000..80a2481d7 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/resources/junit-platform.properties @@ -0,0 +1,17 @@ +# +# Copyright 2023 Amazon.com, Inc. or its affiliates. +# Licensed under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +# because of LambdaLoggingAspect static initialization of the LoggingManager, we need to +# set an order in the unit tests, especially LambdaLoggingAspectTest needs to be first +junit.jupiter.testclass.order.default=org.junit.jupiter.api.ClassOrderer$OrderAnnotation \ No newline at end of file diff --git a/powertools-logging/powertools-logging-logback/src/test/resources/logback-test.xml b/powertools-logging/powertools-logging-logback/src/test/resources/logback-test.xml new file mode 100644 index 000000000..e118a03de --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/resources/logback-test.xml @@ -0,0 +1,27 @@ + + + + + + + + target/logfile.json + + + + + + target/ecslogfile.json + + + + + + + + + + + + + \ No newline at end of file diff --git a/powertools-logging/spotbugs-exclude.xml b/powertools-logging/spotbugs-exclude.xml new file mode 100644 index 000000000..0437849ae --- /dev/null +++ b/powertools-logging/spotbugs-exclude.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPathConstants.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPaths.java similarity index 69% rename from powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPathConstants.java rename to powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPaths.java index ce43c9aa0..6fb38502f 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPathConstants.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/CorrelationIdPaths.java @@ -17,21 +17,25 @@ /** * Supported Event types from which Correlation ID can be extracted */ -public class CorrelationIdPathConstants { +public class CorrelationIdPaths { /** * To use when function is expecting API Gateway Rest API Request event */ - public static final String API_GATEWAY_REST = "/requestContext/requestId"; + public static final String API_GATEWAY_REST = "requestContext.requestId"; /** * To use when function is expecting API Gateway HTTP API Request event */ - public static final String API_GATEWAY_HTTP = "/requestContext/requestId"; + public static final String API_GATEWAY_HTTP = "requestContext.requestId"; /** * To use when function is expecting Application Load balancer Request event */ - public static final String APPLICATION_LOAD_BALANCER = "/headers/x-amzn-trace-id"; + public static final String APPLICATION_LOAD_BALANCER = "headers.\"x-amzn-trace-id\""; /** * To use when function is expecting Event Bridge Request event */ - public static final String EVENT_BRIDGE = "/id"; + public static final String EVENT_BRIDGE = "id"; + /** + * To use when function is expecting an AppSync request + */ + public static final String APPSYNC_RESOLVER = "request.headers.\"x-amzn-trace-id\""; } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java index 9932eb700..05a9cfe31 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java @@ -34,18 +34,19 @@ * {@code com.amazonaws.services.lambda.runtime.Context}

* *
    - *
  • FunctionName
  • - *
  • FunctionVersion
  • - *
  • InvokedFunctionArn
  • - *
  • MemoryLimitInMB
  • + *
  • function_name
  • + *
  • function_version
  • + *
  • function_arn
  • + *
  • function_memory_size
  • + *
  • function_request_id
  • *
* *

By default {@code Logging} will also create keys for:

* *
    - *
  • coldStart - True if this is the first invocation of this Lambda execution environment; else False
  • + *
  • cold_start - True if this is the first invocation of this Lambda execution environment; else False
  • *
  • service - The value of the 'POWER_TOOLS_SERVICE_NAME' environment variable or 'service_undefined'
  • - *
  • samplingRate - The value of the 'POWERTOOLS_LOGGER_SAMPLE_RATE' environment variable or value of samplingRate field or 0. + *
  • sampling_rate - The value of the 'POWERTOOLS_LOGGER_SAMPLE_RATE' environment variable or value of sampling_rate field or 0. * Valid value is from 0.0 to 1.0. Value outside this range is silently ignored.
  • *
* @@ -56,17 +57,35 @@ *

By default {@code Logging} will not log the event which has trigger the invoke of the Lambda function. * This can be enabled using {@code @Logging(logEvent = true)}.

* - *

By default {@code Logging} all debug logs will follow log4j2 configuration unless configured via - * POWERTOOLS_LOGGER_SAMPLE_RATE environment variable {@code @Logging(samplingRate = <0.0-1.0>)}.

- * *

To append additional keys to each log entry you can use {@link LoggingUtils#appendKey(String, String)}

*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Logging { + /** + * Set to true if you want to log the event received by the Lambda function handler.
+ * Can also be configured with the 'POWERTOOLS_LOGGER_LOG_EVENT' environment variable + */ boolean logEvent() default false; + /** + * Set to true if you want to log the response sent by the Lambda function handler.
+ * Can also be configured with the 'POWERTOOLS_LOGGER_LOG_RESPONE' environment variable + */ + boolean logResponse() default false; + + /** + * Set to true if you want to log the exception thrown by the Lambda function handler. + * It is already logged by AWS Lambda but with no context information. Setting this to true + * will log the exception and all the powertools additional fields, for more context.
+ * Can also be configured with the 'POWERTOOLS_LOGGER_LOG_ERROR' environment variable + */ + boolean logError() default false; + + /** + * Sampling rate to change log level to DEBUG. (values must be >=0.0, <=1.0) + */ double samplingRate() default 0; /** diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java index 6e11573cc..d7ceb8ccd 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java @@ -14,18 +14,22 @@ package software.amazon.lambda.powertools.logging; -import static java.util.Arrays.asList; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID; import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.Arrays; import java.util.Map; -import org.apache.logging.log4j.ThreadContext; +import org.slf4j.MDC; +import software.amazon.lambda.powertools.utilities.JsonConfig; /** - * A class of helper functions to add additional functionality to Logging. - *

- * {@see Logging} + * A class of helper functions to add functionality to Logging. + * Adding/removing keys is based on MDC, which is ThreadSafe. */ public final class LoggingUtils { + + public static final String LOG_MESSAGES_AS_JSON = "PowertoolsLogMessagesAsJson"; + private static ObjectMapper objectMapper; private LoggingUtils() { @@ -39,7 +43,7 @@ private LoggingUtils() { * @param value The value to be logged */ public static void appendKey(String key, String value) { - ThreadContext.put(key, value); + MDC.put(key, value); } @@ -50,7 +54,7 @@ public static void appendKey(String key, String value) { * @param customKeys Map of custom keys values to be appended to logs */ public static void appendKeys(Map customKeys) { - ThreadContext.putAll(customKeys); + customKeys.forEach(MDC::put); } /** @@ -59,7 +63,7 @@ public static void appendKeys(Map customKeys) { * @param customKey The name of the key to be logged */ public static void removeKey(String customKey) { - ThreadContext.remove(customKey); + MDC.remove(customKey); } @@ -69,7 +73,7 @@ public static void removeKey(String customKey) { * @param keys Map of custom keys values to be appended to logs */ public static void removeKeys(String... keys) { - ThreadContext.removeAll(asList(keys)); + Arrays.stream(keys).forEach(MDC::remove); } /** @@ -78,24 +82,42 @@ public static void removeKeys(String... keys) { * @param value The value of the correlation id */ public static void setCorrelationId(String value) { - ThreadContext.put("correlation_id", value); + MDC.put(CORRELATION_ID.getName(), value); + } + + /** + * Get correlation id attribute. Maybe null. + * @return correlation id set `@Logging(correlationIdPath="JMESPATH Expression")` or `LoggingUtils.setCorrelationId("value")` + */ + public static String getCorrelationId() { + return MDC.get(CORRELATION_ID.getName()); + } + + /** + * When set to true, will log messages as JSON (without escaping string). + * Useful to log events or big JSON objects. + * @param value boolean to specify if yes or no messages should be logged as JSON (default is false) + */ + public static void logMessagesAsJson(boolean value) { + MDC.put(LOG_MESSAGES_AS_JSON, String.valueOf(value)); } /** * Sets the instance of ObjectMapper object which is used for serialising event when - * {@code @Logging(logEvent = true)}. + * {@code @Logging(logEvent = true, logResponse = true)}. + * + * Not Thread Safe, the object mapper is static, changing it in different threads can lead to unexpected behaviour * * @param objectMapper Custom implementation of object mapper to be used for logging serialised event */ - public static void defaultObjectMapper(ObjectMapper objectMapper) { + public static void setObjectMapper(ObjectMapper objectMapper) { LoggingUtils.objectMapper = objectMapper; } - public static ObjectMapper objectMapper() { - if (null == objectMapper) { - objectMapper = new ObjectMapper(); + public static ObjectMapper getObjectMapper() { + if (LoggingUtils.objectMapper == null) { + LoggingUtils.objectMapper = JsonConfig.get().getObjectMapper(); } - - return objectMapper; + return LoggingUtils.objectMapper; } } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/AbstractJacksonLayoutCopy.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/AbstractJacksonLayoutCopy.java deleted file mode 100644 index 17d09729f..000000000 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/AbstractJacksonLayoutCopy.java +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging.internal; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonRootName; -import com.fasterxml.jackson.annotation.JsonUnwrapped; -import com.fasterxml.jackson.core.JsonGenerationException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectWriter; -import java.io.IOException; -import java.io.Writer; -import java.nio.charset.Charset; -import java.util.LinkedHashMap; -import java.util.Map; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.Marker; -import org.apache.logging.log4j.ThreadContext; -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; -import org.apache.logging.log4j.core.config.plugins.PluginElement; -import org.apache.logging.log4j.core.impl.Log4jLogEvent; -import org.apache.logging.log4j.core.impl.ThrowableProxy; -import org.apache.logging.log4j.core.jackson.XmlConstants; -import org.apache.logging.log4j.core.layout.AbstractStringLayout; -import org.apache.logging.log4j.core.lookup.StrSubstitutor; -import org.apache.logging.log4j.core.time.Instant; -import org.apache.logging.log4j.core.util.KeyValuePair; -import org.apache.logging.log4j.core.util.StringBuilderWriter; -import org.apache.logging.log4j.message.Message; -import org.apache.logging.log4j.util.ReadOnlyStringMap; -import org.apache.logging.log4j.util.Strings; - -@Deprecated -abstract class AbstractJacksonLayoutCopy extends AbstractStringLayout { - - protected static final String DEFAULT_EOL = "\r\n"; - protected static final String COMPACT_EOL = Strings.EMPTY; - protected final String eol; - protected final ObjectWriter objectWriter; - protected final boolean compact; - protected final boolean complete; - protected final boolean includeNullDelimiter; - protected final ResolvableKeyValuePair[] additionalFields; - - @Deprecated - protected AbstractJacksonLayoutCopy(final Configuration config, final ObjectWriter objectWriter, - final Charset charset, - final boolean compact, final boolean complete, final boolean eventEol, - final Serializer headerSerializer, - final Serializer footerSerializer) { - this(config, objectWriter, charset, compact, complete, eventEol, headerSerializer, footerSerializer, false); - } - - @Deprecated - protected AbstractJacksonLayoutCopy(final Configuration config, final ObjectWriter objectWriter, - final Charset charset, - final boolean compact, final boolean complete, final boolean eventEol, - final Serializer headerSerializer, - final Serializer footerSerializer, final boolean includeNullDelimiter) { - this(config, objectWriter, charset, compact, complete, eventEol, null, headerSerializer, footerSerializer, - includeNullDelimiter, null); - } - - protected AbstractJacksonLayoutCopy(final Configuration config, final ObjectWriter objectWriter, - final Charset charset, - final boolean compact, final boolean complete, final boolean eventEol, - final String endOfLine, final Serializer headerSerializer, - final Serializer footerSerializer, final boolean includeNullDelimiter, - final KeyValuePair[] additionalFields) { - super(config, charset, headerSerializer, footerSerializer); - this.objectWriter = objectWriter; - this.compact = compact; - this.complete = complete; - this.eol = endOfLine != null ? endOfLine : compact && !eventEol ? COMPACT_EOL : DEFAULT_EOL; - this.includeNullDelimiter = includeNullDelimiter; - this.additionalFields = prepareAdditionalFields(config, additionalFields); - } - - protected static boolean valueNeedsLookup(final String value) { - return value != null && value.contains("${"); - } - - private static ResolvableKeyValuePair[] prepareAdditionalFields(final Configuration config, - final KeyValuePair[] additionalFields) { - if (additionalFields == null || additionalFields.length == 0) { - // No fields set - return ResolvableKeyValuePair.EMPTY_ARRAY; - } - - // Convert to specific class which already determines whether values needs lookup during serialization - final ResolvableKeyValuePair[] resolvableFields = new ResolvableKeyValuePair[additionalFields.length]; - - for (int i = 0; i < additionalFields.length; i++) { - final ResolvableKeyValuePair resolvable = - resolvableFields[i] = new ResolvableKeyValuePair(additionalFields[i]); - - // Validate - if (config == null && resolvable.valueNeedsLookup) { - throw new IllegalArgumentException( - "configuration needs to be set when there are additional fields with variables"); - } - } - - return resolvableFields; - } - - private static LogEvent convertMutableToLog4jEvent(final LogEvent event) { - return event instanceof Log4jLogEvent ? event : Log4jLogEvent.createMemento(event); - } - - /** - * Formats a {@link org.apache.logging.log4j.core.LogEvent}. - * - * @param event The LogEvent. - * @return The XML representation of the LogEvent. - */ - @Override - public String toSerializable(final LogEvent event) { - final StringBuilderWriter writer = new StringBuilderWriter(); - try { - toSerializable(event, writer); - return writer.toString(); - } catch (final IOException e) { - // Should this be an ISE or IAE? - LOGGER.error(e); - return Strings.EMPTY; - } - } - - protected Object wrapLogEvent(final LogEvent event) { - if (additionalFields.length > 0) { - // Construct map for serialization - note that we are intentionally using original LogEvent - final Map additionalFieldsMap = resolveAdditionalFields(event); - // This class combines LogEvent with AdditionalFields during serialization - return new LogEventWithAdditionalFields(event, additionalFieldsMap); - } else if (event instanceof Message) { - // If the LogEvent implements the Messagee interface Jackson will not treat is as a LogEvent. - return new ReadOnlyLogEventWrapper(event); - } else { - // No additional fields, return original object - return event; - } - } - - private Map resolveAdditionalFields(final LogEvent logEvent) { - // Note: LinkedHashMap retains order - final Map additionalFieldsMap = new LinkedHashMap<>(additionalFields.length); - final StrSubstitutor strSubstitutor = configuration.getStrSubstitutor(); - - // Go over each field - for (final ResolvableKeyValuePair pair : additionalFields) { - if (pair.valueNeedsLookup) { - // Resolve value - additionalFieldsMap.put(pair.key, strSubstitutor.replace(logEvent, pair.value)); - } else { - // Plain text value - additionalFieldsMap.put(pair.key, pair.value); - } - } - - return additionalFieldsMap; - } - - public void toSerializable(final LogEvent event, final Writer writer) - throws JsonGenerationException, JsonMappingException, IOException { - objectWriter.writeValue(writer, wrapLogEvent(convertMutableToLog4jEvent(event))); - writer.write(eol); - if (includeNullDelimiter) { - writer.write('\0'); - } - markEvent(); - } - - public static abstract class Builder> extends AbstractStringLayout.Builder { - - @PluginBuilderAttribute - private boolean eventEol; - - @PluginBuilderAttribute - private String endOfLine; - - @PluginBuilderAttribute - private boolean compact; - - @PluginBuilderAttribute - private boolean complete; - - @PluginBuilderAttribute - private boolean locationInfo; - - @PluginBuilderAttribute - private boolean properties; - - @PluginBuilderAttribute - private boolean includeStacktrace = true; - - @PluginBuilderAttribute - private boolean stacktraceAsString = false; - - @PluginBuilderAttribute - private boolean includeNullDelimiter = false; - - @PluginBuilderAttribute - private boolean includeTimeMillis = false; - - @PluginElement("AdditionalField") - private KeyValuePair[] additionalFields; - - protected String toStringOrNull(final byte[] header) { - return header == null ? null : new String(header, Charset.defaultCharset()); - } - - public boolean getEventEol() { - return eventEol; - } - - public B setEventEol(final boolean eventEol) { - this.eventEol = eventEol; - return asBuilder(); - } - - public String getEndOfLine() { - return endOfLine; - } - - public B setEndOfLine(final String endOfLine) { - this.endOfLine = endOfLine; - return asBuilder(); - } - - public boolean isCompact() { - return compact; - } - - public B setCompact(final boolean compact) { - this.compact = compact; - return asBuilder(); - } - - public boolean isComplete() { - return complete; - } - - public B setComplete(final boolean complete) { - this.complete = complete; - return asBuilder(); - } - - public boolean isLocationInfo() { - return locationInfo; - } - - public B setLocationInfo(final boolean locationInfo) { - this.locationInfo = locationInfo; - return asBuilder(); - } - - public boolean isProperties() { - return properties; - } - - public B setProperties(final boolean properties) { - this.properties = properties; - return asBuilder(); - } - - /** - * If "true", includes the stacktrace of any Throwable in the generated data, defaults to "true". - * - * @return If "true", includes the stacktrace of any Throwable in the generated data, defaults to "true". - */ - public boolean isIncludeStacktrace() { - return includeStacktrace; - } - - /** - * If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". - * - * @param includeStacktrace If "true", includes the stacktrace of any Throwable in the generated JSON, defaults to "true". - * @return this builder - */ - public B setIncludeStacktrace(final boolean includeStacktrace) { - this.includeStacktrace = includeStacktrace; - return asBuilder(); - } - - public boolean isStacktraceAsString() { - return stacktraceAsString; - } - - /** - * Whether to format the stacktrace as a string, and not a nested object (optional, defaults to false). - * - * @return this builder - */ - public B setStacktraceAsString(final boolean stacktraceAsString) { - this.stacktraceAsString = stacktraceAsString; - return asBuilder(); - } - - public boolean isIncludeNullDelimiter() { - return includeNullDelimiter; - } - - /** - * Whether to include NULL byte as delimiter after each event (optional, default to false). - * - * @return this builder - */ - public B setIncludeNullDelimiter(final boolean includeNullDelimiter) { - this.includeNullDelimiter = includeNullDelimiter; - return asBuilder(); - } - - public boolean isIncludeTimeMillis() { - return includeTimeMillis; - } - - /** - * Whether to include the timestamp (in addition to the Instant) (optional, default to false). - * - * @return this builder - */ - public B setIncludeTimeMillis(final boolean includeTimeMillis) { - this.includeTimeMillis = includeTimeMillis; - return asBuilder(); - } - - public KeyValuePair[] getAdditionalFields() { - return additionalFields; - } - - /** - * Additional fields to set on each log event. - * - * @return this builder - */ - public B setAdditionalFields(final KeyValuePair[] additionalFields) { - this.additionalFields = additionalFields; - return asBuilder(); - } - } - - @JsonRootName(XmlConstants.ELT_EVENT) - public static class LogEventWithAdditionalFields { - - private final Object logEvent; - private final Map additionalFields; - - public LogEventWithAdditionalFields(final Object logEvent, final Map additionalFields) { - this.logEvent = logEvent; - this.additionalFields = additionalFields; - } - - @JsonUnwrapped - public Object getLogEvent() { - return logEvent; - } - - @JsonAnyGetter - @SuppressWarnings("unused") - public Map getAdditionalFields() { - return additionalFields; - } - } - - protected static class ResolvableKeyValuePair { - - /** - * The empty array. - */ - static final ResolvableKeyValuePair[] EMPTY_ARRAY = {}; - - final String key; - final String value; - final boolean valueNeedsLookup; - - ResolvableKeyValuePair(final KeyValuePair pair) { - this.key = pair.getKey(); - this.value = pair.getValue(); - this.valueNeedsLookup = AbstractJacksonLayoutCopy.valueNeedsLookup(this.value); - } - } - - private static class ReadOnlyLogEventWrapper implements LogEvent { - - @JsonIgnore - private final LogEvent event; - - public ReadOnlyLogEventWrapper(LogEvent event) { - this.event = event; - } - - @Override - public LogEvent toImmutable() { - return event.toImmutable(); - } - - @Override - public Map getContextMap() { - return event.getContextMap(); - } - - @Override - public ReadOnlyStringMap getContextData() { - return event.getContextData(); - } - - @Override - public ThreadContext.ContextStack getContextStack() { - return event.getContextStack(); - } - - @Override - public String getLoggerFqcn() { - return event.getLoggerFqcn(); - } - - @Override - public Level getLevel() { - return event.getLevel(); - } - - @Override - public String getLoggerName() { - return event.getLoggerName(); - } - - @Override - public Marker getMarker() { - return event.getMarker(); - } - - @Override - public Message getMessage() { - return event.getMessage(); - } - - @Override - public long getTimeMillis() { - return event.getTimeMillis(); - } - - @Override - public Instant getInstant() { - return event.getInstant(); - } - - @Override - public StackTraceElement getSource() { - return event.getSource(); - } - - @Override - public String getThreadName() { - return event.getThreadName(); - } - - @Override - public long getThreadId() { - return event.getThreadId(); - } - - @Override - public int getThreadPriority() { - return event.getThreadPriority(); - } - - @Override - public Throwable getThrown() { - return event.getThrown(); - } - - @Override - public ThrowableProxy getThrownProxy() { - return event.getThrownProxy(); - } - - @Override - public boolean isEndOfBatch() { - return event.isEndOfBatch(); - } - - @Override - public void setEndOfBatch(boolean endOfBatch) { - - } - - @Override - public boolean isIncludeLocation() { - return event.isIncludeLocation(); - } - - @Override - public void setIncludeLocation(boolean locationRequired) { - - } - - @Override - public long getNanoTime() { - return event.getNanoTime(); - } - } -} \ No newline at end of file diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefautlLoggingManager.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefautlLoggingManager.java new file mode 100644 index 000000000..5326f53e6 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefautlLoggingManager.java @@ -0,0 +1,35 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import org.slf4j.Logger; +import org.slf4j.event.Level; + +/** + * When no LoggingManager is found, setting a default one with no action on logging implementation + * Powertools cannot change the log level based on the environment variable, will use the logger configuration + */ +public class DefautlLoggingManager implements LoggingManager { + + @Override + public void setLogLevel(Level logLevel) { + // do nothing + } + + @Override + public Level getLogLevel(Logger logger) { + return Level.ERROR; + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JacksonFactoryCopy.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JacksonFactoryCopy.java deleted file mode 100644 index 6b568be30..000000000 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JacksonFactoryCopy.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging.internal; - -import com.fasterxml.jackson.core.PrettyPrinter; -import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; -import com.fasterxml.jackson.core.util.MinimalPrettyPrinter; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; -import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; -import java.util.HashSet; -import java.util.Set; -import org.apache.logging.log4j.core.impl.Log4jLogEvent; -import org.apache.logging.log4j.core.jackson.JsonConstants; -import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper; - -@Deprecated -abstract class JacksonFactoryCopy { - - abstract protected String getPropertyNameForTimeMillis(); - - abstract protected String getPropertyNameForInstant(); - - abstract protected String getPropertNameForContextMap(); - - abstract protected String getPropertNameForSource(); - - abstract protected String getPropertNameForNanoTime(); - - abstract protected PrettyPrinter newCompactPrinter(); - - abstract protected ObjectMapper newObjectMapper(); - - abstract protected PrettyPrinter newPrettyPrinter(); - - ObjectWriter newWriter(final boolean locationInfo, final boolean properties, final boolean compact) { - return newWriter(locationInfo, properties, compact, false); - } - - ObjectWriter newWriter(final boolean locationInfo, final boolean properties, final boolean compact, - final boolean includeMillis) { - final SimpleFilterProvider filters = new SimpleFilterProvider(); - final Set except = new HashSet<>(3); - if (!locationInfo) { - except.add(this.getPropertNameForSource()); - } - if (!properties) { - except.add(this.getPropertNameForContextMap()); - } - if (includeMillis) { - except.add(getPropertyNameForInstant()); - } else { - except.add(getPropertyNameForTimeMillis()); - } - except.add(this.getPropertNameForNanoTime()); - filters.addFilter(Log4jLogEvent.class.getName(), SimpleBeanPropertyFilter.serializeAllExcept(except)); - final ObjectWriter writer = - this.newObjectMapper().writer(compact ? this.newCompactPrinter() : this.newPrettyPrinter()); - return writer.with(filters); - } - - static class JSON extends JacksonFactoryCopy { - - private final boolean encodeThreadContextAsList; - private final boolean includeStacktrace; - private final boolean stacktraceAsString; - private final boolean objectMessageAsJsonObject; - - public JSON(final boolean encodeThreadContextAsList, final boolean includeStacktrace, - final boolean stacktraceAsString, final boolean objectMessageAsJsonObject) { - this.encodeThreadContextAsList = encodeThreadContextAsList; - this.includeStacktrace = includeStacktrace; - this.stacktraceAsString = stacktraceAsString; - this.objectMessageAsJsonObject = objectMessageAsJsonObject; - } - - @Override - protected String getPropertNameForContextMap() { - return JsonConstants.ELT_CONTEXT_MAP; - } - - @Override - protected String getPropertyNameForTimeMillis() { - return JsonConstants.ELT_TIME_MILLIS; - } - - @Override - protected String getPropertyNameForInstant() { - return JsonConstants.ELT_INSTANT; - } - - @Override - protected String getPropertNameForSource() { - return JsonConstants.ELT_SOURCE; - } - - @Override - protected String getPropertNameForNanoTime() { - return JsonConstants.ELT_NANO_TIME; - } - - @Override - protected PrettyPrinter newCompactPrinter() { - return new MinimalPrettyPrinter(); - } - - @Override - protected ObjectMapper newObjectMapper() { - return new Log4jJsonObjectMapper(encodeThreadContextAsList, includeStacktrace, stacktraceAsString, - objectMessageAsJsonObject); - } - - @Override - protected PrettyPrinter newPrettyPrinter() { - return new DefaultPrettyPrinter(); - } - - } - -} \ No newline at end of file diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonLayout.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonLayout.java deleted file mode 100644 index fd646ab50..000000000 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonLayout.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging.internal; - -import static java.time.Instant.ofEpochMilli; -import static java.time.format.DateTimeFormatter.ISO_ZONED_DATE_TIME; - -import com.fasterxml.jackson.annotation.JsonAnyGetter; -import com.fasterxml.jackson.annotation.JsonGetter; -import com.fasterxml.jackson.annotation.JsonRootName; -import com.fasterxml.jackson.annotation.JsonUnwrapped; -import java.io.IOException; -import java.io.Writer; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import org.apache.logging.log4j.core.Layout; -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.DefaultConfiguration; -import org.apache.logging.log4j.core.config.Node; -import org.apache.logging.log4j.core.config.plugins.Plugin; -import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute; -import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory; -import org.apache.logging.log4j.core.jackson.XmlConstants; -import org.apache.logging.log4j.core.layout.PatternLayout; -import org.apache.logging.log4j.core.util.KeyValuePair; -import org.apache.logging.log4j.util.Strings; - -/*** - * Note: The LambdaJsonLayout should be considered to be deprecated. Please use JsonTemplateLayout instead. - */ -@Deprecated -@Plugin(name = "LambdaJsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true) -public final class LambdaJsonLayout extends AbstractJacksonLayoutCopy { - static final String CONTENT_TYPE = "application/json"; - private static final String DEFAULT_FOOTER = "]"; - private static final String DEFAULT_HEADER = "["; - - private LambdaJsonLayout(final Configuration config, final boolean locationInfo, final boolean properties, - final boolean encodeThreadContextAsList, - final boolean complete, final boolean compact, final boolean eventEol, - final String headerPattern, final String footerPattern, final Charset charset, - final boolean includeStacktrace, final boolean stacktraceAsString, - final boolean includeNullDelimiter, - final KeyValuePair[] additionalFields, final boolean objectMessageAsJsonObject) { - super(config, new JacksonFactoryCopy.JSON(encodeThreadContextAsList, includeStacktrace, stacktraceAsString, - objectMessageAsJsonObject).newWriter( - locationInfo, properties, compact), - charset, compact, complete, eventEol, - null, - PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern) - .setDefaultPattern(DEFAULT_HEADER).build(), - PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern) - .setDefaultPattern(DEFAULT_FOOTER).build(), - includeNullDelimiter, - additionalFields); - } - - @PluginBuilderFactory - public static > B newBuilder() { - return new Builder().asBuilder(); - } - - /** - * Creates a JSON Layout using the default settings. Useful for testing. - * - * @return A JSON Layout. - */ - public static LambdaJsonLayout createDefaultLayout() { - return new LambdaJsonLayout(new DefaultConfiguration(), false, false, false, false, false, false, - DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, null, false); - } - - /** - * Returns appropriate JSON header. - * - * @return a byte array containing the header, opening the JSON array. - */ - @Override - public byte[] getHeader() { - if (!this.complete) { - return null; - } - final StringBuilder buf = new StringBuilder(); - final String str = serializeToString(getHeaderSerializer()); - if (str != null) { - buf.append(str); - } - buf.append(this.eol); - return getBytes(buf.toString()); - } - - /** - * Returns appropriate JSON footer. - * - * @return a byte array containing the footer, closing the JSON array. - */ - @Override - public byte[] getFooter() { - if (!this.complete) { - return null; - } - final StringBuilder buf = new StringBuilder(); - buf.append(this.eol); - final String str = serializeToString(getFooterSerializer()); - if (str != null) { - buf.append(str); - } - buf.append(this.eol); - return getBytes(buf.toString()); - } - - @Override - public Map getContentFormat() { - final Map result = new HashMap<>(); - result.put("version", "2.0"); - return result; - } - - /** - * @return The content type. - */ - @Override - public String getContentType() { - return CONTENT_TYPE + "; charset=" + this.getCharset(); - } - - @Override - public Object wrapLogEvent(final LogEvent event) { - Map additionalFieldsMap = resolveAdditionalFields(event); - // This class combines LogEvent with AdditionalFields during serialization - return new LogEventWithAdditionalFields(event, additionalFieldsMap); - } - - @Override - public void toSerializable(final LogEvent event, final Writer writer) throws IOException { - if (complete && eventCount > 0) { - writer.append(", "); - } - super.toSerializable(event, writer); - } - - private Map resolveAdditionalFields(LogEvent logEvent) { - // Note: LinkedHashMap retains order - final Map additionalFieldsMap = new LinkedHashMap<>(additionalFields.length); - - // Go over MDC - logEvent.getContextData().forEach((key, value) -> - { - if (Strings.isNotBlank(key) && value != null) { - additionalFieldsMap.put(key, value); - } - }); - - return additionalFieldsMap; - } - - public static class Builder> extends AbstractJacksonLayoutCopy.Builder - implements org.apache.logging.log4j.core.util.Builder { - - @PluginBuilderAttribute - private boolean propertiesAsList; - - @PluginBuilderAttribute - private boolean objectMessageAsJsonObject; - - public Builder() { - super(); - setCharset(StandardCharsets.UTF_8); - } - - @Override - public LambdaJsonLayout build() { - final boolean encodeThreadContextAsList = isProperties() && propertiesAsList; - final String headerPattern = toStringOrNull(getHeader()); - final String footerPattern = toStringOrNull(getFooter()); - return new LambdaJsonLayout(getConfiguration(), isLocationInfo(), isProperties(), encodeThreadContextAsList, - isComplete(), isCompact(), getEventEol(), headerPattern, footerPattern, getCharset(), - isIncludeStacktrace(), isStacktraceAsString(), isIncludeNullDelimiter(), - getAdditionalFields(), getObjectMessageAsJsonObject()); - } - - public boolean isPropertiesAsList() { - return propertiesAsList; - } - - public B setPropertiesAsList(final boolean propertiesAsList) { - this.propertiesAsList = propertiesAsList; - return asBuilder(); - } - - public boolean getObjectMessageAsJsonObject() { - return objectMessageAsJsonObject; - } - - public B setObjectMessageAsJsonObject(final boolean objectMessageAsJsonObject) { - this.objectMessageAsJsonObject = objectMessageAsJsonObject; - return asBuilder(); - } - } - - @JsonRootName(XmlConstants.ELT_EVENT) - public static class LogEventWithAdditionalFields { - - private final LogEvent logEvent; - private final Map additionalFields; - - public LogEventWithAdditionalFields(LogEvent logEvent, Map additionalFields) { - this.logEvent = logEvent; - this.additionalFields = additionalFields; - } - - @JsonUnwrapped - public Object getLogEvent() { - return logEvent; - } - - @JsonAnyGetter - public Map getAdditionalFields() { - return additionalFields; - } - - @JsonGetter("timestamp") - public String getTimestamp() { - return ISO_ZONED_DATE_TIME.format( - ZonedDateTime.from(ofEpochMilli(logEvent.getTimeMillis()).atZone(ZoneId.systemDefault()))); - } - } -} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java index 2e17ce692..48f67700d 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java @@ -27,80 +27,146 @@ import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.serviceName; import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKey; import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKeys; -import static software.amazon.lambda.powertools.logging.LoggingUtils.objectMapper; import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.LAMBDA_LOG_LEVEL; +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_ERROR; +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_EVENT; +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_LEVEL; +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_RESPONSE; +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_SAMPLING_RATE; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SERVICE; import com.amazonaws.services.lambda.runtime.Context; -import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; - +import io.burt.jmespath.Expression; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.util.Map; +import java.io.PrintStream; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Optional; import java.util.Random; - -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.ThreadContext; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.Configurator; -import org.apache.logging.log4j.core.util.IOUtils; +import java.util.ServiceLoader; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.DeclarePrecedence; import org.aspectj.lang.annotation.Pointcut; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.MarkerFactory; +import org.slf4j.event.Level; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.utilities.JsonConfig; + @Aspect @DeclarePrecedence("*, software.amazon.lambda.powertools.logging.internal.LambdaLoggingAspect") public final class LambdaLoggingAspect { - private static final Logger LOG = LogManager.getLogger(LambdaLoggingAspect.class); - private static final String POWERTOOLS_LOG_LEVEL = System.getenv("POWERTOOLS_LOG_LEVEL"); - + private static final Logger LOG = LoggerFactory.getLogger(LambdaLoggingAspect.class); private static final Random SAMPLER = new Random(); - private static final String SAMPLING_RATE = System.getenv("POWERTOOLS_LOGGER_SAMPLE_RATE"); - private static Boolean LOG_EVENT; + private static Level LEVEL_AT_INITIALISATION; /* not final for test purpose */ - private static Level LEVEL_AT_INITIALISATION; + private static final LoggingManager LOGGING_MANAGER; static { + LOGGING_MANAGER = getLoggingManagerFromServiceLoader(); + + setLogLevel(); + + LEVEL_AT_INITIALISATION = LOGGING_MANAGER.getLogLevel(LOG); + } + + static void setLogLevel() { if (POWERTOOLS_LOG_LEVEL != null) { - Level powertoolsLevel = Level.getLevel(POWERTOOLS_LOG_LEVEL); + Level powertoolsLevel = getLevelFromString(POWERTOOLS_LOG_LEVEL); if (LAMBDA_LOG_LEVEL != null) { - Level lambdaLevel = Level.getLevel(LAMBDA_LOG_LEVEL); - if (powertoolsLevel.intLevel() > lambdaLevel.intLevel()) { + Level lambdaLevel = getLevelFromString(LAMBDA_LOG_LEVEL); + if (powertoolsLevel.toInt() < lambdaLevel.toInt()) { LOG.warn("Current log level ({}) does not match AWS Lambda Advanced Logging Controls minimum log level ({}). This can lead to data loss, consider adjusting them.", POWERTOOLS_LOG_LEVEL, LAMBDA_LOG_LEVEL); } } - resetLogLevels(powertoolsLevel); + setLogLevels(powertoolsLevel); } else if (LAMBDA_LOG_LEVEL != null) { - resetLogLevels(Level.getLevel(LAMBDA_LOG_LEVEL)); + setLogLevels(getLevelFromString(LAMBDA_LOG_LEVEL)); } + } - LEVEL_AT_INITIALISATION = LOG.getLevel(); + private static Level getLevelFromString(String level) { + if (Arrays.stream(Level.values()).anyMatch(slf4jLevel -> slf4jLevel.name().equalsIgnoreCase(level))) { + return Level.valueOf(level.toUpperCase()); + } else { + // FATAL does not exist in slf4j + if ("FATAL".equalsIgnoreCase(level)) { + return Level.ERROR; + } + } + // default to INFO if incorrect value + return Level.INFO; + } + + /** + * Use {@link ServiceLoader} to lookup for a {@link LoggingManager}. + * A file software.amazon.lambda.powertools.logging.internal.LoggingManager must be created in + * META-INF/services/ folder with the appropriate implementation of the {@link LoggingManager} + * + * @return an instance of {@link LoggingManager} + * @throws IllegalStateException if no {@link LoggingManager} could be found + */ + @SuppressWarnings("java:S106") // S106: System.err is used rather than logger to make sure message is printed + private static LoggingManager getLoggingManagerFromServiceLoader() { + ServiceLoader loggingManagers; + SecurityManager securityManager = System.getSecurityManager(); + if (securityManager == null) { + loggingManagers = ServiceLoader.load(LoggingManager.class); + } else { + final PrivilegedAction> action = () -> ServiceLoader.load(LoggingManager.class); + loggingManagers = AccessController.doPrivileged(action); + } + + List loggingManagerList = new ArrayList<>(); + for (LoggingManager lm : loggingManagers) { + loggingManagerList.add(lm); + } + return getLoggingManager(loggingManagerList, System.err); + } - String logEvent = System.getenv("POWERTOOLS_LOGGER_LOG_EVENT"); - if (logEvent != null) { - LOG_EVENT = Boolean.parseBoolean(logEvent); + static LoggingManager getLoggingManager(List loggingManagerList, PrintStream printStream) { + LoggingManager loggingManager; + if (loggingManagerList.isEmpty()) { + printStream.println("ERROR. No LoggingManager was found on the classpath"); + printStream.println("ERROR. Applying default LoggingManager: POWERTOOLS_LOG_LEVEL variable is ignored"); + printStream.println("ERROR. Make sure to add either powertools-logging-log4j or powertools-logging-logback to your dependencies"); + loggingManager = new DefautlLoggingManager(); } else { - LOG_EVENT = false; + if (loggingManagerList.size() > 1) { + printStream.println("WARN. Multiple LoggingManagers were found on the classpath"); + for (LoggingManager manager : loggingManagerList) { + printStream.println("WARN. Found LoggingManager: [" + manager + "]"); + } + printStream.println("WARN. Make sure to have only one of powertools-logging-log4j OR powertools-logging-logback to your dependencies"); + printStream.println("WARN. Using the first LoggingManager found on the classpath: [" + loggingManagerList.get(0) + "]"); + } + loggingManager = loggingManagerList.get(0); } + return loggingManager; } - private static void resetLogLevels(Level logLevel) { - LoggerContext ctx = (LoggerContext) LogManager.getContext(false); - Configurator.setAllLevels(LogManager.getRootLogger().getName(), logLevel); - ctx.updateLoggers(); + private static void setLogLevels(Level logLevel) { + LOGGING_MANAGER.setLogLevel(logLevel); } @SuppressWarnings({"EmptyMethod"}) @@ -108,41 +174,91 @@ private static void resetLogLevels(Level logLevel) { public void callAt(Logging logging) { } + /** + * Main method of the aspect + */ @Around(value = "callAt(logging) && execution(@Logging * *.*(..))", argNames = "pjp,logging") public Object around(ProceedingJoinPoint pjp, Logging logging) throws Throwable { - Object[] proceedArgs = pjp.getArgs(); + + boolean isOnRequestHandler = placedOnRequestHandler(pjp); + boolean isOnRequestStreamHandler = placedOnStreamHandler(pjp); setLogLevelBasedOnSamplingRate(pjp, logging); - Context extractedContext = extractContext(pjp); + addLambdaContextToLoggingContext(pjp); + + getXrayTraceId().ifPresent(xRayTraceId -> appendKey(FUNCTION_TRACE_ID.getName(), xRayTraceId)); + + Object[] proceedArgs = logEvent(pjp, logging, isOnRequestHandler, isOnRequestStreamHandler); + + if (!logging.correlationIdPath().isEmpty()) { + captureCorrelationId(logging.correlationIdPath(), proceedArgs, isOnRequestHandler, isOnRequestStreamHandler); + } - if (null != extractedContext) { - appendKeys(DefaultLambdaFields.values(extractedContext)); - appendKey("coldStart", isColdStart() ? "true" : "false"); - appendKey("service", serviceName()); + // To log the result of a RequestStreamHandler (OutputStream), we need to do the following: + // 1. backup a reference to the OutputStream provided by Lambda + // 2. create a temporary OutputStream and pass it to the handler method + // 3. retrieve this temporary stream to log it (if enabled) + // 4. write it back to the OutputStream provided by Lambda + OutputStream backupOutputStream = null; + if ((logging.logResponse() || POWERTOOLS_LOG_RESPONSE) && isOnRequestStreamHandler) { + backupOutputStream = (OutputStream) proceedArgs[1]; + proceedArgs[1] = new ByteArrayOutputStream(); } - getXrayTraceId().ifPresent(xRayTraceId -> appendKey("xray_trace_id", xRayTraceId)); + Object lambdaFunctionResponse; - // Check that the environment variable was enabled explicitly - // Or that the handler was annotated with @Logging(logEvent = true) - if (LOG_EVENT || logging.logEvent()) { - proceedArgs = logEvent(pjp); + try { + lambdaFunctionResponse = pjp.proceed(proceedArgs); + } catch (Throwable t) { + if (logging.logError() || POWERTOOLS_LOG_ERROR) { + // logging the exception with additional context + logger(pjp).error(MarkerFactory.getMarker("FATAL"), "Exception in Lambda Handler", t); + } + throw t; + } finally { + if (logging.clearState()) { + MDC.clear(); + } + coldStartDone(); } - if (!logging.correlationIdPath().isEmpty()) { - proceedArgs = captureCorrelationId(logging.correlationIdPath(), pjp); + if ((logging.logResponse() || POWERTOOLS_LOG_RESPONSE)) { + if (isOnRequestHandler) { + logRequestHandlerResponse(pjp, lambdaFunctionResponse); + } else if (isOnRequestStreamHandler && backupOutputStream != null) { + byte[] bytes = ((ByteArrayOutputStream)proceedArgs[1]).toByteArray(); + logRequestStreamHandlerResponse(pjp, bytes); + backupOutputStream.write(bytes); + } } - Object proceed = pjp.proceed(proceedArgs); + return lambdaFunctionResponse; + } + + private Object[] logEvent(ProceedingJoinPoint pjp, Logging logging, + boolean isOnRequestHandler, boolean isOnRequestStreamHandler) { + Object[] proceedArgs = pjp.getArgs(); - if (logging.clearState()) { - ThreadContext.clearMap(); + if (logging.logEvent() || POWERTOOLS_LOG_EVENT) { + if (isOnRequestHandler) { + logRequestHandlerEvent(pjp, pjp.getArgs()[0]); + } else if (isOnRequestStreamHandler) { + proceedArgs = logRequestStreamHandlerEvent(pjp); + } } + return proceedArgs; + } + + private void addLambdaContextToLoggingContext(ProceedingJoinPoint pjp) { + Context extractedContext = extractContext(pjp); - coldStartDone(); - return proceed; + if (extractedContext != null) { + appendKeys(PowertoolsLoggedFields.setValuesFromLambdaContext(extractedContext)); + appendKey(FUNCTION_COLD_START.getName(), isColdStart() ? "true" : "false"); + appendKey(SERVICE.getName(), serviceName()); + } } private void setLogLevelBasedOnSamplingRate(final ProceedingJoinPoint pjp, @@ -152,12 +268,12 @@ private void setLogLevelBasedOnSamplingRate(final ProceedingJoinPoint pjp, if (isHandlerMethod(pjp)) { if (samplingRate < 0 || samplingRate > 1) { - LOG.debug("Skipping sampling rate configuration because of invalid value. Sampling rate: {}", + LOG.warn("Skipping sampling rate configuration because of invalid value. Sampling rate: {}", samplingRate); return; } - appendKey("samplingRate", String.valueOf(samplingRate)); + appendKey(PowertoolsLoggedFields.SAMPLING_RATE.getName(), String.valueOf(samplingRate)); if (samplingRate == 0) { return; @@ -166,130 +282,132 @@ private void setLogLevelBasedOnSamplingRate(final ProceedingJoinPoint pjp, float sample = SAMPLER.nextFloat(); if (samplingRate > sample) { - resetLogLevels(Level.DEBUG); + setLogLevels(Level.DEBUG); - LOG.debug("Changed log level to DEBUG based on Sampling configuration. " + - "Sampling Rate: {}, Sampler Value: {}.", samplingRate, sample); - } else if (LEVEL_AT_INITIALISATION != LOG.getLevel()) { - resetLogLevels(LEVEL_AT_INITIALISATION); + LOG.debug("Changed log level to DEBUG based on Sampling configuration. " + + "Sampling Rate: {}, Sampler Value: {}.", samplingRate, sample); + } else if (LEVEL_AT_INITIALISATION != LOGGING_MANAGER.getLogLevel(LOG)) { + setLogLevels(LEVEL_AT_INITIALISATION); } } } private double samplingRate(final Logging logging) { - if (null != SAMPLING_RATE) { + String sampleRate = POWERTOOLS_SAMPLING_RATE; + if (null != sampleRate) { try { - return Double.parseDouble(SAMPLING_RATE); + return Double.parseDouble(sampleRate); } catch (NumberFormatException e) { - LOG.debug("Skipping sampling rate on environment variable configuration because of invalid " + - "value. Sampling rate: {}", SAMPLING_RATE); + LOG.warn("Skipping sampling rate on environment variable configuration because of invalid " + + "value. Sampling rate: {}", sampleRate); } } return logging.samplingRate(); } - private Object[] logEvent(final ProceedingJoinPoint pjp) { - Object[] args = pjp.getArgs(); - - if (isHandlerMethod(pjp)) { - if (placedOnRequestHandler(pjp)) { - Logger log = logger(pjp); - asJson(pjp, pjp.getArgs()[0]) - .ifPresent(log::info); - } + private void logRequestHandlerEvent(final ProceedingJoinPoint pjp, final Object event) { + Logger log = logger(pjp); + if (log.isInfoEnabled()) { + LoggingUtils.logMessagesAsJson(true); + asJson(event).ifPresent(log::info); + LoggingUtils.logMessagesAsJson(false); + } + } - if (placedOnStreamHandler(pjp)) { - args = logFromInputStream(pjp); + private Object[] logRequestStreamHandlerEvent(final ProceedingJoinPoint pjp) { + Object[] args = pjp.getArgs(); + Logger log = logger(pjp); + if (log.isInfoEnabled()) { + LoggingUtils.logMessagesAsJson(true); + try { + byte[] bytes = bytesFromInputStreamSafely((InputStream) pjp.getArgs()[0]); + args[0] = new ByteArrayInputStream(bytes); + // do not log asJson as it can be something else (String, XML...) + log.info("{}", new String(bytes, UTF_8)); + } catch (IOException e) { + LOG.warn("Failed to log event from supplied input stream.", e); } + LoggingUtils.logMessagesAsJson(false); } - return args; } - private Object[] captureCorrelationId(final String correlationIdPath, - final ProceedingJoinPoint pjp) { - Object[] args = pjp.getArgs(); - if (isHandlerMethod(pjp)) { - if (placedOnRequestHandler(pjp)) { - Object arg = pjp.getArgs()[0]; - JsonNode jsonNode = objectMapper().valueToTree(arg); - - setCorrelationIdFromNode(correlationIdPath, pjp, jsonNode); - - return args; - } + private void logRequestHandlerResponse(final ProceedingJoinPoint pjp, final Object response) { + Logger log = logger(pjp); + if (log.isInfoEnabled()) { + LoggingUtils.logMessagesAsJson(true); + asJson(response).ifPresent(log::info); + LoggingUtils.logMessagesAsJson(false); + } + } - if (placedOnStreamHandler(pjp)) { - try { - byte[] bytes = bytesFromInputStreamSafely((InputStream) pjp.getArgs()[0]); - JsonNode jsonNode = objectMapper().readTree(bytes); - args[0] = new ByteArrayInputStream(bytes); + private void logRequestStreamHandlerResponse(final ProceedingJoinPoint pjp, final byte[] bytes) { + Logger log = logger(pjp); + if (log.isInfoEnabled()) { + LoggingUtils.logMessagesAsJson(true); + // we do not log with asJson as it can be something else (String, XML, ...) + log.info("{}", new String(bytes, UTF_8)); + LoggingUtils.logMessagesAsJson(false); + } + } - setCorrelationIdFromNode(correlationIdPath, pjp, jsonNode); + private void captureCorrelationId(final String correlationIdPath, + Object[] proceedArgs, + final boolean isOnRequestHandler, + final boolean isOnRequestStreamHandler) { + if (isOnRequestHandler) { + JsonNode jsonNode = LoggingUtils.getObjectMapper().valueToTree(proceedArgs[0]); + setCorrelationIdFromNode(correlationIdPath, jsonNode); + } else if (isOnRequestStreamHandler) { + try { + byte[] bytes = bytesFromInputStreamSafely((InputStream) proceedArgs[0]); + JsonNode jsonNode = LoggingUtils.getObjectMapper().readTree(bytes); + proceedArgs[0] = new ByteArrayInputStream(bytes); - return args; - } catch (IOException e) { - Logger log = logger(pjp); - log.warn("Failed to capture correlation id on event from supplied input stream.", e); - } + setCorrelationIdFromNode(correlationIdPath, jsonNode); + } catch (IOException e) { + LOG.warn("Failed to capture correlation id on event from supplied input stream.", e); } } - - return args; } - private void setCorrelationIdFromNode(String correlationIdPath, ProceedingJoinPoint pjp, JsonNode jsonNode) { - JsonNode node = jsonNode.at(JsonPointer.compile(correlationIdPath)); + private void setCorrelationIdFromNode(String correlationIdPath, JsonNode jsonNode) { + Expression jmesExpression = JsonConfig.get().getJmesPath().compile(correlationIdPath); + JsonNode node = jmesExpression.search(jsonNode); String asText = node.asText(); if (null != asText && !asText.isEmpty()) { LoggingUtils.setCorrelationId(asText); } else { - logger(pjp).debug("Unable to extract any correlation id. Is your function expecting supported event type?"); + LOG.warn("Unable to extract any correlation id. Is your function expecting supported event type?"); } } - private Object[] logFromInputStream(final ProceedingJoinPoint pjp) { - Object[] args = pjp.getArgs(); - - try { - byte[] bytes = bytesFromInputStreamSafely((InputStream) pjp.getArgs()[0]); - args[0] = new ByteArrayInputStream(bytes); - Logger log = logger(pjp); - - asJson(pjp, objectMapper().readValue(bytes, Map.class)) - .ifPresent(log::info); - - } catch (IOException e) { - Logger log = logger(pjp); - log.debug("Failed to log event from supplied input stream.", e); - } - - return args; - } private byte[] bytesFromInputStreamSafely(final InputStream inputStream) throws IOException { try (ByteArrayOutputStream out = new ByteArrayOutputStream(); - InputStreamReader reader = new InputStreamReader(inputStream, UTF_8)) { + InputStreamReader reader = new InputStreamReader(inputStream, UTF_8)) { OutputStreamWriter writer = new OutputStreamWriter(out, UTF_8); - - IOUtils.copy(reader, writer); + int n; + char[] buffer = new char[4096]; + while (-1 != (n = reader.read(buffer))) { + writer.write(buffer, 0, n); + } writer.flush(); return out.toByteArray(); } } - private Optional asJson(final ProceedingJoinPoint pjp, - final Object target) { + private Optional asJson(final Object target) { try { - return ofNullable(objectMapper().writeValueAsString(target)); + return ofNullable(LoggingUtils.getObjectMapper().writeValueAsString(target)); } catch (JsonProcessingException e) { - logger(pjp).error("Failed logging event of type {}", target.getClass(), e); + LOG.error("Failed logging object of type {}", target.getClass(), e); return empty(); } } private Logger logger(final ProceedingJoinPoint pjp) { - return LogManager.getLogger(pjp.getSignature().getDeclaringType()); + return LoggerFactory.getLogger(pjp.getSignature().getDeclaringType()); } } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolver.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolver.java deleted file mode 100644 index 500b36c95..000000000 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolver.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging.internal; - -import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.LAMBDA_LOG_FORMAT; -import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.LOG_DATE_RFC3339_FORMAT; - -import java.util.Locale; -import java.util.TimeZone; -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.time.MutableInstant; -import org.apache.logging.log4j.layout.template.json.JsonTemplateLayoutDefaults; -import org.apache.logging.log4j.layout.template.json.resolver.EventResolver; -import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverConfig; -import org.apache.logging.log4j.layout.template.json.util.InstantFormatter; -import org.apache.logging.log4j.layout.template.json.util.JsonWriter; - -/** - * Default timestamp used by log4j is not RFC3339, which is used by Lambda internally to filter logs. - * When `AWS_LAMBDA_LOG_FORMAT` is set to JSON (i.e. using Lambda logging configuration), we should use the appropriate pattern, - * otherwise logs with invalid date format are considered as INFO. - * Inspired from org.apache.logging.log4j.layout.template.json.resolver.TimestampResolver - * - * TODO: remove in v2 an replace with the good pattern in LambdaJsonLayout.json - */ -public class LambdaTimestampResolver implements EventResolver { - - private final EventResolver internalResolver; - - public LambdaTimestampResolver(final TemplateResolverConfig config) { - final PatternResolverContext patternResolverContext = - PatternResolverContext.fromConfig(config); - internalResolver = new PatternResolver(patternResolverContext); - } - - @Override - public void resolve(LogEvent value, JsonWriter jsonWriter) { - internalResolver.resolve(value, jsonWriter); - } - - static String getName() { - return "lambda-timestamp"; - } - - private static final class PatternResolverContext { - - public static final String PATTERN = "pattern"; - private final InstantFormatter formatter; - - private final StringBuilder lastFormattedInstantBuffer = new StringBuilder(); - - private final MutableInstant lastFormattedInstant = new MutableInstant(); - - private PatternResolverContext( - final String pattern, - final TimeZone timeZone, - final Locale locale) { - this.formatter = InstantFormatter - .newBuilder() - .setPattern(pattern) - .setTimeZone(timeZone) - .setLocale(locale) - .build(); - lastFormattedInstant.initFromEpochSecond(-1, 0); - } - - private static PatternResolverContext fromConfig( - final TemplateResolverConfig config) { - final String pattern = readPattern(config); - final TimeZone timeZone = readTimeZone(config); - final Locale locale = config.getLocale(new String[]{PATTERN, "locale"}); - return new PatternResolverContext(pattern, timeZone, locale); - } - - private static String readPattern(final TemplateResolverConfig config) { - final String format = config.getString(new String[]{PATTERN, "format"}); - return format != null - ? format - : getLambdaTimestampFormatOrDefault(); - } - - private static String getLambdaTimestampFormatOrDefault() { - return "JSON".equals(LAMBDA_LOG_FORMAT) ? LOG_DATE_RFC3339_FORMAT : - JsonTemplateLayoutDefaults.getTimestampFormatPattern(); - } - - private static TimeZone readTimeZone(final TemplateResolverConfig config) { - final String timeZoneId = config.getString(new String[]{PATTERN, "timeZone"}); - if (timeZoneId == null) { - return JsonTemplateLayoutDefaults.getTimeZone(); - } - boolean found = false; - for (final String availableTimeZone : TimeZone.getAvailableIDs()) { - if (availableTimeZone.equalsIgnoreCase(timeZoneId)) { - found = true; - break; - } - } - if (!found) { - throw new IllegalArgumentException( - "invalid timestamp time zone: " + config); - } - return TimeZone.getTimeZone(timeZoneId); - } - - } - - private static final class PatternResolver implements EventResolver { - - private final PatternResolverContext patternResolverContext; - - private PatternResolver(final PatternResolverContext patternResolverContext) { - this.patternResolverContext = patternResolverContext; - } - - @Override - public synchronized void resolve( - final LogEvent logEvent, - final JsonWriter jsonWriter) { - - // Format timestamp if it doesn't match the last cached one. - final boolean instantMatching = patternResolverContext.formatter.isInstantMatching( - patternResolverContext.lastFormattedInstant, - logEvent.getInstant()); - if (!instantMatching) { - - // Format the timestamp. - patternResolverContext.lastFormattedInstantBuffer.setLength(0); - patternResolverContext.lastFormattedInstant.initFrom(logEvent.getInstant()); - patternResolverContext.formatter.format( - patternResolverContext.lastFormattedInstant, - patternResolverContext.lastFormattedInstantBuffer); - - // Write the formatted timestamp. - final StringBuilder jsonWriterStringBuilder = jsonWriter.getStringBuilder(); - final int startIndex = jsonWriterStringBuilder.length(); - jsonWriter.writeString(patternResolverContext.lastFormattedInstantBuffer); - - // Cache the written value. - patternResolverContext.lastFormattedInstantBuffer.setLength(0); - patternResolverContext.lastFormattedInstantBuffer.append( - jsonWriterStringBuilder, - startIndex, - jsonWriterStringBuilder.length()); - - } - - // Write the cached formatted timestamp. - else { - jsonWriter.writeRawString( - patternResolverContext.lastFormattedInstantBuffer); - } - - } - - } -} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolverFactory.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolverFactory.java deleted file mode 100644 index 2022c6d4a..000000000 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaTimestampResolverFactory.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging.internal; - -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.config.plugins.Plugin; -import org.apache.logging.log4j.core.config.plugins.PluginFactory; -import org.apache.logging.log4j.layout.template.json.resolver.EventResolverContext; -import org.apache.logging.log4j.layout.template.json.resolver.EventResolverFactory; -import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolver; -import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverConfig; -import org.apache.logging.log4j.layout.template.json.resolver.TemplateResolverFactory; - -@Plugin(name = "LambdaTimestampResolverFactory", category = TemplateResolverFactory.CATEGORY) -public final class LambdaTimestampResolverFactory implements EventResolverFactory { - - private static final LambdaTimestampResolverFactory INSTANCE = new LambdaTimestampResolverFactory(); - - private LambdaTimestampResolverFactory() { - } - - @PluginFactory - public static LambdaTimestampResolverFactory getInstance() { - return INSTANCE; - } - - @Override - public String getName() { - return LambdaTimestampResolver.getName(); - } - - @Override - public TemplateResolver create(EventResolverContext context, - TemplateResolverConfig config) { - return new LambdaTimestampResolver(config); - } -} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java index e58ca4109..989608a77 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java @@ -14,12 +14,18 @@ package software.amazon.lambda.powertools.logging.internal; -public class LoggingConstants { - public static final String LAMBDA_LOG_LEVEL = System.getenv("AWS_LAMBDA_LOG_LEVEL"); +class LoggingConstants { + static String LAMBDA_LOG_LEVEL = System.getenv("AWS_LAMBDA_LOG_LEVEL"); /* not final for test purpose */ - public static final String LAMBDA_LOG_FORMAT = System.getenv("AWS_LAMBDA_LOG_FORMAT"); + static String POWERTOOLS_LOG_LEVEL = System.getenv("POWERTOOLS_LOG_LEVEL"); /* not final for test purpose */ - public static final String LOG_DATE_RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + static String POWERTOOLS_SAMPLING_RATE = System.getenv("POWERTOOLS_LOGGER_SAMPLE_RATE"); /* not final for test purpose */ + + static boolean POWERTOOLS_LOG_EVENT = "true".equals(System.getenv("POWERTOOLS_LOGGER_LOG_EVENT")); /* not final for test purpose */ + + static boolean POWERTOOLS_LOG_RESPONSE = "true".equals(System.getenv("POWERTOOLS_LOGGER_LOG_RESPONSE")); /* not final for test purpose */ + + static boolean POWERTOOLS_LOG_ERROR = "true".equals(System.getenv("POWERTOOLS_LOGGER_LOG_ERROR")); /* not final for test purpose */ private LoggingConstants() { // constants diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingManager.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingManager.java new file mode 100644 index 000000000..51d05b25d --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingManager.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import org.slf4j.Logger; +import org.slf4j.event.Level; + +/** + * Due to limitations of SLF4J, we need to rely on implementations for some operations: + *

    + *
  • Accessing to all loggers and change their Level
  • + *
  • Retrieving the log Level of a Logger
  • + *
+ * + *

+ * This interface is used for these operations and implementations are provided in submodules and loaded thanks to a {@link java.util.ServiceLoader} + * (define a file named software.amazon.lambda.powertools.logging.internal.LoggingManager + * in src/main/resources/META-INF/services with the qualified name of the implementation). + */ +public interface LoggingManager { + /** + * Change the log Level of all loggers (named and root) + * + * @param logLevel the log Level (slf4j) to apply + */ + void setLogLevel(Level logLevel); + + /** + * Retrieve the log Level of a specific logger + * + * @param logger the logger (slf4j) for which to retrieve the log Level + * @return the Level (slf4j) of this logger. + * Note that SLF4J only support ERROR, WARN, INFO, DEBUG, TRACE while some frameworks may support others (OFF, FATAL, ...) + */ + Level getLogLevel(Logger logger); +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefaultLambdaFields.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java similarity index 59% rename from powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefaultLambdaFields.java rename to powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java index 2461ae771..6e0047f4f 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefaultLambdaFields.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java @@ -16,22 +16,38 @@ import com.amazonaws.services.lambda.runtime.Context; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; -enum DefaultLambdaFields { - FUNCTION_NAME("functionName"), - FUNCTION_VERSION("functionVersion"), - FUNCTION_ARN("functionArn"), - FUNCTION_MEMORY_SIZE("functionMemorySize"), - FUNCTION_REQUEST_ID("function_request_id"); +/** + * Fields added in the logs by Powertools. + * Same as python + */ +public enum PowertoolsLoggedFields { + FUNCTION_NAME("function_name"), + FUNCTION_VERSION("function_version"), + FUNCTION_ARN("function_arn"), + FUNCTION_MEMORY_SIZE("function_memory_size"), + FUNCTION_REQUEST_ID("function_request_id"), + FUNCTION_COLD_START("cold_start"), + FUNCTION_TRACE_ID("xray_trace_id"), + SAMPLING_RATE("sampling_rate"), + CORRELATION_ID("correlation_id"), + SERVICE("service"); private final String name; - DefaultLambdaFields(String name) { + PowertoolsLoggedFields(String name) { this.name = name; } - static Map values(Context context) { + public static List stringValues() { + return Stream.of(values()).map(PowertoolsLoggedFields::getName).collect(Collectors.toList()); + } + + static Map setValuesFromLambdaContext(Context context) { Map hashMap = new HashMap<>(); hashMap.put(FUNCTION_NAME.name, context.getFunctionName()); diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsResolver.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsResolver.java deleted file mode 100644 index dc9816932..000000000 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsResolver.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging.internal; - -import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.layout.template.json.resolver.EventResolver; -import org.apache.logging.log4j.layout.template.json.util.JsonWriter; -import org.apache.logging.log4j.util.ReadOnlyStringMap; - -final class PowertoolsResolver implements EventResolver { - - private final EventResolver internalResolver; - - PowertoolsResolver() { - internalResolver = new EventResolver() { - @Override - public boolean isResolvable(LogEvent value) { - ReadOnlyStringMap contextData = value.getContextData(); - return null != contextData && !contextData.isEmpty(); - } - - @Override - public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { - StringBuilder stringBuilder = jsonWriter.getStringBuilder(); - // remove dummy field to kick inn powertools resolver - stringBuilder.setLength(stringBuilder.length() - 4); - - // Inject all the context information. - ReadOnlyStringMap contextData = logEvent.getContextData(); - contextData.forEach((key, value) -> - { - jsonWriter.writeSeparator(); - jsonWriter.writeString(key); - stringBuilder.append(':'); - jsonWriter.writeValue(value); - }); - } - }; - } - - static String getName() { - return "powertools"; - } - - @Override - public void resolve(LogEvent value, JsonWriter jsonWriter) { - internalResolver.resolve(value, jsonWriter); - } - - @Override - public boolean isResolvable(LogEvent value) { - return internalResolver.isResolvable(value); - } -} diff --git a/powertools-logging/src/main/resources/LambdaEcsLayout.json b/powertools-logging/src/main/resources/LambdaEcsLayout.json deleted file mode 100644 index 4ab9c7ce2..000000000 --- a/powertools-logging/src/main/resources/LambdaEcsLayout.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "@timestamp": { - "$resolver": "timestamp", - "pattern": { - "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", - "timeZone": "UTC" - } - }, - "ecs.version": "1.2.0", - "log.level": { - "$resolver": "level", - "field": "name" - }, - "message": { - "$resolver": "message", - "stringified": true - }, - "process.thread.name": { - "$resolver": "thread", - "field": "name" - }, - "log.logger": { - "$resolver": "logger", - "field": "name" - }, - "labels": { - "$resolver": "mdc", - "flatten": true, - "stringified": true - }, - "tags": { - "$resolver": "ndc" - }, - "error.type": { - "$resolver": "exception", - "field": "className" - }, - "error.message": { - "$resolver": "exception", - "field": "message" - }, - "error.stack_trace": { - "$resolver": "exception", - "field": "stackTrace", - "stackTrace": { - "stringified": true - } - }, - "": { - "$resolver": "powertools" - } -} \ No newline at end of file diff --git a/powertools-logging/src/main/resources/LambdaJsonLayout.json b/powertools-logging/src/main/resources/LambdaJsonLayout.json deleted file mode 100644 index da3385032..000000000 --- a/powertools-logging/src/main/resources/LambdaJsonLayout.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "timestamp": { - "$resolver": "lambda-timestamp" - }, - "instant": { - "epochSecond": { - "$resolver": "timestamp", - "epoch": { - "unit": "secs", - "rounded": true - } - }, - "nanoOfSecond": { - "$resolver": "timestamp", - "epoch": { - "unit": "secs.nanos" - } - } - }, - "thread": { - "$resolver": "thread", - "field": "name" - }, - "level": { - "$resolver": "level", - "field": "name" - }, - "loggerName": { - "$resolver": "logger", - "field": "name" - }, - "message": { - "$resolver": "message", - "stringified": true - }, - "thrown": { - "message": { - "$resolver": "exception", - "field": "message" - }, - "name": { - "$resolver": "exception", - "field": "className" - }, - "extendedStackTrace": { - "$resolver": "exception", - "field": "stackTrace" - } - }, - "contextStack": { - "$resolver": "ndc" - }, - "endOfBatch": { - "$resolver": "endOfBatch" - }, - "loggerFqcn": { - "$resolver": "logger", - "field": "fqcn" - }, - "threadId": { - "$resolver": "thread", - "field": "id" - }, - "threadPriority": { - "$resolver": "thread", - "field": "priority" - }, - "source": { - "class": { - "$resolver": "source", - "field": "className" - }, - "method": { - "$resolver": "source", - "field": "methodName" - }, - "file": { - "$resolver": "source", - "field": "fileName" - }, - "line": { - "$resolver": "source", - "field": "lineNumber" - } - }, - "": { - "$resolver": "powertools" - } -} diff --git a/powertools-logging/src/main/resources/log4j2.component.properties b/powertools-logging/src/main/resources/log4j2.component.properties deleted file mode 100644 index 3c392dd13..000000000 --- a/powertools-logging/src/main/resources/log4j2.component.properties +++ /dev/null @@ -1,2 +0,0 @@ -log4j.layout.jsonTemplate.timestampFormatPattern=yyyy-MM-dd'T'HH:mm:ss.SSSZz -#log4j.layout.jsonTemplate.timeZone= \ No newline at end of file diff --git a/powertools-logging/src/test/java/org/apache/logging/log4j/core/layout/LambdaJsonLayoutTest.java b/powertools-logging/src/test/java/org/apache/logging/log4j/core/layout/LambdaJsonLayoutTest.java deleted file mode 100644 index 95fb9c47f..000000000 --- a/powertools-logging/src/test/java/org/apache/logging/log4j/core/layout/LambdaJsonLayoutTest.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.logging.log4j.core.layout; - -import static java.util.Collections.emptyMap; -import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; -import static org.assertj.core.api.Assertions.as; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.nio.channels.FileChannel; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.time.format.ResolverStyle; -import java.util.Map; -import org.apache.logging.log4j.Level; -import org.assertj.core.api.InstanceOfAssertFactories; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabled; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolSamplingEnabled; -import software.amazon.lambda.powertools.logging.internal.LambdaLoggingAspect; - -class LambdaJsonLayoutTest { - private RequestHandler handler = new PowerLogToolEnabled(); - - @Mock - private Context context; - - @BeforeEach - void setUp() throws IOException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { - openMocks(this); - setupContext(); - //Make sure file is cleaned up before running full stack logging regression - FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); - resetLogLevel(Level.INFO); - } - - @Test - void shouldLogInStructuredFormat() throws IOException { - handler.handleRequest("test", context); - - assertThat(Files.lines(Paths.get("target/logfile.json"))) - .hasSize(1) - .allSatisfy(line -> assertThat(parseToMap(line)) - .containsEntry("functionName", "testFunction") - .containsEntry("functionVersion", "1") - .containsEntry("functionMemorySize", "10") - .containsEntry("functionArn", "testArn") - .containsKey("timestamp") - .containsKey("message") - .containsKey("service")); - } - - @Test - void shouldLogWithRFC3339TimestampFormat_WhenLambdaLoggingIsJSON() throws Exception { - // Given: AWS_LAMBDA_LOG_FORMAT=JSON defined in pom.xml - - // When - handler.handleRequest("test", context); - - // Then - assertThat(Files.lines(Paths.get("target/logfile.json"))) - .hasSize(1) - .allSatisfy(line -> assertThat(parseToMap(line)) - .extracting("timestamp", as(InstanceOfAssertFactories.STRING)) - .satisfies(s -> assertThat(hasDateFormat(s, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")).isTrue())); - } - - private boolean hasDateFormat(String timestamp, String format) { - DateTimeFormatter dtf = DateTimeFormatter.ofPattern(format).withResolverStyle(ResolverStyle.STRICT); - try { - dtf.parse(timestamp); - return true; - } catch (DateTimeParseException e) { - return false; - } - } - - @Test - void shouldModifyLogLevelBasedOnEnvVariable() - throws IllegalAccessException, IOException, NoSuchMethodException, InvocationTargetException { - resetLogLevel(Level.DEBUG); - - handler.handleRequest("test", context); - - assertThat(Files.lines(Paths.get("target/logfile.json"))) - .hasSize(2) - .satisfies(line -> - { - assertThat(parseToMap(line.get(0))) - .containsEntry("level", "INFO") - .containsEntry("message", "Test event"); - - assertThat(parseToMap(line.get(1))) - .containsEntry("level", "DEBUG") - .containsEntry("message", "Test debug event"); - }); - } - - @Test - void shouldModifyLogLevelBasedOnSamplingRule() throws IOException { - handler = new PowerLogToolSamplingEnabled(); - - handler.handleRequest("test", context); - - assertThat(Files.lines(Paths.get("target/logfile.json"))) - .hasSize(3) - .satisfies(line -> - { - assertThat(parseToMap(line.get(0))) - .containsEntry("level", "DEBUG") - .containsEntry("loggerName", LambdaLoggingAspect.class.getCanonicalName()); - - assertThat(parseToMap(line.get(1))) - .containsEntry("level", "INFO") - .containsEntry("message", "Test event"); - - assertThat(parseToMap(line.get(2))) - .containsEntry("level", "DEBUG") - .containsEntry("message", "Test debug event"); - }); - } - - private void resetLogLevel(Level level) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - Method resetLogLevels = LambdaLoggingAspect.class.getDeclaredMethod("resetLogLevels", Level.class); - resetLogLevels.setAccessible(true); - resetLogLevels.invoke(null, level); - writeStaticField(LambdaLoggingAspect.class, "LEVEL_AT_INITIALISATION", level, true); - } - - private Map parseToMap(String stringAsJson) { - try { - return new ObjectMapper().readValue(stringAsJson, Map.class); - } catch (JsonProcessingException e) { - fail("Failed parsing logger line " + stringAsJson); - return emptyMap(); - } - } - - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - } -} \ No newline at end of file diff --git a/powertools-logging/src/test/java/org/slf4j/test/OutputChoice.java b/powertools-logging/src/test/java/org/slf4j/test/OutputChoice.java new file mode 100644 index 000000000..9a6d56b81 --- /dev/null +++ b/powertools-logging/src/test/java/org/slf4j/test/OutputChoice.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + *

+ * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *

+ * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.slf4j.test; + +import java.io.PrintStream; + +/** + * This class encapsulates the user's choice of output target. + * + * @see ... + */ +class OutputChoice { + + final OutputChoiceType outputChoiceType; + final PrintStream targetPrintStream; + OutputChoice(OutputChoiceType outputChoiceType) { + if (outputChoiceType == OutputChoiceType.FILE) { + throw new IllegalArgumentException(); + } + this.outputChoiceType = outputChoiceType; + if (outputChoiceType == OutputChoiceType.CACHED_SYS_OUT) { + this.targetPrintStream = System.out; + } else if (outputChoiceType == OutputChoiceType.CACHED_SYS_ERR) { + this.targetPrintStream = System.err; + } else { + this.targetPrintStream = null; + } + } + + OutputChoice(PrintStream printStream) { + this.outputChoiceType = OutputChoiceType.FILE; + this.targetPrintStream = printStream; + } + + PrintStream getTargetPrintStream() { + switch (outputChoiceType) { + case SYS_OUT: + return System.out; + case SYS_ERR: + return System.err; + case CACHED_SYS_ERR: + case CACHED_SYS_OUT: + case FILE: + return targetPrintStream; + default: + throw new IllegalArgumentException(); + } + + } + + enum OutputChoiceType { + SYS_OUT, CACHED_SYS_OUT, SYS_ERR, CACHED_SYS_ERR, FILE; + } + +} diff --git a/powertools-logging/src/test/java/org/slf4j/test/TestLogger.java b/powertools-logging/src/test/java/org/slf4j/test/TestLogger.java new file mode 100644 index 000000000..2a9322592 --- /dev/null +++ b/powertools-logging/src/test/java/org/slf4j/test/TestLogger.java @@ -0,0 +1,452 @@ +/** + * Copyright (c) 2004-2022 QOS.ch Sarl (Switzerland) + * All rights reserved. + *

+ * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *

+ * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.slf4j.test; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.Marker; +import org.slf4j.event.Level; +import org.slf4j.event.LoggingEvent; +import org.slf4j.helpers.LegacyAbstractLogger; +import org.slf4j.helpers.MessageFormatter; +import org.slf4j.helpers.NormalizedParameters; +import org.slf4j.spi.LocationAwareLogger; + +/** + *

+ * Simple implementation of {@link Logger} that sends all enabled log messages, + * for all defined loggers, to the console ({@code System.err}). The following + * system properties are supported to configure the behavior of this logger: + * + * + *

    + *
  • org.slf4j.simpleLogger.logFile - The output target which can + * be the path to a file, or the special values "System.out" and + * "System.err". Default is "System.err".
  • + * + *
  • org.slf4j.simpleLogger.cacheOutputStream - If the output + * target is set to "System.out" or "System.err" (see preceding entry), by + * default, logs will be output to the latest value referenced by + * System.out/err variables. By setting this parameter to true, the + * output stream will be cached, i.e. assigned once at initialization time and + * re-used independently of the current value referenced by + * System.out/err.
  • + * + *
  • org.slf4j.simpleLogger.defaultLogLevel - Default log level + * for all instances of SimpleLogger. Must be one of ("trace", "debug", "info", + * "warn", "error" or "off"). If not specified, defaults to "info".
  • + * + *
  • org.slf4j.simpleLogger.log.a.b.c - Logging detail + * level for a SimpleLogger instance named "a.b.c". Right-side value must be one + * of "trace", "debug", "info", "warn", "error" or "off". When a SimpleLogger + * named "a.b.c" is initialized, its level is assigned from this property. If + * unspecified, the level of nearest parent logger will be used, and if none is + * set, then the value specified by + * org.slf4j.simpleLogger.defaultLogLevel will be used.
  • + * + *
  • org.slf4j.simpleLogger.showDateTime - Set to + * true if you want the current date and time to be included in + * output messages. Default is false
  • + * + *
  • org.slf4j.simpleLogger.dateTimeFormat - The date and time + * format to be used in the output messages. The pattern describing the date and + * time format is defined by + * SimpleDateFormat. If the format is not specified or is + * invalid, the number of milliseconds since start up will be output.
  • + * + *
  • org.slf4j.simpleLogger.showThreadName -Set to + * true if you want to output the current thread name. Defaults to + * true.
  • + * + *
  • (since version 1.7.33 and 2.0.0-alpha6) org.slf4j.simpleLogger.showThreadId - + * If you would like to output the current thread id, then set to + * true. Defaults to false.
  • + * + *
  • org.slf4j.simpleLogger.showLogName - Set to + * true if you want the Logger instance name to be included in + * output messages. Defaults to true.
  • + * + *
  • org.slf4j.simpleLogger.showShortLogName - Set to + * true if you want the last component of the name to be included + * in output messages. Defaults to false.
  • + * + *
  • org.slf4j.simpleLogger.levelInBrackets - Should the level + * string be output in brackets? Defaults to false.
  • + * + *
  • org.slf4j.simpleLogger.warnLevelString - The string value + * output for the warn level. Defaults to WARN.
  • + * + *
+ * + *

+ * In addition to looking for system properties with the names specified above, + * this implementation also checks for a class loader resource named + * "simplelogger.properties", and includes any matching definitions + * from this resource (if it exists). + * + * + *

+ * With no configuration, the default output includes the relative time in + * milliseconds, thread name, the level, logger name, and the message followed + * by the line separator for the host. In log4j terms it amounts to the "%r [%t] + * %level %logger - %m%n" pattern. + * + *

+ * Sample output follows. + * + * + *

+ * 176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order.
+ * 225 [main] INFO examples.SortAlgo - Entered the sort method.
+ * 304 [main] INFO examples.SortAlgo - Dump of integer array:
+ * 317 [main] INFO examples.SortAlgo - Element [0] = 0
+ * 331 [main] INFO examples.SortAlgo - Element [1] = 1
+ * 343 [main] INFO examples.Sort - The next log statement should be an error message.
+ * 346 [main] ERROR examples.SortAlgo - Tried to dump an uninitialized array.
+ *   at org.log4j.examples.SortAlgo.dump(SortAlgo.java:58)
+ *   at org.log4j.examples.Sort.main(Sort.java:64)
+ * 467 [main] INFO  examples.Sort - Exiting main method.
+ * 
+ * + *

+ * This implementation is heavily inspired by + * Apache Commons Logging's + * SimpleLog. + * + * + * @author Ceki Gülcü + * @author Scott Sanders + * @author Rod Waldhoff + * @author Robert Burrell Donkin + * @author Cédrik LIME + */ +public class TestLogger extends LegacyAbstractLogger { + + /** + * All system properties used by SimpleLogger start with this + * prefix + */ + public static final String SYSTEM_PREFIX = "org.slf4j.simpleLogger."; + public static final String LOG_KEY_PREFIX = TestLogger.SYSTEM_PREFIX + "log."; + public static final String CACHE_OUTPUT_STREAM_STRING_KEY = TestLogger.SYSTEM_PREFIX + "cacheOutputStream"; + public static final String WARN_LEVEL_STRING_KEY = TestLogger.SYSTEM_PREFIX + "warnLevelString"; + public static final String LEVEL_IN_BRACKETS_KEY = TestLogger.SYSTEM_PREFIX + "levelInBrackets"; + public static final String LOG_FILE_KEY = TestLogger.SYSTEM_PREFIX + "logFile"; + public static final String SHOW_SHORT_LOG_NAME_KEY = TestLogger.SYSTEM_PREFIX + "showShortLogName"; + public static final String SHOW_LOG_NAME_KEY = TestLogger.SYSTEM_PREFIX + "showLogName"; + public static final String SHOW_THREAD_NAME_KEY = TestLogger.SYSTEM_PREFIX + "showThreadName"; + public static final String SHOW_THREAD_ID_KEY = TestLogger.SYSTEM_PREFIX + "showThreadId"; + public static final String DATE_TIME_FORMAT_KEY = TestLogger.SYSTEM_PREFIX + "dateTimeFormat"; + public static final String SHOW_DATE_TIME_KEY = TestLogger.SYSTEM_PREFIX + "showDateTime"; + public static final String DEFAULT_LOG_LEVEL_KEY = TestLogger.SYSTEM_PREFIX + "defaultLogLevel"; + protected static final int LOG_LEVEL_TRACE = LocationAwareLogger.TRACE_INT; + protected static final int LOG_LEVEL_DEBUG = LocationAwareLogger.DEBUG_INT; + protected static final int LOG_LEVEL_INFO = LocationAwareLogger.INFO_INT; + protected static final int LOG_LEVEL_WARN = LocationAwareLogger.WARN_INT; + protected static final int LOG_LEVEL_ERROR = LocationAwareLogger.ERROR_INT; + // The OFF level can only be used in configuration files to disable logging. + // It has + // no printing method associated with it in o.s.Logger interface. + protected static final int LOG_LEVEL_OFF = LOG_LEVEL_ERROR + 10; + static final String TID_PREFIX = "tid="; + static final TestLoggerConfiguration CONFIG_PARAMS = new TestLoggerConfiguration(); + private static final long serialVersionUID = -632788891211436180L; + private static final long START_TIME = System.currentTimeMillis(); + static char SP = ' '; + private static boolean INITIALIZED = false; + /** The current log level */ + protected int currentLogLevel = LOG_LEVEL_INFO; + /** The short name of this simple log instance */ + private transient String shortLogName = null; + + /** + * Package access allows only {@link TestLoggerFactory} to instantiate + * SimpleLogger instances. + */ + TestLogger(String name) { + this.name = name; + + String levelString = recursivelyComputeLevelString(); + if (levelString != null) { + this.currentLogLevel = TestLoggerConfiguration.stringToLevel(levelString); + } else { + this.currentLogLevel = CONFIG_PARAMS.defaultLogLevel; + } + } + + static void lazyInit() { + if (INITIALIZED) { + return; + } + INITIALIZED = true; + init(); + } + + // external software might be invoking this method directly. Do not rename + // or change its semantics. + static void init() { + CONFIG_PARAMS.init(); + } + + public int getLogLevel() { + return currentLogLevel; + } + + public void setLogLevel(String levelString) { + this.currentLogLevel = TestLoggerConfiguration.stringToLevel(levelString); + } + + String recursivelyComputeLevelString() { + String tempName = name; + String levelString = null; + int indexOfLastDot = tempName.length(); + while ((levelString == null) && (indexOfLastDot > -1)) { + tempName = tempName.substring(0, indexOfLastDot); + levelString = CONFIG_PARAMS.getStringProperty(TestLogger.LOG_KEY_PREFIX + tempName, null); + indexOfLastDot = String.valueOf(tempName).lastIndexOf("."); + } + return levelString; + } + + /** + * To avoid intermingling of log messages and associated stack traces, the two + * operations are done in a synchronized block. + * + * @param buf + * @param t + */ + void write(StringBuilder buf, Throwable t) { + PrintStream targetStream = CONFIG_PARAMS.outputChoice.getTargetPrintStream(); + + synchronized (CONFIG_PARAMS) { + targetStream.println(buf.toString()); + writeThrowable(t, targetStream); + targetStream.flush(); + } + + } + + protected void writeThrowable(Throwable t, PrintStream targetStream) { + if (t != null) { + t.printStackTrace(targetStream); + } + } + + private String getFormattedDate() { + Date now = new Date(); + String dateText; + synchronized (CONFIG_PARAMS.dateFormatter) { + dateText = CONFIG_PARAMS.dateFormatter.format(now); + } + return dateText; + } + + private String computeShortName() { + return name.substring(name.lastIndexOf(".") + 1); + } + + // /** + // * For formatted messages, first substitute arguments and then log. + // * + // * @param level + // * @param format + // * @param arg1 + // * @param arg2 + // */ + // private void formatAndLog(int level, String format, Object arg1, Object arg2) { + // if (!isLevelEnabled(level)) { + // return; + // } + // FormattingTuple tp = MessageFormatter.format(format, arg1, arg2); + // log(level, tp.getMessage(), tp.getThrowable()); + // } + + // /** + // * For formatted messages, first substitute arguments and then log. + // * + // * @param level + // * @param format + // * @param arguments + // * a list of 3 ore more arguments + // */ + // private void formatAndLog(int level, String format, Object... arguments) { + // if (!isLevelEnabled(level)) { + // return; + // } + // FormattingTuple tp = MessageFormatter.arrayFormat(format, arguments); + // log(level, tp.getMessage(), tp.getThrowable()); + // } + + /** + * Is the given log level currently enabled? + * + * @param logLevel is this level enabled? + * @return whether the logger is enabled for the given level + */ + protected boolean isLevelEnabled(int logLevel) { + // log level are numerically ordered so can use simple numeric + // comparison + return (logLevel >= currentLogLevel); + } + + /** Are {@code trace} messages currently enabled? */ + public boolean isTraceEnabled() { + return isLevelEnabled(LOG_LEVEL_TRACE); + } + + /** Are {@code debug} messages currently enabled? */ + public boolean isDebugEnabled() { + return isLevelEnabled(LOG_LEVEL_DEBUG); + } + + /** Are {@code info} messages currently enabled? */ + public boolean isInfoEnabled() { + return isLevelEnabled(LOG_LEVEL_INFO); + } + + /** Are {@code warn} messages currently enabled? */ + public boolean isWarnEnabled() { + return isLevelEnabled(LOG_LEVEL_WARN); + } + + /** Are {@code error} messages currently enabled? */ + public boolean isErrorEnabled() { + return isLevelEnabled(LOG_LEVEL_ERROR); + } + + /** + * SimpleLogger's implementation of + * {@link org.slf4j.helpers.AbstractLogger#handleNormalizedLoggingCall(Level, Marker, String, Object[], Throwable) AbstractLogger#handleNormalizedLoggingCall} + * } + * + * @param level the SLF4J level for this event + * @param marker The marker to be used for this event, may be null. + * @param messagePattern The message pattern which will be parsed and formatted + * @param arguments the array of arguments to be formatted, may be null + * @param throwable The exception whose stack trace should be logged, may be null + */ + @Override + protected void handleNormalizedLoggingCall(Level level, Marker marker, String messagePattern, Object[] arguments, + Throwable throwable) { + + List markers = null; + + if (marker != null) { + markers = new ArrayList<>(); + markers.add(marker); + } + + innerHandleNormalizedLoggingCall(level, markers, messagePattern, arguments, throwable); + } + + private void innerHandleNormalizedLoggingCall(Level level, List markers, String messagePattern, + Object[] arguments, Throwable t) { + + StringBuilder buf = new StringBuilder(32); + + // Append date-time if so configured + if (CONFIG_PARAMS.showDateTime) { + if (CONFIG_PARAMS.dateFormatter != null) { + buf.append(getFormattedDate()); + buf.append(SP); + } else { + buf.append(System.currentTimeMillis() - START_TIME); + buf.append(SP); + } + } + + // Append current thread name if so configured + if (CONFIG_PARAMS.showThreadName) { + buf.append('['); + buf.append(Thread.currentThread().getName()); + buf.append("] "); + } + + if (CONFIG_PARAMS.showThreadId) { + buf.append(TID_PREFIX); + buf.append(Thread.currentThread().getId()); + buf.append(SP); + } + + if (CONFIG_PARAMS.levelInBrackets) { + buf.append('['); + } + + // Append a readable representation of the log level + String levelStr = level.name(); + buf.append(levelStr); + if (CONFIG_PARAMS.levelInBrackets) { + buf.append(']'); + } + buf.append(SP); + + // Append the name of the log instance if so configured + if (CONFIG_PARAMS.showShortLogName) { + if (shortLogName == null) { + shortLogName = computeShortName(); + } + buf.append(String.valueOf(shortLogName)).append(" - "); + } else if (CONFIG_PARAMS.showLogName) { + buf.append(String.valueOf(name)).append(" - "); + } + + if (markers != null) { + buf.append(SP); + for (Marker marker : markers) { + buf.append(marker.getName()).append(SP); + } + } + + String formattedMessage = MessageFormatter.basicArrayFormat(messagePattern, arguments); + + // Append the message + buf.append(formattedMessage); + + write(buf, t); + } + + public void log(LoggingEvent event) { + int levelInt = event.getLevel().toInt(); + + if (!isLevelEnabled(levelInt)) { + return; + } + + NormalizedParameters np = NormalizedParameters.normalize(event); + + innerHandleNormalizedLoggingCall(event.getLevel(), event.getMarkers(), np.getMessage(), np.getArguments(), + event.getThrowable()); + } + + @Override + protected String getFullyQualifiedCallerName() { + return null; + } + +} diff --git a/powertools-logging/src/test/java/org/slf4j/test/TestLoggerConfiguration.java b/powertools-logging/src/test/java/org/slf4j/test/TestLoggerConfiguration.java new file mode 100644 index 000000000..7601dbfde --- /dev/null +++ b/powertools-logging/src/test/java/org/slf4j/test/TestLoggerConfiguration.java @@ -0,0 +1,204 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + *

+ * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *

+ * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.slf4j.test; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Properties; +import org.slf4j.helpers.Util; + +/** + * This class holds configuration values for {@link TestLogger}. The + * values are computed at runtime. See {@link TestLogger} documentation for + * more information. + * + * + * @author Ceki Gülcü + * @author Scott Sanders + * @author Rod Waldhoff + * @author Robert Burrell Donkin + * @author Cédrik LIME + * + * @since 1.7.25 + */ +public class TestLoggerConfiguration { + + final static boolean SHOW_LOG_NAME_DEFAULT = true; + private static final String CONFIGURATION_FILE = "testlogger.properties"; + private static final boolean SHOW_DATE_TIME_DEFAULT = false; + private static final String DATE_TIME_FORMAT_STR_DEFAULT = null; + private static final boolean SHOW_THREAD_NAME_DEFAULT = true; + /** + * See https://jira.qos.ch/browse/SLF4J-499 + * @since 1.7.33 and 2.0.0-alpha6 + */ + private static final boolean SHOW_THREAD_ID_DEFAULT = false; + private static final boolean SHOW_SHORT_LOG_NAME_DEFAULT = false; + private static final boolean LEVEL_IN_BRACKETS_DEFAULT = false; + private static final String LOG_FILE_DEFAULT = "System.err"; + private static final boolean CACHE_OUTPUT_STREAM_DEFAULT = false; + private static final String WARN_LEVELS_STRING_DEFAULT = "WARN"; + static int DEFAULT_LOG_LEVEL_DEFAULT = TestLogger.LOG_LEVEL_INFO; + private static String dateTimeFormatStr = DATE_TIME_FORMAT_STR_DEFAULT; + private final Properties properties = new Properties(); + int defaultLogLevel = DEFAULT_LOG_LEVEL_DEFAULT; + boolean showDateTime = SHOW_DATE_TIME_DEFAULT; + DateFormat dateFormatter = null; + boolean showThreadName = SHOW_THREAD_NAME_DEFAULT; + boolean showThreadId = SHOW_THREAD_ID_DEFAULT; + boolean showLogName = SHOW_LOG_NAME_DEFAULT; + boolean showShortLogName = SHOW_SHORT_LOG_NAME_DEFAULT; + boolean levelInBrackets = LEVEL_IN_BRACKETS_DEFAULT; + OutputChoice outputChoice = null; + String warnLevelString = WARN_LEVELS_STRING_DEFAULT; + private String logFile = LOG_FILE_DEFAULT; + private boolean cacheOutputStream = CACHE_OUTPUT_STREAM_DEFAULT; + + static int stringToLevel(String levelStr) { + if ("trace".equalsIgnoreCase(levelStr)) { + return TestLogger.LOG_LEVEL_TRACE; + } else if ("debug".equalsIgnoreCase(levelStr)) { + return TestLogger.LOG_LEVEL_DEBUG; + } else if ("info".equalsIgnoreCase(levelStr)) { + return TestLogger.LOG_LEVEL_INFO; + } else if ("warn".equalsIgnoreCase(levelStr)) { + return TestLogger.LOG_LEVEL_WARN; + } else if ("error".equalsIgnoreCase(levelStr)) { + return TestLogger.LOG_LEVEL_ERROR; + } else if ("off".equalsIgnoreCase(levelStr)) { + return TestLogger.LOG_LEVEL_OFF; + } + // assume INFO by default + return TestLogger.LOG_LEVEL_INFO; + } + + private static OutputChoice computeOutputChoice(String logFile, boolean cacheOutputStream) { + if ("System.err".equalsIgnoreCase(logFile)) { + if (cacheOutputStream) { + return new OutputChoice(OutputChoice.OutputChoiceType.CACHED_SYS_ERR); + } else { + return new OutputChoice(OutputChoice.OutputChoiceType.SYS_ERR); + } + } else if ("System.out".equalsIgnoreCase(logFile)) { + if (cacheOutputStream) { + return new OutputChoice(OutputChoice.OutputChoiceType.CACHED_SYS_OUT); + } else { + return new OutputChoice(OutputChoice.OutputChoiceType.SYS_OUT); + } + } else { + try { + FileOutputStream fos = new FileOutputStream(logFile); + PrintStream printStream = new PrintStream(fos); + return new OutputChoice(printStream); + } catch (FileNotFoundException e) { + Util.report("Could not open [" + logFile + "]. Defaulting to System.err", e); + return new OutputChoice(OutputChoice.OutputChoiceType.SYS_ERR); + } + } + } + + void init() { + loadProperties(); + + String defaultLogLevelString = getStringProperty(TestLogger.DEFAULT_LOG_LEVEL_KEY, null); + if (defaultLogLevelString != null) { + defaultLogLevel = stringToLevel(defaultLogLevelString); + } + + showLogName = getBooleanProperty(TestLogger.SHOW_LOG_NAME_KEY, TestLoggerConfiguration.SHOW_LOG_NAME_DEFAULT); + showShortLogName = getBooleanProperty(TestLogger.SHOW_SHORT_LOG_NAME_KEY, SHOW_SHORT_LOG_NAME_DEFAULT); + showDateTime = getBooleanProperty(TestLogger.SHOW_DATE_TIME_KEY, SHOW_DATE_TIME_DEFAULT); + showThreadName = getBooleanProperty(TestLogger.SHOW_THREAD_NAME_KEY, SHOW_THREAD_NAME_DEFAULT); + showThreadId = getBooleanProperty(TestLogger.SHOW_THREAD_ID_KEY, SHOW_THREAD_ID_DEFAULT); + dateTimeFormatStr = getStringProperty(TestLogger.DATE_TIME_FORMAT_KEY, DATE_TIME_FORMAT_STR_DEFAULT); + levelInBrackets = getBooleanProperty(TestLogger.LEVEL_IN_BRACKETS_KEY, LEVEL_IN_BRACKETS_DEFAULT); + warnLevelString = getStringProperty(TestLogger.WARN_LEVEL_STRING_KEY, WARN_LEVELS_STRING_DEFAULT); + + logFile = getStringProperty(TestLogger.LOG_FILE_KEY, logFile); + + cacheOutputStream = getBooleanProperty(TestLogger.CACHE_OUTPUT_STREAM_STRING_KEY, CACHE_OUTPUT_STREAM_DEFAULT); + outputChoice = computeOutputChoice(logFile, cacheOutputStream); + + if (dateTimeFormatStr != null) { + try { + dateFormatter = new SimpleDateFormat(dateTimeFormatStr); + } catch (IllegalArgumentException e) { + Util.report("Bad date format in " + CONFIGURATION_FILE + "; will output relative time", e); + } + } + } + + private void loadProperties() { + // Add props from the resource testlogger.properties + InputStream in = AccessController.doPrivileged((PrivilegedAction) () -> { + ClassLoader threadCL = Thread.currentThread().getContextClassLoader(); + if (threadCL != null) { + return threadCL.getResourceAsStream(CONFIGURATION_FILE); + } else { + return ClassLoader.getSystemResourceAsStream(CONFIGURATION_FILE); + } + }); + if (null != in) { + try { + properties.load(in); + } catch (java.io.IOException e) { + // ignored + } finally { + try { + in.close(); + } catch (java.io.IOException e) { + // ignored + } + } + } + } + + String getStringProperty(String name, String defaultValue) { + String prop = getStringProperty(name); + return (prop == null) ? defaultValue : prop; + } + + boolean getBooleanProperty(String name, boolean defaultValue) { + String prop = getStringProperty(name); + return (prop == null) ? defaultValue : "true".equalsIgnoreCase(prop); + } + + String getStringProperty(String name) { + String prop = null; + try { + prop = System.getProperty(name); + } catch (SecurityException e) { + ; // Ignore + } + return (prop == null) ? properties.getProperty(name) : prop; + } + +} diff --git a/powertools-logging/src/test/java/org/slf4j/test/TestLoggerFactory.java b/powertools-logging/src/test/java/org/slf4j/test/TestLoggerFactory.java new file mode 100644 index 000000000..d597b5706 --- /dev/null +++ b/powertools-logging/src/test/java/org/slf4j/test/TestLoggerFactory.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + *

+ * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *

+ * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.slf4j.test; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; + +/** + * An implementation of {@link ILoggerFactory} which always returns + * {@link TestLogger} instances. + * + * @author Ceki Gülcü + */ +public class TestLoggerFactory implements ILoggerFactory { + + ConcurrentMap loggerMap; + + public TestLoggerFactory() { + loggerMap = new ConcurrentHashMap<>(); + TestLogger.lazyInit(); + } + + public Map getLoggers() { + return loggerMap; + } + + /** + * Return an appropriate {@link TestLogger} instance by name. + */ + public Logger getLogger(String name) { + Logger simpleLogger = loggerMap.get(name); + if (simpleLogger != null) { + return simpleLogger; + } else { + Logger newInstance = new TestLogger(name); + Logger oldInstance = loggerMap.putIfAbsent(name, newInstance); + return oldInstance == null ? newInstance : oldInstance; + } + } + + /** + * Clear the internal logger cache. + * + * This method is intended to be called by classes (in the same package) for + * testing purposes. This method is internal. It can be modified, renamed or + * removed at any time without notice. + * + * You are strongly discouraged from calling this method in production code. + */ + void reset() { + loggerMap.clear(); + } +} diff --git a/powertools-logging/src/test/java/org/slf4j/test/TestServiceProvider.java b/powertools-logging/src/test/java/org/slf4j/test/TestServiceProvider.java new file mode 100644 index 000000000..357360d1e --- /dev/null +++ b/powertools-logging/src/test/java/org/slf4j/test/TestServiceProvider.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2004-2011 QOS.ch + * All rights reserved. + *

+ * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *

+ * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + *

+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.slf4j.test; + +import org.slf4j.ILoggerFactory; +import org.slf4j.IMarkerFactory; +import org.slf4j.helpers.BasicMDCAdapter; +import org.slf4j.helpers.BasicMarkerFactory; +import org.slf4j.spi.MDCAdapter; +import org.slf4j.spi.SLF4JServiceProvider; + +/** + * Copy of the org.slf4j.simple.SimpleServiceProvider, replacing the NoOpMDCAdapter with a BasicMDCAdapter to test the MDC + */ +public class TestServiceProvider implements SLF4JServiceProvider { + /** + * Declare the version of the SLF4J API this implementation is compiled against. + * The value of this field is modified with each major release. + */ + // to avoid constant folding by the compiler, this field must *not* be final + public static String REQUESTED_API_VERSION = "2.0.99"; // !final + + private ILoggerFactory loggerFactory; + private IMarkerFactory markerFactory; + private MDCAdapter mdcAdapter; + + public ILoggerFactory getLoggerFactory() { + return loggerFactory; + } + + @Override + public IMarkerFactory getMarkerFactory() { + return markerFactory; + } + + @Override + public MDCAdapter getMDCAdapter() { + return mdcAdapter; + } + + @Override + public String getRequestedApiVersion() { + return REQUESTED_API_VERSION; + } + + @Override + public void initialize() { + + loggerFactory = new TestLoggerFactory(); + markerFactory = new BasicMarkerFactory(); + mdcAdapter = new BasicMDCAdapter(); + } + +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/LoggingUtilsTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/LoggingUtilsTest.java index 8889fb93c..04e977c58 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/LoggingUtilsTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/LoggingUtilsTest.java @@ -16,73 +16,99 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import java.util.HashMap; import java.util.Map; -import org.apache.logging.log4j.ThreadContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.MDC; +import software.amazon.lambda.powertools.utilities.JsonConfig; class LoggingUtilsTest { @BeforeEach void setUp() { - ThreadContext.clearAll(); + MDC.clear(); } @Test - void shouldSetCustomKeyOnThreadContext() { - LoggingUtils.appendKey("test", "value"); + void shouldSetCustomKeyInLoggingContext() { + LoggingUtils.appendKey("org/slf4j/test", "value"); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .hasSize(1) - .containsEntry("test", "value"); + .containsEntry("org/slf4j/test", "value"); } @Test - void shouldSetCustomKeyAsMapOnThreadContext() { + void shouldSetCustomKeyAsMapInLoggingContext() { Map customKeys = new HashMap<>(); - customKeys.put("test", "value"); + customKeys.put("org/slf4j/test", "value"); customKeys.put("test1", "value1"); LoggingUtils.appendKeys(customKeys); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .hasSize(2) - .containsEntry("test", "value") + .containsEntry("org/slf4j/test", "value") .containsEntry("test1", "value1"); } @Test - void shouldRemoveCustomKeyOnThreadContext() { - LoggingUtils.appendKey("test", "value"); + void shouldRemoveCustomKeyInLoggingContext() { + LoggingUtils.appendKey("org/slf4j/test", "value"); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .hasSize(1) - .containsEntry("test", "value"); + .containsEntry("org/slf4j/test", "value"); - LoggingUtils.removeKey("test"); + LoggingUtils.removeKey("org/slf4j/test"); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .isEmpty(); } @Test - void shouldRemoveCustomKeysOnThreadContext() { + void shouldRemoveCustomKeysInLoggingContext() { Map customKeys = new HashMap<>(); - customKeys.put("test", "value"); + customKeys.put("org/slf4j/test", "value"); customKeys.put("test1", "value1"); LoggingUtils.appendKeys(customKeys); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .hasSize(2) - .containsEntry("test", "value") + .containsEntry("org/slf4j/test", "value") .containsEntry("test1", "value1"); - LoggingUtils.removeKeys("test", "test1"); + LoggingUtils.removeKeys("org/slf4j/test", "test1"); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .isEmpty(); } + + @Test + void shouldAddCorrelationIdToLoggingContext() { + String id = "correlationID_12345"; + LoggingUtils.setCorrelationId(id); + + assertThat(MDC.getCopyOfContextMap()) + .hasSize(1) + .containsEntry("correlation_id", id); + + assertThat(LoggingUtils.getCorrelationId()).isEqualTo(id); + } + + @Test + void shouldGetObjectMapper() { + assertThat(LoggingUtils.getObjectMapper()).isNotNull(); + assertThat(LoggingUtils.getObjectMapper()).isEqualTo(JsonConfig.get().getObjectMapper()); + + ObjectMapper mapper = new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + LoggingUtils.setObjectMapper(mapper); + assertThat(LoggingUtils.getObjectMapper()).isEqualTo(mapper); + + } } \ No newline at end of file diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventEnabledWithCustomMapper.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventEnabledWithCustomMapper.java deleted file mode 100644 index 838de1216..000000000 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventEnabledWithCustomMapper.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging.handlers; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializerProvider; -import com.fasterxml.jackson.databind.module.SimpleModule; -import com.fasterxml.jackson.databind.ser.std.StdSerializer; -import java.io.IOException; -import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; - -public class PowerToolLogEventEnabledWithCustomMapper implements RequestHandler { - - static { - ObjectMapper objectMapper = new ObjectMapper(); - SimpleModule module = new SimpleModule(); - module.addSerializer(S3EventNotification.class, new S3EventNotificationSerializer()); - objectMapper.registerModule(module); - LoggingUtils.defaultObjectMapper(objectMapper); - } - - @Logging(logEvent = true) - @Override - public Object handleRequest(S3EventNotification input, Context context) { - return null; - } - - static class S3EventNotificationSerializer extends StdSerializer { - - public S3EventNotificationSerializer() { - this(null); - } - - public S3EventNotificationSerializer(Class t) { - super(t); - } - - @Override - public void serialize(S3EventNotification o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) - throws IOException { - jsonGenerator.writeStartObject(); - jsonGenerator.writeStringField("eventSource", o.getRecords().get(0).getEventSource()); - jsonGenerator.writeEndObject(); - } - } -} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogAlbCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogAlbCorrelationId.java index a32e3e06e..065d4c5b0 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogAlbCorrelationId.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogAlbCorrelationId.java @@ -14,17 +14,17 @@ package software.amazon.lambda.powertools.logging.handlers; -import static software.amazon.lambda.powertools.logging.CorrelationIdPathConstants.APPLICATION_LOAD_BALANCER; +import static software.amazon.lambda.powertools.logging.CorrelationIdPaths.APPLICATION_LOAD_BALANCER; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; public class PowertoolsLogAlbCorrelationId implements RequestHandler { - private final Logger LOG = LogManager.getLogger(PowertoolsLogAlbCorrelationId.class); + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogAlbCorrelationId.class); @Override @Logging(correlationIdPath = APPLICATION_LOAD_BALANCER) diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogApiGatewayHttpApiCorrelationId.java similarity index 78% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogApiGatewayHttpApiCorrelationId.java index 54d87d5cb..922a09f13 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayHttpApiCorrelationId.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogApiGatewayHttpApiCorrelationId.java @@ -14,17 +14,17 @@ package software.amazon.lambda.powertools.logging.handlers; -import static software.amazon.lambda.powertools.logging.CorrelationIdPathConstants.API_GATEWAY_HTTP; +import static software.amazon.lambda.powertools.logging.CorrelationIdPaths.API_GATEWAY_HTTP; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; -public class PowerLogToolApiGatewayHttpApiCorrelationId implements RequestHandler { - private final Logger LOG = LogManager.getLogger(PowerLogToolApiGatewayHttpApiCorrelationId.class); +public class PowertoolsLogApiGatewayHttpApiCorrelationId implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogApiGatewayHttpApiCorrelationId.class); @Override @Logging(correlationIdPath = API_GATEWAY_HTTP) diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogApiGatewayRestApiCorrelationId.java similarity index 78% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogApiGatewayRestApiCorrelationId.java index 2b6e5a8d4..7271e1d24 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolApiGatewayRestApiCorrelationId.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogApiGatewayRestApiCorrelationId.java @@ -14,17 +14,17 @@ package software.amazon.lambda.powertools.logging.handlers; -import static software.amazon.lambda.powertools.logging.CorrelationIdPathConstants.API_GATEWAY_REST; +import static software.amazon.lambda.powertools.logging.CorrelationIdPaths.API_GATEWAY_REST; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; -public class PowerLogToolApiGatewayRestApiCorrelationId implements RequestHandler { - private final Logger LOG = LogManager.getLogger(PowerLogToolApiGatewayRestApiCorrelationId.class); +public class PowertoolsLogApiGatewayRestApiCorrelationId implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogApiGatewayRestApiCorrelationId.class); @Override @Logging(correlationIdPath = API_GATEWAY_REST) diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogAppSyncCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogAppSyncCorrelationId.java new file mode 100644 index 000000000..fbe2bc89b --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogAppSyncCorrelationId.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.handlers; + +import static software.amazon.lambda.powertools.logging.CorrelationIdPaths.APPSYNC_RESOLVER; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogAppSyncCorrelationId implements RequestStreamHandler { + + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogAppSyncCorrelationId.class); + + @Override + @Logging(correlationIdPath = APPSYNC_RESOLVER) + public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { + LOG.info("Test event"); + } +} \ No newline at end of file diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabledWithClearState.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogClearState.java similarity index 67% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabledWithClearState.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogClearState.java index f21d9f118..e1829a777 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabledWithClearState.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogClearState.java @@ -16,23 +16,20 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.logging.LoggingUtils; -public class PowertoolsLogEnabledWithClearState implements RequestHandler { - private static final Logger LOG = LogManager.getLogger(PowertoolsLogEnabledWithClearState.class); - public static int COUNT = 1; +public class PowertoolsLogClearState implements RequestHandler, Object> { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogClearState.class); @Override @Logging(clearState = true) - public Object handleRequest(Object input, Context context) { - if (COUNT == 1) { - LoggingUtils.appendKey("TestKey", "TestValue"); - } + public Object handleRequest(Map input, Context context) { + LoggingUtils.appendKey("mySuperSecret", input.get("mySuperSecret")); LOG.info("Test event"); - COUNT++; return null; } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolDisabled.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogDisabled.java similarity index 91% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolDisabled.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogDisabled.java index 48a2e3b81..54e887e40 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolDisabled.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogDisabled.java @@ -17,7 +17,7 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; -public class PowerToolDisabled implements RequestHandler { +public class PowertoolsLogDisabled implements RequestHandler { @Override public Object handleRequest(Object input, Context context) { diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolDisabledForStream.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogDisabledForStream.java similarity index 92% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolDisabledForStream.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogDisabledForStream.java index 7f93145c7..7f7418ed6 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolDisabledForStream.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogDisabledForStream.java @@ -19,7 +19,7 @@ import java.io.InputStream; import java.io.OutputStream; -public class PowerToolDisabledForStream implements RequestStreamHandler { +public class PowertoolsLogDisabledForStream implements RequestStreamHandler { @Override public void handleRequest(InputStream input, OutputStream output, Context context) { diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabled.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabled.java new file mode 100644 index 000000000..d6c79a445 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabled.java @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogEnabled implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogEnabled.class); + private final boolean throwError; + + public PowertoolsLogEnabled(boolean throwError) { + this.throwError = throwError; + } + + public PowertoolsLogEnabled() { + this(false); + } + + @Override + @Logging + public Object handleRequest(Object input, Context context) { + if (throwError) { + throw new RuntimeException("Something went wrong"); + } + LOG.error("Test error event"); + LOG.warn("Test warn event"); + LOG.info("Test event"); + LOG.debug("Test debug event"); + return "Bonjour le monde"; + } + + @Logging + public void anotherMethod() { + System.out.println("test"); + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolEnabledForStream.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabledForStream.java similarity index 93% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolEnabledForStream.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabledForStream.java index 83a370437..c95627302 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolEnabledForStream.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabledForStream.java @@ -20,7 +20,7 @@ import java.io.OutputStream; import software.amazon.lambda.powertools.logging.Logging; -public class PowerLogToolEnabledForStream implements RequestStreamHandler { +public class PowertoolsLogEnabledForStream implements RequestStreamHandler { @Logging @Override diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogError.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogError.java new file mode 100644 index 000000000..a6b1ed915 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogError.java @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogError implements RequestHandler { + + @Override + @Logging(logError = true) + public Object handleRequest(Object input, Context context) { + throw new UnsupportedOperationException("This is an error"); + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventEnabled.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEvent.java similarity index 92% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventEnabled.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEvent.java index 8a960fa87..87677d601 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventEnabled.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEvent.java @@ -18,10 +18,10 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import software.amazon.lambda.powertools.logging.Logging; -public class PowerToolLogEventEnabled implements RequestHandler { +public class PowertoolsLogEvent implements RequestHandler { - @Logging(logEvent = true) @Override + @Logging(logEvent = true) public Object handleRequest(Object input, Context context) { return null; } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventBridgeCorrelationId.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventBridgeCorrelationId.java index 53e06cb2e..04d56d38c 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventBridgeCorrelationId.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventBridgeCorrelationId.java @@ -14,20 +14,20 @@ package software.amazon.lambda.powertools.logging.handlers; -import static software.amazon.lambda.powertools.logging.CorrelationIdPathConstants.EVENT_BRIDGE; +import static software.amazon.lambda.powertools.logging.CorrelationIdPaths.EVENT_BRIDGE; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; public class PowertoolsLogEventBridgeCorrelationId implements RequestStreamHandler { - private final Logger LOG = LogManager.getLogger(PowertoolsLogEventBridgeCorrelationId.class); + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogEventBridgeCorrelationId.class); @Override @Logging(correlationIdPath = EVENT_BRIDGE) diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventDisabled.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventDisabled.java similarity index 89% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventDisabled.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventDisabled.java index 77103e450..fc1feb52d 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventDisabled.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventDisabled.java @@ -18,9 +18,9 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import software.amazon.lambda.powertools.logging.Logging; -public class PowerToolLogEventDisabled implements RequestHandler { +public class PowertoolsLogEventDisabled implements RequestHandler { - @Logging(logEvent = false) + @Logging @Override public Object handleRequest(Object input, Context context) { return null; diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventEnabledForStream.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventForStream.java similarity index 80% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventEnabledForStream.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventForStream.java index 9de76586f..350b29cde 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerToolLogEventEnabledForStream.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventForStream.java @@ -23,12 +23,12 @@ import java.util.Map; import software.amazon.lambda.powertools.logging.Logging; -public class PowerToolLogEventEnabledForStream implements RequestStreamHandler { +public class PowertoolsLogEventForStream implements RequestStreamHandler { - @Logging(logEvent = true) @Override - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { + @Logging(logEvent = true) + public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { ObjectMapper mapper = new ObjectMapper(); - mapper.writeValue(output, mapper.readValue(input, Map.class)); + mapper.writeValue(outputStream, mapper.readValue(inputStream, Map.class)); } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponse.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponse.java new file mode 100644 index 000000000..001bde3ed --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponse.java @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogResponse implements RequestHandler { + + @Override + @Logging(logResponse = true) + public Object handleRequest(Object input, Context context) { + return "Hola mundo"; + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponseForStream.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponseForStream.java new file mode 100644 index 000000000..38be5c025 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponseForStream.java @@ -0,0 +1,35 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogResponseForStream implements RequestStreamHandler { + + @Override + @Logging(logResponse = true) + public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { + byte[] buf = new byte[1024]; + int length; + while ((length = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, length); + } + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolEnabled.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogSamplingDisabled.java similarity index 68% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolEnabled.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogSamplingDisabled.java index df68ea14f..5e2a7f148 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolEnabled.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogSamplingDisabled.java @@ -16,23 +16,18 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; -public class PowerLogToolEnabled implements RequestHandler { - private final Logger LOG = LogManager.getLogger(PowerLogToolEnabled.class); +public class PowertoolsLogSamplingDisabled implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogSamplingDisabled.class); @Override - @Logging - public Object handleRequest(Object input, Context context) { + @Logging(samplingRate = 0.0) + public Boolean handleRequest(Object input, Context context) { LOG.info("Test event"); LOG.debug("Test debug event"); - return null; - } - - @Logging - public void anotherMethod() { - System.out.println("test"); + return LOG.isDebugEnabled(); } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolSamplingEnabled.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogSamplingEnabled.java similarity index 74% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolSamplingEnabled.java rename to powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogSamplingEnabled.java index 357520395..6a8c37896 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowerLogToolSamplingEnabled.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogSamplingEnabled.java @@ -16,18 +16,18 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; -public class PowerLogToolSamplingEnabled implements RequestHandler { - private final Logger LOG = LogManager.getLogger(PowerLogToolSamplingEnabled.class); +public class PowertoolsLogSamplingEnabled implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogSamplingEnabled.class); @Override @Logging(samplingRate = 1.0) - public Object handleRequest(Object input, Context context) { + public Boolean handleRequest(Object input, Context context) { LOG.info("Test event"); LOG.debug("Test debug event"); - return null; + return LOG.isDebugEnabled(); } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index 453e1de29..bc5e53675 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -14,18 +14,24 @@ package software.amazon.lambda.powertools.logging.internal; -import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; import static java.util.stream.Collectors.joining; import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; +import static org.assertj.core.api.Assertions.contentOf; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.openMocks; -import static org.skyscreamer.jsonassert.JSONAssert.assertEquals; import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getProperty; import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_NAME; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_REQUEST_ID; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_VERSION; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SERVICE; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; @@ -33,52 +39,61 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; -import com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.amazonaws.services.lambda.runtime.tests.annotations.Event; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.ThreadContext; -import org.json.JSONException; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.mockito.Mock; import org.mockito.MockedStatic; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.event.Level; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.common.internal.SystemWrapper; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayHttpApiCorrelationId; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolApiGatewayRestApiCorrelationId; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabled; -import software.amazon.lambda.powertools.logging.handlers.PowerLogToolEnabledForStream; -import software.amazon.lambda.powertools.logging.handlers.PowerToolDisabled; -import software.amazon.lambda.powertools.logging.handlers.PowerToolDisabledForStream; -import software.amazon.lambda.powertools.logging.handlers.PowerToolLogEventDisabled; -import software.amazon.lambda.powertools.logging.handlers.PowerToolLogEventEnabled; -import software.amazon.lambda.powertools.logging.handlers.PowerToolLogEventEnabledForStream; -import software.amazon.lambda.powertools.logging.handlers.PowerToolLogEventEnabledWithCustomMapper; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId; -import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabledWithClearState; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayRestApiCorrelationId; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAppSyncCorrelationId; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogClearState; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogDisabled; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogDisabledForStream; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabled; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabledForStream; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogError; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEvent; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventBridgeCorrelationId; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventDisabled; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventForStream; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponse; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponseForStream; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogSamplingDisabled; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogSamplingEnabled; class LambdaLoggingAspectTest { + private static final Logger LOG = LoggerFactory.getLogger(LambdaLoggingAspectTest.class); private static final int EXPECTED_CONTEXT_SIZE = 8; private RequestStreamHandler requestStreamHandler; private RequestHandler requestHandler; @@ -87,210 +102,327 @@ class LambdaLoggingAspectTest { private Context context; @BeforeEach - void setUp() throws IllegalAccessException, IOException, NoSuchMethodException, InvocationTargetException { + void setUp() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException { openMocks(this); - ThreadContext.clearAll(); + MDC.clear(); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); setupContext(); - requestHandler = new PowerLogToolEnabled(); - requestStreamHandler = new PowerLogToolEnabledForStream(); + requestHandler = new PowertoolsLogEnabled(); + requestStreamHandler = new PowertoolsLogEnabledForStream(); + resetLogLevel(Level.INFO); + writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", null, true); + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", null, true); + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_EVENT", false, true); + writeStaticField(LoggingConstants.class, "POWERTOOLS_SAMPLING_RATE", null, true); + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } + } + + @AfterEach + void cleanUp() throws IOException { //Make sure file is cleaned up before running full stack logging regression FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); - resetLogLevel(Level.INFO); + } + + @Test + void shouldLogDebugWhenPowertoolsLevelEnvVarIsDebug() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "DEBUG", true); + + // WHEN + LambdaLoggingAspect.setLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isTrue(); + } + + @Test + void shouldLogInfoWhenPowertoolsLevelEnvVarIsInfo() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "INFO", true); + + // WHEN + LambdaLoggingAspect.setLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isTrue(); + } + + @Test + void shouldLogInfoWhenPowertoolsLevelEnvVarIsInvalid() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "INVALID", true); + + // WHEN + LambdaLoggingAspect.setLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isTrue(); + } + + @Test + void shouldLogWarnWhenPowertoolsLevelEnvVarIsWarn() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "WARN", true); + + // WHEN + LambdaLoggingAspect.setLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isFalse(); + assertThat(LOG.isWarnEnabled()).isTrue(); + } + + @Test + void shouldLogErrorWhenPowertoolsLevelEnvVarIsError() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "ERROR", true); + + // WHEN + LambdaLoggingAspect.setLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isFalse(); + assertThat(LOG.isWarnEnabled()).isFalse(); + assertThat(LOG.isErrorEnabled()).isTrue(); + } + + @Test + void shouldLogErrorWhenPowertoolsLevelEnvVarIsFatal() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "FATAL", true); + + // WHEN + LambdaLoggingAspect.setLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isFalse(); + assertThat(LOG.isWarnEnabled()).isFalse(); + assertThat(LOG.isErrorEnabled()).isTrue(); + } + + @Test + void shouldLogWarnWhenPowertoolsLevelEnvVarIsWarnAndLambdaLevelVarIsInfo() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "WARN", true); + writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", "INFO", true); + + // WHEN + LambdaLoggingAspect.setLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isFalse(); + assertThat(LOG.isWarnEnabled()).isTrue(); + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).doesNotContain(" does not match AWS Lambda Advanced Logging Controls minimum log level"); + } + + @Test + void shouldLogInfoWhenPowertoolsLevelEnvVarIsInfoAndLambdaLevelVarIsWarn() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "INFO", true); + writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", "WARN", true); + + // WHEN + LambdaLoggingAspect.setLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isTrue(); + File logFile = new File("target/logfile.json"); + // should log a warning as powertools level is lower than lambda level + assertThat(contentOf(logFile)).contains("Current log level (INFO) does not match AWS Lambda Advanced Logging Controls minimum log level (WARN). This can lead to data loss, consider adjusting them."); + } + + @Test + void shouldLogWarnWhenPowertoolsLevelEnvVarINotSetAndLambdaLevelVarIsWarn() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", null, true); + writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", "WARN", true); + + // WHEN + LambdaLoggingAspect.setLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isFalse(); + assertThat(LOG.isWarnEnabled()).isTrue(); } @Test void shouldSetLambdaContextWhenEnabled() { requestHandler.handleRequest(new Object(), context); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) - .containsEntry(DefaultLambdaFields.FUNCTION_ARN.getName(), "testArn") - .containsEntry(DefaultLambdaFields.FUNCTION_MEMORY_SIZE.getName(), "10") - .containsEntry(DefaultLambdaFields.FUNCTION_VERSION.getName(), "1") - .containsEntry(DefaultLambdaFields.FUNCTION_NAME.getName(), "testFunction") - .containsEntry(DefaultLambdaFields.FUNCTION_REQUEST_ID.getName(), "RequestId") - .containsKey("coldStart") - .containsKey("service"); + .containsEntry(FUNCTION_ARN.getName(), "testArn") + .containsEntry(FUNCTION_MEMORY_SIZE.getName(), "10") + .containsEntry(FUNCTION_VERSION.getName(), "1") + .containsEntry(FUNCTION_NAME.getName(), "testFunction") + .containsEntry(FUNCTION_REQUEST_ID.getName(), "RequestId") + .containsKey(FUNCTION_COLD_START.getName()) + .containsKey(SERVICE.getName()); } @Test void shouldSetLambdaContextForStreamHandlerWhenEnabled() throws IOException { - requestStreamHandler = new PowerLogToolEnabledForStream(); + requestStreamHandler = new PowertoolsLogEnabledForStream(); requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), context); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) - .containsEntry(DefaultLambdaFields.FUNCTION_ARN.getName(), "testArn") - .containsEntry(DefaultLambdaFields.FUNCTION_MEMORY_SIZE.getName(), "10") - .containsEntry(DefaultLambdaFields.FUNCTION_VERSION.getName(), "1") - .containsEntry(DefaultLambdaFields.FUNCTION_NAME.getName(), "testFunction") - .containsEntry(DefaultLambdaFields.FUNCTION_REQUEST_ID.getName(), "RequestId") - .containsKey("coldStart") - .containsKey("service"); + .containsEntry(FUNCTION_ARN.getName(), "testArn") + .containsEntry(FUNCTION_MEMORY_SIZE.getName(), "10") + .containsEntry(FUNCTION_VERSION.getName(), "1") + .containsEntry(FUNCTION_NAME.getName(), "testFunction") + .containsEntry(FUNCTION_REQUEST_ID.getName(), "RequestId") + .containsKey(FUNCTION_COLD_START.getName()) + .containsKey(SERVICE.getName()); } @Test - void shouldSetColdStartFlag() throws IOException { + void shouldSetColdStartFlagOnFirstCallNotOnSecondCall() throws IOException { requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), context); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) - .containsEntry("coldStart", "true"); + .containsEntry(FUNCTION_COLD_START.getName(), "true"); requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), context); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) - .containsEntry("coldStart", "false"); + .containsEntry(FUNCTION_COLD_START.getName(), "false"); } @Test void shouldNotSetLambdaContextWhenDisabled() { - requestHandler = new PowerToolDisabled(); + requestHandler = new PowertoolsLogDisabled(); requestHandler.handleRequest(new Object(), context); - assertThat(ThreadContext.getImmutableContext()) - .isEmpty(); + assertThat(MDC.getCopyOfContextMap()).isNull(); } @Test void shouldNotSetLambdaContextForStreamHandlerWhenDisabled() throws IOException { - requestStreamHandler = new PowerToolDisabledForStream(); + requestStreamHandler = new PowertoolsLogDisabledForStream(); requestStreamHandler.handleRequest(null, null, context); - assertThat(ThreadContext.getImmutableContext()) - .isEmpty(); + assertThat(MDC.getCopyOfContextMap()).isNull(); } @Test - void shouldHaveNoEffectIfNotUsedOnLambdaHandler() { - PowerLogToolEnabled handler = new PowerLogToolEnabled(); + void shouldClearStateWhenClearStateIsTrue() { + PowertoolsLogClearState handler = new PowertoolsLogClearState(); - handler.anotherMethod(); + handler.handleRequest(Collections.singletonMap("mySuperSecret", "P@ssw0Rd"), context); - assertThat(ThreadContext.getImmutableContext()) - .isEmpty(); + assertThat(MDC.getCopyOfContextMap()).isNull(); } @Test - void shouldLogEventForHandler() throws IOException, JSONException { - requestHandler = new PowerToolLogEventEnabled(); - S3EventNotification s3EventNotification = s3EventNotification(); - - requestHandler.handleRequest(s3EventNotification, context); + void shouldLogDebugWhenSamplingEqualsOne() { + PowertoolsLogSamplingEnabled handler = new PowertoolsLogSamplingEnabled(); - Map log = parseToMap(Files.lines(Paths.get("target/logfile.json")).collect(joining())); + Boolean debugEnabled = handler.handleRequest(new Object(), context); - String event = (String) log.get("message"); - - String expectEvent = new BufferedReader( - new InputStreamReader(this.getClass().getResourceAsStream("/s3EventNotification.json"))) - .lines().collect(joining("\n")); - - assertEquals(expectEvent, event, false); + assertThat(debugEnabled).isTrue(); } - /** - * If POWERTOOLS_LOGGER_LOG_EVENT was set to true, the handler should log, despite @Logging(logEvent=false) - * - * @throws IOException - */ @Test - void shouldLogEventForHandlerWhenEnvVariableSetToTrue() throws IOException, IllegalAccessException, JSONException { - try { - writeStaticField(LambdaLoggingAspect.class, "LOG_EVENT", Boolean.TRUE, true); - - requestHandler = new PowerToolLogEventDisabled(); - S3EventNotification s3EventNotification = s3EventNotification(); - - requestHandler.handleRequest(s3EventNotification, context); + void shouldLogDebugWhenSamplingEnvVarEqualsOne() throws IllegalAccessException { + // GIVEN + LoggingConstants.POWERTOOLS_SAMPLING_RATE = "1"; + PowertoolsLogEnabled handler = new PowertoolsLogEnabled(); - Map log = parseToMap(Files.lines(Paths.get("target/logfile.json")).collect(joining())); + // WHEN + handler.handleRequest(new Object(), context); - String event = (String) log.get("message"); - - String expectEvent = new BufferedReader( - new InputStreamReader(this.getClass().getResourceAsStream("/s3EventNotification.json"))) - .lines().collect(joining("\n")); - - assertEquals(expectEvent, event, false); - } finally { - writeStaticField(LambdaLoggingAspect.class, "LOG_EVENT", Boolean.FALSE, true); - } + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("Test debug event"); } - /** - * If POWERTOOLS_LOGGER_LOG_EVENT was set to false and @Logging(logEvent=false), the handler shouldn't log - * - * @throws IOException - */ @Test - void shouldNotLogEventForHandlerWhenEnvVariableSetToFalse() throws IOException { - requestHandler = new PowerToolLogEventDisabled(); - S3EventNotification s3EventNotification = s3EventNotification(); + void shouldNotLogDebugWhenSamplingEnvVarIsTooBig() throws IllegalAccessException { + // GIVEN + LoggingConstants.POWERTOOLS_SAMPLING_RATE = "42"; - requestHandler.handleRequest(s3EventNotification, context); + // WHEN + requestHandler.handleRequest(new Object(), context); - Assertions.assertEquals(0, - Files.lines(Paths.get("target/logfile.json")).collect(joining()).length()); + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).doesNotContain("Test debug event"); } @Test - void shouldLogEventForHandlerWithOverriddenObjectMapper() throws IOException, JSONException { - RequestHandler handler = new PowerToolLogEventEnabledWithCustomMapper(); - S3EventNotification s3EventNotification = s3EventNotification(); - - handler.handleRequest(s3EventNotification, context); - - Map log = parseToMap(Files.lines(Paths.get("target/logfile.json")).collect(joining())); + void shouldNotLogDebugWhenSamplingEnvVarIsInvalid() { + // GIVEN + LoggingConstants.POWERTOOLS_SAMPLING_RATE = "NotANumber"; - String event = (String) log.get("message"); - - String expectEvent = new BufferedReader( - new InputStreamReader(this.getClass().getResourceAsStream("/customizedLogEvent.json"))) - .lines().collect(joining("\n")); + // WHEN + requestHandler.handleRequest(new Object(), context); - assertEquals(expectEvent, event, false); + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).doesNotContain("Test debug event"); + assertThat(contentOf(logFile)).contains( + "Skipping sampling rate on environment variable configuration because of invalid value"); } @Test - void shouldLogEventForStreamAndLambdaStreamIsValid() throws IOException, JSONException { - requestStreamHandler = new PowerToolLogEventEnabledForStream(); - ByteArrayOutputStream output = new ByteArrayOutputStream(); - S3EventNotification s3EventNotification = s3EventNotification(); + void shouldNotLogDebugWhenSamplingEqualsZero() { + // GIVEN + LoggingConstants.POWERTOOLS_SAMPLING_RATE = "0"; + PowertoolsLogSamplingDisabled handler = new PowertoolsLogSamplingDisabled(); - requestStreamHandler.handleRequest( - new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(s3EventNotification)), output, context); - - assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) - .isNotEmpty(); + // WHEN + Boolean debugEnabled = handler.handleRequest(new Object(), context); - Map log = parseToMap(Files.lines(Paths.get("target/logfile.json")).collect(joining())); + // THEN + assertThat(debugEnabled).isFalse(); + } - String event = (String) log.get("message"); + @Test + void shouldHaveNoEffectIfNotUsedOnLambdaHandler() { + // GIVEN + PowertoolsLogEnabled handler = new PowertoolsLogEnabled(); - String expectEvent = new BufferedReader( - new InputStreamReader(this.getClass().getResourceAsStream("/s3EventNotification.json"))) - .lines().collect(joining("\n")); + // WHEN + handler.anotherMethod(); - assertEquals(expectEvent, event, false); + // THEN + assertThat(MDC.getCopyOfContextMap()).isNull(); } @Test void shouldLogServiceNameWhenEnvVarSet() throws IllegalAccessException { + // GIVEN writeStaticField(LambdaHandlerProcessor.class, "SERVICE_NAME", "testService", true); + + // WHEN requestHandler.handleRequest(new Object(), context); - assertThat(ThreadContext.getImmutableContext()) + // THEN + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) - .containsEntry("service", "testService"); + .containsEntry(SERVICE.getName(), "testService"); } @Test @@ -305,7 +437,7 @@ void shouldLogxRayTraceIdSystemPropertySet() { requestHandler.handleRequest(new Object(), context); - assertThat(ThreadContext.getImmutableContext()) + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE + 1) .containsEntry("xray_trace_id", xRayTraceId); } @@ -313,27 +445,191 @@ void shouldLogxRayTraceIdSystemPropertySet() { @Test void shouldLogxRayTraceIdEnvVarSet() { + // GIVEN String xRayTraceId = "1-5759e988-bd862e3fe1be46a994272793"; try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { mocked.when(() -> getenv("_X_AMZN_TRACE_ID")) .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); + // WHEN requestHandler.handleRequest(new Object(), context); - assertThat(ThreadContext.getImmutableContext()) + // THEN + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE + 1) - .containsEntry("xray_trace_id", xRayTraceId); + .containsEntry(FUNCTION_TRACE_ID.getName(), xRayTraceId); + } + } + + @Test + void shouldLogEventForHandlerWithLogEventAnnotation() { + // GIVEN + requestHandler = new PowertoolsLogEvent(); + + // WHEN + requestHandler.handleRequest(singletonList("ListOfOneElement"), context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("[\"ListOfOneElement\"]"); + } + + @Test + void shouldLogEventForHandlerWhenEnvVariableSetToTrue() throws IllegalAccessException { + try { + // GIVEN + LoggingConstants.POWERTOOLS_LOG_EVENT = true; + + requestHandler = new PowertoolsLogEnabled(); + + SQSEvent.SQSMessage message = new SQSEvent.SQSMessage(); + message.setBody("body"); + message.setMessageId("1234abcd"); + message.setAwsRegion("eu-west-1"); + + // WHEN + requestHandler.handleRequest(message, context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("\"body\":\"body\"").contains("\"messageId\":\"1234abcd\"").contains("\"awsRegion\":\"eu-west-1\""); + } finally { + LoggingConstants.POWERTOOLS_LOG_EVENT = false; + } + } + + @Test + void shouldNotLogEventForHandlerWhenEnvVariableSetToFalse() throws IOException { + // GIVEN + LoggingConstants.POWERTOOLS_LOG_EVENT = false; + + // WHEN + requestHandler = new PowertoolsLogEventDisabled(); + requestHandler.handleRequest(singletonList("ListOfOneElement"), context); + + // THEN + Assertions.assertEquals(0, + Files.lines(Paths.get("target/logfile.json")).collect(joining()).length()); + } + + @Test + void shouldLogEventForStreamHandler() throws IOException { + // GIVEN + requestStreamHandler = new PowertoolsLogEventForStream(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + + // WHEN + requestStreamHandler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(Collections.singletonMap("key", "value"))), output, context); + + // THEN + assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) + .isNotEmpty(); + + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("{\"key\":\"value\"}"); + } + + @Test + void shouldLogResponseForHandlerWithLogResponseAnnotation() { + // GIVEN + requestHandler = new PowertoolsLogResponse(); + + // WHEN + requestHandler.handleRequest("input", context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("Hola mundo"); + } + + @Test + void shouldLogResponseForHandlerWhenEnvVariableSetToTrue() throws IllegalAccessException { + try { + // GIVEN + LoggingConstants.POWERTOOLS_LOG_RESPONSE = true; + + requestHandler = new PowertoolsLogEnabled(); + + // WHEN + requestHandler.handleRequest("input", context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("Bonjour le monde"); + } finally { + LoggingConstants.POWERTOOLS_LOG_RESPONSE = false; + } + } + + @Test + void shouldLogResponseForStreamHandler() throws IOException { + // GIVEN + requestStreamHandler = new PowertoolsLogResponseForStream(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + String input = "BobThe Sponge"; + + // WHEN + requestStreamHandler.handleRequest(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)), output, context); + + // THEN + assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) + .isEqualTo(input); + + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains(input); + } + + @Test + void shouldLogErrorForHandlerWithLogErrorAnnotation() { + // GIVEN + requestHandler = new PowertoolsLogError(); + + // WHEN + try { + requestHandler.handleRequest("input", context); + } catch (Exception e) { + // ignore + } + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("This is an error"); + } + + @Test + void shouldLogErrorForHandlerWhenEnvVariableSetToTrue() throws IllegalAccessException { + try { + // GIVEN + LoggingConstants.POWERTOOLS_LOG_ERROR = true; + + requestHandler = new PowertoolsLogEnabled(true); + + // WHEN + try { + requestHandler.handleRequest("input", context); + } catch (Exception e) { + // ignore + } + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("Something went wrong"); + } finally { + LoggingConstants.POWERTOOLS_LOG_ERROR = false; } } @ParameterizedTest @Event(value = "apiGatewayProxyEventV1.json", type = APIGatewayProxyRequestEvent.class) void shouldLogCorrelationIdOnAPIGatewayProxyRequestEvent(APIGatewayProxyRequestEvent event) { - RequestHandler handler = new PowerLogToolApiGatewayRestApiCorrelationId(); + // GIVEN + RequestHandler handler = new PowertoolsLogApiGatewayRestApiCorrelationId(); + + // WHEN handler.handleRequest(event, context); - assertThat(ThreadContext.getImmutableContext()) + // THEN + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE + 1) .containsEntry("correlation_id", event.getRequestContext().getRequestId()); } @@ -341,10 +637,14 @@ void shouldLogCorrelationIdOnAPIGatewayProxyRequestEvent(APIGatewayProxyRequestE @ParameterizedTest @Event(value = "apiGatewayProxyEventV2.json", type = APIGatewayV2HTTPEvent.class) void shouldLogCorrelationIdOnAPIGatewayV2HTTPEvent(APIGatewayV2HTTPEvent event) { - RequestHandler handler = new PowerLogToolApiGatewayHttpApiCorrelationId(); + // GIVEN + RequestHandler handler = new PowertoolsLogApiGatewayHttpApiCorrelationId(); + + // WHEN handler.handleRequest(event, context); - assertThat(ThreadContext.getImmutableContext()) + // THEN + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE + 1) .containsEntry("correlation_id", event.getRequestContext().getRequestId()); } @@ -352,46 +652,92 @@ void shouldLogCorrelationIdOnAPIGatewayV2HTTPEvent(APIGatewayV2HTTPEvent event) @ParameterizedTest @Event(value = "albEvent.json", type = ApplicationLoadBalancerRequestEvent.class) void shouldLogCorrelationIdOnALBEvent(ApplicationLoadBalancerRequestEvent event) { + // GIVEN RequestHandler handler = new PowertoolsLogAlbCorrelationId(); + + // WHEN handler.handleRequest(event, context); - assertThat(ThreadContext.getImmutableContext()) + // THEN + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE + 1) .containsEntry("correlation_id", event.getHeaders().get("x-amzn-trace-id")); } @Test void shouldLogCorrelationIdOnStreamHandler() throws IOException { + // GIVEN RequestStreamHandler handler = new PowertoolsLogEventBridgeCorrelationId(); String eventId = "3"; - String event = "{\"id\":" + eventId + "}"; // CorrelationIdPathConstants.EVENT_BRIDGE + String event = "{\"id\":" + eventId + "}"; // CorrelationIdPath.EVENT_BRIDGE ByteArrayInputStream inputStream = new ByteArrayInputStream(event.getBytes()); + + // WHEN handler.handleRequest(inputStream, new ByteArrayOutputStream(), context); + // THEN + assertThat(MDC.getCopyOfContextMap()) + .hasSize(EXPECTED_CONTEXT_SIZE + 1) + .containsEntry("correlation_id", eventId); + } - assertThat(ThreadContext.getImmutableContext()) + @Test + void shouldLogCorrelationIdOnAppSyncEvent() throws IOException { + // GIVEN + RequestStreamHandler handler = new PowertoolsLogAppSyncCorrelationId(); + String eventId = "456"; + String event = "{\"request\":{\"headers\":{\"x-amzn-trace-id\":" + eventId + "}}}"; // CorrelationIdPath.APPSYNC_RESOLVER + ByteArrayInputStream inputStream = new ByteArrayInputStream(event.getBytes()); + + // WHEN + handler.handleRequest(inputStream, new ByteArrayOutputStream(), context); + + // THEN + assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE + 1) .containsEntry("correlation_id", eventId); } @Test - void shouldLogAndClearLogContextOnEachRequest() throws IOException { - requestHandler = new PowertoolsLogEnabledWithClearState(); - S3EventNotification s3EventNotification = s3EventNotification(); + void testMultipleLoggingManagers_shouldWarnAndSelectFirstOne() throws UnsupportedEncodingException { + // GIVEN + List list = new ArrayList<>(); + list.add(new TestLoggingManager()); + list.add(new DefautlLoggingManager()); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream stream = new PrintStream(outputStream); + + // WHEN + LambdaLoggingAspect.getLoggingManager(list, stream); + + // THEN + String output = outputStream.toString("UTF-8"); + assertThat(output) + .contains("WARN. Multiple LoggingManagers were found on the classpath") + .contains("WARN. Make sure to have only one of powertools-logging-log4j OR powertools-logging-logback to your dependencies") + .contains("WARN. Using the first LoggingManager found on the classpath: [" + list.get(0) + "]"); + } - requestHandler.handleRequest(s3EventNotification, context); - requestHandler.handleRequest(s3EventNotification, context); + @Test + void testNoLoggingManagers_shouldWarnAndCreateDefault() throws UnsupportedEncodingException { + // GIVEN + List list = new ArrayList<>(); - List logLines = Files.lines(Paths.get("target/logfile.json")).collect(Collectors.toList()); - Map invokeLog = parseToMap(logLines.get(0)); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream stream = new PrintStream(outputStream); - assertThat(invokeLog) - .containsEntry("TestKey", "TestValue"); + // WHEN + LoggingManager loggingManager = LambdaLoggingAspect.getLoggingManager(list, stream); - invokeLog = parseToMap(logLines.get(1)); + // THEN + String output = outputStream.toString("UTF-8"); + assertThat(output) + .contains("ERROR. No LoggingManager was found on the classpath") + .contains("ERROR. Applying default LoggingManager: POWERTOOLS_LOG_LEVEL variable is ignored") + .contains("ERROR. Make sure to add either powertools-logging-log4j or powertools-logging-logback to your dependencies"); - assertThat(invokeLog) - .doesNotContainKey("TestKey"); + assertThat(loggingManager).isExactlyInstanceOf(DefautlLoggingManager.class); } private void setupContext() { @@ -404,44 +750,9 @@ private void setupContext() { private void resetLogLevel(Level level) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - Method resetLogLevels = LambdaLoggingAspect.class.getDeclaredMethod("resetLogLevels", Level.class); - resetLogLevels.setAccessible(true); - resetLogLevels.invoke(null, level); + Method setLogLevels = LambdaLoggingAspect.class.getDeclaredMethod("setLogLevels", Level.class); + setLogLevels.setAccessible(true); + setLogLevels.invoke(null, level); writeStaticField(LambdaLoggingAspect.class, "LEVEL_AT_INITIALISATION", level, true); } - - private S3EventNotification s3EventNotification() { - S3EventNotification.S3EventNotificationRecord record = - new S3EventNotification.S3EventNotificationRecord("us-west-2", - "ObjectCreated:Put", - "aws:s3", - null, - "2.1", - new S3EventNotification.RequestParametersEntity("127.0.0.1"), - new S3EventNotification.ResponseElementsEntity("C3D13FE58DE4C810", - "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"), - new S3EventNotification.S3Entity("testConfigRule", - new S3EventNotification.S3BucketEntity("mybucket", - new S3EventNotification.UserIdentityEntity("A3NL1KOZZKExample"), - "arn:aws:s3:::mybucket"), - new S3EventNotification.S3ObjectEntity("HappyFace.jpg", - 1024L, - "d41d8cd98f00b204e9800998ecf8427e", - "096fKKXTRTtl3on89fVO.nfljtsv6qko", - "0055AED6DCD90281E5"), - "1.0"), - new S3EventNotification.UserIdentityEntity("AIDAJDPLRKLG7UEXAMPLE") - ); - - return new S3EventNotification(singletonList(record)); - } - - private Map parseToMap(String stringAsJson) { - try { - return new ObjectMapper().readValue(stringAsJson, Map.class); - } catch (JsonProcessingException e) { - fail("Failed parsing logger line " + stringAsJson); - return emptyMap(); - } - } } \ No newline at end of file diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/TestLoggingManager.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/TestLoggingManager.java new file mode 100644 index 000000000..0958e0d3b --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/TestLoggingManager.java @@ -0,0 +1,32 @@ +package software.amazon.lambda.powertools.logging.internal; + +import org.slf4j.ILoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; +import org.slf4j.test.TestLogger; +import org.slf4j.test.TestLoggerFactory; + +public class TestLoggingManager implements LoggingManager { + + private final TestLoggerFactory loggerFactory; + + public TestLoggingManager() { + ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory(); + if (!(loggerFactory instanceof TestLoggerFactory)) { + throw new RuntimeException( + "LoggerFactory does not match required type: " + TestLoggerFactory.class.getName()); + } + this.loggerFactory = (TestLoggerFactory) loggerFactory; + } + + @Override + public void setLogLevel(Level logLevel) { + loggerFactory.getLoggers().forEach((key, logger) -> ((TestLogger) logger).setLogLevel(logLevel.toString())); + } + + @Override + public Level getLogLevel(Logger logger) { + return org.slf4j.event.Level.intToLevel(((TestLogger) logger).getLogLevel()); + } +} diff --git a/powertools-logging/src/test/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider b/powertools-logging/src/test/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider new file mode 100644 index 000000000..ade4bb1e2 --- /dev/null +++ b/powertools-logging/src/test/resources/META-INF/services/org.slf4j.spi.SLF4JServiceProvider @@ -0,0 +1 @@ +org.slf4j.test.TestServiceProvider \ No newline at end of file diff --git a/powertools-logging/src/test/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager b/powertools-logging/src/test/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager new file mode 100644 index 000000000..adbf7ae69 --- /dev/null +++ b/powertools-logging/src/test/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager @@ -0,0 +1,15 @@ +# +# Copyright 2023 Amazon.com, Inc. or its affiliates. +# Licensed under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +software.amazon.lambda.powertools.logging.internal.TestLoggingManager \ No newline at end of file diff --git a/powertools-logging/src/test/resources/log4j2.xml b/powertools-logging/src/test/resources/log4j2.xml deleted file mode 100644 index 22a44ee8b..000000000 --- a/powertools-logging/src/test/resources/log4j2.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/powertools-logging/src/test/resources/s3EventNotification.json b/powertools-logging/src/test/resources/s3EventNotification.json deleted file mode 100644 index feb88ec02..000000000 --- a/powertools-logging/src/test/resources/s3EventNotification.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "records":[ - { - "eventVersion":"2.1", - "eventSource":"aws:s3", - "awsRegion":"us-west-2", - "eventName":"ObjectCreated:Put", - "userIdentity":{ - "principalId":"AIDAJDPLRKLG7UEXAMPLE" - }, - "requestParameters":{ - "sourceIPAddress":"127.0.0.1" - }, - "responseElements":{ - "xAmzId2":"C3D13FE58DE4C810", - "xAmzRequestId":"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD" - }, - "s3":{ - "s3SchemaVersion":"1.0", - "configurationId":"testConfigRule", - "bucket":{ - "name":"mybucket", - "ownerIdentity":{ - "principalId":"A3NL1KOZZKExample" - }, - "arn":"arn:aws:s3:::mybucket" - }, - "object":{ - "key":"HappyFace.jpg", - "size":1024, - "eTag":"d41d8cd98f00b204e9800998ecf8427e", - "versionId":"096fKKXTRTtl3on89fVO.nfljtsv6qko", - "sequencer":"0055AED6DCD90281E5" - } - } - } - ] -} \ No newline at end of file diff --git a/powertools-logging/src/test/resources/testlogger.properties b/powertools-logging/src/test/resources/testlogger.properties new file mode 100644 index 000000000..84b7beaae --- /dev/null +++ b/powertools-logging/src/test/resources/testlogger.properties @@ -0,0 +1,3 @@ +org.slf4j.simpleLogger.defaultLogLevel=warn +org.slf4j.simpleLogger.log.software.amazon.lambda.powertools=info +org.slf4j.simpleLogger.logFile=target/logfile.json \ No newline at end of file diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 8c9ce79ad..7de1efa3f 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -27,7 +27,7 @@ 2.0.0-SNAPSHOT - Powertools for AWS Lambda (Java) library Metrics + Powertools for AWS Lambda (Java) - Metrics A suite of utilities for AWS Lambda Functions that make creating custom metrics via AWS Embedded Metric Format asynchronously easier. @@ -56,6 +56,11 @@ + + org.aspectj + aspectjrt + provided + software.amazon.lambda powertools-common diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 1bc662457..54065aab2 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -26,11 +26,16 @@ powertools-parameters - Powertools for AWS Lambda (Java) library Parameters + Powertools for AWS Lambda (Java) - Parameters Set of utilities to retrieve parameters - common interface + + org.aspectj + aspectjrt + provided + software.amazon.lambda powertools-common diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index d92d68fb0..d1b2de826 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -27,7 +27,7 @@ powertools-serialization jar - Powertools for AWS Lambda (Java) library Serialization Utilities + Powertools for AWS Lambda (Java) - Serialization Utilities @@ -64,8 +64,8 @@ aws-lambda-java-events - org.apache.logging.log4j - log4j-slf4j2-impl + org.slf4j + slf4j-api com.fasterxml.jackson.core diff --git a/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java b/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java index baa6a0367..e961f21fa 100644 --- a/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java +++ b/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java @@ -82,6 +82,6 @@ public void addFunction(T function) { } private static class ConfigHolder { - private final static JsonConfig instance = new JsonConfig(); + private static final JsonConfig instance = new JsonConfig(); } } diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 6498d3772..1625fd0cb 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -27,7 +27,7 @@ 2.0.0-SNAPSHOT - Powertools for AWS Lambda (Java) library Tracing + Powertools for AWS Lambda (Java) - Tracing A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. @@ -56,6 +56,11 @@ + + org.aspectj + aspectjrt + provided + software.amazon.lambda powertools-common diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 269513a46..bd57fa6c5 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -27,7 +27,7 @@ 2.0.0-SNAPSHOT - Powertools for AWS Lambda (Java) validation library + Powertools for AWS Lambda (Java) - Validation Json schema validation for Lambda events and responses diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java index 143f0584d..ccc5a4c2c 100644 --- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java @@ -97,6 +97,6 @@ public ObjectMapper getObjectMapper() { } private static class ConfigHolder { - private final static ValidationConfig instance = new ValidationConfig(); + private static final ValidationConfig instance = new ValidationConfig(); } } diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index dc22f22b6..2d61cc68d 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -46,22 +46,6 @@ - - - - - - - - - - - - - - - - @@ -80,20 +64,12 @@ - - - - - - + + - - - - - - + + @@ -130,12 +106,21 @@ + + + + + + + + + - + @@ -156,7 +141,7 @@ - + From bb9bb2e540b58938caf29a46731f4fedc8fea155 Mon Sep 17 00:00:00 2001 From: Jason Harris Date: Tue, 12 Dec 2023 10:51:10 +0000 Subject: [PATCH 112/577] chore: SAM and Terraform IaC extracted from pr_build and simplified approach. (#1533) * SAM and Terraform IaC extracted from pr_build and simplified approach. * Update .github/workflows/pr_iac_lint.yml Co-authored-by: Scott Gerring --------- Co-authored-by: Jason Harris Co-authored-by: Scott Gerring --- .github/workflows/pr_build.yml | 21 ------------- .github/workflows/pr_iac_lint.yml | 49 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/pr_iac_lint.yml diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 3cf3a5425..7a02b08d4 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -79,33 +79,12 @@ jobs: if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 working-directory: examples/powertools-examples-core/kotlin run: ./gradlew build - - name: Setup Terraform - if: ${{ matrix.java == '11' }} - uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 #v2.0.3 - name: Setup AWS credentials if: ${{ matrix.java == '11' }} uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} aws-region: ${{ env.AWS_REGION }} - - name: Terraform validate - working-directory: examples/powertools-examples-core/terraform - if: ${{ matrix.java == '11' }} - run: | - terraform -version - terraform init -backend=false - terraform validate - terraform plan - - name: Setup Terraform lint - if: ${{ matrix.java == '11' }} - uses: terraform-linters/setup-tflint@a5a1af8c6551fb10c53f1cd4ba62359f1973746f # v3.1.1 - - name: Terraform lint - working-directory: examples/powertools-examples-core/terraform - if: ${{ matrix.java == '11' }} - run: | - tflint --version - tflint --init - tflint -f compact - name: Upload coverage to Codecov uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 if: ${{ matrix.java == '11' }} # publish results once diff --git a/.github/workflows/pr_iac_lint.yml b/.github/workflows/pr_iac_lint.yml new file mode 100644 index 000000000..1ed2077f5 --- /dev/null +++ b/.github/workflows/pr_iac_lint.yml @@ -0,0 +1,49 @@ +name: Validate IaC + +on: + push: + branches: + - main + - v2 + pull_request: + branches: + - main + - v2 + paths: + - 'examples/**' +jobs: + linter: + runs-on: ubuntu-latest + strategy: + matrix: + project: ["sam", "gradle", "kotlin"] + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Setup java JDK + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + with: + distribution: 'corretto' + java-version: 11 + - name: Run SAM validator to check syntax of IaC templates - Java + working-directory: examples/powertools-examples-core/${{ matrix.project }} + run: | + sam build + sam validate --lint + - name: Setup Terraform + uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 #v2.0.3 + - name: Run Terraform validator to check syntax of IaC templates and produce a plan of changes + working-directory: examples/powertools-examples-core/terraform + run: | + mvn install + terraform -version + terraform init -backend=false + terraform validate + terraform plan + - name: Setup Terraform lint + uses: terraform-linters/setup-tflint@a5a1af8c6551fb10c53f1cd4ba62359f1973746f # v3.1.1 + - name: Run Terraform lint to check for best practices, errors, deprecated syntax etc. + working-directory: examples/powertools-examples-core/terraform + run: | + tflint --version + tflint --init + tflint -f compact \ No newline at end of file From 516db4e25b21891cb03fd63eb00c25a6bb0a2b5d Mon Sep 17 00:00:00 2001 From: jdoherty Date: Thu, 14 Dec 2023 06:52:42 +0000 Subject: [PATCH 113/577] chore: cleanup poms and reduce warning noise (#1535) * pom cleanup and reduce warning noise * added variable for version --- examples/pom.xml | 1 + examples/powertools-examples-batch/pom.xml | 1 + .../pom.xml | 1 + .../cdk/app/pom.xml | 1 + .../cdk/infra/pom.xml | 1 + .../terraform/pom.xml | 1 + .../powertools-examples-idempotency/pom.xml | 1 + .../powertools-examples-parameters/pom.xml | 1 + .../powertools-examples-serialization/pom.xml | 1 + .../powertools-examples-validation/pom.xml | 1 + pom.xml | 40 ++++++++++--------- powertools-cloudformation/pom.xml | 22 ---------- powertools-common/pom.xml | 23 ----------- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 22 ---------- powertools-large-messages/pom.xml | 22 ---------- powertools-logging/pom.xml | 5 ++- powertools-metrics/pom.xml | 22 ---------- powertools-parameters/pom.xml | 1 - powertools-serialization/pom.xml | 22 ---------- powertools-tracing/pom.xml | 23 ----------- powertools-validation/pom.xml | 23 ----------- .../validation/internal/ValidationAspect.java | 7 ++-- 23 files changed, 38 insertions(+), 206 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index 943cad950..f864c3c04 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -48,6 +48,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index a1b4c0bbc..947f146b3 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -136,6 +136,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index bee97e52a..8851daa6d 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -144,6 +144,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index f8d340f3b..f964782e3 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -132,6 +132,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 053bd239c..f4d82141b 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -34,6 +34,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index c6f838619..94f79a5fd 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -118,6 +118,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 5a040fec0..19d7a2272 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -176,6 +176,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 3630811f3..a08747ff2 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -108,6 +108,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 2c8fc951a..106fe7cbb 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -41,6 +41,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index ed33568cb..1c39ee8a0 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -106,6 +106,7 @@ org.apache.maven.plugins maven-deploy-plugin + 3.1.1 true diff --git a/pom.xml b/pom.xml index b7227cf8a..7577659f4 100644 --- a/pom.xml +++ b/pom.xml @@ -32,6 +32,25 @@ GitHub Issues https://github.com/aws-powertools/powertools-lambda-java/issues + + + https://github.com/aws-powertools/powertools-lambda-java.git + + + + Powertools for AWS Lambda (Java) Team + Amazon Web Services + https://aws.amazon.com/ + + + + + + ossrh + https://aws.oss.sonatype.org/content/repositories/snapshots + + + Apache License, Version 2.0 @@ -63,21 +82,11 @@ powertools-parameters/powertools-parameters-tests - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - - Powertools for AWS Lambda (Java) team - Amazon Web Services - https://aws.amazon.com/ - - - 1.8 1.8 + 3.1.1 + 2.20.0 2.22.0 2.0.7 2.15.3 @@ -103,13 +112,6 @@ 1.5.0 - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - - diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 79071d532..e3e4748d6 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -32,28 +32,6 @@ A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda (Java) Team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 363d2e944..15409e1f6 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -29,29 +29,6 @@ Powertools for AWS Lambda (Java) - Common Internal Utilities Internal utilities shared by the Powertools for AWS Lambda (Java) modules. Do not use directly in your project. - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index a64e7a354..9d84ce9f2 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -184,7 +184,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + ${maven.deploy.plugin.version} true diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index eda7bd982..fd53cd9e2 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -31,28 +31,6 @@ - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index af031ff21..4206183de 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -31,28 +31,6 @@ Powertools for AWS Lambda (Java) - Large messages - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - - org.aspectj diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 56ca0e62b..43c65a3b0 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -17,16 +17,17 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + powertools-parent software.amazon.lambda 2.0.0-SNAPSHOT - powertools-logging - jar Powertools for AWS Lambda (Java) - Logging Set of utility for better logging - common + powertools-logging + jar diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 7de1efa3f..0daa49664 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -32,28 +32,6 @@ A suite of utilities for AWS Lambda Functions that make creating custom metrics via AWS Embedded Metric Format asynchronously easier. - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 54065aab2..6c90e30a8 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -27,7 +27,6 @@ powertools-parameters Powertools for AWS Lambda (Java) - Parameters - Set of utilities to retrieve parameters - common interface diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index d1b2de826..454b30d3e 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -31,28 +31,6 @@ - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 1625fd0cb..9d60d4f40 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -31,29 +31,6 @@ A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index bd57fa6c5..a5fc4a890 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -31,29 +31,6 @@ Json schema validation for Lambda events and responses - https://aws.amazon.com/lambda/ - - GitHub Issues - https://github.com/aws-powertools/powertools-lambda-java/issues - - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java index 978be16de..bcbba9e03 100644 --- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java @@ -22,10 +22,6 @@ import static software.amazon.lambda.powertools.validation.ValidationUtils.getJsonSchema; import static software.amazon.lambda.powertools.validation.ValidationUtils.validate; -import java.util.Collections; -import java.util.List; -import java.util.Map; - import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; @@ -47,6 +43,9 @@ import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.amazonaws.services.lambda.runtime.events.ScheduledEvent; import com.networknt.schema.JsonSchema; +import java.util.Collections; +import java.util.List; +import java.util.Map; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; From fb14bcfee1aae8e03b8c8081b2478edefc9b5b87 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Thu, 14 Dec 2023 10:46:10 +0100 Subject: [PATCH 114/577] chore: Support spotbugs running anywhere (#1537) * Allow spotbugs & checkstyle to run from any subdirectory * Clean up spotbugs-exclude --- .mvn/README | 2 + checkstyle.xml | 2 +- examples/spotbugs-exclude.xml | 20 ------ pom.xml | 7 +- powertools-logging/spotbugs-exclude.xml | 30 -------- powertools-parameters/spotbugs-exclude.xml | 82 ---------------------- spotbugs-exclude.xml | 65 ++++++++++++++++- 7 files changed, 71 insertions(+), 137 deletions(-) create mode 100644 .mvn/README delete mode 100644 examples/spotbugs-exclude.xml delete mode 100644 powertools-logging/spotbugs-exclude.xml delete mode 100644 powertools-parameters/spotbugs-exclude.xml diff --git a/.mvn/README b/.mvn/README new file mode 100644 index 000000000..a851f5e55 --- /dev/null +++ b/.mvn/README @@ -0,0 +1,2 @@ +This is here purely so that we can get the root directory using maven.multiModuleProjectDirectory + diff --git a/checkstyle.xml b/checkstyle.xml index 34ef98ef2..680d8808c 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -51,7 +51,7 @@ - + diff --git a/examples/spotbugs-exclude.xml b/examples/spotbugs-exclude.xml deleted file mode 100644 index e33e65478..000000000 --- a/examples/spotbugs-exclude.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7577659f4..a4df4116a 100644 --- a/pom.xml +++ b/pom.xml @@ -110,6 +110,10 @@ 1.0.6 0.6.0 1.5.0 + + + ${maven.multiModuleProjectDirectory} @@ -544,7 +548,7 @@ true - ../spotbugs-exclude.xml + ${project.rootdir}/spotbugs-exclude.xml @@ -641,6 +645,7 @@ maven-checkstyle-plugin 3.3.0 + basedir=${project.rootdir} checkstyle.xml true true diff --git a/powertools-logging/spotbugs-exclude.xml b/powertools-logging/spotbugs-exclude.xml deleted file mode 100644 index 0437849ae..000000000 --- a/powertools-logging/spotbugs-exclude.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/powertools-parameters/spotbugs-exclude.xml b/powertools-parameters/spotbugs-exclude.xml deleted file mode 100644 index d48e9bee1..000000000 --- a/powertools-parameters/spotbugs-exclude.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index 2d61cc68d..747752130 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -39,7 +39,34 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -58,6 +85,18 @@ + + + + + + + + + + + + @@ -103,6 +142,26 @@ + + + + + + + + + + + + + + + + + + + + @@ -171,5 +230,5 @@ - - \ No newline at end of file + + From f625b334ec55c679e3bf0c513e8cb865a192efdd Mon Sep 17 00:00:00 2001 From: ritigupt <102658810+ritigupt@users.noreply.github.com> Date: Tue, 2 Jan 2024 18:19:24 +0530 Subject: [PATCH 115/577] Removing LambdaJsonLayout from logging in examples (#1545) --- .../src/main/resources/log4j2.xml | 2 +- .../src/main/resources/log4j2.xml | 2 +- powertools-tracing/src/test/resources/log4j2.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-parameters/src/main/resources/log4j2.xml b/examples/powertools-examples-parameters/src/main/resources/log4j2.xml index 033da8a11..fe943d707 100644 --- a/examples/powertools-examples-parameters/src/main/resources/log4j2.xml +++ b/examples/powertools-examples-parameters/src/main/resources/log4j2.xml @@ -2,7 +2,7 @@ - + diff --git a/examples/powertools-examples-serialization/src/main/resources/log4j2.xml b/examples/powertools-examples-serialization/src/main/resources/log4j2.xml index 033da8a11..fe943d707 100644 --- a/examples/powertools-examples-serialization/src/main/resources/log4j2.xml +++ b/examples/powertools-examples-serialization/src/main/resources/log4j2.xml @@ -2,7 +2,7 @@ - + diff --git a/powertools-tracing/src/test/resources/log4j2.xml b/powertools-tracing/src/test/resources/log4j2.xml index 108e32b75..030d11725 100644 --- a/powertools-tracing/src/test/resources/log4j2.xml +++ b/powertools-tracing/src/test/resources/log4j2.xml @@ -2,7 +2,7 @@ - + From 47fab11f33d05e14e75415315f5f8f7600b9a308 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Wed, 3 Jan 2024 09:07:11 +0100 Subject: [PATCH 116/577] chore: Remove empty CDK test (#1542) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove CDK test * Build core utilities so that sam validator can find them * Remove CDK test * Ok just build it all * Remove the plan ... * Remove terraform plan from iac lint --------- Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> --- .github/workflows/pr_iac_lint.yml | 5 +- .../infra/src/test/java/cdk/CdkStackTest.java | 48 ------------------- 2 files changed, 4 insertions(+), 49 deletions(-) delete mode 100644 examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java diff --git a/.github/workflows/pr_iac_lint.yml b/.github/workflows/pr_iac_lint.yml index 1ed2077f5..c6e17ab1c 100644 --- a/.github/workflows/pr_iac_lint.yml +++ b/.github/workflows/pr_iac_lint.yml @@ -24,6 +24,10 @@ jobs: with: distribution: 'corretto' java-version: 11 + - name: Build Project + working-directory: . + run: | + mvn install -DskipTests - name: Run SAM validator to check syntax of IaC templates - Java working-directory: examples/powertools-examples-core/${{ matrix.project }} run: | @@ -38,7 +42,6 @@ jobs: terraform -version terraform init -backend=false terraform validate - terraform plan - name: Setup Terraform lint uses: terraform-linters/setup-tflint@a5a1af8c6551fb10c53f1cd4ba62359f1973746f # v3.1.1 - name: Run Terraform lint to check for best practices, errors, deprecated syntax etc. diff --git a/examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java b/examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java deleted file mode 100644 index 29cb15545..000000000 --- a/examples/powertools-examples-core/cdk/infra/src/test/java/cdk/CdkStackTest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package cdk; - -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; -import software.amazon.awscdk.App; -import software.amazon.awscdk.assertions.Template; - -public class CdkStackTest { - - @Test - public void testStack() { - App app = new App(); - CdkStack stack = new CdkStack(app, "test"); - - Template template = Template.fromStack(stack); - - // There should be 2 lambda functions, one to handle regular input, and another for streaming - template.resourceCountIs("AWS::Lambda::Function", 2); - - // API Gateway should exist - template.resourceCountIs("AWS::ApiGateway::RestApi", 1); - - // API Gateway should have a path pointing to the regular Lambda - Map resourceProperties = new HashMap<>(); - resourceProperties.put("PathPart", "hello"); - template.hasResourceProperties("AWS::ApiGateway::Resource", resourceProperties); - - // API Gateway should have a path pointing to the streaming Lambda - resourceProperties = new HashMap<>(); - resourceProperties.put("PathPart", "hellostream"); - template.hasResourceProperties("AWS::ApiGateway::Resource", resourceProperties); - } -} From e7933c23bc33767d6e8887e8e0d5c36a5d0f7a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:16:04 +0100 Subject: [PATCH 117/577] dependabot on v2 branch (#1548) --- .github/dependabot.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1454df79c..28adf2bc1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,3 +11,12 @@ updates: # Ignore Mockito 5.X.X as it does not support Java 8 - dependency-name: "org.mockito:mockito-*" update-types: ["version-update:semver-major"] + + - package-ecosystem: "maven" + directory: "/" + target-branch: "v2" + schedule: + interval: "weekly" + labels: + - "maven" + - "dependencies" From 3963d6d1f58c9618959f7a7044189a4a32d9b3fc Mon Sep 17 00:00:00 2001 From: ritigupt <102658810+ritigupt@users.noreply.github.com> Date: Wed, 24 Jan 2024 13:21:37 +0530 Subject: [PATCH 118/577] fix(v2): Fix params builder to provide default transformation manager (#1549) * Add default transformation manager in builders and add unit tests * undo the pom change * undo the pom change --- .../appconfig/AppConfigProviderBuilder.java | 4 +++- .../parameters/appconfig/AppConfigProviderTest.java | 13 +++++++++++++ .../dynamodb/DynamoDbProviderBuilder.java | 3 +++ .../parameters/dynamodb/DynamoDbProviderTest.java | 11 +++++++++++ .../parameters/secrets/SecretsProviderBuilder.java | 4 +++- .../parameters/secrets/SecretsProviderTest.java | 13 +++++++++++++ .../parameters/ssm/SSMProviderBuilder.java | 3 +++ .../powertools/parameters/ssm/SSMProviderTest.java | 12 ++++++++++++ 8 files changed, 61 insertions(+), 2 deletions(-) diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java index dadacb843..b6f6cd809 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderBuilder.java @@ -51,7 +51,9 @@ public AppConfigProvider build() { if (application == null) { throw new IllegalStateException("No application provided; please provide one"); } - + if (transformationManager == null) { + transformationManager = new TransformationManager(); + } // Create a AppConfigDataClient if we haven't been given one if (client == null) { client = AppConfigDataClient.builder() diff --git a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java index ded568e8d..039611875 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java @@ -17,7 +17,9 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatRuntimeException; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.MockitoAnnotations.openMocks; +import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -216,4 +218,15 @@ public void testAppConfigProviderBuilderMissingApplication_throwsException() { .build()) .withMessage("No application provided; please provide one"); } + @Test + public void testAppConfigProvider_withoutParameter_shouldHaveDefaultTransformationManager() { + + // Act + AppConfigProvider appConfigProvider = AppConfigProvider.builder() + .withEnvironment("test") + .withApplication("app") + .build(); + // Assert + assertDoesNotThrow(()->appConfigProvider.withTransformation(json)); + } } diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java index 6b6610ba1..b98ff285d 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderBuilder.java @@ -61,6 +61,9 @@ public DynamoDbProvider build() { if (client == null) { client = createClient(); } + if (transformationManager == null) { + transformationManager = new TransformationManager(); + } provider = new DynamoDbProvider(cacheManager, transformationManager, client, table); return provider; diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java index 68bfd7cdb..10d756c69 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java @@ -16,7 +16,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.MockitoAnnotations.openMocks; +import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; import java.util.HashMap; import java.util.Map; @@ -225,5 +227,14 @@ public void testDynamoDBBuilderMissingTable_throwsException() { .withCacheManager(new CacheManager()) .build()); } + @Test + public void testDynamoDBBuilder_withoutParameter_shouldHaveDefaultTransformationManager() { + + // Act + DynamoDbProvider dynamoDbProvider = DynamoDbProvider.builder().withTable("test-table") + .build(); + // Assert + assertDoesNotThrow(()->dynamoDbProvider.withTransformation(json)); + } } diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java index 125425200..c5806689f 100644 --- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java +++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java @@ -59,7 +59,9 @@ public SecretsProvider build() { if (client == null) { client = createClient(); } - + if(transformationManager == null){ + transformationManager = new TransformationManager(); + } provider = new SecretsProvider(cacheManager, transformationManager, client); return provider; diff --git a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java index 21173cad1..a2607dd2c 100644 --- a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java +++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java @@ -16,10 +16,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatRuntimeException; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; import java.time.temporal.ChronoUnit; import java.util.Base64; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -105,4 +108,14 @@ public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() assertNotNull(secretsProvider); assertNotNull(secretsProvider.getClient()); } + + @Test + public void testGetSecretsProvider_withoutParameter_shouldHaveDefaultTransformationManager() { + + // Act + SecretsProvider secretsProvider = SecretsProvider.builder() + .build(); + // Assert + assertDoesNotThrow(()->secretsProvider.withTransformation(json)); + } } diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java index 3b4fff1b3..4c26463fb 100644 --- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java +++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderBuilder.java @@ -57,6 +57,9 @@ public SSMProvider build() { client = createClient(); } + if(transformationManager == null){ + transformationManager = new TransformationManager(); + } provider = new SSMProvider(cacheManager, transformationManager, client); return provider; diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java index b105da438..db45dc21c 100644 --- a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java +++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java @@ -16,6 +16,8 @@ import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; import java.time.temporal.ChronoUnit; import java.util.ArrayList; @@ -194,6 +196,16 @@ public void getMultipleWithNextToken() { assertThat(request2.nextToken()).isEqualTo("123abc"); } + @Test + public void testSSMProvider_withoutParameter_shouldHaveDefaultTransformationManager() { + + // Act + SSMProvider ssmProvider = SSMProvider.builder() + .build(); + // Assert + assertDoesNotThrow(()->ssmProvider.withTransformation(json)); + } + private void initMock(String expectedValue) { Parameter parameter = Parameter.builder().value(expectedValue).build(); GetParameterResponse result = GetParameterResponse.builder().parameter(parameter).build(); From b0af349a64d04732f989ace73a76f7b7a9d7b1fa Mon Sep 17 00:00:00 2001 From: Subhash Kovela <46015546+subhash686@users.noreply.github.com> Date: Tue, 13 Feb 2024 06:26:09 -0500 Subject: [PATCH 119/577] Maintenance: Upgraded jackson and aws xray versions (#1556) --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a4df4116a..f0f5e051e 100644 --- a/pom.xml +++ b/pom.xml @@ -89,9 +89,9 @@ 2.20.0 2.22.0 2.0.7 - 2.15.3 + 2.16.0 2.21.0 - 2.14.0 + 2.15.0 2.1.3 UTF-8 1.2.3 From 82d4b308778b4408359a99797af648f20889bbf4 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Tue, 13 Feb 2024 15:50:40 +0100 Subject: [PATCH 120/577] chore(v2): Split powertools idempotency module (without redis impl) (#1559) * Introducing sub-modules in the idempotency module * Updating the idempotency documentation * Move test resource to the dynamodb idempotency sub-module * Renaming common module to core and refactoring package name for repo implementation * fix spotbugs for multiple modules and new pr_artifacts * fix spotbugs for multiple modules * fix spotbugs for multiple modules - with pom property * fix spotbugs for multiple modules - multiple spotbugs files * Try fixing java8 build * fix aspectj weaving * Clean-up pom dependencies and remove awssdk#StringUtils usage * Fix sonar issues * Fix some merge issues --------- Co-authored-by: Eleni Dimitropoulou <12170229+eldimi@users.noreply.github.com> Co-authored-by: Jerome Van Der Linden --- .github/workflows/pr_artifacts_size.yml | 3 +- .github/workflows/pr_build.yml | 1 + docs/utilities/idempotency.md | 12 +- .../powertools-examples-idempotency/pom.xml | 4 +- .../src/main/java/helloworld/App.java | 2 +- pom.xml | 20 --- powertools-batch/pom.xml | 1 + powertools-idempotency/pom.xml | 68 ++-------- .../powertools-idempotency-core/pom.xml | 42 ++++++ .../powertools/idempotency/Constants.java | 0 .../powertools/idempotency/Idempotency.java | 0 .../idempotency/IdempotencyConfig.java | 5 +- .../idempotency/IdempotencyKey.java | 0 .../powertools/idempotency/Idempotent.java | 1 + ...IdempotencyAlreadyInProgressException.java | 0 .../IdempotencyConfigurationException.java | 0 ...IdempotencyInconsistentStateException.java | 0 ...IdempotencyItemAlreadyExistsException.java | 0 .../IdempotencyItemNotFoundException.java | 0 .../exceptions/IdempotencyKeyException.java | 0 .../IdempotencyPersistenceLayerException.java | 0 .../IdempotencyValidationException.java | 0 .../internal/IdempotencyHandler.java | 11 +- .../internal/IdempotentAspect.java | 9 +- .../idempotency/internal/cache/LRUCache.java | 0 .../persistence/BasePersistenceStore.java | 38 +++--- .../idempotency/persistence/DataRecord.java | 3 +- .../persistence/PersistenceStore.java | 3 +- .../handlers/IdempotencyEnabledFunction.java | 0 .../handlers/IdempotencyInternalFunction.java | 0 ...dempotencyInternalFunctionInternalKey.java | 0 .../IdempotencyInternalFunctionInvalid.java | 0 .../IdempotencyInternalFunctionVoid.java | 0 .../handlers/IdempotencyStringFunction.java | 0 .../IdempotencyWithErrorFunction.java | 0 .../internal/IdempotencyAspectTest.java | 29 ++-- .../internal/cache/LRUCacheTest.java | 4 +- .../powertools/idempotency/model/Basket.java | 0 .../powertools/idempotency/model/Product.java | 0 .../persistence/BasePersistenceStoreTest.java | 15 ++- .../src/test/resources/apigw_event.json | 0 .../powertools-idempotency-dynamodb/pom.xml | 126 ++++++++++++++++++ .../dynamodb}/DynamoDBPersistenceStore.java | 31 +++-- .../DynamoDBConfig.java | 2 +- .../IdempotencyTest.java | 4 +- .../handlers/IdempotencyFunction.java | 21 +-- .../DynamoDBPersistenceStoreTest.java | 22 +-- .../src/test/resources/apigw_event2.json | 0 powertools-idempotency/spotbugs-exclude.xml | 46 +++++++ .../powertools-parameters-appconfig/pom.xml | 6 +- .../powertools-parameters-dynamodb/pom.xml | 5 + .../powertools-parameters-secrets/pom.xml | 5 + .../powertools-parameters-ssm/pom.xml | 5 + powertools-validation/pom.xml | 5 + spotbugs-exclude.xml | 10 +- 55 files changed, 379 insertions(+), 180 deletions(-) create mode 100644 powertools-idempotency/powertools-idempotency-core/pom.xml rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/Constants.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java (99%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyKey.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java (99%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyAlreadyInProgressException.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyConfigurationException.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyInconsistentStateException.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemNotFoundException.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyKeyException.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyPersistenceLayerException.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyValidationException.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java (99%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java (99%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java (96%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DataRecord.java (99%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/PersistenceStore.java (99%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyEnabledFunction.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunction.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionInternalKey.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionInvalid.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyInternalFunctionVoid.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyStringFunction.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyWithErrorFunction.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java (99%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCacheTest.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/model/Basket.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/model/Product.java (100%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java (99%) rename powertools-idempotency/{ => powertools-idempotency-core}/src/test/resources/apigw_event.json (100%) create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/pom.xml rename powertools-idempotency/{src/main/java/software/amazon/lambda/powertools/idempotency/persistence => powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb}/DynamoDBPersistenceStore.java (98%) rename powertools-idempotency/{src/test/java/software/amazon/lambda/powertools/idempotency => powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb}/DynamoDBConfig.java (98%) rename powertools-idempotency/{src/test/java/software/amazon/lambda/powertools/idempotency => powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb}/IdempotencyTest.java (93%) rename powertools-idempotency/{src/test/java/software/amazon/lambda/powertools/idempotency => powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb}/handlers/IdempotencyFunction.java (93%) rename powertools-idempotency/{src/test/java/software/amazon/lambda/powertools/idempotency/persistence => powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb}/DynamoDBPersistenceStoreTest.java (99%) rename powertools-idempotency/{ => powertools-idempotency-dynamodb}/src/test/resources/apigw_event2.json (100%) create mode 100644 powertools-idempotency/spotbugs-exclude.xml diff --git a/.github/workflows/pr_artifacts_size.yml b/.github/workflows/pr_artifacts_size.yml index 1d905af01..2244f7b06 100644 --- a/.github/workflows/pr_artifacts_size.yml +++ b/.github/workflows/pr_artifacts_size.yml @@ -11,7 +11,8 @@ on: - 'powertools-core/**' # not in v2 - 'powertools-common/**' # v2 only - 'powertools-e2e-tests/**' - - 'powertools-idempotency/**' + - 'powertools-idempotency-core/**' + - 'powertools-idempotency-dynamodb/**' - 'powertools-large-messages/**' - 'powertools-logging/**' - 'powertools-metrics/**' diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index e86f49753..5373f4b4c 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -26,6 +26,7 @@ on: push: branches: - main + - v2 paths: - 'powertools-batch/**' - 'powertools-cloudformation/**' diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index 5392b8d4c..f4defbdfd 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -35,7 +35,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl ... software.amazon.lambda - powertools-idempotency + powertools-idempotency-dynamodb {{ powertools.version }} ... @@ -56,7 +56,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl software.amazon.lambda - powertools-idempotency + powertools-idempotency-dynamodb @@ -80,7 +80,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl ... software.amazon.lambda - powertools-idempotency + powertools-idempotency-dynamodb {{ powertools.version }} ... @@ -101,7 +101,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl software.amazon.lambda - powertools-idempotency + powertools-idempotency-dynamodb @@ -131,7 +131,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl } dependencies { - aspect 'software.amazon.lambda:powertools-idempotency:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-idempotency-dynamodb:{{ powertools.version }}' } sourceCompatibility = 11 // or higher @@ -151,7 +151,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl } dependencies { - aspect 'software.amazon.lambda:powertools-idempotency:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-idempotency-dynamodb:{{ powertools.version }}' } sourceCompatibility = 1.8 diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 19d7a2272..39d6a8172 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -41,7 +41,7 @@ software.amazon.lambda - powertools-idempotency + powertools-idempotency-dynamodb ${project.version} @@ -95,7 +95,7 @@ software.amazon.lambda - powertools-idempotency + powertools-idempotency-dynamodb diff --git a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java index cf0c0ee31..0c4693230 100644 --- a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java @@ -32,7 +32,7 @@ import software.amazon.lambda.powertools.idempotency.Idempotency; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; import software.amazon.lambda.powertools.idempotency.Idempotent; -import software.amazon.lambda.powertools.idempotency.persistence.DynamoDBPersistenceStore; +import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.utilities.JsonConfig; diff --git a/pom.xml b/pom.xml index f0f5e051e..0c7ca43d3 100644 --- a/pom.xml +++ b/pom.xml @@ -32,25 +32,6 @@ GitHub Issues https://github.com/aws-powertools/powertools-lambda-java/issues - - - https://github.com/aws-powertools/powertools-lambda-java.git - - - - Powertools for AWS Lambda (Java) Team - Amazon Web Services - https://aws.amazon.com/ - - - - - - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots - - - Apache License, Version 2.0 @@ -421,7 +402,6 @@ - process-sources compile test-compile diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index eaafdb56e..1886f56e6 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -25,6 +25,7 @@ powertools-batch + com.amazonaws diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index fd53cd9e2..fddef497a 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -25,13 +25,19 @@ powertools-idempotency - jar + pom - Powertools for AWS Lambda (Java) - Idempotency + Powertools for AWS Lambda (Java) library Idempotency + + + powertools-idempotency-core + powertools-idempotency-dynamodb + + org.aspectj @@ -42,34 +48,6 @@ software.amazon.lambda powertools-common - - software.amazon.lambda - powertools-serialization - - - com.amazonaws - aws-lambda-java-core - - - software.amazon.awssdk - dynamodb - - - software.amazon.awssdk - netty-nio-client - - - software.amazon.awssdk - apache-client - - - - - software.amazon.awssdk - url-connection-client - ${aws.sdk.version} - - org.junit.jupiter @@ -106,20 +84,6 @@ aws-lambda-java-tests test - - com.amazonaws - DynamoDBLocal - [1.12,2.0) - test - - - - io.github.ganadist.sqlite4java - libsqlite4java-osx-aarch64 - 1.0.392 - test - dylib - @@ -150,22 +114,6 @@ - - org.apache.maven.plugins - maven-jar-plugin - 3.3.0 - - - - software.amazon.awssdk.enhanced.dynamodb - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - \ No newline at end of file diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml new file mode 100644 index 000000000..302cc24f5 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -0,0 +1,42 @@ + + + + + 4.0.0 + + + software.amazon.lambda + powertools-idempotency + 2.0.0-SNAPSHOT + + + powertools-idempotency-core + jar + + Powertools for AWS Lambda (Java) library Idempotency - Core + + Idempotency module common implementation + + + + + software.amazon.lambda + powertools-serialization + + + + \ No newline at end of file diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Constants.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Constants.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Constants.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Constants.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java similarity index 99% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java index 58d0a7f5b..2b22cac51 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java @@ -15,9 +15,10 @@ package software.amazon.lambda.powertools.idempotency; import com.amazonaws.services.lambda.runtime.Context; -import java.time.Duration; import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache; +import java.time.Duration; + /** * Configuration of the idempotency feature. Use the {@link Builder} to create an instance. */ @@ -92,7 +93,7 @@ public static class Builder { private int localCacheMaxItems = 256; private boolean useLocalCache = false; - private long expirationInSeconds = 60 * 60; // 1 hour + private long expirationInSeconds = 60 * 60L; // 1 hour private String eventKeyJMESPath; private String payloadValidationJMESPath; private boolean throwOnNoIdempotencyKey = false; diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyKey.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyKey.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyKey.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyKey.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java similarity index 99% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java index 6ca40a0e1..d08874492 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotent.java @@ -15,6 +15,7 @@ package software.amazon.lambda.powertools.idempotency; import com.amazonaws.services.lambda.runtime.Context; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyAlreadyInProgressException.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyAlreadyInProgressException.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyAlreadyInProgressException.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyAlreadyInProgressException.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyConfigurationException.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyConfigurationException.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyConfigurationException.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyConfigurationException.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyInconsistentStateException.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyInconsistentStateException.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyInconsistentStateException.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyInconsistentStateException.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemNotFoundException.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemNotFoundException.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemNotFoundException.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemNotFoundException.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyKeyException.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyKeyException.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyKeyException.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyKeyException.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyPersistenceLayerException.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyPersistenceLayerException.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyPersistenceLayerException.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyPersistenceLayerException.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyValidationException.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyValidationException.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyValidationException.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyValidationException.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java similarity index 99% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java index 2875ab3d1..7982d911a 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java @@ -14,13 +14,8 @@ package software.amazon.lambda.powertools.idempotency.internal; -import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.EXPIRED; -import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS; - import com.amazonaws.services.lambda.runtime.Context; import com.fasterxml.jackson.databind.JsonNode; -import java.time.Instant; -import java.util.OptionalInt; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; @@ -37,6 +32,12 @@ import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; import software.amazon.lambda.powertools.utilities.JsonConfig; +import java.time.Instant; +import java.util.OptionalInt; + +import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.EXPIRED; +import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS; + /** * Internal class that will handle the Idempotency, and use the {@link software.amazon.lambda.powertools.idempotency.persistence.PersistenceStore} * to store the result of previous calls. diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java similarity index 99% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java index 0b9d729f4..ea6d743f0 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java @@ -14,12 +14,8 @@ package software.amazon.lambda.powertools.idempotency.internal; -import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnRequestHandler; - import com.amazonaws.services.lambda.runtime.Context; import com.fasterxml.jackson.databind.JsonNode; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @@ -33,6 +29,11 @@ import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyConfigurationException; import software.amazon.lambda.powertools.utilities.JsonConfig; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnRequestHandler; + /** * Aspect that handles the {@link Idempotent} annotation. * It uses the {@link IdempotencyHandler} to actually do the job. diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java similarity index 100% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java similarity index 96% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java rename to powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java index ac5044972..bafbcbd42 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java @@ -14,12 +14,20 @@ package software.amazon.lambda.powertools.idempotency.persistence; -import static software.amazon.lambda.powertools.common.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; - import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectWriter; import io.burt.jmespath.Expression; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyKeyException; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyValidationException; +import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache; +import software.amazon.lambda.powertools.utilities.JsonConfig; + import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -33,16 +41,8 @@ import java.util.Spliterators; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import software.amazon.awssdk.utils.StringUtils; -import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; -import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; -import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; -import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyKeyException; -import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyValidationException; -import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache; -import software.amazon.lambda.powertools.utilities.JsonConfig; + +import static software.amazon.lambda.powertools.common.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; /** * Persistence layer that will store the idempotency result. @@ -55,7 +55,7 @@ public abstract class BasePersistenceStore implements PersistenceStore { protected boolean payloadValidationEnabled = false; private String functionName = ""; private boolean configured = false; - private long expirationInSeconds = 60 * 60; // 1 hour default + private long expirationInSeconds = 60 * 60L; // 1 hour default private boolean useLocalCache = false; private LRUCache cache; private String eventKeyJMESPath; @@ -73,7 +73,7 @@ public abstract class BasePersistenceStore implements PersistenceStore { public void configure(IdempotencyConfig config, String functionName) { String funcEnv = System.getenv(LAMBDA_FUNCTION_NAME_ENV); this.functionName = funcEnv != null ? funcEnv : "testFunction"; - if (!StringUtils.isEmpty(functionName)) { + if (functionName != null && !functionName.isEmpty()) { this.functionName += "." + functionName; } @@ -339,7 +339,7 @@ private MessageDigest getHashAlgorithm() { private void validatePayload(JsonNode data, DataRecord dataRecord) throws IdempotencyValidationException { if (payloadValidationEnabled) { String dataHash = getHashedPayload(data); - if (!StringUtils.equals(dataHash, dataRecord.getPayloadHash())) { + if (!isEqual(dataRecord.getPayloadHash(), dataHash)) { throw new IdempotencyValidationException("Payload does not match stored record for this event key"); } } @@ -402,4 +402,12 @@ void configure(IdempotencyConfig config, String functionName, LRUCache + + + + 4.0.0 + + + software.amazon.lambda + powertools-idempotency + 2.0.0-SNAPSHOT + + + powertools-idempotency-dynamodb + jar + + Powertools for AWS Lambda (Java) library Idempotency - DynamoDB + + DynamoDB implementation for the idempotency module + + + + + software.amazon.lambda + powertools-idempotency-core + ${project.version} + + + software.amazon.awssdk + url-connection-client + ${aws.sdk.version} + + + software.amazon.awssdk + dynamodb + + + software.amazon.awssdk + netty-nio-client + + + software.amazon.awssdk + apache-client + + + + + + + com.amazonaws + DynamoDBLocal + [1.12,2.0) + test + + + + io.github.ganadist.sqlite4java + libsqlite4java-osx-aarch64 + 1.0.392 + test + dylib + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + software.amazon.awssdk.enhanced.dynamodb + + + + + + dev.aspectj + aspectj-maven-plugin + ${aspectj-maven-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + ignore + ${project.build.sourceEncoding} + + + software.amazon.lambda + powertools-idempotency-core + + + + + + + compile + test-compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + \ No newline at end of file diff --git a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java similarity index 98% rename from powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java rename to powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java index 054f61ef3..0e20e396f 100644 --- a/powertools-idempotency/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStore.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java @@ -12,19 +12,8 @@ * */ -package software.amazon.lambda.powertools.idempotency.persistence; +package software.amazon.lambda.powertools.idempotency.persistence.dynamodb; -import static software.amazon.lambda.powertools.common.internal.LambdaConstants.AWS_REGION_ENV; -import static software.amazon.lambda.powertools.common.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; -import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS; - -import java.time.Instant; -import java.util.AbstractMap; -import java.util.HashMap; -import java.util.Map; -import java.util.OptionalLong; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; @@ -39,11 +28,25 @@ import software.amazon.awssdk.services.dynamodb.model.GetItemResponse; import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; -import software.amazon.awssdk.utils.StringUtils; import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; import software.amazon.lambda.powertools.idempotency.Constants; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; +import software.amazon.lambda.powertools.idempotency.persistence.BasePersistenceStore; +import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; +import software.amazon.lambda.powertools.idempotency.persistence.PersistenceStore; + +import java.time.Instant; +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.Map; +import java.util.OptionalLong; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static software.amazon.lambda.powertools.common.internal.LambdaConstants.AWS_REGION_ENV; +import static software.amazon.lambda.powertools.common.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; +import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS; /** * DynamoDB version of the {@link PersistenceStore}. Will store idempotency data in DynamoDB.
@@ -310,7 +313,7 @@ public static class Builder { * @return an instance of the {@link DynamoDBPersistenceStore} */ public DynamoDBPersistenceStore build() { - if (StringUtils.isEmpty(tableName)) { + if (tableName == null || "".equals(tableName)) { throw new IllegalArgumentException("Table name is not specified"); } return new DynamoDBPersistenceStore(tableName, keyAttr, staticPkValue, sortKeyAttr, expiryAttr, diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/DynamoDBConfig.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/DynamoDBConfig.java similarity index 98% rename from powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/DynamoDBConfig.java rename to powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/DynamoDBConfig.java index 66ddb53ac..30b4976d7 100644 --- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/DynamoDBConfig.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/DynamoDBConfig.java @@ -12,7 +12,7 @@ * */ -package software.amazon.lambda.powertools.idempotency; +package software.amazon.lambda.powertools.idempotency.dynamodb; import com.amazonaws.services.dynamodbv2.local.main.ServerRunner; import com.amazonaws.services.dynamodbv2.local.server.DynamoDBProxyServer; diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/IdempotencyTest.java similarity index 93% rename from powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java rename to powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/IdempotencyTest.java index c94fec3db..be915b610 100644 --- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/IdempotencyTest.java @@ -12,7 +12,7 @@ * */ -package software.amazon.lambda.powertools.idempotency; +package software.amazon.lambda.powertools.idempotency.dynamodb; import static org.assertj.core.api.Assertions.assertThat; @@ -25,7 +25,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import software.amazon.awssdk.services.dynamodb.model.ScanRequest; -import software.amazon.lambda.powertools.idempotency.handlers.IdempotencyFunction; +import software.amazon.lambda.powertools.idempotency.dynamodb.handlers.IdempotencyFunction; public class IdempotencyTest extends DynamoDBConfig { diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/handlers/IdempotencyFunction.java similarity index 93% rename from powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java rename to powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/handlers/IdempotencyFunction.java index 43e191fc2..1296a75c7 100644 --- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunction.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/handlers/IdempotencyFunction.java @@ -12,12 +12,21 @@ * */ -package software.amazon.lambda.powertools.idempotency.handlers; +package software.amazon.lambda.powertools.idempotency.dynamodb.handlers; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.lambda.powertools.idempotency.Idempotency; +import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; +import software.amazon.lambda.powertools.idempotency.Idempotent; +import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; +import software.amazon.lambda.powertools.utilities.JsonConfig; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -25,17 +34,9 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import software.amazon.awssdk.services.dynamodb.DynamoDbClient; -import software.amazon.lambda.powertools.idempotency.Idempotency; -import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; -import software.amazon.lambda.powertools.idempotency.Idempotent; -import software.amazon.lambda.powertools.idempotency.persistence.DynamoDBPersistenceStore; -import software.amazon.lambda.powertools.utilities.JsonConfig; public class IdempotencyFunction implements RequestHandler { - private static final Logger LOG = LoggerFactory.getLogger(IdempotencyFunction.class); + private final static Logger LOG = LogManager.getLogger(IdempotencyFunction.class); public boolean handlerExecuted = false; diff --git a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStoreTest.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java similarity index 99% rename from powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStoreTest.java rename to powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java index b19cebfe1..cc682a81f 100644 --- a/powertools-idempotency/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/DynamoDBPersistenceStoreTest.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java @@ -12,16 +12,8 @@ * */ -package software.amazon.lambda.powertools.idempotency.persistence; +package software.amazon.lambda.powertools.idempotency.persistence.dynamodb; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -39,10 +31,20 @@ import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; import software.amazon.awssdk.services.dynamodb.model.ScanRequest; import software.amazon.lambda.powertools.idempotency.Constants; -import software.amazon.lambda.powertools.idempotency.DynamoDBConfig; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; +import software.amazon.lambda.powertools.idempotency.dynamodb.DynamoDBConfig; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; +import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** * These test are using DynamoDBLocal and sqlite, see https://nickolasfisher.com/blog/Configuring-an-In-Memory-DynamoDB-instance-with-Java-for-Integration-Testing diff --git a/powertools-idempotency/src/test/resources/apigw_event2.json b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/resources/apigw_event2.json similarity index 100% rename from powertools-idempotency/src/test/resources/apigw_event2.json rename to powertools-idempotency/powertools-idempotency-dynamodb/src/test/resources/apigw_event2.json diff --git a/powertools-idempotency/spotbugs-exclude.xml b/powertools-idempotency/spotbugs-exclude.xml new file mode 100644 index 000000000..9a2369c75 --- /dev/null +++ b/powertools-idempotency/spotbugs-exclude.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 3a3018c7c..34b1238f6 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -21,7 +21,6 @@ powertools-parameters ${project.version}
- software.amazon.awssdk appconfigdata @@ -36,6 +35,11 @@ + + org.aspectj + aspectjrt + provided + diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index ad32bdff8..2ec6ad27c 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -36,6 +36,11 @@ + + org.aspectj + aspectjrt + provided + diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 6c4501ca3..3275d0ee0 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -36,6 +36,11 @@ + + org.aspectj + aspectjrt + provided + diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 80276189d..65332c9ef 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -36,6 +36,11 @@ + + org.aspectj + aspectjrt + provided + diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index a5fc4a890..0de38c1c1 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -33,6 +33,11 @@ + + org.aspectj + aspectjrt + provided + software.amazon.lambda powertools-common diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index 747752130..ee39b5d0f 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -27,6 +27,10 @@ + + + + @@ -106,6 +110,10 @@ + + + + @@ -127,7 +135,7 @@ - + From 81514216a988904867d0c6689d6dceaf1748874b Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Tue, 13 Feb 2024 16:10:09 +0100 Subject: [PATCH 121/577] Update README.md (#1560) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa4b872b7..83b026d15 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **This is pre-release code for Powertools for AWS Lambda (Java) V2! Please check out the `main` branch for the stable release** -![aws provider](https://img.shields.io/badge/provider-AWS-orange?logo=amazon-aws&color=ff9900) ![Build status](https://github.com/aws-powertools/powertools-lambda-java/actions/workflows/build.yml/badge.svg) ![Maven Central](https://img.shields.io/maven-central/v/software.amazon.lambda/powertools-parent) [![codecov.io](https://codecov.io/github/aws-powertools/powertools-lambda-java/branch/main/graphs/badge.svg)](https://app.codecov.io/gh/aws-powertools/powertools-lambda-java) +![aws provider](https://img.shields.io/badge/provider-AWS-orange?logo=amazon-aws&color=ff9900) [![V2 Build Status](https://github.com/aws-powertools/powertools-lambda-java/actions/workflows/pr_build.yml/badge.svg?branch=v2)](https://github.com/aws-powertools/powertools-lambda-java/actions/workflows/pr_build.yml) **MAVEN DEPLOY NOT DONE** [![codecov.io](https://codecov.io/github/aws-powertools/powertools-lambda-java/branch/v2/graphs/badge.svg)](https://app.codecov.io/gh/aws-powertools/powertools-lambda-java/tree/v2) Powertools for AWS Lambda (Java) is a developer toolkit to implement Serverless best practices and increase developer velocity. From 982f4e0c3bc5aaadcd09b138a9bd61603986f94f Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Thu, 22 Feb 2024 09:27:37 +0100 Subject: [PATCH 122/577] chore: remove unecessary creds acquisition (#1572) --- .github/workflows/pr_build.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 7a02b08d4..54c2599c3 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -79,12 +79,6 @@ jobs: if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 working-directory: examples/powertools-examples-core/kotlin run: ./gradlew build - - name: Setup AWS credentials - if: ${{ matrix.java == '11' }} - uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 - with: - role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} - aws-region: ${{ env.AWS_REGION }} - name: Upload coverage to Codecov uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 if: ${{ matrix.java == '11' }} # publish results once From d49d89b6eaa8fd39054c9dc102e6974792fa5c68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:35:21 +0100 Subject: [PATCH 123/577] build(deps): bump org.jacoco:jacoco-maven-plugin from 0.8.10 to 0.8.11 (#1509) Bumps [org.jacoco:jacoco-maven-plugin](https://github.com/jacoco/jacoco) from 0.8.10 to 0.8.11. - [Release notes](https://github.com/jacoco/jacoco/releases) - [Commits](https://github.com/jacoco/jacoco/compare/v0.8.10...v0.8.11) --- updated-dependencies: - dependency-name: org.jacoco:jacoco-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3c30dc260..df1f4e16c 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ 1.9.7 1.13.1 3.1.2 - 0.8.10 + 0.8.11 1.6.13 3.6.0 3.3.0 From 69c262bd41953c95dd53eaf4d62982c6ef59392e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:39:04 +0100 Subject: [PATCH 124/577] build(deps): bump com.amazonaws:aws-lambda-java-serialization (#1573) Bumps [com.amazonaws:aws-lambda-java-serialization](https://github.com/aws/aws-lambda-java-libs) from 1.1.2 to 1.1.5. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-serialization dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index df1f4e16c..9f6bcf875 100644 --- a/pom.xml +++ b/pom.xml @@ -81,7 +81,7 @@ UTF-8 1.2.3 3.11.3 - 1.1.2 + 1.1.5 3.11.0 1.9.7 1.13.1 From 1813e5fe73f3c1bf82ef062e1e5dedd361a651d2 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Thu, 22 Feb 2024 15:32:26 +0100 Subject: [PATCH 125/577] chore(v2): Merge down from main (#1574) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: HelloWorldStreamFunction in examples fails with sam (#1532) * Setting up Kotlin environment. Converting test to Kotlin. * Deploying via SAM successfully. * Added Kotlin example. * Removing unused Gradle build file. * Adding SAM template so can be used as an existing project and Java target compatibility * Adding SAM template so can be used as an existing project * Updating guidance to use SAM for build and deploy * Restructuring separate Java and Kotlin examples. * Updating core examples readme to represent new structure for Java and Kotlin examples. * Refactoring application code for efficiency, updating build to cover tests too and is more idiomatic and readme to be more descriptive * Updating to fix trailing \n * Updating guidance to be more specific for examples * Adopting new mechanism for specifying jvm target. * accommodating new project structure * Fixing link typo after refactoring * Setting up Kotlin environment. Converting test to Kotlin. * Deploying via SAM successfully. * Added Kotlin example. * Removing unused Gradle build file. * Adding SAM template so can be used as an existing project and Java target compatibility * Adding SAM template so can be used as an existing project * Updating guidance to use SAM for build and deploy * Restructuring separate Java and Kotlin examples. * Updating core examples readme to represent new structure for Java and Kotlin examples. * Refactoring application code for efficiency, updating build to cover tests too and is more idiomatic and readme to be more descriptive * Updating to fix trailing \n * Updating guidance to be more specific for examples * Adopting new mechanism for specifying jvm target. * accommodating new project structure * Fixing link typo after refactoring * Flattening structure back to original to make merging easier for v2 * Adding build for Kotlin Gradle * Adding build for Kotlin Gradle - Restructuring Java examples to v1 approach * Correcting paths * Adding SNAPSHOT support and local capability for Maven. Testing using Java 1.8 * Reviewed and updated against PR comments. * Un-commenting examples * Adding validation step for IaC SAM * Adding Terraform for Java projects IaC validator and linter * Adding additional projects for SAM validation and matrix approach * Refactoring stream function to process input logging example with a Lambda Function URL instead of APIGW. * Demonstrating Java streaming response * Refactoring stream function to process input logging example to return * Update CONTRIBUTING.md * fix: get trace id from system property when env var is not set (#1503) * fix: check if XRAY Trace ID is present in System property * chore: remove erroneous extra char in tests * fix #1500 (#1506) * feat: Add support for POWERTOOLS_LOGGER_LOG_EVENT (#1510) * chore: Addition of Warn Message If Invalid Annotation Key While Tracing #1511 (#1512) * feat: ALC (#1514) * handle AWS_LAMBDA_LOG configuration * ALC documentation + code review * update doc * chore:Prep release 1.18.0 (#1515) * chore:prep release 1.18.0 * update version * update version in kotlin example * maven local repo in gradle example * update changelog --------- Co-authored-by: scottgerring * chore: update version to next snapshot: 1-19.0-SNAPSHOT (#1516) * update version to next snapshot: 1-19.0-SNAPSHOT * update version to next snapshot: 1-19.0-SNAPSHOT * update version to next snapshot: 1-19.0-SNAPSHOT * building only for LTS * Add some more margin to the test pause (#1518) * test: e2e tests with java 21 (#1517) * e2e tests with java 21 * Run Java21 tests using the Java17 compiler * Run all of the E2E tests in parallel, not just the first 3 * Try again * . * Let's try again * Add some comment on Java21 to the repo * Add caveat about lambda runtimes * Clean up wording a little --------- Co-authored-by: Scott Gerring * update doc for ALC (#1520) * chore: Testing java21 aspectj pre-release (#1519) * e2e tests with java 21 * use aspectj 1.9.21-SNAPSHOT * Fix log4j2.xml missing in logging test for java21 * rollback double runtime * remove comment * keep aspectj 1.9.7 in parent for java8 compatibility * use M1 instead of snapshot * update documentation for aspectj * update documentation for aspectj --------- Co-authored-by: Jerome Van Der Linden * chore: Remove build cruft * Adding context for using RequestStreamHandler * removing pr_lint * Update examples/powertools-examples-core/sam/src/main/java/helloworld/AppStream.java Clarify usage of RequestStreamHandler. Co-authored-by: Alexey Soshin --------- Co-authored-by: Jason Harris Co-authored-by: Scott Gerring Co-authored-by: Jason Harris Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> Co-authored-by: Michele Ricciardi Co-authored-by: Alexey Soshin Co-authored-by: jdoherty Co-authored-by: Scott Gerring Co-authored-by: Jerome Van Der Linden * deps: bump aspectj to 1.9.21 for jdk21 (#1536) * chore: SAM and Terraform IaC extracted from pr_build and simplified approach. (#1533) * SAM and Terraform IaC extracted from pr_build and simplified approach. * Update .github/workflows/pr_iac_lint.yml Co-authored-by: Scott Gerring --------- Co-authored-by: Jason Harris Co-authored-by: Scott Gerring * chore: Remove empty CDK test (#1542) * Remove CDK test * Build core utilities so that sam validator can find them * Remove CDK test * Ok just build it all * Remove the plan ... * Remove terraform plan from iac lint --------- Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * dependabot on v2 branch (#1548) * chore: remove unecessary creds acquisition (#1572) * Merge from main --------- Co-authored-by: Jason Harris Co-authored-by: Jason Harris Co-authored-by: Jason Harris Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> Co-authored-by: Michele Ricciardi Co-authored-by: Alexey Soshin Co-authored-by: jdoherty Co-authored-by: Jerome Van Der Linden --- .github/dependabot.yml | 9 ++++ .github/workflows/pr_build.yml | 27 ---------- .github/workflows/pr_iac_lint.yml | 52 +++++++++++++++++++ docs/index.md | 3 -- .../src/main/java/helloworld/AppStream.java | 29 +++++++++-- .../infra/src/test/java/cdk/CdkStackTest.java | 48 ----------------- .../src/main/java/helloworld/AppStream.java | 29 +++++++++-- powertools-e2e-tests/handlers/pom.xml | 2 +- 8 files changed, 112 insertions(+), 87 deletions(-) create mode 100644 .github/workflows/pr_iac_lint.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1454df79c..28adf2bc1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,3 +11,12 @@ updates: # Ignore Mockito 5.X.X as it does not support Java 8 - dependency-name: "org.mockito:mockito-*" update-types: ["version-update:semver-major"] + + - package-ecosystem: "maven" + directory: "/" + target-branch: "v2" + schedule: + interval: "weekly" + labels: + - "maven" + - "dependencies" diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 5373f4b4c..4fa8dc7c0 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -80,33 +80,6 @@ jobs: if: ${{ matrix.java != '8' }} working-directory: examples/powertools-examples-core-utilities/kotlin run: ./gradlew build - - name: Setup Terraform - if: ${{ matrix.java == '11' }} - uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 #v2.0.3 - - name: Setup AWS credentials - if: ${{ matrix.java == '11' }} - uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 - with: - role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} - aws-region: ${{ env.AWS_REGION }} - - name: Terraform validate - working-directory: examples/powertools-examples-core-utilities/terraform - if: ${{ matrix.java == '11' }} - run: | - terraform -version - terraform init -backend=false - terraform validate - terraform plan - - name: Setup Terraform lint - if: ${{ matrix.java == '11' }} - uses: terraform-linters/setup-tflint@a5a1af8c6551fb10c53f1cd4ba62359f1973746f # v3.1.1 - - name: Terraform lint - working-directory: examples/powertools-examples-core-utilities/terraform - if: ${{ matrix.java == '11' }} - run: | - tflint --version - tflint --init - tflint -f compact - name: Upload coverage to Codecov uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 if: ${{ matrix.java == '11' }} # publish results once diff --git a/.github/workflows/pr_iac_lint.yml b/.github/workflows/pr_iac_lint.yml new file mode 100644 index 000000000..c6e17ab1c --- /dev/null +++ b/.github/workflows/pr_iac_lint.yml @@ -0,0 +1,52 @@ +name: Validate IaC + +on: + push: + branches: + - main + - v2 + pull_request: + branches: + - main + - v2 + paths: + - 'examples/**' +jobs: + linter: + runs-on: ubuntu-latest + strategy: + matrix: + project: ["sam", "gradle", "kotlin"] + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Setup java JDK + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + with: + distribution: 'corretto' + java-version: 11 + - name: Build Project + working-directory: . + run: | + mvn install -DskipTests + - name: Run SAM validator to check syntax of IaC templates - Java + working-directory: examples/powertools-examples-core/${{ matrix.project }} + run: | + sam build + sam validate --lint + - name: Setup Terraform + uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 #v2.0.3 + - name: Run Terraform validator to check syntax of IaC templates and produce a plan of changes + working-directory: examples/powertools-examples-core/terraform + run: | + mvn install + terraform -version + terraform init -backend=false + terraform validate + - name: Setup Terraform lint + uses: terraform-linters/setup-tflint@a5a1af8c6551fb10c53f1cd4ba62359f1973746f # v3.1.1 + - name: Run Terraform lint to check for best practices, errors, deprecated syntax etc. + working-directory: examples/powertools-examples-core/terraform + run: | + tflint --version + tflint --init + tflint -f compact \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 884e02476..06c9beb6d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -306,9 +306,6 @@ Use the following [dependency matrix](https://github.com/eclipse-aspectj/aspectj | `11-17` | `1.9.20.1` | | `21` | `1.9.21` | -_Note: 1.9.21 is not yet available and Java 21 not yet officially supported by aspectj, but you can already use the `1.9.21.M1`_ - - ## Environment variables !!! info diff --git a/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/AppStream.java index 401ef8c48..94806cc38 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/AppStream.java +++ b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/AppStream.java @@ -17,22 +17,43 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import com.fasterxml.jackson.databind.ObjectMapper; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.Map; +import java.nio.charset.StandardCharsets; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.metrics.Metrics; +import java.io.InputStreamReader; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; + public class AppStream implements RequestStreamHandler { private static final ObjectMapper mapper = new ObjectMapper(); + private final static Logger log = LogManager.getLogger(AppStream.class); @Override @Logging(logEvent = true) @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - Map map = mapper.readValue(input, Map.class); + // RequestStreamHandler can be used instead of RequestHandler for cases when you'd like to deserialize request body or serialize response body yourself, instead of allowing that to happen automatically + // Note that you still need to return a proper JSON for API Gateway to handle + // See Lambda Response format for examples: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html + public void handleRequest(InputStream input, OutputStream output, Context context) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); + PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8)))) { - System.out.println(map.size()); + log.info("Received: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(reader))); + + writer.write("{\"body\": \"" + System.currentTimeMillis() + "\"} "); + } catch (IOException e) { + log.error("Something has gone wrong: ", e); + } } } + diff --git a/examples/powertools-examples-core-utilities/cdk/infra/src/test/java/cdk/CdkStackTest.java b/examples/powertools-examples-core-utilities/cdk/infra/src/test/java/cdk/CdkStackTest.java index 29cb15545..e69de29bb 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/src/test/java/cdk/CdkStackTest.java +++ b/examples/powertools-examples-core-utilities/cdk/infra/src/test/java/cdk/CdkStackTest.java @@ -1,48 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package cdk; - -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.Test; -import software.amazon.awscdk.App; -import software.amazon.awscdk.assertions.Template; - -public class CdkStackTest { - - @Test - public void testStack() { - App app = new App(); - CdkStack stack = new CdkStack(app, "test"); - - Template template = Template.fromStack(stack); - - // There should be 2 lambda functions, one to handle regular input, and another for streaming - template.resourceCountIs("AWS::Lambda::Function", 2); - - // API Gateway should exist - template.resourceCountIs("AWS::ApiGateway::RestApi", 1); - - // API Gateway should have a path pointing to the regular Lambda - Map resourceProperties = new HashMap<>(); - resourceProperties.put("PathPart", "hello"); - template.hasResourceProperties("AWS::ApiGateway::Resource", resourceProperties); - - // API Gateway should have a path pointing to the streaming Lambda - resourceProperties = new HashMap<>(); - resourceProperties.put("PathPart", "hellostream"); - template.hasResourceProperties("AWS::ApiGateway::Resource", resourceProperties); - } -} diff --git a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java index 401ef8c48..94806cc38 100644 --- a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java +++ b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java @@ -17,22 +17,43 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import com.fasterxml.jackson.databind.ObjectMapper; + import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.Map; +import java.nio.charset.StandardCharsets; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.metrics.Metrics; +import java.io.InputStreamReader; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; + public class AppStream implements RequestStreamHandler { private static final ObjectMapper mapper = new ObjectMapper(); + private final static Logger log = LogManager.getLogger(AppStream.class); @Override @Logging(logEvent = true) @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { - Map map = mapper.readValue(input, Map.class); + // RequestStreamHandler can be used instead of RequestHandler for cases when you'd like to deserialize request body or serialize response body yourself, instead of allowing that to happen automatically + // Note that you still need to return a proper JSON for API Gateway to handle + // See Lambda Response format for examples: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html + public void handleRequest(InputStream input, OutputStream output, Context context) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); + PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8)))) { - System.out.println(map.size()); + log.info("Received: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(reader))); + + writer.write("{\"body\": \"" + System.currentTimeMillis() + "\"} "); + } catch (IOException e) { + log.error("Something has gone wrong: ", e); + } } } + diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 412593da9..ef5be4df4 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -213,7 +213,7 @@ [21,) - 1.9.21.M1 + 1.9.21 From c6bdf96dff840f366103edb245179b233d24e320 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Thu, 22 Feb 2024 15:39:47 +0100 Subject: [PATCH 126/577] fix PR lint (#1575) --- .github/workflows/pr_iac_lint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_iac_lint.yml b/.github/workflows/pr_iac_lint.yml index c6e17ab1c..39c2bc5df 100644 --- a/.github/workflows/pr_iac_lint.yml +++ b/.github/workflows/pr_iac_lint.yml @@ -29,14 +29,14 @@ jobs: run: | mvn install -DskipTests - name: Run SAM validator to check syntax of IaC templates - Java - working-directory: examples/powertools-examples-core/${{ matrix.project }} + working-directory: examples/powertools-examples-core-utilities//${{ matrix.project }} run: | sam build sam validate --lint - name: Setup Terraform uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 #v2.0.3 - name: Run Terraform validator to check syntax of IaC templates and produce a plan of changes - working-directory: examples/powertools-examples-core/terraform + working-directory: examples/powertools-examples-core-utilities/terraform run: | mvn install terraform -version From e62e2cd700eb4c0ea824acef1c3533a4f570393d Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Thu, 22 Feb 2024 15:46:32 +0100 Subject: [PATCH 127/577] chore(v2): Fix IaC lint (#1576) * fix PR lint * And another one --- .github/workflows/pr_iac_lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_iac_lint.yml b/.github/workflows/pr_iac_lint.yml index 39c2bc5df..09ba5f02b 100644 --- a/.github/workflows/pr_iac_lint.yml +++ b/.github/workflows/pr_iac_lint.yml @@ -45,7 +45,7 @@ jobs: - name: Setup Terraform lint uses: terraform-linters/setup-tflint@a5a1af8c6551fb10c53f1cd4ba62359f1973746f # v3.1.1 - name: Run Terraform lint to check for best practices, errors, deprecated syntax etc. - working-directory: examples/powertools-examples-core/terraform + working-directory: examples/powertools-examples-core-utilities/terraform run: | tflint --version tflint --init From c389372a322c84fa86e7ab2b3170e190ea4d58ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 09:08:51 +0100 Subject: [PATCH 128/577] build(deps): bump org.apache.maven.plugins:maven-artifact-plugin (#1567) Bumps [org.apache.maven.plugins:maven-artifact-plugin](https://github.com/apache/maven-artifact-plugin) from 3.4.1 to 3.5.0. - [Commits](https://github.com/apache/maven-artifact-plugin/compare/maven-artifact-plugin-3.4.1...maven-artifact-plugin-3.5.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-artifact-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Scott Gerring --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0c7ca43d3..3dee839dc 100644 --- a/pom.xml +++ b/pom.xml @@ -384,7 +384,7 @@ org.apache.maven.plugins maven-artifact-plugin - 3.4.1 + 3.5.0 true From c26ada613651e6d25fe13d59d62d70870f9ab47f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 09:09:15 +0100 Subject: [PATCH 129/577] build(deps): bump aws.sdk.version from 2.21.0 to 2.24.5 (#1566) Bumps `aws.sdk.version` from 2.21.0 to 2.24.5. Updates `software.amazon.awssdk:bom` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:http-client-spi` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:url-connection-client` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:dynamodb` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:s3` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:lambda` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:kinesis` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:cloudwatch` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:xray` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:sqs` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:cloudformation` from 2.21.0 to 2.24.5 Updates `software.amazon.awssdk:sts` from 2.21.0 to 2.24.5 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Scott Gerring --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 8851daa6d..795834a8f 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 11 1.2.3 3.11.3 - 2.21.0 + 2.24.5 1.9.20.1 diff --git a/pom.xml b/pom.xml index 3dee839dc..f7a794707 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 2.22.0 2.0.7 2.16.0 - 2.21.0 + 2.24.5 2.15.0 2.1.3 UTF-8 From 0c23a18b9f637adb2a56a0a690f008f5994fe1b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 09:09:29 +0100 Subject: [PATCH 130/577] build(deps): bump org.assertj:assertj-core from 3.24.2 to 3.25.3 (#1565) Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.24.2 to 3.25.3. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.24.2...assertj-build-3.25.3) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Scott Gerring --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f7a794707..4fa6e0039 100644 --- a/pom.xml +++ b/pom.xml @@ -291,7 +291,7 @@ org.assertj assertj-core - 3.24.2 + 3.25.3 test From 1ec0d171ba4e90fd921ec79da44b3b1da53f7bc0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 09:10:24 +0100 Subject: [PATCH 131/577] build(deps): bump org.apache.maven.plugins:maven-javadoc-plugin (#1564) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.0 to 3.6.3. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.0...maven-javadoc-plugin-3.6.3) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Scott Gerring --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4fa6e0039..0b5cd16cb 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ 3.1.2 0.8.10 1.6.13 - 3.6.0 + 3.6.3 3.3.0 3.1.0 5.10.0 From 8a8bd136064e6223be2c1d5656b9987815259b35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 09:43:31 +0100 Subject: [PATCH 132/577] build(deps): bump org.apache.maven.plugins:maven-artifact-plugin (#1485) Bumps [org.apache.maven.plugins:maven-artifact-plugin](https://github.com/apache/maven-artifact-plugin) from 3.4.1 to 3.5.0. - [Commits](https://github.com/apache/maven-artifact-plugin/compare/maven-artifact-plugin-3.4.1...maven-artifact-plugin-3.5.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-artifact-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Scott Gerring --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9f6bcf875..0d0710634 100644 --- a/pom.xml +++ b/pom.xml @@ -365,7 +365,7 @@ org.apache.maven.plugins maven-artifact-plugin - 3.4.1 + 3.5.0 true From 4f6889133fc4d570cb6f62d74ca54ca484838e00 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 09:43:55 +0100 Subject: [PATCH 133/577] build(deps): bump log4j.version from 2.20.0 to 2.22.1 (#1547) Bumps `log4j.version` from 2.20.0 to 2.22.1. Updates `org.apache.logging.log4j:log4j-core` from 2.20.0 to 2.22.1 Updates `org.apache.logging.log4j:log4j-slf4j2-impl` from 2.20.0 to 2.22.1 Updates `org.apache.logging.log4j:log4j-api` from 2.20.0 to 2.22.1 Updates `org.apache.logging.log4j:log4j-layout-template-json` from 2.20.0 to 2.22.1 Updates `org.apache.logging.log4j:log4j-jcl` from 2.20.0 to 2.22.1 --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-slf4j2-impl dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-api dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-layout-template-json dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-jcl dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Scott Gerring --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core/cdk/app/pom.xml | 2 +- examples/powertools-examples-core/sam/pom.xml | 2 +- examples/powertools-examples-core/serverless/pom.xml | 2 +- examples/powertools-examples-core/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 54d6b50ef..c843d5adc 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -10,7 +10,7 @@ AWS Lambda Powertools for Java library Examples - CloudFormation - 2.20.0 + 2.22.1 1.8 1.8 1.2.3 diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml index 9d9435ac3..7f2328227 100644 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ b/examples/powertools-examples-core/cdk/app/pom.xml @@ -10,7 +10,7 @@ Powertools for AWS Lambda (Java) library Examples - Core - 2.20.0 + 2.22.1 1.8 1.8 diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index 16f82ebd6..9451b0628 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -10,7 +10,7 @@ Powertools for AWS Lambda (Java) library Examples - Core - 2.20.0 + 2.22.1 1.8 1.8 diff --git a/examples/powertools-examples-core/serverless/pom.xml b/examples/powertools-examples-core/serverless/pom.xml index f8d9ab684..8e6b93528 100644 --- a/examples/powertools-examples-core/serverless/pom.xml +++ b/examples/powertools-examples-core/serverless/pom.xml @@ -10,7 +10,7 @@ Powertools for AWS Lambda (Java) library Examples - Core - 2.20.0 + 2.22.1 1.8 1.8 diff --git a/examples/powertools-examples-core/terraform/pom.xml b/examples/powertools-examples-core/terraform/pom.xml index eef73207e..6551aaae1 100644 --- a/examples/powertools-examples-core/terraform/pom.xml +++ b/examples/powertools-examples-core/terraform/pom.xml @@ -10,7 +10,7 @@ Powertools for AWS Lambda (Java) library Examples - Core - 2.20.0 + 2.22.1 1.8 1.8 diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index bf4c041bf..9e705f4b0 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -23,7 +23,7 @@ Powertools for AWS Lambda (Java) library Examples - Idempotency - 2.20.0 + 2.22.1 1.8 1.8 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index a6737bfed..bb11e93fe 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -8,7 +8,7 @@ Powertools for AWS Lambda (Java) library Examples - SQS - 2.20.0 + 2.22.1 1.8 1.8 diff --git a/pom.xml b/pom.xml index 0d0710634..c56d9db10 100644 --- a/pom.xml +++ b/pom.xml @@ -73,7 +73,7 @@ 1.8 1.8 - 2.20.0 + 2.22.1 2.15.3 2.21.0 2.14.0 From 05853833393bc35af3d21d5d3616e8661c0b75e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 10:31:17 +0100 Subject: [PATCH 134/577] build(deps-dev): bump org.yaml:snakeyaml from 2.1 to 2.2 (#1400) Bumps [org.yaml:snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) from 2.1 to 2.2. - [Commits](https://bitbucket.org/snakeyaml/snakeyaml/branches/compare/snakeyaml-2.2..snakeyaml-2.1) --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Scott Gerring --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 8a0b65f32..540490f20 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -159,7 +159,7 @@ org.yaml snakeyaml - 2.1 + 2.2 test From 5074d2e344d8ad8a2068f58f88d4a2650c9c9788 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:15:31 +0100 Subject: [PATCH 135/577] build(deps): bump aws.xray.recorder.version from 2.15.0 to 2.15.1 (#1577) Bumps `aws.xray.recorder.version` from 2.15.0 to 2.15.1. Updates `com.amazonaws:aws-xray-recorder-sdk-core` from 2.15.0 to 2.15.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.15.0...v2.15.1) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core` from 2.15.0 to 2.15.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.15.0...v2.15.1) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2` from 2.15.0 to 2.15.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.15.0...v2.15.1) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor` from 2.15.0 to 2.15.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.15.0...v2.15.1) --- updated-dependencies: - dependency-name: com.amazonaws:aws-xray-recorder-sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0b5cd16cb..7b126a426 100644 --- a/pom.xml +++ b/pom.xml @@ -72,7 +72,7 @@ 2.0.7 2.16.0 2.24.5 - 2.15.0 + 2.15.1 2.1.3 UTF-8 1.2.3 From 91993f4dac70c44c20b6bb8c2f1bbc02742829b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:15:46 +0100 Subject: [PATCH 136/577] build(deps): bump aws.sdk.version from 2.21.1 to 2.24.10 (#1580) Bumps `aws.sdk.version` from 2.21.1 to 2.24.10. Updates `software.amazon.awssdk:url-connection-client` from 2.21.1 to 2.24.10 Updates `software.amazon.awssdk:sdk-core` from 2.21.1 to 2.24.10 Updates `software.amazon.awssdk:kinesis` from 2.21.1 to 2.24.10 Updates `software.amazon.awssdk:sqs` from 2.21.1 to 2.24.10 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.21.1 to 2.24.10 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 947f146b3..159ff52cd 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 11 11 1.9.20.1 - 2.21.1 + 2.24.10 From 9020f46af33a192d03f6bdd2b4848f0f262a917f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:44:28 +0100 Subject: [PATCH 137/577] build(deps): bump org.apache.maven.plugins:maven-shade-plugin (#1582) Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/apache/maven-shade-plugin/releases) - [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.0...maven-shade-plugin-3.5.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-shade-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core/cdk/app/pom.xml | 2 +- examples/powertools-examples-core/sam/pom.xml | 2 +- examples/powertools-examples-core/serverless/pom.xml | 2 +- examples/powertools-examples-core/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index c8f829997..d3539d919 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -97,7 +97,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.2 package diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index c843d5adc..e8526e14d 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -122,7 +122,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.2 package diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml index 7f2328227..561aae686 100644 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ b/examples/powertools-examples-core/cdk/app/pom.xml @@ -90,7 +90,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.2 package diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index 9451b0628..2e95644b6 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -89,7 +89,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.2 package diff --git a/examples/powertools-examples-core/serverless/pom.xml b/examples/powertools-examples-core/serverless/pom.xml index 8e6b93528..59820ffec 100644 --- a/examples/powertools-examples-core/serverless/pom.xml +++ b/examples/powertools-examples-core/serverless/pom.xml @@ -90,7 +90,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.2 package diff --git a/examples/powertools-examples-core/terraform/pom.xml b/examples/powertools-examples-core/terraform/pom.xml index 6551aaae1..7fe562072 100644 --- a/examples/powertools-examples-core/terraform/pom.xml +++ b/examples/powertools-examples-core/terraform/pom.xml @@ -90,7 +90,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.2 package diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 9e705f4b0..c841c0f38 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -135,7 +135,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.2 package diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index bb11e93fe..0e1382faa 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -95,7 +95,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.5.2 package From d60eb14173b50b43889f26ce41153b50fe064491 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:44:44 +0100 Subject: [PATCH 138/577] build(deps): bump aws.xray.recorder.version from 2.14.0 to 2.15.1 (#1583) Bumps `aws.xray.recorder.version` from 2.14.0 to 2.15.1. Updates `com.amazonaws:aws-xray-recorder-sdk-core` from 2.14.0 to 2.15.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.14.0...v2.15.1) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core` from 2.14.0 to 2.15.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.14.0...v2.15.1) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2` from 2.14.0 to 2.15.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.14.0...v2.15.1) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor` from 2.14.0 to 2.15.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.14.0...v2.15.1) --- updated-dependencies: - dependency-name: com.amazonaws:aws-xray-recorder-sdk-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c56d9db10..3ed285f61 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ 2.22.1 2.15.3 2.21.0 - 2.14.0 + 2.15.1 2.1.3 UTF-8 1.2.3 From c7980592ae75b44649ef015ccc275e5f3f5a24ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:48:34 +0100 Subject: [PATCH 139/577] build(deps): bump commons-io:commons-io from 2.13.0 to 2.15.1 (#1584) Bumps commons-io:commons-io from 2.13.0 to 2.15.1. --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 540490f20..e33c592c4 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -103,7 +103,7 @@ commons-io commons-io - 2.13.0 + 2.15.1 From 79378a10e5bdb2522bea1bea7e234da5b6795991 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:52:18 +0100 Subject: [PATCH 140/577] build(deps): bump aws.sdk.version from 2.21.0 to 2.24.10 (#1581) Bumps `aws.sdk.version` from 2.21.0 to 2.24.10. Updates `software.amazon.awssdk:bom` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:http-client-spi` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:url-connection-client` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:sqs` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:s3` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:dynamodb` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:lambda` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:kinesis` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:cloudwatch` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:xray` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:cloudformation` from 2.21.0 to 2.24.10 Updates `software.amazon.awssdk:sts` from 2.21.0 to 2.24.10 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index e8526e14d..3b2cf6df0 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.21.0 + 2.24.10 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 0e1382faa..d83a900c0 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.21.1 + 2.24.10 com.amazonaws diff --git a/pom.xml b/pom.xml index 3ed285f61..1337d2721 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,7 @@ 1.8 2.22.1 2.15.3 - 2.21.0 + 2.24.10 2.15.1 2.1.3 UTF-8 From 55bd043fa6487d5fc34e51b6dd27c347786bf39f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Mon, 26 Feb 2024 17:34:41 +0100 Subject: [PATCH 141/577] Update pr_artifacts_size.yml adding permissions --- .github/workflows/pr_artifacts_size.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_artifacts_size.yml b/.github/workflows/pr_artifacts_size.yml index f37f83a8d..36bf301df 100644 --- a/.github/workflows/pr_artifacts_size.yml +++ b/.github/workflows/pr_artifacts_size.yml @@ -26,6 +26,8 @@ on: jobs: codecheck: runs-on: ubuntu-latest + permissions: + pull-requests: write steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java JDK 11 @@ -61,4 +63,4 @@ jobs: comment-id: ${{ steps.find-comment.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} body-path: 'report.md' - edit-mode: replace \ No newline at end of file + edit-mode: replace From cdad9904bef63e7cf04da7da3c1cecc772249cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Mon, 26 Feb 2024 17:40:35 +0100 Subject: [PATCH 142/577] Update pr_artifacts_size.yml --- .github/workflows/pr_artifacts_size.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr_artifacts_size.yml b/.github/workflows/pr_artifacts_size.yml index 36bf301df..ab9ca9859 100644 --- a/.github/workflows/pr_artifacts_size.yml +++ b/.github/workflows/pr_artifacts_size.yml @@ -28,6 +28,7 @@ jobs: runs-on: ubuntu-latest permissions: pull-requests: write + issues: read steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java JDK 11 From 2289d974d2901b144f66f66f9faabb09aa1933a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 17:50:54 +0100 Subject: [PATCH 143/577] build(deps): bump io.burt:jmespath-jackson from 0.5.1 to 0.6.0 (#1587) Bumps [io.burt:jmespath-jackson](https://github.com/burtcorp/jmespath-java) from 0.5.1 to 0.6.0. - [Release notes](https://github.com/burtcorp/jmespath-java/releases) - [Commits](https://github.com/burtcorp/jmespath-java/compare/jmespath-0.5.1...jmespath-0.6.0) --- updated-dependencies: - dependency-name: io.burt:jmespath-jackson dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1337d2721..2ad359a3a 100644 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,7 @@ 3.1.0 5.10.0 1.0.6 - 0.5.1 + 0.6.0 From 98900325c67d27708979fb09d8a0fbb1df1063e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 17:54:29 +0100 Subject: [PATCH 144/577] build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1586) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.100.0 to 2.130.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.100.0...v2.130.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index e2a1d6b9a..021aa98a4 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -7,7 +7,7 @@ 1.19.0-SNAPSHOT UTF-8 - 2.100.0 + 2.130.0 [10.0.0,11.0.0) 5.10.0 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index e33c592c4..450d1f5c1 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ 1.8 1.8 10.3.0 - 2.109.0 + 2.130.0 From 716cfc899e4ad099e61eefec4a1200245074ee61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 21:23:29 +0100 Subject: [PATCH 145/577] build(deps): bump org.codehaus.mojo:exec-maven-plugin (#1585) Bumps [org.codehaus.mojo:exec-maven-plugin](https://github.com/mojohaus/exec-maven-plugin) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/mojohaus/exec-maven-plugin/releases) - [Commits](https://github.com/mojohaus/exec-maven-plugin/compare/exec-maven-plugin-3.1.0...3.2.0) --- updated-dependencies: - dependency-name: org.codehaus.mojo:exec-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core/cdk/infra/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-core/cdk/infra/pom.xml b/examples/powertools-examples-core/cdk/infra/pom.xml index 021aa98a4..05e643c4d 100644 --- a/examples/powertools-examples-core/cdk/infra/pom.xml +++ b/examples/powertools-examples-core/cdk/infra/pom.xml @@ -25,7 +25,7 @@ org.codehaus.mojo exec-maven-plugin - 3.1.0 + 3.2.0 cdk.CdkApp From 5bf9b3ddec0209e747961a33da2e24d9178a2670 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Wed, 28 Feb 2024 12:59:20 +0100 Subject: [PATCH 146/577] chore(v2): e2e tests (#1571) * Chore: fix e2e tests and build config * Use the right aspect library --- examples/powertools-examples-idempotency/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency/pom.xml | 4 ++-- .../software/amazon/lambda/powertools/e2e/Function.java | 2 +- .../handlers/largemessage_idempotent/pom.xml | 4 ++-- .../software/amazon/lambda/powertools/e2e/Function.java | 2 +- powertools-e2e-tests/handlers/pom.xml | 8 +++++--- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 39d6a8172..9a9351ea5 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -95,7 +95,7 @@ software.amazon.lambda - powertools-idempotency-dynamodb + powertools-idempotency-core diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index da2bbfb80..e3a67a5b5 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -15,7 +15,7 @@ software.amazon.lambda - powertools-idempotency + powertools-idempotency-dynamodb software.amazon.lambda @@ -43,7 +43,7 @@ software.amazon.lambda - powertools-idempotency + powertools-idempotency-core software.amazon.lambda diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index e4c2f2b9a..16109778d 100644 --- a/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -27,7 +27,7 @@ import software.amazon.lambda.powertools.idempotency.Idempotency; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; import software.amazon.lambda.powertools.idempotency.Idempotent; -import software.amazon.lambda.powertools.idempotency.persistence.DynamoDBPersistenceStore; +import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; import software.amazon.lambda.powertools.logging.Logging; diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index 8cb2cb52c..b57063346 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -15,7 +15,7 @@ software.amazon.lambda - powertools-idempotency + powertools-idempotency-dynamodb software.amazon.lambda @@ -47,7 +47,7 @@ software.amazon.lambda - powertools-idempotency + powertools-idempotency-core software.amazon.lambda diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/largemessage_idempotent/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index 5269b37c9..6c9d4e8cf 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -37,7 +37,7 @@ import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; import software.amazon.lambda.powertools.idempotency.IdempotencyKey; import software.amazon.lambda.powertools.idempotency.Idempotent; -import software.amazon.lambda.powertools.idempotency.persistence.DynamoDBPersistenceStore; +import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; import software.amazon.lambda.powertools.largemessages.LargeMessage; import software.amazon.lambda.powertools.logging.Logging; diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index ef5be4df4..1bf26f871 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -32,10 +32,7 @@ logging tracing metrics - batch idempotency - largemessage - largemessage_idempotent parameters validation-alb-event validation-apigw-event @@ -75,6 +72,11 @@ powertools-idempotency ${lambda.powertools.version} + + software.amazon.lambda + powertools-idempotency-dynamodb + ${lambda.powertools.version} + software.amazon.lambda powertools-parameters-appconfig From 7dff30c1afd1bf710ac0984aecc6efc973ef31cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Wed, 28 Feb 2024 13:29:34 +0100 Subject: [PATCH 147/577] feat: advanced logging (#1539) * improve logging * adding arguments to log events * !update ObjectMapper configuration * remove LoggingUtils appendKey, use standard MDC * examples in the end * clean sonar warnings * clean spotbugs issues * code review comments * update documentation * remove LoggingUtils --------- Co-authored-by: Scott Gerring --- docs/core/logging.md | 359 ++++------- .../cdk/app/src/main/java/helloworld/App.java | 4 +- .../gradle/src/main/java/helloworld/App.java | 7 +- .../kotlin/src/main/kotlin/helloworld/App.kt | 11 +- .../sam/src/main/java/helloworld/App.java | 7 +- .../src/main/java/helloworld/App.java | 12 +- .../src/main/java/helloworld/App.java | 16 +- pom.xml | 2 +- .../lambda/powertools/e2e/Function.java | 4 +- .../persistence/BasePersistenceStoreTest.java | 28 +- .../handlers/IdempotencyFunction.java | 35 +- .../json/resolver/PowertoolsResolver.java | 115 ++-- .../src/main/resources/LambdaJsonLayout.json | 3 +- ...a => PowertoolsResolverArgumentsTest.java} | 35 +- .../json/resolver/PowertoolsResolverTest.java | 8 + ...nMessage.java => PowertoolsArguments.java} | 31 +- .../handler/PowertoolsLogEnabled.java | 6 +- .../powertools/logging/logback/JsonUtils.java | 139 ++++ .../logging/logback/LambdaEcsEncoder.java | 165 +++-- .../logging/logback/LambdaJsonEncoder.java | 134 ++-- .../logging/logback/internal/JsonUtils.java | 130 ---- .../logback/internal/LambdaEcsSerializer.java | 187 ------ .../internal/LambdaJsonSerializer.java | 150 ----- .../internal/LambdaJsonEncoderTest.java | 213 ++++++- ...nMessage.java => PowertoolsArguments.java} | 28 +- .../handler/PowertoolsLogEnabled.java | 6 +- .../internal/handler/PowertoolsLogEvent.java | 28 + .../handler}/PowertoolsLogEventDisabled.java | 4 +- .../handler/PowertoolsLogEventForStream.java | 34 + .../handler/PowertoolsLogResponse.java | 28 + .../PowertoolsLogResponseForStream.java | 35 + .../lambda/powertools/logging/Logging.java | 3 +- .../powertools/logging/LoggingUtils.java | 123 ---- .../logging/argument/ArrayArgument.java | 43 ++ .../logging/argument/JsonArgument.java | 42 ++ .../logging/argument/KeyValueArgument.java | 49 ++ .../logging/argument/MapArgument.java | 48 ++ .../logging/argument/StructuredArgument.java | 45 ++ .../logging/argument/StructuredArguments.java | 129 ++++ .../logging/internal/JsonSerializer.java | 599 ++++++++++++++++++ .../logging/internal/LambdaLoggingAspect.java | 57 +- .../test/java/org/slf4j/test/TestLogger.java | 12 + .../powertools/logging/LoggingUtilsTest.java | 114 ---- .../argument/StructuredArgumentsTest.java | 105 +++ .../handlers/PowertoolsLogClearState.java | 4 +- .../handlers/PowertoolsLogEnabled.java | 6 +- .../logging/handlers/PowertoolsLogEvent.java | 8 + .../handlers/PowertoolsLogEventEnvVar.java | 36 ++ .../handlers/PowertoolsLogEventForStream.java | 8 + .../handlers/PowertoolsLogResponse.java | 7 + .../PowertoolsLogResponseForStream.java | 8 + .../logging/internal/JsonSerializerTest.java | 149 +++++ .../internal/LambdaLoggingAspectTest.java | 122 ++-- .../powertools/logging/model/Basket.java | 67 ++ .../powertools/logging/model/Product.java | 84 +++ .../powertools/utilities/JsonConfig.java | 26 +- .../utilities/EventDeserializerTest.java | 17 - spotbugs-exclude.xml | 11 +- 58 files changed, 2538 insertions(+), 1348 deletions(-) rename powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/{PowertoolsMessageResolverTest.java => PowertoolsResolverArgumentsTest.java} (70%) rename powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/{PowertoolsJsonMessage.java => PowertoolsArguments.java} (62%) create mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/JsonUtils.java delete mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/JsonUtils.java delete mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaEcsSerializer.java delete mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaJsonSerializer.java rename powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/{PowertoolsJsonMessage.java => PowertoolsArguments.java} (62%) create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEvent.java rename powertools-logging/{src/test/java/software/amazon/lambda/powertools/logging/handlers => powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler}/PowertoolsLogEventDisabled.java (90%) create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEventForStream.java create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogResponse.java create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogResponseForStream.java delete mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/ArrayArgument.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/JsonArgument.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/KeyValueArgument.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/MapArgument.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArgument.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArguments.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java delete mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/LoggingUtilsTest.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/argument/StructuredArgumentsTest.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventEnvVar.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/JsonSerializerTest.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/model/Basket.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/model/Product.java diff --git a/docs/core/logging.md b/docs/core/logging.md index f0fba760a..5306c55df 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -338,73 +338,6 @@ Your logs will always include the following keys in your structured logging: | **xray_trace_id** | String | "1-5759e988-bd862e3fe1be46a994272793" | X-Ray Trace ID when [Tracing is enabled](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank"} | | **error** | Map | `{ "name": "InvalidAmountException", "message": "Amount must be superior to 0", "stack": "at..." }` | Eventual exception (e.g. when doing `logger.error("Error", new InvalidAmountException("Amount must be superior to 0"));`) | -### Log messages as JSON -By default, `message` is logged as a `String` (e.g `"message": "The message"`). When logging JSON content, -you may want to avoid the escaped String (`"message:"{\"key\":\"value\"}"`) for better readability. -You can use `LoggingUtils.logMessagesAsJson(true)` to enable this programmatically. - -=== "PaymentFunction.java" - - ```java hl_lines="14 15 17-20" - import static software.amazon.lambda.powertools.utilities.EventDeserializer.extractDataFrom; - import software.amazon.lambda.powertools.logging.LoggingUtils; - import software.amazon.lambda.powertools.utilities.JsonConfig; - // ... other imports - - public class PaymentFunction implements RequestHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); - - @Logging - public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - Order order = extractDataFrom(input).as(Order.class); - - // logged as a String - LOGGER.debug("{}", JsonConfig.get().getObjectMapper().writeValueAsString(order)); - - // Logged as JSON - LoggingUtils.logMessagesAsJson(true); - LOGGER.debug("{}", JsonConfig.get().getObjectMapper().writeValueAsString(order)); - LoggingUtils.logMessagesAsJson(false); - - // ... - } - } - ``` - -=== "Order.java" - - ```java - public class Order { - private String id; - private Date date; - private Double amount; - } - ``` - -=== "Example CloudWatch Logs" - - ```json hl_lines="3 9-13" - { - "level": "DEBUG", - "message": "{\"id\":\"435iuh2j3hb4\", \"date\":\"2023-12-01T14:48:59\", \"amount\":435.5}", - "timestamp": "2023-12-01T14:49:19.293Z", - "service": "payment", - } - { - "level": "DEBUG", - "message": { - "id": "435iuh2j3hb4", - "date": "2023-12-01T14:48:59", - "amount":435.5 - }, - "timestamp": "2023-12-01T14:49:19.312Z", - "service": "payment", - } - ``` - -You can also achieve this more broadly for all JSON messages (see advanced configuration for [log4j](#log-messages-as-json_1) & [logback](#log-messages-as-json_2)). - ## Additional structured keys ### Logging Lambda context information @@ -463,58 +396,6 @@ including our custom [JMESPath Functions](../utilities/serialization.md#built-in "correlation_id": "correlation_id_value" } ``` - -**setCorrelationId method** - -You can also use `LoggingUtils.setCorrelationId()` method to inject it anywhere else in your code. - -=== "AppSetCorrelationId.java" - - ```java hl_lines="8" - public class AppSetCorrelationId implements RequestHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(AppSetCorrelationId.class); - - @Logging - public String handleRequest(final ScheduledEvent event, final Context context) { - // ... - LoggingUtils.setCorrelationId(event.getId()); - LOGGER.info("Scheduled Event") - // ... - } - } - ``` - -=== "Example Schedule Event" - - ```json hl_lines="2" - { - "id": "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c", - "detail-type": "Scheduled Event", - "source": "aws.events", - "account": "123456789012", - "time": "2023-12-01T14:49:19Z", - "region": "us-east-1", - "resources": [ - "arn:aws:events:us-east-1:123456789012:rule/ExampleRule" - ], - "detail": {} - } - ``` - -=== "CloudWatch Logs with correlation id" - - ```json hl_lines="6" - { - "level": "INFO", - "message": "Scheduled Event", - "timestamp": "2023-12-01T14:49:19.293Z", - "service": "payment", - "correlation_id": "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c" - } - ``` -???+ tip - You can retrieve correlation IDs via `LoggingUtils.getCorrelationId()` method if needed. **Known correlation IDs** @@ -563,14 +444,16 @@ we provide [built-in JMESPath expressions](#built-in-correlation-id-expressions) #### Custom keys -???+ warning "Custom keys are persisted across warm invocations" - Always set additional keys as part of your handler method to ensure they have the latest value, or explicitly clear them with [`clearState=true`](#clearing-state). +** Using StructuredArguments ** -To append an additional key in your logs, you can use the `LoggingUtils.appendKey()` or `LoggingUtils.appendKeys()` for multiple keys: +To append additional keys in your logs, you can use the `StructuredArguments` class: === "PaymentFunction.java" - ```java hl_lines="8 9 15 16" + ```java hl_lines="1 2 11 17" + import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; + import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entries; + public class PaymentFunction implements RequestHandler { private static final Logger LOGGER = LoggerFactory.getLogger(AppLogResponse.class); @@ -578,20 +461,18 @@ To append an additional key in your logs, you can use the `LoggingUtils.appendKe @Logging public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { // ... - LoggingUtils.appendKey("orderId", order.getId()); - LOGGER.info("Collecting payment"); + LOGGER.info("Collecting payment", entry("orderId", order.getId())); // ... Map customKeys = new HashMap<>(); customKeys.put("paymentId", payment.getId()); customKeys.put("amount", payment.getAmount); - LoggingUtils.appendKeys(customKeys); - LOGGER.info("Payment successful"); + LOGGER.info("Payment successful", entries(customKeys)); } } ``` -=== "Example CloudWatch Logs" +=== "CloudWatch Logs for PaymentFunction" ```json hl_lines="7 16-18" { @@ -615,73 +496,153 @@ To append an additional key in your logs, you can use the `LoggingUtils.appendKe } ``` -???+ tip "Additional keys are based on the MDC" - Mapped Diagnostic Context (MDC) is essentially a Key-Value store. It is supported by the [SLF4J API](https://www.slf4j.org/manual.html#mdc){target="_blank"}, - [logback](https://logback.qos.ch/manual/mdc.html){target="_blank"} and log4j (known as [ThreadContext](https://logging.apache.org/log4j/2.x/manual/thread-context.html){target="_blank"}). - - `LoggingUtils.appendKey("key", "value")` is equivalent to `MDC.put("key", "value")`. +`StructuredArguments` provides several options: + - `entry` to add one key and value into the log structure. Note that value can be any object type. + - `entries` to add multiple keys and values (from a Map) into the log structure. Note that values can be any object type. + - `json` to add a key and raw json (string) as value into the log structure. + - `array` to add one key and multiple values into the log structure. Note that values can be any object type. -### Removing additional keys - -You can remove any additional key from entry using `LoggingUtils.removeKey()` or `LoggingUtils.removeKeys()` for multiple keys: +=== "OrderFunction.java" -=== "PaymentFunction.java" + ```java hl_lines="1 2 11 17" + import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; + import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.array; - ```java hl_lines="19 20" - public class PaymentFunction implements RequestHandler { + public class OrderFunction implements RequestHandler { private static final Logger LOGGER = LoggerFactory.getLogger(AppLogResponse.class); - @Logging(logResponse = true) + @Logging public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { // ... - LoggingUtils.appendKey("orderId", order.getId()); - LOGGER.info("Collecting payment"); - - // ... - Map customKeys = new HashMap<>(); - customKeys.put("paymentId", payment.getId()); - customKeys.put("amount", payment.getAmount); - LoggingUtils.appendKeys(customKeys); - LOGGER.info("Payment successful"); - + LOGGER.info("Processing order", entry("order", order), array("products", productList)); // ... - LoggingUtils.removeKey("orderId"); - LoggingUtils.removeKeys("paymentId", "amount"); - - return response; } } ``` -=== "Example CloudWatch Logs" - Response is logged (`logResponse=true`) without the additional keys: +=== "CloudWatch Logs for OrderFunction" - ```json - ... + ```json hl_lines="7 13" { "level": "INFO", - "message": { - "statusCode": 200, - "isBase64Encoded": false, - "body": ..., - "headers": ..., - "multiValueHeaders": ... - }, + "message": "Processing order", "service": "payment", - "timestamp": "2023-12-01T14:49:20.118Z", - "xray_trace_id": "1-6569f266-4b0c7f97280dcd8428d3c9b5" + "timestamp": "2023-12-01T14:49:19.293Z", + "xray_trace_id": "1-6569f266-4b0c7f97280dcd8428d3c9b5", + "order": { + "orderId": 23542, + "amount": 459.99, + "date": "2023-12-01T14:49:19.018Z", + "customerId": 328496 + }, + "products": [ + { + "productId": 764330, + "name": "product1", + "quantity": 1, + "price": 300 + }, + { + "productId": 798034, + "name": "product42", + "quantity": 1, + "price": 159.99 + } + ] } ``` -???+ tip "Additional keys are based on the MDC" - `LoggingUtils.removeKey("key")` is equivalent to `MDC.remove("key")`. +???+ tip "Use arguments without log placeholders" + As shown in the example above, you can use arguments (with `StructuredArguments`) without placeholders (`{}`) in the message. + If you add the placeholders, the arguments will be logged both as an additional field and also as a string in the log message, using the `toString()` method. + + === "Function1.java" + + ```java + LOGGER.info("Processing {}", entry("order", order)); + ``` + + === "Order.java" + + ```java hl_lines="5" + public class Order { + // ... + + @Override + public String toString() { + return "Order{" + + "orderId=" + id + + ", amount=" + amount + + ", date='" + date + '\'' + + ", customerId=" + customerId + + '}'; + } + } + ``` + + === "CloudWatch Logs Function1" + + ```json hl_lines="3 7" + { + "level": "INFO", + "message": "Processing order=Order{orderId=23542, amount=459.99, date='2023-12-01T14:49:19.018Z', customerId=328496}", + "service": "payment", + "timestamp": "2023-12-01T14:49:19.293Z", + "xray_trace_id": "1-6569f266-4b0c7f97280dcd8428d3c9b5", + "order": { + "orderId": 23542, + "amount": 459.99, + "date": "2023-12-01T14:49:19.018Z", + "customerId": 328496 + } + } + ``` + + You can also combine structured arguments with non structured ones. For example: + + === "Function2.java" + ```java + LOGGER.info("Processing order {}", order.getOrderId(), entry("order", order)); + ``` + + === "CloudWatch Logs Function2" + ```json + { + "level": "INFO", + "message": "Processing order 23542", + "service": "payment", + "timestamp": "2023-12-01T14:49:19.293Z", + "xray_trace_id": "1-6569f266-4b0c7f97280dcd8428d3c9b5", + "order": { + "orderId": 23542, + "amount": 459.99, + "date": "2023-12-01T14:49:19.018Z", + "customerId": 328496 + } + } + ``` + +** Using MDC ** + +Mapped Diagnostic Context (MDC) is essentially a Key-Value store. It is supported by the [SLF4J API](https://www.slf4j.org/manual.html#mdc){target="_blank"}, +[logback](https://logback.qos.ch/manual/mdc.html){target="_blank"} and log4j (known as [ThreadContext](https://logging.apache.org/log4j/2.x/manual/thread-context.html){target="_blank"}). You can use the following standard: + +`MDC.put("key", "value");` + +???+ warning "Custom keys stored in the MDC are persisted across warm invocations" + Always set additional keys as part of your handler method to ensure they have the latest value, or explicitly clear them with [`clearState=true`](#clearing-state). + + +### Removing additional keys + +You can remove additional keys added with the MDC using `MDC.remove("key")`. #### Clearing state Logger is commonly initialized in the global scope. Due to [Lambda Execution Context reuse](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html){target="_blank"}, -this means that custom keys can be persisted across invocations. If you want all custom keys to be deleted, you can use +this means that custom keys, added with the MDC can be persisted across invocations. If you want all custom keys to be deleted, you can use `clearState=true` attribute on the `@Logging` annotation. === "CreditCardFunction.java" @@ -694,7 +655,7 @@ this means that custom keys can be persisted across invocations. If you want all @Logging(clearState = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { // ... - LoggingUtils.appendKey("cardNumber", card.getId()); + MDC.put("cardNumber", card.getId()); LOGGER.info("Updating card information"); // ... } @@ -727,8 +688,7 @@ this means that custom keys can be persisted across invocations. If you want all } ``` -???+ tip "Additional keys are based on the MDC" - `clearState` is based on `MDC.clear()`. State clearing is automatically done at the end of the execution of the handler if set to `true`. +`clearState` is based on `MDC.clear()`. State clearing is automatically done at the end of the execution of the handler if set to `true`. ## Logging incoming event @@ -952,22 +912,6 @@ The `JsonTemplateLayout` is automatically configured with the provided template: You can create your own template and leverage the [PowertoolsResolver](https://github.com/aws-powertools/powertools-lambda-java/tree/v2/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java){target="_blank"} and any other resolver to log the desired fields with the desired format. Some examples of customization are given below: -#### Log messages as JSON -`message` field is not handled with the standard [`MessageResolver`](https://logging.apache.org/log4j/2.x/manual/json-template-layout.html#event-template-resolver-message){target="_blank"} but by the `PowertoolsResolver`. -With this resolver, you can choose to log all the JSON messages as JSON and not as String. - -=== "my-custom-template.json" - - ```json - { - "message": { - "$resolver": "powertools", - "field": "message", - "asJson": true - } - } - ``` - #### Customising date format Utility by default emits `timestamp` field in the logs in format `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` and in system default timezone. @@ -1015,16 +959,6 @@ Logback configuration is done in _logback.xml_ and the Powertools [`LambdaJsonEn The `LambdaJsonEncoder` can be customized in different ways: -#### Log messages as JSON - -With the following configuration, you choose to log all the JSON messages as JSON and not as String (default is `false`): - -```xml - - true - -``` - #### Customising date format Utility by default emits `timestamp` field in the logs in format `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'` and in system default timezone. If you need to customize format and timezone, you can change use the following: @@ -1071,33 +1005,6 @@ If you need to customize format and timezone, you can change use the following: ``` -## Override default object mapper - -You can optionally choose to override default object mapper which is used to serialize lambda function events. You might -want to supply custom object mapper in order to control how serialisation is done, for example, when you want to log only -specific fields from received event due to security. - -=== "App.java" - - ```java hl_lines="6-10" - public class App implements RequestHandler { - - private static final Logger LOGGER = LoggerFactory.getLogger(App.class); - - static { - ObjectMapper objectMapper = new ObjectMapper() - .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS) - .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); - LoggingUtils.setObjectMapper(objectMapper); - } - - @Logging(logEvent = true) - public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { - // ... - } - } - ``` - ## Elastic Common Schema (ECS) Support Utility also supports [Elastic Common Schema(ECS)](https://www.elastic.co/guide/en/ecs/current/ecs-reference.html){target="_blank"} format. diff --git a/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java index 18eea0560..5aa268ffe 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java @@ -31,10 +31,10 @@ import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import software.amazon.cloudwatchlogs.emf.model.DimensionSet; import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; import software.amazon.lambda.powertools.metrics.Metrics; import software.amazon.lambda.powertools.tracing.CaptureMode; import software.amazon.lambda.powertools.tracing.Tracing; @@ -62,7 +62,7 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); }); - LoggingUtils.appendKey("test", "willBeLogged"); + MDC.put("test", "willBeLogged"); APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() .withHeaders(headers); diff --git a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java index 36ef72ae7..b1a701b8f 100644 --- a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java @@ -14,6 +14,7 @@ package helloworld; +import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; @@ -31,10 +32,10 @@ import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import software.amazon.cloudwatchlogs.emf.model.DimensionSet; import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; import software.amazon.lambda.powertools.metrics.Metrics; import software.amazon.lambda.powertools.tracing.CaptureMode; import software.amazon.lambda.powertools.tracing.Tracing; @@ -63,13 +64,13 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); }); - LoggingUtils.appendKey("test", "willBeLogged"); + MDC.put("test", "willBeLogged"); APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() .withHeaders(headers); try { final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); - log.info(pageContents); + log.info("", entry("ip", pageContents)); TracingUtils.putAnnotation("Test", "New"); String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); diff --git a/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt b/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt index 1c925d4f4..8e8857079 100644 --- a/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt +++ b/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt @@ -18,23 +18,21 @@ import com.amazonaws.services.lambda.runtime.RequestHandler import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent import com.amazonaws.xray.entities.Subsegment -import org.slf4j.Logger import org.slf4j.LoggerFactory +import org.slf4j.MDC import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger import software.amazon.cloudwatchlogs.emf.model.DimensionSet import software.amazon.cloudwatchlogs.emf.model.Unit import software.amazon.lambda.powertools.logging.Logging -import software.amazon.lambda.powertools.logging.LoggingUtils +import software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry import software.amazon.lambda.powertools.metrics.Metrics import software.amazon.lambda.powertools.metrics.MetricsUtils import software.amazon.lambda.powertools.tracing.CaptureMode import software.amazon.lambda.powertools.tracing.Tracing import software.amazon.lambda.powertools.tracing.TracingUtils -import java.io.BufferedReader import java.io.IOException import java.io.InputStreamReader import java.net.URL -import java.util.stream.Collectors /** * Handler for requests to Lambda function. @@ -44,7 +42,6 @@ class App : RequestHandler { - private final static Logger log = LogManager.getLogger(App.class); + private static final Logger log = LogManager.getLogger(App.class); + + @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); @@ -60,13 +64,13 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); }); - LoggingUtils.appendKey("test", "willBeLogged"); + MDC.put("test", "willBeLogged"); APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() .withHeaders(headers); try { final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); - log.info(pageContents); + log.info("", entry("ip", pageContents)); TracingUtils.putAnnotation("Test", "New"); String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); diff --git a/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/App.java index dacd7f1d4..e0b1a2979 100644 --- a/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/App.java @@ -14,6 +14,7 @@ package helloworld; +import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; @@ -31,10 +32,10 @@ import java.util.stream.Collectors; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.slf4j.MDC; import software.amazon.cloudwatchlogs.emf.model.DimensionSet; import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; import software.amazon.lambda.powertools.metrics.Metrics; import software.amazon.lambda.powertools.tracing.CaptureMode; import software.amazon.lambda.powertools.tracing.Tracing; @@ -44,14 +45,11 @@ * Handler for requests to Lambda function. */ public class App implements RequestHandler { - private final static Logger log = LogManager.getLogger(App.class); + private static final Logger log = LogManager.getLogger(App.class); - // This is controlled by POWERTOOLS_LOGGER_SAMPLE_RATE environment variable - // @Logging(logEvent = true, samplingRate = 0.7) - // This is controlled by POWERTOOLS_METRICS_NAMESPACE environment variable - // @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - // This is controlled by POWERTOOLS_TRACER_CAPTURE_ERROR environment variable + @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); @@ -66,13 +64,13 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); }); - LoggingUtils.appendKey("test", "willBeLogged"); + MDC.put("test", "willBeLogged"); APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() .withHeaders(headers); try { final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); - log.info(pageContents); + log.info("", entry("ip", pageContents)); TracingUtils.putAnnotation("Test", "New"); String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); diff --git a/pom.xml b/pom.xml index 7b126a426..b9b8da3bc 100644 --- a/pom.xml +++ b/pom.xml @@ -55,12 +55,12 @@ powertools-large-messages powertools-e2e-tests powertools-batch - examples powertools-parameters/powertools-parameters-ssm powertools-parameters/powertools-parameters-secrets powertools-parameters/powertools-parameters-dynamodb powertools-parameters/powertools-parameters-appconfig powertools-parameters/powertools-parameters-tests + examples diff --git a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index c2634533d..58492653a 100644 --- a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -18,15 +18,15 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; public class Function implements RequestHandler { private static final Logger LOG = LoggerFactory.getLogger(Function.class); @Logging public String handleRequest(Input input, Context context) { - LoggingUtils.appendKeys(input.getKeys()); + input.getKeys().forEach(MDC::put); LOG.info(input.getMessage()); return "OK"; diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java index 41d7e2957..f770679ee 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java @@ -91,7 +91,7 @@ public void saveInProgress_defaultConfig() { assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS); assertThat(dr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); assertThat(dr.getResponseData()).isNull(); - assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction#7b40f56c086de5aa91dc467456329ed2"); + assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction#8d6a8f173b46479eff55e0997864a514"); assertThat(dr.getPayloadHash()).isEqualTo(""); assertThat(dr.getInProgressExpiryTimestamp()).isEmpty(); assertThat(status).isEqualTo(1); @@ -109,7 +109,7 @@ public void saveInProgress_withRemainingTime() { assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS); assertThat(dr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); assertThat(dr.getResponseData()).isNull(); - assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction#7b40f56c086de5aa91dc467456329ed2"); + assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction#8d6a8f173b46479eff55e0997864a514"); assertThat(dr.getPayloadHash()).isEqualTo(""); assertThat(dr.getInProgressExpiryTimestamp().orElse(-1)).isEqualTo( now.plus(lambdaTimeoutMs, ChronoUnit.MILLIS).toEpochMilli()); @@ -228,7 +228,7 @@ public void saveSuccess_shouldUpdateRecord() throws JsonProcessingException { assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); assertThat(dr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); assertThat(dr.getResponseData()).isEqualTo(JsonConfig.get().getObjectMapper().writeValueAsString(product)); - assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction#7b40f56c086de5aa91dc467456329ed2"); + assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction#8d6a8f173b46479eff55e0997864a514"); assertThat(dr.getPayloadHash()).isEqualTo(""); assertThat(status).isEqualTo(2); assertThat(cache).isEmpty(); @@ -247,11 +247,11 @@ public void saveSuccess_withCacheEnabled_shouldSaveInCache() throws JsonProcessi assertThat(status).isEqualTo(2); assertThat(cache).hasSize(1); - DataRecord record = cache.get("testFunction#7b40f56c086de5aa91dc467456329ed2"); + DataRecord record = cache.get("testFunction#8d6a8f173b46479eff55e0997864a514"); assertThat(record.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); assertThat(record.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); assertThat(record.getResponseData()).isEqualTo(JsonConfig.get().getObjectMapper().writeValueAsString(product)); - assertThat(record.getIdempotencyKey()).isEqualTo("testFunction#7b40f56c086de5aa91dc467456329ed2"); + assertThat(record.getIdempotencyKey()).isEqualTo("testFunction#8d6a8f173b46479eff55e0997864a514"); assertThat(record.getPayloadHash()).isEqualTo(""); } @@ -270,7 +270,7 @@ public void getRecord_shouldReturnRecordFromPersistence() Instant now = Instant.now(); DataRecord record = persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), now); - assertThat(record.getIdempotencyKey()).isEqualTo("testFunction.myfunc#7b40f56c086de5aa91dc467456329ed2"); + assertThat(record.getIdempotencyKey()).isEqualTo("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514"); assertThat(record.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS); assertThat(record.getResponseData()).isEqualTo("Response"); assertThat(status).isEqualTo(0); @@ -286,15 +286,15 @@ public void getRecord_cacheEnabledNotExpired_shouldReturnRecordFromCache() Instant now = Instant.now(); DataRecord dr = new DataRecord( - "testFunction.myfunc#7b40f56c086de5aa91dc467456329ed2", + "testFunction.myfunc#8d6a8f173b46479eff55e0997864a514", DataRecord.Status.COMPLETED, now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(), "result of the function", null); - cache.put("testFunction.myfunc#7b40f56c086de5aa91dc467456329ed2", dr); + cache.put("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514", dr); DataRecord record = persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), now); - assertThat(record.getIdempotencyKey()).isEqualTo("testFunction.myfunc#7b40f56c086de5aa91dc467456329ed2"); + assertThat(record.getIdempotencyKey()).isEqualTo("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514"); assertThat(record.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); assertThat(record.getResponseData()).isEqualTo("result of the function"); assertThat(status).isEqualTo(-1); // getRecord must not be called (retrieve from cache) @@ -310,15 +310,15 @@ public void getRecord_cacheEnabledExpired_shouldReturnRecordFromPersistence() Instant now = Instant.now(); DataRecord dr = new DataRecord( - "testFunction.myfunc#7b40f56c086de5aa91dc467456329ed2", + "testFunction.myfunc#8d6a8f173b46479eff55e0997864a514", DataRecord.Status.COMPLETED, now.minus(3, ChronoUnit.SECONDS).getEpochSecond(), "result of the function", null); - cache.put("testFunction.myfunc#7b40f56c086de5aa91dc467456329ed2", dr); + cache.put("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514", dr); DataRecord record = persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), now); - assertThat(record.getIdempotencyKey()).isEqualTo("testFunction.myfunc#7b40f56c086de5aa91dc467456329ed2"); + assertThat(record.getIdempotencyKey()).isEqualTo("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514"); assertThat(record.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS); assertThat(record.getResponseData()).isEqualTo("Response"); assertThat(status).isEqualTo(0); @@ -363,8 +363,8 @@ public void deleteRecord_cacheEnabled_shouldDeleteRecordFromCache() { persistenceStore.configure(IdempotencyConfig.builder() .withUseLocalCache(true).build(), null, cache); - cache.put("testFunction#7b40f56c086de5aa91dc467456329ed2", - new DataRecord("testFunction#7b40f56c086de5aa91dc467456329ed2", DataRecord.Status.COMPLETED, 123, null, + cache.put("testFunction#8d6a8f173b46479eff55e0997864a514", + new DataRecord("testFunction#8d6a8f173b46479eff55e0997864a514", DataRecord.Status.COMPLETED, 123, null, null)); persistenceStore.deleteRecord(JsonConfig.get().getObjectMapper().valueToTree(event), new ArithmeticException()); assertThat(status).isEqualTo(3); diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/handlers/IdempotencyFunction.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/handlers/IdempotencyFunction.java index 1296a75c7..227eea39e 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/handlers/IdempotencyFunction.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/handlers/IdempotencyFunction.java @@ -18,26 +18,15 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import java.util.HashMap; +import java.util.Map; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.lambda.powertools.idempotency.Idempotency; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; import software.amazon.lambda.powertools.idempotency.Idempotent; import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; -import software.amazon.lambda.powertools.utilities.JsonConfig; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; public class IdempotencyFunction implements RequestHandler { - private final static Logger LOG = LogManager.getLogger(IdempotencyFunction.class); - public boolean handlerExecuted = false; public IdempotencyFunction(DynamoDbClient client) { @@ -66,28 +55,10 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() .withHeaders(headers); - try { - String address = JsonConfig.get().getObjectMapper().readTree(input.getBody()).get("address").asText(); - final String pageContents = this.getPageContents(address); - String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); - LOG.debug("ip is {}", pageContents); return response .withStatusCode(200) - .withBody(output); - - } catch (IOException e) { - return response - .withBody("{}") - .withStatusCode(500); - } - } + .withBody("{ \"message\": \"hello world\"}"); - // we could actually also put the @Idempotent annotation here - private String getPageContents(String address) throws IOException { - URL url = new URL(address); - try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { - return br.lines().collect(Collectors.joining(System.lineSeparator())); - } } } diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java index 95086a085..c98da7833 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java +++ b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java @@ -14,8 +14,7 @@ package org.apache.logging.log4j.layout.template.json.resolver; -import static java.lang.Boolean.TRUE; -import static software.amazon.lambda.powertools.logging.LoggingUtils.LOG_MESSAGES_AS_JSON; +import static java.util.Arrays.stream; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; @@ -26,18 +25,18 @@ import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SAMPLING_RATE; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SERVICE; -import com.fasterxml.jackson.core.JacksonException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.util.Collections; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.layout.template.json.util.JsonWriter; -import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.util.ReadOnlyStringMap; import software.amazon.lambda.powertools.common.internal.LambdaConstants; import software.amazon.lambda.powertools.common.internal.SystemWrapper; +import software.amazon.lambda.powertools.logging.argument.StructuredArgument; +import software.amazon.lambda.powertools.logging.internal.JsonSerializer; import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; /** @@ -170,76 +169,42 @@ public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { } }; - /** - * Use a custom message resolver to permit to log json string in json format without escaped quotes. - */ - private static final class MessageResolver implements EventResolver { - private final ObjectMapper mapper = new ObjectMapper() - .enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS); - private final boolean logMessagesAsJsonGlobal; - - public MessageResolver(boolean logMessagesAsJson) { - this.logMessagesAsJsonGlobal = logMessagesAsJson; - } - - public boolean isValidJson(String json) { - if (!(json.startsWith("{") || json.startsWith("["))) { - return false; - } - try { - mapper.readTree(json); - } catch (JacksonException e) { - return false; - } - return true; - } - - @Override - public boolean isResolvable(LogEvent logEvent) { - final Message msg = logEvent.getMessage(); - return null != msg && null != msg.getFormattedMessage(); - } - - @Override - public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { - String message = logEvent.getMessage().getFormattedMessage(); - - String logMessagesAsJsonLocal = logEvent.getContextData().getValue(LOG_MESSAGES_AS_JSON); - Boolean logMessagesAsJson = null; - if (logMessagesAsJsonLocal != null) { - logMessagesAsJson = Boolean.parseBoolean(logMessagesAsJsonLocal); - } - - if (((logMessagesAsJsonGlobal && logMessagesAsJson == null) || TRUE.equals(logMessagesAsJson)) - && isValidJson(message)) { - jsonWriter.writeRawString(message); - } else { - jsonWriter.writeString(message); - } - } - } - + @SuppressWarnings("java:S106") private static final EventResolver NON_POWERTOOLS_FIELD_RESOLVER = (LogEvent logEvent, JsonWriter jsonWriter) -> { StringBuilder stringBuilder = jsonWriter.getStringBuilder(); - // remove dummy field to kick in powertools resolver - stringBuilder.setLength(stringBuilder.length() - 4); - - // Inject all the context information. - ReadOnlyStringMap contextData = logEvent.getContextData(); - contextData.forEach((key, value) -> { - if (!PowertoolsLoggedFields.stringValues().contains(key) && !LOG_MESSAGES_AS_JSON.equals(key)) { - jsonWriter.writeSeparator(); - jsonWriter.writeString(key); - stringBuilder.append(':'); - jsonWriter.writeValue(value); + try (JsonSerializer serializer = new JsonSerializer(stringBuilder)) { + + // remove dummy field to kick in powertools resolver + stringBuilder.setLength(stringBuilder.length() - 4); + + // log other MDC values + ReadOnlyStringMap contextData = logEvent.getContextData(); + contextData.forEach((key, value) -> { + if (!PowertoolsLoggedFields.stringValues().contains(key)) { + serializer.writeSeparator(); + serializer.writeObjectField(key, value); + } + }); + + // log structured arguments + Object[] arguments = logEvent.getMessage().getParameters(); + if (arguments != null) { + stream(arguments).filter(StructuredArgument.class::isInstance).forEach(argument -> { + serializer.writeRaw(','); + try { + ((StructuredArgument) argument).writeTo(serializer); + } catch (IOException e) { + System.err.printf("Failed to encode log event, error: %s.%n", e.getMessage()); + } + }); } - }); + } }; private final EventResolver internalResolver; - private static final Map eventResolverMap = Stream.of(new Object[][] { + private static final Map eventResolverMap = Collections.unmodifiableMap(Stream.of(new Object[][] { { SERVICE.getName(), SERVICE_RESOLVER }, { FUNCTION_NAME.getName(), FUNCTION_NAME_RESOLVER }, { FUNCTION_VERSION.getName(), FUNCTION_VERSION_RESOLVER }, @@ -251,7 +216,7 @@ && isValidJson(message)) { { SAMPLING_RATE.getName(), SAMPLING_RATE_RESOLVER }, { "region", REGION_RESOLVER }, { "account_id", ACCOUNT_ID_RESOLVER } - }).collect(Collectors.toMap(data -> (String) data[0], data -> (EventResolver) data[1])); + }).collect(Collectors.toMap(data -> (String) data[0], data -> (EventResolver) data[1]))); PowertoolsResolver(final TemplateResolverConfig config) { @@ -259,17 +224,9 @@ && isValidJson(message)) { if (fieldName == null) { internalResolver = NON_POWERTOOLS_FIELD_RESOLVER; } else { - boolean logMessagesAsJson = false; - if (config.exists("asJson")) { - logMessagesAsJson = config.getBoolean("asJson"); - } - if ("message".equals(fieldName)) { - internalResolver = new MessageResolver(logMessagesAsJson); - } else { - internalResolver = eventResolverMap.get(fieldName); - } + internalResolver = eventResolverMap.get(fieldName); if (internalResolver == null) { - throw new IllegalArgumentException("unknown field: " + fieldName); + throw new IllegalArgumentException("Unknown field: " + fieldName); } } } diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json index d8d8810f6..8b811ee5f 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json @@ -4,8 +4,7 @@ "field": "name" }, "message": { - "$resolver": "powertools", - "field": "message" + "$resolver": "message" }, "error": { "message": { diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsMessageResolverTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java similarity index 70% rename from powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsMessageResolverTest.java rename to powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java index a00b78906..24014a759 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsMessageResolverTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java @@ -35,12 +35,10 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.slf4j.MDC; -import software.amazon.lambda.powertools.logging.LoggingUtils; -import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsJsonMessage; -import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments; @Order(2) -class PowertoolsMessageResolverTest { +class PowertoolsResolverArgumentsTest { @Mock private Context context; @@ -67,9 +65,9 @@ void cleanUp() throws IOException { } @Test - void shouldLogJsonMessageWithoutEscapedStringsWhenSettingLogAsJson() { + void shouldLogArgumentsAsJsonWhenUsingRawJson() { // GIVEN - PowertoolsJsonMessage requestHandler = new PowertoolsJsonMessage(); + PowertoolsArguments requestHandler = new PowertoolsArguments(PowertoolsArguments.ArgumentFormat.JSON); SQSEvent.SQSMessage msg = new SQSEvent.SQSMessage(); msg.setMessageId("1212abcd"); msg.setBody("plop"); @@ -85,24 +83,33 @@ void shouldLogJsonMessageWithoutEscapedStringsWhenSettingLogAsJson() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"message\":{\"messageId\":\"1212abcd\",\"receiptHandle\":null,\"body\":\"plop\",\"md5OfBody\":null,\"md5OfMessageAttributes\":null,\"eventSourceArn\":null,\"eventSource\":\"eb\",\"awsRegion\":\"eu-west-1\",\"attributes\":null,\"messageAttributes\":{\"keyAttribute\":{\"stringValue\":null,\"binaryValue\":null,\"stringListValues\":[\"val1\",\"val2\",\"val3\"],\"binaryListValues\":null,\"dataType\":null}}}") + .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") - .contains("\"message\":\"{\\\"key\\\":\\\"value\\\"}\"") - .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"") - .doesNotContain(LoggingUtils.LOG_MESSAGES_AS_JSON); + .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); } @Test - void shouldLogStringMessageWhenNotJson() { + void shouldLogArgumentsAsJsonWhenUsingKeyValue() { // GIVEN - PowertoolsLogEnabled requestHandler = new PowertoolsLogEnabled(); + PowertoolsArguments requestHandler = new PowertoolsArguments(PowertoolsArguments.ArgumentFormat.ENTRY); + SQSEvent.SQSMessage msg = new SQSEvent.SQSMessage(); + msg.setMessageId("1212abcd"); + msg.setBody("plop"); + msg.setEventSource("eb"); + msg.setAwsRegion("eu-west-1"); + SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); + attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); + msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); // WHEN - requestHandler.handleRequest(null, context); + requestHandler.handleRequest(msg, context); // THEN File logFile = new File("target/logfile.json"); - assertThat(contentOf(logFile)).contains("\"message\":\"Test debug event\""); + assertThat(contentOf(logFile)) + .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + .contains("\"message\":\"1212abcd\"") + .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); } private void setupContext() { diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java index 1aa98fdef..073cd7026 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java @@ -15,6 +15,7 @@ package org.apache.logging.log4j.layout.template.json.resolver; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mockStatic; import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; @@ -70,6 +71,13 @@ void shouldResolveAccountId() { assertThat(result).isEqualTo("\"123456789012\""); } + @Test + void unknownField_shouldThrowException() { + assertThatThrownBy(() -> resolveField("custom-random-unknown-field", "custom-random-unknown-field", "Once apon a time in Switzerland...")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Unknown field: custom-random-unknown-field"); + } + @Test void shouldResolveRegion() { try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java similarity index 62% rename from powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java rename to powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java index 3d196e5fb..387074590 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java @@ -14,29 +14,38 @@ package software.amazon.lambda.powertools.logging.internal.handler; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID; + import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.fasterxml.jackson.core.JsonProcessingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.logging.argument.StructuredArguments; import software.amazon.lambda.powertools.utilities.JsonConfig; -public class PowertoolsJsonMessage implements RequestHandler { - private final Logger LOG = LoggerFactory.getLogger(PowertoolsJsonMessage.class); +public class PowertoolsArguments implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsArguments.class); + private final ArgumentFormat argumentFormat; + + public PowertoolsArguments(ArgumentFormat argumentFormat) { + this.argumentFormat = argumentFormat; + } @Override @Logging(clearState = true) public String handleRequest(SQSEvent.SQSMessage input, Context context) { try { - LoggingUtils.logMessagesAsJson(true); - LOG.debug(JsonConfig.get().getObjectMapper().writeValueAsString(input)); - - LoggingUtils.logMessagesAsJson(false); - LOG.debug("{\"key\":\"value\"}"); - + MDC.put(CORRELATION_ID.getName(), input.getMessageId()); + if (argumentFormat == ArgumentFormat.JSON) { + LOG.debug("SQS Event", StructuredArguments.json("input", + JsonConfig.get().getObjectMapper().writeValueAsString(input))); + } else { + LOG.debug("SQS Event", StructuredArguments.entry("input", input)); + } LOG.debug("{}", input.getMessageId()); LOG.warn("Message body = {} and id = \"{}\"", input.getBody(), input.getMessageId()); } catch (JsonProcessingException e) { @@ -44,4 +53,8 @@ public String handleRequest(SQSEvent.SQSMessage input, Context context) { } return input.getMessageId(); } + + public enum ArgumentFormat { + JSON, ENTRY + } } diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java index faa722756..e8c0c5851 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java @@ -18,8 +18,8 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; public class PowertoolsLogEnabled implements RequestHandler { private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogEnabled.class); @@ -27,8 +27,8 @@ public class PowertoolsLogEnabled implements RequestHandler { @Override @Logging(clearState = true) public Object handleRequest(Object input, Context context) { - LoggingUtils.appendKey("myKey", "myValue"); + MDC.put("myKey", "myValue"); LOG.debug("Test debug event"); - return null; + return "Bonjour le monde"; } } diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/JsonUtils.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/JsonUtils.java new file mode 100644 index 000000000..b98a8eada --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/JsonUtils.java @@ -0,0 +1,139 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.logback; + +import ch.qos.logback.classic.spi.ILoggingEvent; +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; +import java.util.TimeZone; +import java.util.TreeMap; +import software.amazon.lambda.powertools.logging.argument.StructuredArgument; +import software.amazon.lambda.powertools.logging.internal.JsonSerializer; +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; + +/** + * Json tools to serialize common fields + */ +final class JsonUtils { + + private JsonUtils() { + // static utils + } + + static void serializeTimestamp(JsonSerializer generator, long timestamp, String timestampFormat, + String timestampFormatTimezoneId, String timestampAttributeName) { + String formattedTimestamp; + if (timestampFormat == null || timestamp < 0) { + formattedTimestamp = String.valueOf(timestamp); + } else { + Date date = new Date(timestamp); + DateFormat format = new SimpleDateFormat(timestampFormat); + + if (timestampFormatTimezoneId != null) { + TimeZone tz = TimeZone.getTimeZone(timestampFormatTimezoneId); + format.setTimeZone(tz); + } + formattedTimestamp = format.format(date); + } + generator.writeStringField(timestampAttributeName, formattedTimestamp); + } + + static void serializeMDCEntries(Map mdcPropertyMap, JsonSerializer serializer) { + TreeMap sortedMap = new TreeMap<>(mdcPropertyMap); + for (Map.Entry entry : sortedMap.entrySet()) { + if (!PowertoolsLoggedFields.stringValues().contains(entry.getKey())) { + serializeMDCEntry(entry, serializer); + } + } + } + + static void serializeMDCEntry(Map.Entry entry, JsonSerializer serializer) { + serializer.writeRaw(','); + serializer.writeFieldName(entry.getKey()); + if (isString(entry.getValue())) { + serializer.writeString(entry.getValue()); + } else { + serializer.writeRaw(entry.getValue()); + } + } + + static void serializeArguments(ILoggingEvent event, JsonSerializer serializer) throws IOException { + Object[] arguments = event.getArgumentArray(); + if (arguments != null) { + for (Object argument : arguments) { + if (argument instanceof StructuredArgument) { + serializer.writeRaw(','); + ((StructuredArgument) argument).writeTo(serializer); + } + } + } + } + + /** + * As MDC is a {@code Map}, we need to check the type + * to output numbers and booleans correctly (without quotes) + */ + private static boolean isString(String str) { + if (str == null) { + return true; + } + if ("true".equals(str) || "false".equals(str)) { + return false; // boolean + } + return !isNumeric(str); // number + } + + /** + * Taken from commons-lang3 NumberUtils to avoid include the library + */ + private static boolean isNumeric(final String str) { + if (str == null || str.isEmpty()) { + return false; + } + if (str.charAt(str.length() - 1) == '.') { + return false; + } + if (str.charAt(0) == '-') { + if (str.length() == 1) { + return false; + } + return withDecimalsParsing(str, 1); + } + return withDecimalsParsing(str, 0); + } + + /** + * Taken from commons-lang3 NumberUtils + */ + private static boolean withDecimalsParsing(final String str, final int beginIdx) { + int decimalPoints = 0; + for (int i = beginIdx; i < str.length(); i++) { + final boolean isDecimalPoint = str.charAt(i) == '.'; + if (isDecimalPoint) { + decimalPoints++; + } + if (decimalPoints > 1) { + return false; + } + if (!isDecimalPoint && !Character.isDigit(str.charAt(i))) { + return false; + } + } + return true; + } +} diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java index 1fc98ec67..a1a7daff1 100644 --- a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java @@ -22,6 +22,9 @@ import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_REQUEST_ID; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_VERSION; +import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeArguments; +import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeMDCEntries; +import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeTimestamp; import ch.qos.logback.classic.pattern.ThrowableHandlingConverter; import ch.qos.logback.classic.pattern.ThrowableProxyConverter; @@ -29,9 +32,11 @@ import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.classic.spi.ThrowableProxy; import ch.qos.logback.core.encoder.EncoderBase; +import java.io.IOException; +import java.util.Arrays; import java.util.Map; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; -import software.amazon.lambda.powertools.logging.logback.internal.LambdaEcsSerializer; +import software.amazon.lambda.powertools.logging.internal.JsonSerializer; /** @@ -45,6 +50,29 @@ */ public class LambdaEcsEncoder extends EncoderBase { + protected static final String TIMESTAMP_ATTR_NAME = "@timestamp"; + protected static final String ECS_VERSION_ATTR_NAME = "ecs.version"; + protected static final String LOGGER_ATTR_NAME = "log.logger"; + protected static final String LEVEL_ATTR_NAME = "log.level"; + protected static final String SERVICE_NAME_ATTR_NAME = "service.name"; + protected static final String SERVICE_VERSION_ATTR_NAME = "service.version"; + protected static final String FORMATTED_MESSAGE_ATTR_NAME = "message"; + protected static final String THREAD_ATTR_NAME = "process.thread.name"; + protected static final String EXCEPTION_MSG_ATTR_NAME = "error.message"; + protected static final String EXCEPTION_CLASS_ATTR_NAME = "error.type"; + protected static final String EXCEPTION_STACK_ATTR_NAME = "error.stack_trace"; + protected static final String CLOUD_PROVIDER_ATTR_NAME = "cloud.provider"; + protected static final String CLOUD_REGION_ATTR_NAME = "cloud.region"; + protected static final String CLOUD_ACCOUNT_ATTR_NAME = "cloud.account.id"; + protected static final String CLOUD_SERVICE_ATTR_NAME = "cloud.service.name"; + protected static final String FUNCTION_COLD_START_ATTR_NAME = "faas.coldstart"; + protected static final String FUNCTION_REQUEST_ID_ATTR_NAME = "faas.execution"; + protected static final String FUNCTION_ARN_ATTR_NAME = "faas.id"; + protected static final String FUNCTION_NAME_ATTR_NAME = "faas.name"; + protected static final String FUNCTION_VERSION_ATTR_NAME = "faas.version"; + protected static final String FUNCTION_MEMORY_ATTR_NAME = "faas.memory"; + protected static final String FUNCTION_TRACE_ID_ATTR_NAME = "trace.id"; + protected static final String ECS_VERSION = "1.2.0"; protected static final String CLOUD_PROVIDER = "aws"; protected static final String CLOUD_SERVICE = "lambda"; @@ -56,7 +84,7 @@ public class LambdaEcsEncoder extends EncoderBase { @Override public byte[] headerBytes() { - return null; + return new byte[0]; } /** @@ -65,62 +93,108 @@ public byte[] headerBytes() { * @param event the logging event * @return the encoded bytes */ + + @SuppressWarnings("java:S106") @Override public byte[] encode(ILoggingEvent event) { final Map mdcPropertyMap = event.getMDCPropertyMap(); - StringBuilder builder = new StringBuilder(256); - LambdaEcsSerializer.serializeObjectStart(builder); - LambdaEcsSerializer.serializeTimestamp(builder, event.getTimeStamp(), "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "UTC"); - LambdaEcsSerializer.serializeEcsVersion(builder, ECS_VERSION); - LambdaEcsSerializer.serializeLogLevel(builder, event.getLevel()); - LambdaEcsSerializer.serializeFormattedMessage(builder, event.getFormattedMessage()); - IThrowableProxy throwableProxy = event.getThrowableProxy(); - if (throwableProxy != null) { - if (throwableConverter != null) { - LambdaEcsSerializer.serializeException(builder, throwableProxy.getClassName(), - throwableProxy.getMessage(), throwableConverter.convert(event)); - } else if (throwableProxy instanceof ThrowableProxy) { - LambdaEcsSerializer.serializeException(builder, ((ThrowableProxy) throwableProxy).getThrowable()); - } else { - LambdaEcsSerializer.serializeException(builder, throwableProxy.getClassName(), - throwableProxy.getMessage(), throwableProxyConverter.convert(event)); - } + StringBuilder builder = new StringBuilder(); + try (JsonSerializer serializer = new JsonSerializer(builder)) { + serializer.writeStartObject(); + serializeTimestamp(serializer, event.getTimeStamp(), "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", + "UTC", TIMESTAMP_ATTR_NAME); + serializer.writeRaw(','); + serializer.writeStringField(ECS_VERSION_ATTR_NAME, ECS_VERSION); + serializer.writeRaw(','); + serializer.writeStringField(LEVEL_ATTR_NAME, event.getLevel().toString()); + serializer.writeRaw(','); + serializer.writeStringField(FORMATTED_MESSAGE_ATTR_NAME, event.getFormattedMessage()); + + serializeException(event, serializer); + + serializer.writeRaw(','); + serializer.writeStringField(SERVICE_NAME_ATTR_NAME, LambdaHandlerProcessor.serviceName()); + serializer.writeRaw(','); + serializer.writeStringField(SERVICE_VERSION_ATTR_NAME, mdcPropertyMap.get(FUNCTION_VERSION.getName())); + serializer.writeRaw(','); + serializer.writeStringField(LOGGER_ATTR_NAME, event.getLoggerName()); + serializer.writeRaw(','); + serializer.writeStringField(THREAD_ATTR_NAME, event.getThreadName()); + + String arn = mdcPropertyMap.get(FUNCTION_ARN.getName()); + + serializeCloudInfo(serializer, arn); + + serializeFunctionInfo(serializer, arn, mdcPropertyMap); + + serializeMDCEntries(mdcPropertyMap, serializer); + + serializeArguments(event, serializer); + + serializer.writeEndObject(); + serializer.writeRaw('\n'); + } catch (IOException e) { + System.err.printf("Failed to encode log event, error: %s.%n", e.getMessage()); } - LambdaEcsSerializer.serializeServiceName(builder, LambdaHandlerProcessor.serviceName()); - LambdaEcsSerializer.serializeServiceVersion(builder, mdcPropertyMap.get(FUNCTION_VERSION.getName())); - LambdaEcsSerializer.serializeLoggerName(builder, event.getLoggerName()); - LambdaEcsSerializer.serializeThreadName(builder, event.getThreadName()); - String arn = mdcPropertyMap.get(FUNCTION_ARN.getName()); + return builder.toString().getBytes(UTF_8); + } + + private void serializeFunctionInfo(JsonSerializer serializer, String arn, Map mdcPropertyMap) { + if (includeFaasInfo) { + serializer.writeRaw(','); + serializer.writeStringField(FUNCTION_ARN_ATTR_NAME, arn); + serializer.writeRaw(','); + serializer.writeStringField(FUNCTION_NAME_ATTR_NAME, mdcPropertyMap.get(FUNCTION_NAME.getName())); + serializer.writeRaw(','); + serializer.writeStringField(FUNCTION_VERSION_ATTR_NAME, mdcPropertyMap.get(FUNCTION_VERSION.getName())); + serializer.writeRaw(','); + serializer.writeStringField(FUNCTION_MEMORY_ATTR_NAME, mdcPropertyMap.get(FUNCTION_MEMORY_SIZE.getName())); + serializer.writeRaw(','); + serializer.writeStringField(FUNCTION_REQUEST_ID_ATTR_NAME, mdcPropertyMap.get(FUNCTION_REQUEST_ID.getName())); + serializer.writeRaw(','); + serializer.writeStringField(FUNCTION_COLD_START_ATTR_NAME, mdcPropertyMap.get(FUNCTION_COLD_START.getName())); + serializer.writeRaw(','); + serializer.writeStringField(FUNCTION_TRACE_ID_ATTR_NAME, mdcPropertyMap.get(FUNCTION_TRACE_ID.getName())); + } + } + private void serializeCloudInfo(JsonSerializer serializer, String arn) { if (includeCloudInfo) { - LambdaEcsSerializer.serializeCloudProvider(builder, CLOUD_PROVIDER); - LambdaEcsSerializer.serializeCloudService(builder, CLOUD_SERVICE); + serializer.writeRaw(','); + serializer.writeStringField(CLOUD_PROVIDER_ATTR_NAME, CLOUD_PROVIDER); + serializer.writeRaw(','); + serializer.writeStringField(CLOUD_SERVICE_ATTR_NAME, CLOUD_SERVICE); if (arn != null) { String[] arnParts = arn.split(":"); - LambdaEcsSerializer.serializeCloudRegion(builder, arnParts[3]); - LambdaEcsSerializer.serializeCloudAccountId(builder, arnParts[4]); + serializer.writeRaw(','); + serializer.writeStringField(CLOUD_REGION_ATTR_NAME, arnParts[3]); + serializer.writeRaw(','); + serializer.writeStringField(CLOUD_ACCOUNT_ATTR_NAME, arnParts[4]); } } + } - if (includeFaasInfo) { - LambdaEcsSerializer.serializeFunctionId(builder, arn); - LambdaEcsSerializer.serializeFunctionName(builder, mdcPropertyMap.get(FUNCTION_NAME.getName())); - LambdaEcsSerializer.serializeFunctionVersion(builder, mdcPropertyMap.get(FUNCTION_VERSION.getName())); - LambdaEcsSerializer.serializeFunctionMemory(builder, mdcPropertyMap.get(FUNCTION_MEMORY_SIZE.getName())); - LambdaEcsSerializer.serializeFunctionExecutionId(builder, - mdcPropertyMap.get(FUNCTION_REQUEST_ID.getName())); - LambdaEcsSerializer.serializeColdStart(builder, mdcPropertyMap.get(FUNCTION_COLD_START.getName())); - LambdaEcsSerializer.serializeTraceId(builder, mdcPropertyMap.get(FUNCTION_TRACE_ID.getName())); + private void serializeException(ILoggingEvent event, JsonSerializer serializer) { + IThrowableProxy throwableProxy = event.getThrowableProxy(); + if (throwableProxy != null) { + if (throwableConverter != null) { + serializeException(serializer, throwableProxy.getClassName(), + throwableProxy.getMessage(), throwableConverter.convert(event)); + } else if (throwableProxy instanceof ThrowableProxy) { + Throwable throwable = ((ThrowableProxy) throwableProxy).getThrowable(); + serializeException(serializer, throwable.getClass().getName(), throwable.getMessage(), + Arrays.toString(throwable.getStackTrace())); + } else { + serializeException(serializer, throwableProxy.getClassName(), + throwableProxy.getMessage(), throwableProxyConverter.convert(event)); + } } - LambdaEcsSerializer.serializeAdditionalFields(builder, event.getMDCPropertyMap()); - LambdaEcsSerializer.serializeObjectEnd(builder); - return builder.toString().getBytes(UTF_8); } @Override public byte[] footerBytes() { - return null; + return new byte[0]; } /** @@ -196,4 +270,13 @@ public void setIncludeCloudInfo(boolean includeCloudInfo) { public void setIncludeFaasInfo(boolean includeFaasInfo) { this.includeFaasInfo = includeFaasInfo; } + + private void serializeException(JsonSerializer serializer, String className, String message, String stackTrace) { + serializer.writeRaw(','); + serializer.writeObjectField(EXCEPTION_MSG_ATTR_NAME, message); + serializer.writeRaw(','); + serializer.writeObjectField(EXCEPTION_CLASS_ATTR_NAME, className); + serializer.writeRaw(','); + serializer.writeObjectField(EXCEPTION_STACK_ATTR_NAME, stackTrace); + } } diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaJsonEncoder.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaJsonEncoder.java index b951e266e..9afaf0ab7 100644 --- a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaJsonEncoder.java +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaJsonEncoder.java @@ -15,7 +15,10 @@ package software.amazon.lambda.powertools.logging.logback; import static java.nio.charset.StandardCharsets.UTF_8; -import static software.amazon.lambda.powertools.logging.LoggingUtils.LOG_MESSAGES_AS_JSON; +import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeArguments; +import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeMDCEntries; +import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeMDCEntry; +import static software.amazon.lambda.powertools.logging.logback.JsonUtils.serializeTimestamp; import ch.qos.logback.classic.pattern.ThrowableHandlingConverter; import ch.qos.logback.classic.pattern.ThrowableProxyConverter; @@ -23,25 +26,40 @@ import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.classic.spi.ThrowableProxy; import ch.qos.logback.core.encoder.EncoderBase; -import software.amazon.lambda.powertools.logging.logback.internal.LambdaJsonSerializer; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; +import software.amazon.lambda.powertools.logging.internal.JsonSerializer; +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; /** * Custom encoder for logback that encodes logs in JSON format. - * It does not use a JSON library but a custom serializer ({@link LambdaJsonSerializer}) */ public class LambdaJsonEncoder extends EncoderBase { + protected static final String TIMESTAMP_ATTR_NAME = "timestamp"; + protected static final String LEVEL_ATTR_NAME = "level"; + protected static final String FORMATTED_MESSAGE_ATTR_NAME = "message"; + protected static final String THREAD_ATTR_NAME = "thread"; + protected static final String THREAD_ID_ATTR_NAME = "thread_id"; + protected static final String THREAD_PRIORITY_ATTR_NAME = "thread_priority"; + protected static final String EXCEPTION_MSG_ATTR_NAME = "message"; + protected static final String EXCEPTION_CLASS_ATTR_NAME = "name"; + protected static final String EXCEPTION_STACK_ATTR_NAME = "stack"; + protected static final String EXCEPTION_ATTR_NAME = "error"; + private final ThrowableProxyConverter throwableProxyConverter = new ThrowableProxyConverter(); protected ThrowableHandlingConverter throwableConverter = null; protected String timestampFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; protected String timestampFormatTimezoneId = null; private boolean includeThreadInfo = false; private boolean includePowertoolsInfo = true; - private boolean logMessagesAsJsonGlobal; @Override public byte[] headerBytes() { - return null; + return new byte[0]; } @Override @@ -53,43 +71,83 @@ public void start() { } } + @SuppressWarnings("java:S106") @Override public byte[] encode(ILoggingEvent event) { - StringBuilder builder = new StringBuilder(256); - LambdaJsonSerializer.serializeObjectStart(builder); - LambdaJsonSerializer.serializeLogLevel(builder, event.getLevel()); - LambdaJsonSerializer.serializeFormattedMessage( - builder, - event.getFormattedMessage(), - logMessagesAsJsonGlobal, - event.getMDCPropertyMap().get(LOG_MESSAGES_AS_JSON)); + StringBuilder builder = new StringBuilder(); + try (JsonSerializer serializer = new JsonSerializer(builder)) { + serializer.writeStartObject(); + serializer.writeStringField(LEVEL_ATTR_NAME, event.getLevel().toString()); + serializer.writeRaw(','); + serializer.writeStringField(FORMATTED_MESSAGE_ATTR_NAME, event.getFormattedMessage()); + + serializeException(event, serializer); + + TreeMap sortedMap = new TreeMap<>(event.getMDCPropertyMap()); + serializePowertools(sortedMap, serializer); + + serializeMDCEntries(sortedMap, serializer); + + serializeArguments(event, serializer); + + serializeThreadInfo(event, serializer); + + serializer.writeRaw(','); + serializeTimestamp(serializer, event.getTimeStamp(), + timestampFormat, timestampFormatTimezoneId, TIMESTAMP_ATTR_NAME); + + serializer.writeEndObject(); + serializer.writeRaw('\n'); + } catch (IOException e) { + System.err.printf("Failed to encode log event, error: %s.%n", e.getMessage()); + } + return builder.toString().getBytes(UTF_8); + } + + private void serializeThreadInfo(ILoggingEvent event, JsonSerializer serializer) { + if (includeThreadInfo) { + if (event.getThreadName() != null) { + serializer.writeRaw(','); + serializer.writeStringField(THREAD_ATTR_NAME, event.getThreadName()); + } + serializer.writeRaw(','); + serializer.writeNumberField(THREAD_ID_ATTR_NAME, Thread.currentThread().getId()); + serializer.writeRaw(','); + serializer.writeNumberField(THREAD_PRIORITY_ATTR_NAME, Thread.currentThread().getPriority()); + } + } + + private void serializePowertools(TreeMap sortedMap, JsonSerializer serializer) { + if (includePowertoolsInfo) { + for (Map.Entry entry : sortedMap.entrySet()) { + if (PowertoolsLoggedFields.stringValues().contains(entry.getKey()) + && !(entry.getKey().equals(PowertoolsLoggedFields.SAMPLING_RATE.getName()) && entry.getValue().equals("0.0"))) { + serializeMDCEntry(entry, serializer); + } + } + } + } + + private void serializeException(ILoggingEvent event, JsonSerializer serializer) { IThrowableProxy throwableProxy = event.getThrowableProxy(); if (throwableProxy != null) { if (throwableConverter != null) { - LambdaJsonSerializer.serializeException(builder, throwableProxy.getClassName(), + serializeException(serializer, throwableProxy.getClassName(), throwableProxy.getMessage(), throwableConverter.convert(event)); } else if (throwableProxy instanceof ThrowableProxy) { - LambdaJsonSerializer.serializeException(builder, ((ThrowableProxy) throwableProxy).getThrowable()); + Throwable throwable = ((ThrowableProxy) throwableProxy).getThrowable(); + serializeException(serializer, throwable.getClass().getName(), throwable.getMessage(), + Arrays.toString(throwable.getStackTrace())); } else { - LambdaJsonSerializer.serializeException(builder, throwableProxy.getClassName(), - throwableProxy.getMessage(), throwableProxyConverter.convert(event)); + serializeException(serializer, throwableProxy.getClassName(), throwableProxy.getMessage(), throwableProxyConverter.convert( + event)); } } - LambdaJsonSerializer.serializePowertools(builder, event.getMDCPropertyMap(), includePowertoolsInfo); - if (includeThreadInfo) { - LambdaJsonSerializer.serializeThreadName(builder, event.getThreadName()); - LambdaJsonSerializer.serializeThreadId(builder, String.valueOf(Thread.currentThread().getId())); - LambdaJsonSerializer.serializeThreadPriority(builder, String.valueOf(Thread.currentThread().getPriority())); - } - LambdaJsonSerializer.serializeTimestamp(builder, event.getTimeStamp(), timestampFormat, - timestampFormatTimezoneId); - LambdaJsonSerializer.serializeObjectEnd(builder); - return builder.toString().getBytes(UTF_8); } @Override public byte[] footerBytes() { - return null; + return new byte[0]; } /** @@ -191,18 +249,12 @@ public void setIncludePowertoolsInfo(boolean includePowertoolsInfo) { this.includePowertoolsInfo = includePowertoolsInfo; } - /** - * Specify if messages should be logged as JSON, without escaping string (default is false): - *
- *

{@code
-     *     
-     *         true
-     *     
-     * }
- * - * @param logMessagesAsJson if messages should be looged as JSON (non escaped quotes) - */ - public void setLogMessagesAsJson(boolean logMessagesAsJson) { - this.logMessagesAsJsonGlobal = logMessagesAsJson; + private void serializeException(JsonSerializer serializer, String className, String message, String stackTrace) { + Map map = new HashMap<>(); + map.put(EXCEPTION_MSG_ATTR_NAME, message); + map.put(EXCEPTION_CLASS_ATTR_NAME, className); + map.put(EXCEPTION_STACK_ATTR_NAME, stackTrace); + serializer.writeRaw(','); + serializer.writeObjectField(EXCEPTION_ATTR_NAME, map); } } diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/JsonUtils.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/JsonUtils.java deleted file mode 100644 index e604d10c7..000000000 --- a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/JsonUtils.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging.logback.internal; - -/** - * Json tools to serialize attributes manually, to avoid using further dependencies (jackson, gson...) - */ -public class JsonUtils { - - private JsonUtils() { - // static utils - } - - protected static void serializeAttribute(StringBuilder builder, String attr, String value, boolean notBegin) { - if (value != null) { - if (notBegin) { - builder.append(","); - } - builder.append("\"").append(attr).append("\":"); - boolean isString = isString(value); - if (isString) { - builder.append("\""); - } - builder.append(value); - if (isString) { - builder.append("\""); - } - } - } - - protected static void serializeAttribute(StringBuilder builder, String attr, String value) { - serializeAttribute(builder, attr, value, true); - } - - protected static void serializeMessage(StringBuilder builder, String attr, String value, boolean logAsJson) { - builder.append(","); - builder.append("\"").append(attr).append("\":"); - if (logAsJson) { - builder.append(value); // log JSON without quotes - } else { - builder.append("\""); - builder.append(value.replace("\"", "\\\"")); // escape quotes in string - builder.append("\""); - } - } - - - protected static void serializeAttributeAsString(StringBuilder builder, String attr, String value, - boolean notBegin) { - if (value != null) { - if (notBegin) { - builder.append(","); - } - builder.append("\"") - .append(attr) - .append("\":\"") - .append(value) - .append("\""); - } - } - - protected static void serializeAttributeAsString(StringBuilder builder, String attr, String value) { - serializeAttributeAsString(builder, attr, value, true); - } - - /** - * As MDC is a {@code Map}, we need to check the type - * to output numbers and booleans correctly (without quotes) - */ - private static boolean isString(String str) { - if (str == null) { - return true; - } - if ("true".equals(str) || "false".equals(str)) { - return false; // boolean - } - return !isNumeric(str); // number - } - - /** - * Taken from commons-lang3 NumberUtils to avoid include the library - */ - private static boolean isNumeric(final String str) { - if (str == null || str.isEmpty()) { - return false; - } - if (str.charAt(str.length() - 1) == '.') { - return false; - } - if (str.charAt(0) == '-') { - if (str.length() == 1) { - return false; - } - return withDecimalsParsing(str, 1); - } - return withDecimalsParsing(str, 0); - } - - /** - * Taken from commons-lang3 NumberUtils - */ - private static boolean withDecimalsParsing(final String str, final int beginIdx) { - int decimalPoints = 0; - for (int i = beginIdx; i < str.length(); i++) { - final boolean isDecimalPoint = str.charAt(i) == '.'; - if (isDecimalPoint) { - decimalPoints++; - } - if (decimalPoints > 1) { - return false; - } - if (!isDecimalPoint && !Character.isDigit(str.charAt(i))) { - return false; - } - } - return true; - } -} diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaEcsSerializer.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaEcsSerializer.java deleted file mode 100644 index bab1a32fc..000000000 --- a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaEcsSerializer.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging.logback.internal; - -import ch.qos.logback.classic.Level; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; -import java.util.Map; -import java.util.TimeZone; -import java.util.TreeMap; -import java.util.regex.Matcher; -import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; - -/** - * This class will serialize the log events in ecs format (ElasticSearch).
- *

- * Inspired from the ElasticSearch Serializer co.elastic.logging.EcsJsonSerializer - */ -public class LambdaEcsSerializer { - protected static final String TIMESTAMP_ATTR_NAME = "@timestamp"; - protected static final String ECS_VERSION_ATTR_NAME = "ecs.version"; - protected static final String LOGGER_ATTR_NAME = "log.logger"; - protected static final String LEVEL_ATTR_NAME = "log.level"; - protected static final String SERVICE_NAME_ATTR_NAME = "service.name"; - protected static final String SERVICE_VERSION_ATTR_NAME = "service.version"; - protected static final String SERVICE_ENV_ATTR_NAME = "service.environment"; - protected static final String EVENT_DATASET_ATTR_NAME = "event.dataset"; - protected static final String FORMATTED_MESSAGE_ATTR_NAME = "message"; - protected static final String THREAD_ATTR_NAME = "process.thread.name"; - protected static final String THREAD_ID_ATTR_NAME = "process.thread.id"; - protected static final String EXCEPTION_MSG_ATTR_NAME = "error.message"; - protected static final String EXCEPTION_CLASS_ATTR_NAME = "error.type"; - protected static final String EXCEPTION_STACK_ATTR_NAME = "error.stack_trace"; - protected static final String CLOUD_PROVIDER_ATTR_NAME = "cloud.provider"; - protected static final String CLOUD_REGION_ATTR_NAME = "cloud.region"; - protected static final String CLOUD_ACCOUNT_ATTR_NAME = "cloud.account.id"; - protected static final String CLOUD_SERVICE_ATTR_NAME = "cloud.service.name"; - protected static final String FUNCTION_COLD_START_ATTR_NAME = "faas.coldstart"; - protected static final String FUNCTION_REQUEST_ID_ATTR_NAME = "faas.execution"; - protected static final String FUNCTION_ARN_ATTR_NAME = "faas.id"; - protected static final String FUNCTION_NAME_ATTR_NAME = "faas.name"; - protected static final String FUNCTION_VERSION_ATTR_NAME = "faas.version"; - protected static final String FUNCTION_MEMORY_ATTR_NAME = "faas.memory"; - protected static final String FUNCTION_TRACE_ID_ATTR_NAME = "trace.id"; - - private LambdaEcsSerializer() {} - - public static void serializeObjectStart(StringBuilder builder) { - builder.append('{'); - } - - public static void serializeObjectEnd(StringBuilder builder) { - builder.append("}\n"); - } - - public static void serializeTimestamp(StringBuilder builder, long timestamp, String timestampFormat, - String timestampFormatTimezoneId) { - String formattedTimestamp; - if (timestampFormat == null || timestamp < 0) { - formattedTimestamp = String.valueOf(timestamp); - } else { - Date date = new Date(timestamp); - DateFormat format = new SimpleDateFormat(timestampFormat); - - if (timestampFormatTimezoneId != null) { - TimeZone tz = TimeZone.getTimeZone(timestampFormatTimezoneId); - format.setTimeZone(tz); - } - formattedTimestamp = format.format(date); - } - JsonUtils.serializeAttributeAsString(builder, TIMESTAMP_ATTR_NAME, formattedTimestamp, false); - } - - public static void serializeThreadName(StringBuilder builder, String threadName) { - if (threadName != null) { - JsonUtils.serializeAttributeAsString(builder, THREAD_ATTR_NAME, threadName); - } - } - - public static void serializeLogLevel(StringBuilder builder, Level level) { - JsonUtils.serializeAttributeAsString(builder, LEVEL_ATTR_NAME, level.toString()); - } - - public static void serializeFormattedMessage(StringBuilder builder, String formattedMessage) { - JsonUtils.serializeAttributeAsString(builder, FORMATTED_MESSAGE_ATTR_NAME, - formattedMessage.replace("\"", Matcher.quoteReplacement("\\\""))); - } - - public static void serializeException(StringBuilder builder, String className, String message, String stackTrace) { - JsonUtils.serializeAttributeAsString(builder, EXCEPTION_MSG_ATTR_NAME, message); - JsonUtils.serializeAttributeAsString(builder, EXCEPTION_CLASS_ATTR_NAME, className); - JsonUtils.serializeAttributeAsString(builder, EXCEPTION_STACK_ATTR_NAME, stackTrace); - } - - public static void serializeException(StringBuilder builder, Throwable throwable) { - serializeException(builder, throwable.getClass().getName(), throwable.getMessage(), - Arrays.toString(throwable.getStackTrace())); - } - - public static void serializeThreadId(StringBuilder builder, String threadId) { - JsonUtils.serializeAttributeAsString(builder, THREAD_ID_ATTR_NAME, threadId); - } - - public static void serializeAdditionalFields(StringBuilder builder, Map mdc) { - TreeMap sortedMap = new TreeMap<>(mdc); - - sortedMap.forEach((k, v) -> { - if (!PowertoolsLoggedFields.stringValues().contains(k)) { - JsonUtils.serializeAttributeAsString(builder, k, v); - } - }); - } - - public static void serializeEcsVersion(StringBuilder builder, String ecsVersion) { - JsonUtils.serializeAttributeAsString(builder, ECS_VERSION_ATTR_NAME, ecsVersion); - } - - public static void serializeServiceName(StringBuilder builder, String serviceName) { - JsonUtils.serializeAttributeAsString(builder, SERVICE_NAME_ATTR_NAME, serviceName); - } - - public static void serializeServiceVersion(StringBuilder builder, String serviceVersion) { - JsonUtils.serializeAttributeAsString(builder, SERVICE_VERSION_ATTR_NAME, serviceVersion); - } - - public static void serializeLoggerName(StringBuilder builder, String loggerName) { - JsonUtils.serializeAttributeAsString(builder, LOGGER_ATTR_NAME, loggerName); - } - - public static void serializeCloudProvider(StringBuilder builder, String cloudProvider) { - JsonUtils.serializeAttributeAsString(builder, CLOUD_PROVIDER_ATTR_NAME, cloudProvider); - } - - public static void serializeCloudService(StringBuilder builder, String cloudService) { - JsonUtils.serializeAttributeAsString(builder, CLOUD_SERVICE_ATTR_NAME, cloudService); - } - - public static void serializeCloudRegion(StringBuilder builder, String cloudRegion) { - JsonUtils.serializeAttributeAsString(builder, CLOUD_REGION_ATTR_NAME, cloudRegion); - } - - public static void serializeCloudAccountId(StringBuilder builder, String cloudAccountId) { - JsonUtils.serializeAttributeAsString(builder, CLOUD_ACCOUNT_ATTR_NAME, cloudAccountId); - } - - public static void serializeColdStart(StringBuilder builder, String coldStart) { - JsonUtils.serializeAttributeAsString(builder, FUNCTION_COLD_START_ATTR_NAME, coldStart); - } - - public static void serializeFunctionExecutionId(StringBuilder builder, String requestId) { - JsonUtils.serializeAttributeAsString(builder, FUNCTION_REQUEST_ID_ATTR_NAME, requestId); - } - - public static void serializeFunctionId(StringBuilder builder, String functionArn) { - JsonUtils.serializeAttributeAsString(builder, FUNCTION_ARN_ATTR_NAME, functionArn); - } - - public static void serializeFunctionName(StringBuilder builder, String functionName) { - JsonUtils.serializeAttributeAsString(builder, FUNCTION_NAME_ATTR_NAME, functionName); - } - - public static void serializeFunctionVersion(StringBuilder builder, String functionVersion) { - JsonUtils.serializeAttributeAsString(builder, FUNCTION_VERSION_ATTR_NAME, functionVersion); - } - - public static void serializeFunctionMemory(StringBuilder builder, String functionMemory) { - JsonUtils.serializeAttributeAsString(builder, FUNCTION_MEMORY_ATTR_NAME, functionMemory); - } - - public static void serializeTraceId(StringBuilder builder, String traceId) { - JsonUtils.serializeAttributeAsString(builder, FUNCTION_TRACE_ID_ATTR_NAME, traceId); - } -} diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaJsonSerializer.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaJsonSerializer.java deleted file mode 100644 index 7d7b8d0d7..000000000 --- a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LambdaJsonSerializer.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging.logback.internal; - -import static java.lang.Boolean.TRUE; -import static software.amazon.lambda.powertools.logging.LoggingUtils.LOG_MESSAGES_AS_JSON; - -import ch.qos.logback.classic.Level; -import com.fasterxml.jackson.core.JacksonException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Date; -import java.util.Map; -import java.util.TimeZone; -import java.util.TreeMap; -import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; - -/** - * This class will serialize the log events in json.
- *

- * Inspired from the ElasticSearch Serializer co.elastic.logging.EcsJsonSerializer - */ -public class LambdaJsonSerializer { - protected static final String TIMESTAMP_ATTR_NAME = "timestamp"; - protected static final String LEVEL_ATTR_NAME = "level"; - protected static final String FORMATTED_MESSAGE_ATTR_NAME = "message"; - protected static final String THREAD_ATTR_NAME = "thread"; - protected static final String THREAD_ID_ATTR_NAME = "thread_id"; - protected static final String THREAD_PRIORITY_ATTR_NAME = "thread_priority"; - protected static final String EXCEPTION_MSG_ATTR_NAME = "message"; - protected static final String EXCEPTION_CLASS_ATTR_NAME = "name"; - protected static final String EXCEPTION_STACK_ATTR_NAME = "stack"; - protected static final String EXCEPTION_ATTR_NAME = "error"; - - private LambdaJsonSerializer() {} - - public static void serializeObjectStart(StringBuilder builder) { - builder.append('{'); - } - - public static void serializeObjectEnd(StringBuilder builder) { - builder.append("}\n"); - } - - public static void serializeTimestamp(StringBuilder builder, long timestamp, String timestampFormat, - String timestampFormatTimezoneId) { - String formattedTimestamp; - if (timestampFormat == null || timestamp < 0) { - formattedTimestamp = String.valueOf(timestamp); - } else { - Date date = new Date(timestamp); - DateFormat format = new SimpleDateFormat(timestampFormat); - - if (timestampFormatTimezoneId != null) { - TimeZone tz = TimeZone.getTimeZone(timestampFormatTimezoneId); - format.setTimeZone(tz); - } - formattedTimestamp = format.format(date); - } - JsonUtils.serializeAttribute(builder, TIMESTAMP_ATTR_NAME, formattedTimestamp); - } - - public static void serializeThreadName(StringBuilder builder, String threadName) { - if (threadName != null) { - JsonUtils.serializeAttribute(builder, THREAD_ATTR_NAME, threadName); - } - } - - public static void serializeLogLevel(StringBuilder builder, Level level) { - JsonUtils.serializeAttribute(builder, LEVEL_ATTR_NAME, level.toString(), false); - } - - public static void serializeFormattedMessage(StringBuilder builder, String message, - boolean logMessagesAsJsonGlobal, String logMessagesAsJsonLocal) { - Boolean logMessagesAsJson = null; - if (logMessagesAsJsonLocal != null) { - logMessagesAsJson = Boolean.parseBoolean(logMessagesAsJsonLocal); - } - - boolean logAsJson = ((logMessagesAsJsonGlobal && logMessagesAsJson == null) || TRUE.equals(logMessagesAsJson)) - && isValidJson(message); - JsonUtils.serializeMessage(builder, FORMATTED_MESSAGE_ATTR_NAME, message, logAsJson); - } - - public static void serializeException(StringBuilder builder, String className, String message, String stackTrace) { - builder.append(",\"").append(EXCEPTION_ATTR_NAME).append("\":{"); - JsonUtils.serializeAttribute(builder, EXCEPTION_MSG_ATTR_NAME, message, false); - JsonUtils.serializeAttribute(builder, EXCEPTION_CLASS_ATTR_NAME, className); - JsonUtils.serializeAttribute(builder, EXCEPTION_STACK_ATTR_NAME, stackTrace); - builder.append("}"); - } - - public static void serializeException(StringBuilder builder, Throwable throwable) { - serializeException(builder, throwable.getClass().getName(), throwable.getMessage(), - Arrays.toString(throwable.getStackTrace())); - } - - public static void serializeThreadId(StringBuilder builder, String threadId) { - JsonUtils.serializeAttribute(builder, THREAD_ID_ATTR_NAME, threadId); - } - - public static void serializeThreadPriority(StringBuilder builder, String threadPriority) { - JsonUtils.serializeAttribute(builder, THREAD_PRIORITY_ATTR_NAME, threadPriority); - } - - public static void serializePowertools(StringBuilder builder, Map mdc, - boolean includePowertoolsInfo) { - TreeMap sortedMap = new TreeMap<>(mdc); - sortedMap.forEach((k, v) -> { - if ((includePowertoolsInfo || !PowertoolsLoggedFields.stringValues().contains(k)) // do not log already logged powertools info - && !(k.equals(PowertoolsLoggedFields.SAMPLING_RATE.getName()) && v.equals("0.0")) // do not log sampling rate when 0 - && !LOG_MESSAGES_AS_JSON.equals(k)) // do not log internal keys - { - JsonUtils.serializeAttribute(builder, k, v); - } - }); - - } - - private static final ObjectMapper mapper = new ObjectMapper() - .enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS); - - private static boolean isValidJson(String str) { - if (!(str.startsWith("{") || str.startsWith("["))) { - return false; - } - try { - mapper.readTree(str); - } catch (JacksonException e) { - return false; - } - return true; - } - -} diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index dc8ac429b..638857cb3 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -14,13 +14,13 @@ package software.amazon.lambda.powertools.logging.internal; -import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; +import static java.util.Collections.singletonList; +import static java.util.stream.Collectors.joining; import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.openMocks; -import static software.amazon.lambda.powertools.logging.LoggingUtils.LOG_MESSAGES_AS_JSON; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; @@ -28,11 +28,14 @@ import ch.qos.logback.classic.spi.LoggingEvent; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; @@ -42,7 +45,7 @@ import java.util.Date; import java.util.TimeZone; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -50,10 +53,16 @@ import org.slf4j.LoggerFactory; import org.slf4j.MDC; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; -import software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder; -import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsJsonMessage; +import software.amazon.lambda.powertools.logging.argument.StructuredArgument; +import software.amazon.lambda.powertools.logging.argument.StructuredArguments; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments; import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled; -import software.amazon.lambda.powertools.utilities.JsonConfig; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEvent; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEventDisabled; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEventForStream; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogResponse; +import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogResponseForStream; +import software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder; @Order(2) class LambdaJsonEncoderTest { @@ -62,11 +71,6 @@ class LambdaJsonEncoderTest { @Mock private Context context; - @BeforeAll - private static void init() { - JsonConfig.get().getObjectMapper().setSerializationInclusion(NON_NULL); - } - @BeforeEach void setUp() throws IllegalAccessException, IOException { openMocks(this); @@ -97,13 +101,37 @@ void shouldLogInJsonFormat() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)).contains( - "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":1,\"myKey\":\"myValue\",\"service\":\"testLogback\",\"xray_trace_id\":\"1-63441c4a-abcdef012345678912345678\",\"timestamp\":"); + "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":1,\"service\":\"testLogback\",\"xray_trace_id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\",\"timestamp\":"); + } + + @Test + void shouldLogArgumentsAsJsonWhenUsingRawJson() { + // GIVEN + PowertoolsArguments requestHandler = new PowertoolsArguments(PowertoolsArguments.ArgumentFormat.JSON); + SQSEvent.SQSMessage msg = new SQSEvent.SQSMessage(); + msg.setMessageId("1212abcd"); + msg.setBody("plop"); + msg.setEventSource("eb"); + msg.setAwsRegion("eu-west-1"); + SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); + attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); + msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); + + // WHEN + requestHandler.handleRequest(msg, context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + .contains("\"message\":\"1212abcd\"") + .contains("\"message\":\"Message body = plop and id = \"1212abcd\"\""); } @Test - void shouldLogJsonMessageWithoutEscapedStrings() { + void shouldLogArgumentsAsJsonWhenUsingKeyValue() { // GIVEN - PowertoolsJsonMessage requestHandler = new PowertoolsJsonMessage(); + PowertoolsArguments requestHandler = new PowertoolsArguments(PowertoolsArguments.ArgumentFormat.ENTRY); SQSEvent.SQSMessage msg = new SQSEvent.SQSMessage(); msg.setMessageId("1212abcd"); msg.setBody("plop"); @@ -119,10 +147,9 @@ void shouldLogJsonMessageWithoutEscapedStrings() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"message\":{\"messageId\":\"1212abcd\",\"body\":\"plop\",\"eventSource\":\"eb\",\"awsRegion\":\"eu-west-1\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}}}") + .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") - .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"") - .doesNotContain(LOG_MESSAGES_AS_JSON); + .contains("\"message\":\"Message body = plop and id = \"1212abcd\"\""); } private final LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "message", null, null); @@ -159,10 +186,9 @@ void shouldNotLogPowertoolsInfo() { } @Test - void shouldLogMessagesAsJsonWhenEnabledInLogbackConfig() throws JsonProcessingException { + void shouldLogStructuredArgumentsAsNewEntries() { // GIVEN LambdaJsonEncoder encoder = new LambdaJsonEncoder(); - encoder.setLogMessagesAsJson(true); SQSEvent.SQSMessage msg = new SQSEvent.SQSMessage(); msg.setMessageId("1212abcd"); @@ -172,24 +198,144 @@ void shouldLogMessagesAsJsonWhenEnabledInLogbackConfig() throws JsonProcessingEx SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); + StructuredArgument argument = StructuredArguments.entry("msg", msg); // WHEN - LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, JsonConfig.get().getObjectMapper().writeValueAsString(msg), null, null); + LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, new Object[]{argument}); byte[] encoded = encoder.encode(loggingEvent); String result = new String(encoded, StandardCharsets.UTF_8); // THEN (logged as JSON) assertThat(result) - .contains("\"message\":{\"messageId\":\"1212abcd\",\"body\":\"plop\",\"eventSource\":\"eb\",\"awsRegion\":\"eu-west-1\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}}}"); + .contains("\"message\":\"A message\",\"msg\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}"); + } - // WHEN (disabling logging as json) - encoder.setLogMessagesAsJson(false); - encoded = encoder.encode(loggingEvent); - result = new String(encoded, StandardCharsets.UTF_8); + @Test + void shouldLogEventForHandlerWithLogEventAnnotation() { + // GIVEN + PowertoolsLogEvent requestHandler = new PowertoolsLogEvent(); - // THEN (logged as String) - assertThat(result) - .contains("\"message\":\"{\\\"messageId\\\":\\\"1212abcd\\\",\\\"body\\\":\\\"plop\\\",\\\"eventSource\\\":\\\"eb\\\",\\\"awsRegion\\\":\\\"eu-west-1\\\",\\\"messageAttributes\\\":{\\\"keyAttribute\\\":{\\\"stringListValues\\\":[\\\"val1\\\",\\\"val2\\\",\\\"val3\\\"]}}}\""); + // WHEN + requestHandler.handleRequest(singletonList("ListOfOneElement"), context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("\"event\":[\"ListOfOneElement\"]"); + } + + @Test + void shouldLogEventForHandlerWhenEnvVariableSetToTrue() { + try { + // GIVEN + LoggingConstants.POWERTOOLS_LOG_EVENT = true; + + PowertoolsLogEnabled requestHandler = new PowertoolsLogEnabled(); + + SQSEvent.SQSMessage message = new SQSEvent.SQSMessage(); + message.setBody("body"); + message.setMessageId("1234abcd"); + message.setAwsRegion("eu-west-1"); + + // WHEN + requestHandler.handleRequest(message, context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("\"message\":\"Handler Event\"") + .contains("\"event\":{\"awsRegion\":\"eu-west-1\",\"body\":\"body\",\"messageId\":\"1234abcd\"}"); + } finally { + LoggingConstants.POWERTOOLS_LOG_EVENT = false; + } + } + + @Test + void shouldNotLogEventForHandlerWhenEnvVariableSetToFalse() throws IOException { + // GIVEN + LoggingConstants.POWERTOOLS_LOG_EVENT = false; + + // WHEN + PowertoolsLogEventDisabled requestHandler = new PowertoolsLogEventDisabled(); + requestHandler.handleRequest(singletonList("ListOfOneElement"), context); + + // THEN + Assertions.assertEquals(0, + Files.lines(Paths.get("target/logfile.json")).collect(joining()).length()); + } + + @Test + void shouldLogEventAsStringForStreamHandler() throws IOException { + // GIVEN + PowertoolsLogEventForStream requestStreamHandler = new PowertoolsLogEventForStream(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + + // WHEN + requestStreamHandler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(Collections.singletonMap("key", "value"))), output, context); + + // THEN + assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) + .isNotEmpty(); + + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("\"message\":\"Handler Event\"") + .contains("\"event\":\"{\"key\":\"value\"}\""); // logged as String for StreamHandler + } + + @Test + void shouldLogResponseForHandlerWithLogResponseAnnotation() { + // GIVEN + PowertoolsLogResponse requestHandler = new PowertoolsLogResponse(); + + // WHEN + requestHandler.handleRequest("input", context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("\"message\":\"Handler Response\"") + .contains("\"response\":\"Hola mundo\""); + } + + @Test + void shouldLogResponseForHandlerWhenEnvVariableSetToTrue() { + try { + // GIVEN + LoggingConstants.POWERTOOLS_LOG_RESPONSE = true; + + PowertoolsLogEnabled requestHandler = new PowertoolsLogEnabled(); + + // WHEN + requestHandler.handleRequest("input", context); + + // THEN + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("\"message\":\"Handler Response\"") + .contains("\"response\":\"Bonjour le monde\""); + } finally { + LoggingConstants.POWERTOOLS_LOG_RESPONSE = false; + } + } + + @Test + void shouldLogResponseForStreamHandler() throws IOException { + // GIVEN + PowertoolsLogResponseForStream requestStreamHandler = new PowertoolsLogResponseForStream(); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + String input = "BobThe Sponge"; + + // WHEN + requestStreamHandler.handleRequest(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)), output, context); + + // THEN + assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) + .isEqualTo(input); + + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("\"message\":\"Handler Response\"") + .contains("\"response\":\""+input+"\""); } @Test @@ -238,7 +384,10 @@ void shouldLogException() { String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("\"message\":\"Error\",\"error\":{\"message\":\"Unexpected value\",\"name\":\"java.lang.IllegalStateException\",\"stack\":\"[software.amazon.lambda.powertools.logging.internal.LambdaJsonEncoderTest.shouldLogException"); + assertThat(result).contains("\"message\":\"Error\",\"error\":{") + .contains("\"message\":\"Unexpected value\"") + .contains("\"name\":\"java.lang.IllegalStateException\"") + .contains("\"stack\":\"[software.amazon.lambda.powertools.logging.internal.LambdaJsonEncoderTest.shouldLogException"); // WHEN (configure a custom throwableConverter) encoder = new LambdaJsonEncoder(); @@ -249,7 +398,9 @@ void shouldLogException() { result = new String(encoded, StandardCharsets.UTF_8); // THEN (stack is logged with root cause first) - assertThat(result).contains("\"message\":\"Error\",\"error\":{\"message\":\"Unexpected value\",\"name\":\"java.lang.IllegalStateException\",\"stack\":\"java.lang.IllegalStateException: Unexpected value\n"); + assertThat(result).contains("\"message\":\"Unexpected value\"") + .contains("\"name\":\"java.lang.IllegalStateException\"") + .contains("\"stack\":\"java.lang.IllegalStateException: Unexpected value\n"); } private void setupContext() { diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java similarity index 62% rename from powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java rename to powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java index fdc279319..387074590 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsJsonMessage.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java @@ -14,26 +14,38 @@ package software.amazon.lambda.powertools.logging.internal.handler; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID; + import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.fasterxml.jackson.core.JsonProcessingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; +import software.amazon.lambda.powertools.logging.argument.StructuredArguments; import software.amazon.lambda.powertools.utilities.JsonConfig; -public class PowertoolsJsonMessage implements RequestHandler { - private final Logger LOG = LoggerFactory.getLogger(PowertoolsJsonMessage.class); +public class PowertoolsArguments implements RequestHandler { + private final Logger LOG = LoggerFactory.getLogger(PowertoolsArguments.class); + private final ArgumentFormat argumentFormat; + + public PowertoolsArguments(ArgumentFormat argumentFormat) { + this.argumentFormat = argumentFormat; + } @Override @Logging(clearState = true) public String handleRequest(SQSEvent.SQSMessage input, Context context) { try { - LoggingUtils.logMessagesAsJson(true); - LoggingUtils.setCorrelationId(input.getMessageId()); - LOG.debug(JsonConfig.get().getObjectMapper().writeValueAsString(input)); + MDC.put(CORRELATION_ID.getName(), input.getMessageId()); + if (argumentFormat == ArgumentFormat.JSON) { + LOG.debug("SQS Event", StructuredArguments.json("input", + JsonConfig.get().getObjectMapper().writeValueAsString(input))); + } else { + LOG.debug("SQS Event", StructuredArguments.entry("input", input)); + } LOG.debug("{}", input.getMessageId()); LOG.warn("Message body = {} and id = \"{}\"", input.getBody(), input.getMessageId()); } catch (JsonProcessingException e) { @@ -41,4 +53,8 @@ public String handleRequest(SQSEvent.SQSMessage input, Context context) { } return input.getMessageId(); } + + public enum ArgumentFormat { + JSON, ENTRY + } } diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java index faa722756..e8c0c5851 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java @@ -18,8 +18,8 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; public class PowertoolsLogEnabled implements RequestHandler { private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogEnabled.class); @@ -27,8 +27,8 @@ public class PowertoolsLogEnabled implements RequestHandler { @Override @Logging(clearState = true) public Object handleRequest(Object input, Context context) { - LoggingUtils.appendKey("myKey", "myValue"); + MDC.put("myKey", "myValue"); LOG.debug("Test debug event"); - return null; + return "Bonjour le monde"; } } diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEvent.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEvent.java new file mode 100644 index 000000000..14a7874cb --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEvent.java @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal.handler; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogEvent implements RequestHandler { + + @Override + @Logging(logEvent = true) + public Object handleRequest(Object input, Context context) { + return null; + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventDisabled.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEventDisabled.java similarity index 90% rename from powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventDisabled.java rename to powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEventDisabled.java index fc1feb52d..8171bee3e 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventDisabled.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEventDisabled.java @@ -12,7 +12,7 @@ * */ -package software.amazon.lambda.powertools.logging.handlers; +package software.amazon.lambda.powertools.logging.internal.handler; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; @@ -20,8 +20,8 @@ public class PowertoolsLogEventDisabled implements RequestHandler { - @Logging @Override + @Logging(logEvent = false) public Object handleRequest(Object input, Context context) { return null; } diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEventForStream.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEventForStream.java new file mode 100644 index 000000000..443051204 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEventForStream.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal.handler; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogEventForStream implements RequestStreamHandler { + + @Override + @Logging(logEvent = true) + public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(outputStream, mapper.readValue(inputStream, Map.class)); + } +} diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogResponse.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogResponse.java new file mode 100644 index 000000000..5cbeef487 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogResponse.java @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal.handler; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogResponse implements RequestHandler { + + @Override + @Logging(logResponse = true) + public Object handleRequest(Object input, Context context) { + return "Hola mundo"; + } +} diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogResponseForStream.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogResponseForStream.java new file mode 100644 index 000000000..3378b9421 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogResponseForStream.java @@ -0,0 +1,35 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal.handler; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogResponseForStream implements RequestStreamHandler { + + @Override + @Logging(logResponse = true) + public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { + byte[] buf = new byte[1024]; + int length; + while ((length = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, length); + } + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java index 05a9cfe31..9e5e735d1 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java @@ -57,7 +57,8 @@ *

By default {@code Logging} will not log the event which has trigger the invoke of the Lambda function. * This can be enabled using {@code @Logging(logEvent = true)}.

* - *

To append additional keys to each log entry you can use {@link LoggingUtils#appendKey(String, String)}

+ *

To append additional keys to each log entry you can either use {@link org.slf4j.MDC#put(String, String)} + * or {@link software.amazon.lambda.powertools.logging.argument.StructuredArguments}

*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java deleted file mode 100644 index d7ceb8ccd..000000000 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/LoggingUtils.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging; - -import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID; - -import com.fasterxml.jackson.databind.ObjectMapper; -import java.util.Arrays; -import java.util.Map; -import org.slf4j.MDC; -import software.amazon.lambda.powertools.utilities.JsonConfig; - -/** - * A class of helper functions to add functionality to Logging. - * Adding/removing keys is based on MDC, which is ThreadSafe. - */ -public final class LoggingUtils { - - public static final String LOG_MESSAGES_AS_JSON = "PowertoolsLogMessagesAsJson"; - - private static ObjectMapper objectMapper; - - private LoggingUtils() { - } - - /** - * Appends an additional key and value to each log entry made. Duplicate values - * for the same key will be replaced with the latest. - * - * @param key The name of the key to be logged - * @param value The value to be logged - */ - public static void appendKey(String key, String value) { - MDC.put(key, value); - } - - - /** - * Appends additional key and value to each log entry made. Duplicate values - * for the same key will be replaced with the latest. - * - * @param customKeys Map of custom keys values to be appended to logs - */ - public static void appendKeys(Map customKeys) { - customKeys.forEach(MDC::put); - } - - /** - * Remove an additional key from log entry. - * - * @param customKey The name of the key to be logged - */ - public static void removeKey(String customKey) { - MDC.remove(customKey); - } - - - /** - * Removes additional keys from log entry. - * - * @param keys Map of custom keys values to be appended to logs - */ - public static void removeKeys(String... keys) { - Arrays.stream(keys).forEach(MDC::remove); - } - - /** - * Sets correlation id attribute on the logs. - * - * @param value The value of the correlation id - */ - public static void setCorrelationId(String value) { - MDC.put(CORRELATION_ID.getName(), value); - } - - /** - * Get correlation id attribute. Maybe null. - * @return correlation id set `@Logging(correlationIdPath="JMESPATH Expression")` or `LoggingUtils.setCorrelationId("value")` - */ - public static String getCorrelationId() { - return MDC.get(CORRELATION_ID.getName()); - } - - /** - * When set to true, will log messages as JSON (without escaping string). - * Useful to log events or big JSON objects. - * @param value boolean to specify if yes or no messages should be logged as JSON (default is false) - */ - public static void logMessagesAsJson(boolean value) { - MDC.put(LOG_MESSAGES_AS_JSON, String.valueOf(value)); - } - - /** - * Sets the instance of ObjectMapper object which is used for serialising event when - * {@code @Logging(logEvent = true, logResponse = true)}. - * - * Not Thread Safe, the object mapper is static, changing it in different threads can lead to unexpected behaviour - * - * @param objectMapper Custom implementation of object mapper to be used for logging serialised event - */ - public static void setObjectMapper(ObjectMapper objectMapper) { - LoggingUtils.objectMapper = objectMapper; - } - - public static ObjectMapper getObjectMapper() { - if (LoggingUtils.objectMapper == null) { - LoggingUtils.objectMapper = JsonConfig.get().getObjectMapper(); - } - return LoggingUtils.objectMapper; - } -} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/ArrayArgument.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/ArrayArgument.java new file mode 100644 index 000000000..28b29146e --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/ArrayArgument.java @@ -0,0 +1,43 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.argument; + +import java.util.Objects; +import software.amazon.lambda.powertools.logging.internal.JsonSerializer; + +/** + * See {@link StructuredArguments#array(String, Object...)} + */ +public class ArrayArgument implements StructuredArgument { + private final String key; + private final Object[] values; + + public ArrayArgument(String key, Object[] values) { + this.key = Objects.requireNonNull(key, "Key must not be null"); + this.values = new Object[values.length]; + System.arraycopy(values, 0, this.values, 0, values.length); + } + + @Override + public void writeTo(JsonSerializer serializer) { + serializer.writeFieldName(key); + serializer.writeObject(values); + } + + @Override + public String toString() { + return key + "=" + StructuredArguments.toString(values); + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/JsonArgument.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/JsonArgument.java new file mode 100644 index 000000000..e14f23788 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/JsonArgument.java @@ -0,0 +1,42 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.argument; + +import java.util.Objects; +import software.amazon.lambda.powertools.logging.internal.JsonSerializer; + +/** + * See {@link StructuredArguments#json(String, String)} + */ +public class JsonArgument implements StructuredArgument { + private final String key; + private final String rawJson; + + public JsonArgument(String key, String rawJson) { + this.key = Objects.requireNonNull(key, "key must not be null"); + this.rawJson = Objects.requireNonNull(rawJson, "rawJson must not be null"); + } + + @Override + public void writeTo(JsonSerializer serializer) { + serializer.writeFieldName(key); + serializer.writeRaw(rawJson); + } + + @Override + public String toString() { + return key + "=" + rawJson; + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/KeyValueArgument.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/KeyValueArgument.java new file mode 100644 index 000000000..569667419 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/KeyValueArgument.java @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.argument; + +import java.util.Objects; +import software.amazon.lambda.powertools.logging.internal.JsonSerializer; + +/** + * See {@link StructuredArguments#entry(String, Object)} + */ +public class KeyValueArgument implements StructuredArgument { + private final String key; + private final Object value; + + public KeyValueArgument(String key, Object value) { + this.key = Objects.requireNonNull(key, "Key must not be null"); + this.value = value; + } + + @Override + public void writeTo(JsonSerializer serializer) { + serializer.writeObjectField(key, value); + } + + @Override + public String toString() { + return key + "=" + StructuredArguments.toString(value); + } + + public String getKey() { + return key; + } + + public Object getValue() { + return value; + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/MapArgument.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/MapArgument.java new file mode 100644 index 000000000..9a06ea095 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/MapArgument.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.argument; + +import java.util.HashMap; +import java.util.Map; +import software.amazon.lambda.powertools.logging.internal.JsonSerializer; + +/** + * See {@link StructuredArguments#entries(Map)} + */ +public class MapArgument implements StructuredArgument { + private final Map map; + + public MapArgument(Map map) { + if (map != null) { + this.map = new HashMap<>(map); + } else { + this.map = null; + } + } + + @Override + public void writeTo(JsonSerializer serializer) { + if (map != null) { + for (Map.Entry entry : map.entrySet()) { + serializer.writeObjectField(String.valueOf(entry.getKey()), entry.getValue()); + } + } + } + + @Override + public String toString() { + return String.valueOf(map); + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArgument.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArgument.java new file mode 100644 index 000000000..21fea068d --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArgument.java @@ -0,0 +1,45 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.argument; + +import java.io.IOException; +import org.slf4j.Logger; +import software.amazon.lambda.powertools.logging.internal.JsonSerializer; + +/** + * A wrapper for an argument passed to a log method (e.g. {@link Logger#info(String, Object...)}) + * that adds data to the JSON event. + */ +public interface StructuredArgument { + /** + * Writes the data associated with this argument to the given {@link JsonSerializer}. + * + * @param serializer the {@link JsonSerializer} to produce JSON content + * @throws IOException if an I/O error occurs + */ + void writeTo(JsonSerializer serializer) throws IOException; + + /** + * Writes the data associated with this argument to a {@link String} to be + * included in a log event's formatted message (via parameter substitution). + *

+ * Note that this will only be included in the log event's formatted + * message if the message format includes a parameter for this argument (using {}). + * + * @return String representation of the data associated with this argument + */ + String toString(); + +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArguments.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArguments.java new file mode 100644 index 000000000..8a75b3118 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArguments.java @@ -0,0 +1,129 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.argument; + +import java.util.Arrays; +import java.util.Map; + +/** + * Factory for creating {@link StructuredArgument}s. + * Inspired from the StructuredArgument of logstash-logback-encoder. + */ +public class StructuredArguments { + + private StructuredArguments() { + // nothing to do, use static methods only + } + + /** + * Adds "key": "value" to the JSON structure and "key=value" to the formatted message. + * + * @param key the field name + * @param value the value associated with the key (can be any kind of object) + * @return a {@link StructuredArgument} populated with the data + */ + public static StructuredArgument entry(String key, Object value) { + return new KeyValueArgument(key, value); + } + + /** + * Adds a "key": "value" to the JSON structure for each entry in the map + * and {@code map.toString()} to the formatted message. + * + * @param map {@link Map} holding the key/value pairs + * @return a {@link MapArgument} populated with the data + */ + public static StructuredArgument entries(Map map) { + return new MapArgument(map); + } + + /** + * Adds a field to the JSON structure with key as the key and where value + * is a JSON array of objects AND a string version of the array to the formatted message: + * {@code "key": [value, value]} + * + * @param key the field name + * @param values elements of the array associated with the key + * @return an {@link ArrayArgument} populated with the data + */ + public static StructuredArgument array(String key, Object... values) { + return new ArrayArgument(key, values); + } + + /** + * Adds the {@code rawJson} to the JSON structure and + * the {@code rawJson} to the formatted message. + * + * @param key the field name + * @param rawJson the raw JSON String + * @return a {@link JsonArgument} populated with the data + */ + public static StructuredArgument json(String key, String rawJson) { + return new JsonArgument(key, rawJson); + } + + /** + * Format the argument into a string. + * + * This method mimics the slf4j behavior: + * array objects are formatted as array using {@link Arrays#toString}, + * non array object using {@link String#valueOf}. + * + *

See org.slf4j.helpers.MessageFormatter#deeplyAppendParameter(StringBuilder, Object, Map)} + * + * @param arg the argument to format + * @return formatted string version of the argument + */ + @SuppressWarnings("java:S106") + public static String toString(Object arg) { + + if (arg == null) { + return "null"; + } + + Class argClass = arg.getClass(); + + try { + if (!argClass.isArray()) { + return String.valueOf(arg); + } else { + if (argClass == byte[].class) { + return Arrays.toString((byte[]) arg); + } else if (argClass == short[].class) { + return Arrays.toString((short[]) arg); + } else if (argClass == int[].class) { + return Arrays.toString((int[]) arg); + } else if (argClass == long[].class) { + return Arrays.toString((long[]) arg); + } else if (argClass == char[].class) { + return Arrays.toString((char[]) arg); + } else if (argClass == float[].class) { + return Arrays.toString((float[]) arg); + } else if (argClass == double[].class) { + return Arrays.toString((double[]) arg); + } else if (argClass == boolean[].class) { + return Arrays.toString((boolean[]) arg); + } else { + return Arrays.deepToString((Object[]) arg); + } + } + + } catch (Exception e) { + System.err.println("Failed toString() invocation on an object of type [" + argClass.getName() + "]"); + return "[FAILED toString()]"; + } + } + +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java new file mode 100644 index 000000000..0b4359825 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java @@ -0,0 +1,599 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import com.fasterxml.jackson.core.TreeNode; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.BooleanNode; +import com.fasterxml.jackson.databind.node.MissingNode; +import com.fasterxml.jackson.databind.node.NullNode; +import com.fasterxml.jackson.databind.node.NumericNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.node.POJONode; +import com.fasterxml.jackson.databind.node.TextNode; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import software.amazon.lambda.powertools.utilities.JsonConfig; + +/** + * A simple JSON serializer. + * Used internally for json serialization, not to be used externally. + * We do not use Jackson as we need to serialize each fields of the log event individually. + * Mainly used by logback as log4j is using its own JsonWriter + */ +public class JsonSerializer implements AutoCloseable { + + private final StringBuilder builder; + + public JsonSerializer(StringBuilder builder) { + super(); + if (builder == null) { + throw new IllegalArgumentException("StringBuilder cannot be null"); + } + this.builder = builder; + } + + public void writeStartArray() { + builder.append('['); + } + + public void writeEndArray() { + builder.append(']'); + } + + public void writeStartObject() { + builder.append('{'); + } + + public void writeEndObject() { + builder.append('}'); + } + + public void writeSeparator() { + writeRaw(','); + } + + public void writeFieldName(String name) { + Objects.requireNonNull(name, "field name must not be null"); + writeString(name); + writeRaw(':'); + } + + public void writeString(String text) { + if (text == null) { + writeNull(); + } else { + builder.append("\"").append(text).append("\""); + } + } + + public void writeRaw(String text) { + builder.append(text); + } + + public void writeRaw(char c) { + builder.append(c); + } + + public void writeNumber(short v) { + builder.append(v); + } + + public void writeNumber(int v) { + builder.append(v); + } + + public void writeNumber(long v) { + builder.append(v); + } + + public void writeNumber(BigInteger v) { + builder.append(v); + } + + public void writeNumber(double v) { + builder.append(v); + } + + public void writeNumber(float v) { + builder.append(v); + } + + public void writeNumber(BigDecimal v) { + builder.append(v.toPlainString()); + } + + public void writeBoolean(boolean state) { + builder.append(state); + } + + public void writeArray(final char[] items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + for (int itemIndex = 0; itemIndex < items.length; itemIndex++) { + if (itemIndex > 0) { + writeSeparator(); + } + builder.append('\''); + builder.append(items[itemIndex]); + builder.append('\''); + } + writeEndArray(); + } + } + + public void writeArray(final boolean[] items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + for (int itemIndex = 0; itemIndex < items.length; itemIndex++) { + if (itemIndex > 0) { + writeSeparator(); + } + final boolean item = items[itemIndex]; + writeBoolean(item); + } + writeEndArray(); + } + } + + public void writeArray(final byte[] items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + for (int itemIndex = 0; itemIndex < items.length; itemIndex++) { + if (itemIndex > 0) { + writeSeparator(); + } + final byte item = items[itemIndex]; + writeNumber(item); + } + writeEndArray(); + } + } + + public void writeArray(final short[] items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + for (int itemIndex = 0; itemIndex < items.length; itemIndex++) { + if (itemIndex > 0) { + writeSeparator(); + } + final short item = items[itemIndex]; + writeNumber(item); + } + writeEndArray(); + } + } + + public void writeArray(final int[] items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + for (int itemIndex = 0; itemIndex < items.length; itemIndex++) { + if (itemIndex > 0) { + writeSeparator(); + } + final int item = items[itemIndex]; + writeNumber(item); + } + writeEndArray(); + } + } + + public void writeArray(final long[] items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + for (int itemIndex = 0; itemIndex < items.length; itemIndex++) { + if (itemIndex > 0) { + writeSeparator(); + } + final long item = items[itemIndex]; + writeNumber(item); + } + writeEndArray(); + } + } + + public void writeArray(final float[] items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + for (int itemIndex = 0; itemIndex < items.length; itemIndex++) { + if (itemIndex > 0) { + writeSeparator(); + } + final float item = items[itemIndex]; + writeNumber(item); + } + writeEndArray(); + } + } + + public void writeArray(final double[] items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + for (int itemIndex = 0; itemIndex < items.length; itemIndex++) { + if (itemIndex > 0) { + writeSeparator(); + } + final double item = items[itemIndex]; + writeNumber(item); + } + writeEndArray(); + } + } + + public void writeArray(final Object[] items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + for (int itemIndex = 0; itemIndex < items.length; itemIndex++) { + if (itemIndex > 0) { + writeSeparator(); + } + final Object item = items[itemIndex]; + writeObject(item); + } + writeEndArray(); + } + } + + public void writeNull() { + builder.append("null"); + } + + public void writeArray(final List items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + for (int itemIndex = 0; itemIndex < items.size(); itemIndex++) { + if (itemIndex > 0) { + writeSeparator(); + } + final Object item = items.get(itemIndex); + writeObject(item); + } + writeEndArray(); + } + } + + public void writeArray(final Collection items) { + if (items == null) { + writeNull(); + } else { + writeStartArray(); + Iterator iterator = items.iterator(); + while (iterator.hasNext()) { + writeObject(iterator.next()); + if (iterator.hasNext()) { + writeSeparator(); + } + } + writeEndArray(); + } + } + + public void writeMap(final Map map) { + if (map == null) { + writeNull(); + } else { + writeStartObject(); + for (Iterator> entries = map.entrySet().iterator(); entries.hasNext(); ) { + Map.Entry entry = entries.next(); + writeObjectField(String.valueOf(entry.getKey()), entry.getValue()); + if (entries.hasNext()) { + builder.append(','); + } + } + writeEndObject(); + } + } + + public void writeObject(Object value) { + + // null + if (value == null) { + writeNull(); + } + + else if (value instanceof String) { + writeString((String) value); + } + + // number & boolean + else if (value instanceof Number) { + Number n = (Number) value; + if (n instanceof Integer) { + writeNumber(n.intValue()); + } else if (n instanceof Long) { + writeNumber(n.longValue()); + } else if (n instanceof Double) { + writeNumber(n.doubleValue()); + } else if (n instanceof Float) { + writeNumber(n.floatValue()); + } else if (n instanceof Short) { + writeNumber(n.shortValue()); + } else if (n instanceof Byte) { + writeNumber(n.byteValue()); + } else if (n instanceof BigInteger) { + writeNumber((BigInteger) n); + } else if (n instanceof BigDecimal) { + writeNumber((BigDecimal) n); + } else if (n instanceof AtomicInteger) { + writeNumber(((AtomicInteger) n).get()); + } else if (n instanceof AtomicLong) { + writeNumber(((AtomicLong) n).get()); + } + } else if (value instanceof Boolean) { + writeBoolean((Boolean) value); + } else if (value instanceof AtomicBoolean) { + writeBoolean(((AtomicBoolean) value).get()); + } + + // list & collection + else if (value instanceof List) { + final List list = (List) value; + writeArray(list); + } else if (value instanceof Collection) { + final Collection collection = (Collection) value; + writeArray(collection); + } + + // map + else if (value instanceof Map) { + final Map map = (Map) value; + writeMap(map); + } + + + // arrays + else if (value instanceof char[]) { + final char[] charValues = (char[]) value; + writeArray(charValues); + } else if (value instanceof boolean[]) { + final boolean[] booleanValues = (boolean[]) value; + writeArray(booleanValues); + } else if (value instanceof byte[]) { + final byte[] byteValues = (byte[]) value; + writeArray(byteValues); + } else if (value instanceof short[]) { + final short[] shortValues = (short[]) value; + writeArray(shortValues); + } else if (value instanceof int[]) { + final int[] intValues = (int[]) value; + writeArray(intValues); + } else if (value instanceof long[]) { + final long[] longValues = (long[]) value; + writeArray(longValues); + } else if (value instanceof float[]) { + final float[] floatValues = (float[]) value; + writeArray(floatValues); + } else if (value instanceof double[]) { + final double[] doubleValues = (double[]) value; + writeArray(doubleValues); + } else if (value instanceof Object[]) { + final Object[] values = (Object[]) value; + writeArray(values); + } + + else if (value instanceof JsonNode) { + JsonNode node = (JsonNode) value; + + switch (node.getNodeType()) { + case NULL: + case MISSING: + writeNull(); + break; + + case STRING: + writeString(node.asText()); + break; + + case BOOLEAN: + writeBoolean(node.asBoolean()); + break; + + case NUMBER: + if (node.isInt()) { + writeNumber(node.intValue()); + break; + } + if (node.isLong()) { + writeNumber(node.longValue()); + break; + } + if (node.isShort()) { + writeNumber(node.shortValue()); + break; + } + if (node.isDouble()) { + writeNumber(node.doubleValue()); + break; + } + if (node.isFloat()) { + writeNumber(node.floatValue()); + break; + } + if (node.isBigDecimal()) { + writeNumber(node.decimalValue()); + break; + } + if (node.isBigInteger()) { + writeNumber(node.bigIntegerValue()); + break; + } + break; + case OBJECT: + case POJO: + writeStartObject(); + for (Iterator> entries = node.fields(); entries.hasNext(); ) { + Map.Entry entry = entries.next(); + writeObjectField(entry.getKey(), entry.getValue()); + if (entries.hasNext()) { + builder.append(','); + } + } + writeEndObject(); + return; + + case ARRAY: + ArrayNode arrayNode = (ArrayNode) node; + writeStartArray(); + for (Iterator elements = arrayNode.elements(); elements.hasNext(); ) { + writeObject(elements.next()); + if (elements.hasNext()) { + builder.append(','); + } + } + writeEndArray(); + return; + + default: + break; + } + } else { + try { + // default: try to write object as JSON + writeRaw(JsonConfig.get().getObjectMapper().writeValueAsString(value)); + } catch (Exception e) { + // last chance: toString + writeString(value.toString()); + } + } + } + + public void writeObjectField(String key, Object value) { + writeFieldName(key); + writeObject(value); + } + + public void writeBooleanField(String key, boolean value) { + writeFieldName(key); + writeBoolean(value); + } + + public void writeNullField(String key) { + writeFieldName(key); + writeNull(); + } + + public void writeNumberField(String key, int value) { + writeFieldName(key); + writeNumber(value); + } + + public void writeNumberField(String key, float value) { + writeFieldName(key); + writeNumber(value); + } + + public void writeNumberField(String key, short value) { + writeFieldName(key); + writeNumber(value); + } + + public void writeNumberField(String key, long value) { + writeFieldName(key); + writeNumber(value); + } + + public void writeNumberField(String key, BigInteger value) { + writeFieldName(key); + writeNumber(value); + } + + public void writeNumberField(String key, double value) { + writeFieldName(key); + writeNumber(value); + } + + public void writeNumberField(String key, BigDecimal value) { + writeFieldName(key); + writeNumber(value); + } + + public void writeStringField(String key, String value) { + writeFieldName(key); + writeString(value); + } + + public void writeTree(TreeNode rootNode) { + if (rootNode == null) { + writeNull(); + } else if (rootNode instanceof TextNode) { + writeString(((TextNode) rootNode).asText()); + } else if (rootNode instanceof BooleanNode) { + writeBoolean(((BooleanNode) rootNode).asBoolean()); + } else if (rootNode instanceof NumericNode) { + NumericNode numericNode = (NumericNode) rootNode; + if (numericNode.isInt()) { + writeNumber(numericNode.intValue()); + } else if (numericNode.isLong()) { + writeNumber(numericNode.longValue()); + } else if (numericNode.isShort()) { + writeNumber(numericNode.shortValue()); + } else if (numericNode.isDouble()) { + writeNumber(numericNode.doubleValue()); + } else if (numericNode.isFloat()) { + writeNumber(numericNode.floatValue()); + } else if (numericNode.isBigDecimal()) { + writeNumber(numericNode.decimalValue()); + } else if (numericNode.isBigInteger()) { + writeNumber(numericNode.bigIntegerValue()); + } + } else if (rootNode instanceof ArrayNode) { + ArrayNode arrayNode = (ArrayNode) rootNode; + writeObject(arrayNode); + } else if (rootNode instanceof ObjectNode) { + ObjectNode objectNode = (ObjectNode) rootNode; + writeObject(objectNode); + } else if (rootNode instanceof NullNode || rootNode instanceof MissingNode) { + writeNull(); + } else if (rootNode instanceof POJONode) { + writeObject(((POJONode) rootNode).getPojo()); + } + } + + @Override + public void close() { + // nothing to do + } +} + + diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java index 48f67700d..eccfdae4f 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java @@ -15,8 +15,6 @@ package software.amazon.lambda.powertools.logging.internal; import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.Optional.empty; -import static java.util.Optional.ofNullable; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.coldStartDone; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.extractContext; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; @@ -25,20 +23,19 @@ import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnRequestHandler; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnStreamHandler; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.serviceName; -import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKey; -import static software.amazon.lambda.powertools.logging.LoggingUtils.appendKeys; +import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.LAMBDA_LOG_LEVEL; import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_ERROR; import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_EVENT; import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_LEVEL; import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_RESPONSE; import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_SAMPLING_RATE; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SERVICE; import com.amazonaws.services.lambda.runtime.Context; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import io.burt.jmespath.Expression; import java.io.ByteArrayInputStream; @@ -54,7 +51,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Optional; import java.util.Random; import java.util.ServiceLoader; import org.aspectj.lang.ProceedingJoinPoint; @@ -68,7 +64,6 @@ import org.slf4j.MarkerFactory; import org.slf4j.event.Level; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; import software.amazon.lambda.powertools.utilities.JsonConfig; @@ -188,8 +183,9 @@ public Object around(ProceedingJoinPoint pjp, addLambdaContextToLoggingContext(pjp); - getXrayTraceId().ifPresent(xRayTraceId -> appendKey(FUNCTION_TRACE_ID.getName(), xRayTraceId)); + getXrayTraceId().ifPresent(xRayTraceId -> MDC.put(FUNCTION_TRACE_ID.getName(), xRayTraceId)); + // Log Event Object[] proceedArgs = logEvent(pjp, logging, isOnRequestHandler, isOnRequestStreamHandler); if (!logging.correlationIdPath().isEmpty()) { @@ -210,6 +206,7 @@ public Object around(ProceedingJoinPoint pjp, Object lambdaFunctionResponse; try { + // Call Function Handler lambdaFunctionResponse = pjp.proceed(proceedArgs); } catch (Throwable t) { if (logging.logError() || POWERTOOLS_LOG_ERROR) { @@ -224,6 +221,7 @@ public Object around(ProceedingJoinPoint pjp, coldStartDone(); } + // Log Response if ((logging.logResponse() || POWERTOOLS_LOG_RESPONSE)) { if (isOnRequestHandler) { logRequestHandlerResponse(pjp, lambdaFunctionResponse); @@ -255,9 +253,9 @@ private void addLambdaContextToLoggingContext(ProceedingJoinPoint pjp) { Context extractedContext = extractContext(pjp); if (extractedContext != null) { - appendKeys(PowertoolsLoggedFields.setValuesFromLambdaContext(extractedContext)); - appendKey(FUNCTION_COLD_START.getName(), isColdStart() ? "true" : "false"); - appendKey(SERVICE.getName(), serviceName()); + PowertoolsLoggedFields.setValuesFromLambdaContext(extractedContext).forEach(MDC::put); + MDC.put(FUNCTION_COLD_START.getName(), isColdStart() ? "true" : "false"); + MDC.put(SERVICE.getName(), serviceName()); } } @@ -273,7 +271,7 @@ private void setLogLevelBasedOnSamplingRate(final ProceedingJoinPoint pjp, return; } - appendKey(PowertoolsLoggedFields.SAMPLING_RATE.getName(), String.valueOf(samplingRate)); + MDC.put(PowertoolsLoggedFields.SAMPLING_RATE.getName(), String.valueOf(samplingRate)); if (samplingRate == 0) { return; @@ -305,49 +303,45 @@ private double samplingRate(final Logging logging) { return logging.samplingRate(); } + @SuppressWarnings("java:S3457") private void logRequestHandlerEvent(final ProceedingJoinPoint pjp, final Object event) { Logger log = logger(pjp); if (log.isInfoEnabled()) { - LoggingUtils.logMessagesAsJson(true); - asJson(event).ifPresent(log::info); - LoggingUtils.logMessagesAsJson(false); + log.info("Handler Event", entry("event", event)); } } + @SuppressWarnings("java:S3457") private Object[] logRequestStreamHandlerEvent(final ProceedingJoinPoint pjp) { Object[] args = pjp.getArgs(); Logger log = logger(pjp); if (log.isInfoEnabled()) { - LoggingUtils.logMessagesAsJson(true); try { byte[] bytes = bytesFromInputStreamSafely((InputStream) pjp.getArgs()[0]); args[0] = new ByteArrayInputStream(bytes); // do not log asJson as it can be something else (String, XML...) - log.info("{}", new String(bytes, UTF_8)); + log.info("Handler Event", entry("event", new String(bytes, UTF_8))); } catch (IOException e) { LOG.warn("Failed to log event from supplied input stream.", e); } - LoggingUtils.logMessagesAsJson(false); } return args; } + @SuppressWarnings("java:S3457") private void logRequestHandlerResponse(final ProceedingJoinPoint pjp, final Object response) { Logger log = logger(pjp); if (log.isInfoEnabled()) { - LoggingUtils.logMessagesAsJson(true); - asJson(response).ifPresent(log::info); - LoggingUtils.logMessagesAsJson(false); + log.info("Handler Response", entry("response", response)); } } + @SuppressWarnings("java:S3457") private void logRequestStreamHandlerResponse(final ProceedingJoinPoint pjp, final byte[] bytes) { Logger log = logger(pjp); if (log.isInfoEnabled()) { - LoggingUtils.logMessagesAsJson(true); // we do not log with asJson as it can be something else (String, XML, ...) - log.info("{}", new String(bytes, UTF_8)); - LoggingUtils.logMessagesAsJson(false); + log.info("Handler Response", entry("response", new String(bytes, UTF_8))); } } @@ -356,12 +350,12 @@ private void captureCorrelationId(final String correlationIdPath, final boolean isOnRequestHandler, final boolean isOnRequestStreamHandler) { if (isOnRequestHandler) { - JsonNode jsonNode = LoggingUtils.getObjectMapper().valueToTree(proceedArgs[0]); + JsonNode jsonNode = JsonConfig.get().getObjectMapper().valueToTree(proceedArgs[0]); setCorrelationIdFromNode(correlationIdPath, jsonNode); } else if (isOnRequestStreamHandler) { try { byte[] bytes = bytesFromInputStreamSafely((InputStream) proceedArgs[0]); - JsonNode jsonNode = LoggingUtils.getObjectMapper().readTree(bytes); + JsonNode jsonNode = JsonConfig.get().getObjectMapper().readTree(bytes); proceedArgs[0] = new ByteArrayInputStream(bytes); setCorrelationIdFromNode(correlationIdPath, jsonNode); @@ -377,7 +371,7 @@ private void setCorrelationIdFromNode(String correlationIdPath, JsonNode jsonNod String asText = node.asText(); if (null != asText && !asText.isEmpty()) { - LoggingUtils.setCorrelationId(asText); + MDC.put(CORRELATION_ID.getName(), asText); } else { LOG.warn("Unable to extract any correlation id. Is your function expecting supported event type?"); } @@ -398,15 +392,6 @@ private byte[] bytesFromInputStreamSafely(final InputStream inputStream) throws } } - private Optional asJson(final Object target) { - try { - return ofNullable(LoggingUtils.getObjectMapper().writeValueAsString(target)); - } catch (JsonProcessingException e) { - LOG.error("Failed logging object of type {}", target.getClass(), e); - return empty(); - } - } - private Logger logger(final ProceedingJoinPoint pjp) { return LoggerFactory.getLogger(pjp.getSignature().getDeclaringType()); } diff --git a/powertools-logging/src/test/java/org/slf4j/test/TestLogger.java b/powertools-logging/src/test/java/org/slf4j/test/TestLogger.java index 2a9322592..acc635e75 100644 --- a/powertools-logging/src/test/java/org/slf4j/test/TestLogger.java +++ b/powertools-logging/src/test/java/org/slf4j/test/TestLogger.java @@ -185,6 +185,9 @@ public class TestLogger extends LegacyAbstractLogger { /** The short name of this simple log instance */ private transient String shortLogName = null; + // used for test purpose + private Object[] arguments; + /** * Package access allows only {@link TestLoggerFactory} to instantiate * SimpleLogger instances. @@ -368,6 +371,8 @@ protected void handleNormalizedLoggingCall(Level level, Marker marker, String me private void innerHandleNormalizedLoggingCall(Level level, List markers, String messagePattern, Object[] arguments, Throwable t) { + this.arguments = arguments; + StringBuilder buf = new StringBuilder(32); // Append date-time if so configured @@ -449,4 +454,11 @@ protected String getFullyQualifiedCallerName() { return null; } + public Object[] getArguments() { + return arguments; + } + + public void clearArguments() { + arguments = null; + } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/LoggingUtilsTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/LoggingUtilsTest.java deleted file mode 100644 index 04e977c58..000000000 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/LoggingUtilsTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.logging; - -import static org.assertj.core.api.Assertions.assertThat; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.slf4j.MDC; -import software.amazon.lambda.powertools.utilities.JsonConfig; - - -class LoggingUtilsTest { - - @BeforeEach - void setUp() { - MDC.clear(); - } - - @Test - void shouldSetCustomKeyInLoggingContext() { - LoggingUtils.appendKey("org/slf4j/test", "value"); - - assertThat(MDC.getCopyOfContextMap()) - .hasSize(1) - .containsEntry("org/slf4j/test", "value"); - } - - @Test - void shouldSetCustomKeyAsMapInLoggingContext() { - Map customKeys = new HashMap<>(); - customKeys.put("org/slf4j/test", "value"); - customKeys.put("test1", "value1"); - - LoggingUtils.appendKeys(customKeys); - - assertThat(MDC.getCopyOfContextMap()) - .hasSize(2) - .containsEntry("org/slf4j/test", "value") - .containsEntry("test1", "value1"); - } - - @Test - void shouldRemoveCustomKeyInLoggingContext() { - LoggingUtils.appendKey("org/slf4j/test", "value"); - - assertThat(MDC.getCopyOfContextMap()) - .hasSize(1) - .containsEntry("org/slf4j/test", "value"); - - LoggingUtils.removeKey("org/slf4j/test"); - - assertThat(MDC.getCopyOfContextMap()) - .isEmpty(); - } - - @Test - void shouldRemoveCustomKeysInLoggingContext() { - Map customKeys = new HashMap<>(); - customKeys.put("org/slf4j/test", "value"); - customKeys.put("test1", "value1"); - - LoggingUtils.appendKeys(customKeys); - - assertThat(MDC.getCopyOfContextMap()) - .hasSize(2) - .containsEntry("org/slf4j/test", "value") - .containsEntry("test1", "value1"); - - LoggingUtils.removeKeys("org/slf4j/test", "test1"); - - assertThat(MDC.getCopyOfContextMap()) - .isEmpty(); - } - - @Test - void shouldAddCorrelationIdToLoggingContext() { - String id = "correlationID_12345"; - LoggingUtils.setCorrelationId(id); - - assertThat(MDC.getCopyOfContextMap()) - .hasSize(1) - .containsEntry("correlation_id", id); - - assertThat(LoggingUtils.getCorrelationId()).isEqualTo(id); - } - - @Test - void shouldGetObjectMapper() { - assertThat(LoggingUtils.getObjectMapper()).isNotNull(); - assertThat(LoggingUtils.getObjectMapper()).isEqualTo(JsonConfig.get().getObjectMapper()); - - ObjectMapper mapper = new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); - LoggingUtils.setObjectMapper(mapper); - assertThat(LoggingUtils.getObjectMapper()).isEqualTo(mapper); - - } -} \ No newline at end of file diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/argument/StructuredArgumentsTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/argument/StructuredArgumentsTest.java new file mode 100644 index 000000000..64200e640 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/argument/StructuredArgumentsTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.argument; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.lambda.powertools.logging.internal.JsonSerializer; +import software.amazon.lambda.powertools.logging.model.Basket; +import software.amazon.lambda.powertools.logging.model.Product; + +class StructuredArgumentsTest { + private StringBuilder sb; + private JsonSerializer serializer; + + @BeforeEach + void setUp() { + sb = new StringBuilder(); + serializer = new JsonSerializer(sb); + } + + @Test + void keyValueArgument() throws IOException { + // GIVEN + Basket basket = new Basket(); + basket.add(new Product(42, "Nintendo DS", 299.45)); + basket.add(new Product(98, "Playstation 5", 499.99)); + + // WHEN + StructuredArgument argument = StructuredArguments.entry("basket", basket); + argument.writeTo(serializer); + + // THEN + assertThat(sb.toString()).hasToString("\"basket\":{\"products\":[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]}"); + assertThat(argument.toString()).hasToString("basket=Basket{products=[Product{id=42, name='Nintendo DS', price=299.45}, Product{id=98, name='Playstation 5', price=499.99}]}"); + } + + @Test + void mapArgument() throws IOException { + // GIVEN + Map catalog = new HashMap<>(); + catalog.put("nds", new Product(42, "Nintendo DS", 299.45)); + catalog.put("ps5", new Product(98, "Playstation 5", 499.99)); + + // WHEN + StructuredArgument argument = StructuredArguments.entries(catalog); + argument.writeTo(serializer); + + // THEN + assertThat(sb.toString()) + .contains("\"nds\":{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45}") + .contains("\"ps5\":{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}"); + assertThat(argument.toString()) + .contains("nds=Product{id=42, name='Nintendo DS', price=299.45}") + .contains("ps5=Product{id=98, name='Playstation 5', price=499.99}"); + } + + @Test + void arrayArgument() throws IOException { + // GIVEN + Product[] products = new Product[]{ + new Product(42, "Nintendo DS", 299.45), + new Product(98, "Playstation 5", 499.99) + }; + + // WHEN + StructuredArgument argument = StructuredArguments.array("products", products); + argument.writeTo(serializer); + + // THEN + assertThat(sb.toString()).contains("\"products\":[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]"); + assertThat(argument.toString()).contains("products=[Product{id=42, name='Nintendo DS', price=299.45}, Product{id=98, name='Playstation 5', price=499.99}]"); + } + + @Test + void jsonArgument() throws IOException { + // GIVEN + String rawJson = "{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45}"; + + // WHEN + StructuredArgument argument = StructuredArguments.json("product", rawJson); + argument.writeTo(serializer); + + // THEN + assertThat(sb.toString()).contains("\"product\":{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45}"); + assertThat(argument.toString()).contains("product={\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45}"); + } + +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogClearState.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogClearState.java index e1829a777..cb7fbb408 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogClearState.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogClearState.java @@ -19,8 +19,8 @@ import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.logging.LoggingUtils; public class PowertoolsLogClearState implements RequestHandler, Object> { private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogClearState.class); @@ -28,7 +28,7 @@ public class PowertoolsLogClearState implements RequestHandler input, Context context) { - LoggingUtils.appendKey("mySuperSecret", input.get("mySuperSecret")); + MDC.put("mySuperSecret", input.get("mySuperSecret")); LOG.info("Test event"); return null; } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabled.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabled.java index d6c79a445..aa0a5942c 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabled.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEnabled.java @@ -21,7 +21,7 @@ import software.amazon.lambda.powertools.logging.Logging; public class PowertoolsLogEnabled implements RequestHandler { - private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogEnabled.class); + private static final Logger LOG = LoggerFactory.getLogger(PowertoolsLogEnabled.class); private final boolean throwError; public PowertoolsLogEnabled(boolean throwError) { @@ -49,4 +49,8 @@ public Object handleRequest(Object input, Context context) { public void anotherMethod() { System.out.println("test"); } + + public static Logger getLogger() { + return LOG; + } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEvent.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEvent.java index 87677d601..c83692e95 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEvent.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEvent.java @@ -16,13 +16,21 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; public class PowertoolsLogEvent implements RequestHandler { + private static final Logger logger = LoggerFactory.getLogger(PowertoolsLogEvent.class); + @Override @Logging(logEvent = true) public Object handleRequest(Object input, Context context) { return null; } + + public static Logger getLogger() { + return logger; + } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventEnvVar.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventEnvVar.java new file mode 100644 index 000000000..230394bf7 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventEnvVar.java @@ -0,0 +1,36 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogEventEnvVar implements RequestHandler { + + private final Logger logger = LoggerFactory.getLogger(PowertoolsLogEventEnvVar.class); + + @Override + @Logging + public Object handleRequest(Object input, Context context) { + return null; + } + + public Logger getLogger() { + return logger; + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventForStream.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventForStream.java index 350b29cde..6e27f47ce 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventForStream.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogEventForStream.java @@ -21,14 +21,22 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; public class PowertoolsLogEventForStream implements RequestStreamHandler { + private static final Logger logger = LoggerFactory.getLogger(PowertoolsLogEventForStream.class); + @Override @Logging(logEvent = true) public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.writeValue(outputStream, mapper.readValue(inputStream, Map.class)); } + + public static Logger getLogger() { + return logger; + } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponse.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponse.java index 001bde3ed..e7607d3c9 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponse.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponse.java @@ -16,9 +16,16 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; public class PowertoolsLogResponse implements RequestHandler { + private static final Logger logger = LoggerFactory.getLogger(PowertoolsLogResponse.class); + + public static Logger getLogger() { + return logger; + } @Override @Logging(logResponse = true) diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponseForStream.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponseForStream.java index 38be5c025..fe591627b 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponseForStream.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogResponseForStream.java @@ -19,10 +19,14 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.logging.Logging; public class PowertoolsLogResponseForStream implements RequestStreamHandler { + private static final Logger logger = LoggerFactory.getLogger(PowertoolsLogResponseForStream.class); + @Override @Logging(logResponse = true) public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { @@ -32,4 +36,8 @@ public void handleRequest(InputStream inputStream, OutputStream outputStream, Co outputStream.write(buf, 0, length); } } + + public static Logger getLogger() { + return logger; + } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/JsonSerializerTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/JsonSerializerTest.java new file mode 100644 index 000000000..8b34d32cb --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/JsonSerializerTest.java @@ -0,0 +1,149 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.fasterxml.jackson.core.TreeNode; +import com.fasterxml.jackson.databind.JsonNode; +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.lambda.powertools.logging.model.Basket; +import software.amazon.lambda.powertools.logging.model.Product; +import software.amazon.lambda.powertools.utilities.JsonConfig; + +class JsonSerializerTest { + private StringBuilder sb; + private JsonSerializer generator; + + @BeforeEach + void setUp() { + sb = new StringBuilder(); + generator = new JsonSerializer(sb); + } + + @Test + void writeString_shouldWriteStringWithQuotes() throws IOException { + generator.writeStringField("key", "StringValue"); + assertThat(sb.toString()).hasToString("\"key\":\"StringValue\""); + } + + @Test + void writeBoolean_shouldWriteBooleanValue() throws IOException { + generator.writeBooleanField("key", true); + assertThat(sb.toString()).hasToString("\"key\":true"); + } + + @Test + void writeNull_shouldWriteNullValue() throws IOException { + generator.writeNullField("key"); + assertThat(sb.toString()).hasToString("\"key\":null"); + } + + @Test + void writeInt_shouldWriteIntValue() throws IOException { + generator.writeNumberField("key", 1); + assertThat(sb.toString()).hasToString("\"key\":1"); + } + + @Test + void writeFloat_shouldWriteFloatValue() throws IOException { + generator.writeNumberField("key", 2.4f); + assertThat(sb.toString()).hasToString("\"key\":2.4"); + assertThat(sb.toString()).doesNotContain("F").doesNotContain("f"); // should not contain the F suffix for floats. + } + + @Test + void writeDouble_shouldWriteDoubleValue() throws IOException { + generator.writeNumberField("key", 4.3); + assertThat(sb.toString()).hasToString("\"key\":4.3"); + } + + @Test + void writeLong_shouldWriteLongValue() throws IOException { + generator.writeNumberField("key", 123456789L); + assertThat(sb.toString()).hasToString("\"key\":123456789"); + assertThat(sb.toString()).doesNotContain("L").doesNotContain("l"); // should not contain the L suffix for longs. + } + + @Test + void writeBigDecimal_shouldWriteBigDecimal() throws IOException { + generator.writeNumberField("key", BigDecimal.valueOf(432.1673254564546)); + assertThat(sb.toString()).hasToString("\"key\":432.1673254564546"); + } + + @Test + void writeStringObject_shouldWriteStringWithQuotes() throws IOException { + generator.writeObjectField("key","StringValue"); + assertThat(sb.toString()).hasToString("\"key\":\"StringValue\""); + } + + @Test + void writeMapObject_shouldWriteMapAsJson() throws IOException { + Map map = new HashMap<>(); + map.put("string","StringValue"); + map.put("number", BigInteger.valueOf(1234567890L)); + generator.writeObjectField("map", map); + assertThat(sb.toString()).hasToString("\"map\":{\"number\":1234567890,\"string\":\"StringValue\"}"); + } + + @Test + void writeListObject_shouldWriteListAsArray() throws IOException { + List list = Arrays.asList("val1", "val2", "val3"); + generator.writeObjectField("list", list); + assertThat(sb.toString()).hasToString("\"list\":[\"val1\",\"val2\",\"val3\"]"); + } + + @Test + void writeCustomObject_shouldWriteObjectAsJson() throws IOException { + Basket basket = new Basket(); + basket.add(new Product(42, "Nintendo DS", 299.45)); + basket.add(new Product(98, "Playstation 5", 499.99)); + generator.writeObjectField("basket", basket); + assertThat(sb.toString()).hasToString("\"basket\":{\"products\":[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]}"); + } + + @Test + void writeJsonNodeObject_shouldWriteObjectAsJson() throws IOException { + JsonNode jsonNode = JsonConfig.get().getObjectMapper().readTree( + "[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]"); + generator.writeObjectField("basket", jsonNode); + assertThat(sb.toString()).hasToString("\"basket\":[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]"); + } + + @Test + void writeTreeNodeArrayObject_shouldWriteObjectAsJson() throws IOException { + TreeNode treeNode = JsonConfig.get().getObjectMapper().readTree( + "[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]"); + generator.writeTree(treeNode); + assertThat(sb.toString()).hasToString("[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]"); + } + + @Test + void writeTreeNodeObject_shouldWriteObjectAsJson() throws IOException { + TreeNode treeNode = JsonConfig.get().getObjectMapper().readTree( + "{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45}"); + generator.writeTree(treeNode); + assertThat(sb.toString()).hasToString("{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45}"); + } + +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index bc5e53675..28e20aadd 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -15,7 +15,6 @@ package software.amazon.lambda.powertools.logging.internal; import static java.util.Collections.singletonList; -import static java.util.stream.Collectors.joining; import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; @@ -52,15 +51,14 @@ import java.lang.reflect.Method; import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -70,8 +68,10 @@ import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.slf4j.event.Level; +import org.slf4j.test.TestLogger; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.common.internal.SystemWrapper; +import software.amazon.lambda.powertools.logging.argument.KeyValueArgument; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayRestApiCorrelationId; @@ -84,7 +84,7 @@ import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogError; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEvent; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventBridgeCorrelationId; -import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventDisabled; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventEnvVar; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventForStream; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponse; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponseForStream; @@ -466,51 +466,61 @@ void shouldLogxRayTraceIdEnvVarSet() { void shouldLogEventForHandlerWithLogEventAnnotation() { // GIVEN requestHandler = new PowertoolsLogEvent(); + List listOfOneElement = singletonList("ListOfOneElement"); // WHEN - requestHandler.handleRequest(singletonList("ListOfOneElement"), context); + requestHandler.handleRequest(listOfOneElement, context); // THEN - File logFile = new File("target/logfile.json"); - assertThat(contentOf(logFile)).contains("[\"ListOfOneElement\"]"); + TestLogger logger = (TestLogger) PowertoolsLogEvent.getLogger(); + assertThat(logger.getArguments()).hasSize(1); + KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; + assertThat(argument.getKey()).isEqualTo("event"); + assertThat(argument.getValue()).isEqualTo(listOfOneElement); } @Test - void shouldLogEventForHandlerWhenEnvVariableSetToTrue() throws IllegalAccessException { - try { - // GIVEN - LoggingConstants.POWERTOOLS_LOG_EVENT = true; + void shouldLogEventForHandlerWhenEnvVariableSetToTrue() { + // GIVEN + LoggingConstants.POWERTOOLS_LOG_EVENT = true; - requestHandler = new PowertoolsLogEnabled(); + requestHandler = new PowertoolsLogEventEnvVar(); - SQSEvent.SQSMessage message = new SQSEvent.SQSMessage(); - message.setBody("body"); - message.setMessageId("1234abcd"); - message.setAwsRegion("eu-west-1"); + SQSEvent.SQSMessage message = new SQSEvent.SQSMessage(); + message.setBody("body"); + message.setMessageId("1234abcd"); + message.setAwsRegion("eu-west-1"); - // WHEN - requestHandler.handleRequest(message, context); + // WHEN + requestHandler.handleRequest(message, context); - // THEN - File logFile = new File("target/logfile.json"); - assertThat(contentOf(logFile)).contains("\"body\":\"body\"").contains("\"messageId\":\"1234abcd\"").contains("\"awsRegion\":\"eu-west-1\""); + // THEN + TestLogger logger = (TestLogger) ((PowertoolsLogEventEnvVar)requestHandler).getLogger(); + try { + assertThat(logger.getArguments()).hasSize(1); + KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; + assertThat(argument.getKey()).isEqualTo("event"); + assertThat(argument.getValue()).isEqualTo(message); } finally { LoggingConstants.POWERTOOLS_LOG_EVENT = false; + if (logger != null){ + logger.clearArguments(); + } } } @Test - void shouldNotLogEventForHandlerWhenEnvVariableSetToFalse() throws IOException { + void shouldNotLogEventForHandlerWhenEnvVariableSetToFalse() { // GIVEN LoggingConstants.POWERTOOLS_LOG_EVENT = false; // WHEN - requestHandler = new PowertoolsLogEventDisabled(); + requestHandler = new PowertoolsLogEventEnvVar(); requestHandler.handleRequest(singletonList("ListOfOneElement"), context); // THEN - Assertions.assertEquals(0, - Files.lines(Paths.get("target/logfile.json")).collect(joining()).length()); + TestLogger logger = (TestLogger) ((PowertoolsLogEventEnvVar)requestHandler).getLogger(); + assertThat(logger.getArguments()).isNull(); } @Test @@ -518,16 +528,24 @@ void shouldLogEventForStreamHandler() throws IOException { // GIVEN requestStreamHandler = new PowertoolsLogEventForStream(); ByteArrayOutputStream output = new ByteArrayOutputStream(); + Map map = Collections.singletonMap("key", "value"); // WHEN - requestStreamHandler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(Collections.singletonMap("key", "value"))), output, context); + requestStreamHandler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(map)), output, context); // THEN assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) .isNotEmpty(); - File logFile = new File("target/logfile.json"); - assertThat(contentOf(logFile)).contains("{\"key\":\"value\"}"); + TestLogger logger = (TestLogger) PowertoolsLogEventForStream.getLogger(); + try { + assertThat(logger.getArguments()).hasSize(1); + KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; + assertThat(argument.getKey()).isEqualTo("event"); + assertThat(argument.getValue()).isEqualTo("{\"key\":\"value\"}"); + } finally { + logger.clearArguments(); + } } @Test @@ -539,26 +557,37 @@ void shouldLogResponseForHandlerWithLogResponseAnnotation() { requestHandler.handleRequest("input", context); // THEN - File logFile = new File("target/logfile.json"); - assertThat(contentOf(logFile)).contains("Hola mundo"); + TestLogger logger = (TestLogger) PowertoolsLogResponse.getLogger(); + try { + assertThat(logger.getArguments()).hasSize(1); + KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; + assertThat(argument.getKey()).isEqualTo("response"); + assertThat(argument.getValue()).isEqualTo("Hola mundo"); + } finally { + logger.clearArguments(); + } } @Test - void shouldLogResponseForHandlerWhenEnvVariableSetToTrue() throws IllegalAccessException { - try { - // GIVEN - LoggingConstants.POWERTOOLS_LOG_RESPONSE = true; + void shouldLogResponseForHandlerWhenEnvVariableSetToTrue() { + // GIVEN + LoggingConstants.POWERTOOLS_LOG_RESPONSE = true; - requestHandler = new PowertoolsLogEnabled(); + requestHandler = new PowertoolsLogEnabled(); - // WHEN - requestHandler.handleRequest("input", context); + // WHEN + requestHandler.handleRequest("input", context); - // THEN - File logFile = new File("target/logfile.json"); - assertThat(contentOf(logFile)).contains("Bonjour le monde"); + // THEN + TestLogger logger = (TestLogger) PowertoolsLogEnabled.getLogger(); + try { + assertThat(logger.getArguments()).hasSize(1); + KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; + assertThat(argument.getKey()).isEqualTo("response"); + assertThat(argument.getValue()).isEqualTo("Bonjour le monde"); } finally { LoggingConstants.POWERTOOLS_LOG_RESPONSE = false; + logger.clearArguments(); } } @@ -576,8 +605,15 @@ void shouldLogResponseForStreamHandler() throws IOException { assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) .isEqualTo(input); - File logFile = new File("target/logfile.json"); - assertThat(contentOf(logFile)).contains(input); + TestLogger logger = (TestLogger) PowertoolsLogResponseForStream.getLogger(); + try { + assertThat(logger.getArguments()).hasSize(1); + KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; + assertThat(argument.getKey()).isEqualTo("response"); + assertThat(argument.getValue()).isEqualTo(input); + } finally { + logger.clearArguments(); + } } @Test @@ -598,7 +634,7 @@ void shouldLogErrorForHandlerWithLogErrorAnnotation() { } @Test - void shouldLogErrorForHandlerWhenEnvVariableSetToTrue() throws IllegalAccessException { + void shouldLogErrorForHandlerWhenEnvVariableSetToTrue() { try { // GIVEN LoggingConstants.POWERTOOLS_LOG_ERROR = true; diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/model/Basket.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/model/Basket.java new file mode 100644 index 000000000..0fa544cf1 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/model/Basket.java @@ -0,0 +1,67 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.model; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +public class Basket { + private List products = new ArrayList<>(); + + public Basket() { + } + + public Basket(Product... p) { + products.addAll(Arrays.asList(p)); + } + + public List getProducts() { + return products; + } + + public void setProducts(List products) { + this.products = products; + } + + public void add(Product product) { + products.add(product); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Basket basket = (Basket) o; + return products.equals(basket.products); + } + + @Override + public int hashCode() { + return Objects.hash(products); + } + + @Override + public String toString() { + return "Basket{" + + "products=" + products + + '}'; + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/model/Product.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/model/Product.java new file mode 100644 index 000000000..fee5bc20d --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/model/Product.java @@ -0,0 +1,84 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.model; + +import java.util.Objects; + +public class Product { + private long id; + + private String name; + + private double price; + + public Product() { + } + + public Product(long id, String name, double price) { + this.id = id; + this.name = name; + this.price = price; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Product product = (Product) o; + return id == product.id && Double.compare(product.price, price) == 0 && Objects.equals(name, product.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, price); + } + + @Override + public String toString() { + return "Product{" + + "id=" + id + + ", name='" + name + '\'' + + ", price=" + price + + '}'; + } +} diff --git a/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java b/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java index e961f21fa..fc0f083e5 100644 --- a/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java +++ b/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java @@ -14,29 +14,51 @@ package software.amazon.lambda.powertools.utilities; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.json.JsonMapper; import io.burt.jmespath.JmesPath; import io.burt.jmespath.RuntimeConfiguration; import io.burt.jmespath.function.BaseFunction; import io.burt.jmespath.function.FunctionRegistry; import io.burt.jmespath.jackson.JacksonRuntime; +import java.util.function.Supplier; import software.amazon.lambda.powertools.utilities.jmespath.Base64Function; import software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunction; import software.amazon.lambda.powertools.utilities.jmespath.JsonFunction; -public class JsonConfig { - private static final ThreadLocal om = ThreadLocal.withInitial(ObjectMapper::new); +public final class JsonConfig { + + private static final Supplier objectMapperSupplier = () -> JsonMapper.builder() + // Don't throw an exception when json has extra fields you are not serializing on. + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + // Ignore null values when writing json. + .serializationInclusion(JsonInclude.Include.NON_NULL) + // Write times as a String instead of a Long so its human-readable. + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + // Sort fields in alphabetical order + .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true) + .build(); + + private static final ThreadLocal om = ThreadLocal.withInitial(objectMapperSupplier); + private final FunctionRegistry defaultFunctions = FunctionRegistry.defaultRegistry(); + private final FunctionRegistry customFunctions = defaultFunctions.extend( new Base64Function(), new Base64GZipFunction(), new JsonFunction() ); + private final RuntimeConfiguration configuration = new RuntimeConfiguration.Builder() .withSilentTypeErrors(true) .withFunctionRegistry(customFunctions) .build(); + private JmesPath jmesPath = new JacksonRuntime(configuration, getObjectMapper()); private JsonConfig() { diff --git a/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/EventDeserializerTest.java b/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/EventDeserializerTest.java index fcfdb47e3..2914bd286 100644 --- a/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/EventDeserializerTest.java +++ b/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/EventDeserializerTest.java @@ -39,7 +39,6 @@ import java.util.Map; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import software.amazon.lambda.powertools.utilities.model.Basket; import software.amazon.lambda.powertools.utilities.model.Order; import software.amazon.lambda.powertools.utilities.model.Product; @@ -93,14 +92,6 @@ public void testDeserializeAPIGWEventBodyAsObject_shouldReturnObject(APIGatewayP assertProduct(product); } - @ParameterizedTest - @Event(value = "apigw_event.json", type = APIGatewayProxyRequestEvent.class) - public void testDeserializeAPIGWEventBodyAsWrongObjectType_shouldThrowException(APIGatewayProxyRequestEvent event) { - assertThatThrownBy(() -> extractDataFrom(event).as(Basket.class)) - .isInstanceOf(EventDeserializationException.class) - .hasMessage("Cannot load the event as Basket"); - } - @ParameterizedTest @Event(value = "sns_event.json", type = SNSEvent.class) public void testDeserializeSNSEventMessageAsObject_shouldReturnObject(SNSEvent event) { @@ -164,14 +155,6 @@ public void testDeserializeEmptyEventAsList_shouldThrowException() { .hasMessage("Event content is null: the event may be malformed (missing fields)"); } - @ParameterizedTest - @Event(value = "sqs_event.json", type = SQSEvent.class) - public void testDeserializeSQSEventBodyAsWrongObjectType_shouldThrowException(SQSEvent event) { - assertThatThrownBy(() -> extractDataFrom(event).asListOf(Basket.class)) - .isInstanceOf(EventDeserializationException.class) - .hasMessage("Cannot load the event as a list of Basket"); - } - @ParameterizedTest @Event(value = "apigw_event_no_body.json", type = APIGatewayProxyRequestEvent.class) public void testDeserializeAPIGatewayNoBody_shouldThrowException(APIGatewayProxyRequestEvent event) { diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index ee39b5d0f..a4eb3756f 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -71,6 +71,9 @@ + + + @@ -185,10 +188,6 @@ - - - - @@ -206,10 +205,6 @@ - - - - From 41a6eb3b266c8efe447d9669c614ab425b65826a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 12:16:18 +0100 Subject: [PATCH 148/577] build(deps): bump commons-io:commons-io from 2.13.0 to 2.15.1 (#1590) Bumps commons-io:commons-io from 2.13.0 to 2.15.1. --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 9d84ce9f2..92d8f8291 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -103,7 +103,7 @@ commons-io commons-io - 2.13.0 + 2.15.1 From ffe2091f5b921a2d1211b817a47a03f85fb057a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 12:17:20 +0100 Subject: [PATCH 149/577] build(deps): bump org.apache.maven.plugins:maven-surefire-plugin (#1596) Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.2 to 3.2.5. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.2.5) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- pom.xml | 4 ++-- powertools-logging/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/powertools-examples-core/terraform/pom.xml b/examples/powertools-examples-core/terraform/pom.xml index 7fe562072..4784dc5e0 100644 --- a/examples/powertools-examples-core/terraform/pom.xml +++ b/examples/powertools-examples-core/terraform/pom.xml @@ -124,7 +124,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.2.5 handler diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index c841c0f38..64637be0e 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -120,7 +120,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.2.5 ${project.build.directory}/native-libs diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 2aa813ff4..e5147acc4 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -41,7 +41,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.2.5 dev.aspectj diff --git a/pom.xml b/pom.xml index 2ad359a3a..f9105b9d6 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ 3.11.0 1.9.7 1.13.1 - 3.1.2 + 3.2.5 0.8.11 1.6.13 3.6.0 @@ -527,7 +527,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.2.5 @{argLine} diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 78c36f41a..656b9ee81 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -140,7 +140,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.2.5 JSON diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 788ac9438..49f0cd80c 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -141,7 +141,7 @@ maven-surefire-plugin - 3.1.2 + 3.2.5 eu-central-1 From 67b122723553fa2780cf784994527112d14937a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 12:21:02 +0100 Subject: [PATCH 150/577] build(deps): bump aws.sdk.version from 2.24.5 to 2.25.1 (#1595) Bumps `aws.sdk.version` from 2.24.5 to 2.25.1. Updates `software.amazon.awssdk:bom` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:http-client-spi` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:url-connection-client` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:dynamodb` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:s3` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:lambda` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:kinesis` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:cloudwatch` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:xray` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:sqs` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:cloudformation` from 2.24.5 to 2.25.1 Updates `software.amazon.awssdk:sts` from 2.24.5 to 2.25.1 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 795834a8f..0e0b5cbf7 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 11 1.2.3 3.11.3 - 2.24.5 + 2.25.1 1.9.20.1 diff --git a/pom.xml b/pom.xml index b9b8da3bc..4e80d90ed 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 2.22.0 2.0.7 2.16.0 - 2.24.5 + 2.25.1 2.15.1 2.1.3 UTF-8 From 8f176ccd89aba0772779125d6b7e388018ddc269 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:45:01 +0100 Subject: [PATCH 151/577] build(deps): bump aws.sdk.version from 2.25.1 to 2.25.6 (#1600) Bumps `aws.sdk.version` from 2.25.1 to 2.25.6. Updates `software.amazon.awssdk:bom` from 2.25.1 to 2.25.6 Updates `software.amazon.awssdk:http-client-spi` from 2.25.1 to 2.25.6 Updates `software.amazon.awssdk:url-connection-client` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:dynamodb` from 2.25.1 to 2.25.6 Updates `software.amazon.awssdk:s3` from 2.25.1 to 2.25.6 Updates `software.amazon.awssdk:lambda` from 2.25.1 to 2.25.6 Updates `software.amazon.awssdk:kinesis` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:cloudwatch` from 2.25.1 to 2.25.6 Updates `software.amazon.awssdk:xray` from 2.25.1 to 2.25.6 Updates `software.amazon.awssdk:sqs` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:cloudformation` from 2.25.1 to 2.25.6 Updates `software.amazon.awssdk:sts` from 2.25.1 to 2.25.6 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 0e0b5cbf7..107c8df90 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 11 1.2.3 3.11.3 - 2.25.1 + 2.25.6 1.9.20.1 diff --git a/pom.xml b/pom.xml index 4e80d90ed..aaf7ae002 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 2.22.0 2.0.7 2.16.0 - 2.25.1 + 2.25.6 2.15.1 2.1.3 UTF-8 From 8dec2c9b14e41485426ed45c7871701b784d28a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:59:53 +0100 Subject: [PATCH 152/577] build(deps): bump aws.sdk.version from 2.24.10 to 2.25.6 (#1603) Bumps `aws.sdk.version` from 2.24.10 to 2.25.6. Updates `software.amazon.awssdk:bom` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:http-client-spi` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:url-connection-client` from 2.21.1 to 2.25.6 Updates `software.amazon.awssdk:sqs` from 2.21.1 to 2.25.6 Updates `software.amazon.awssdk:s3` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:dynamodb` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:lambda` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:kinesis` from 2.21.1 to 2.25.6 Updates `software.amazon.awssdk:cloudwatch` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:xray` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:cloudformation` from 2.24.10 to 2.25.6 Updates `software.amazon.awssdk:sts` from 2.24.10 to 2.25.6 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 3b2cf6df0..ef28cf2ab 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -15,7 +15,7 @@ 1.8 1.2.3 3.11.3 - 2.24.10 + 2.25.6 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index d83a900c0..66aca544e 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -27,7 +27,7 @@ software.amazon.awssdk url-connection-client - 2.24.10 + 2.25.6 com.amazonaws diff --git a/pom.xml b/pom.xml index f9105b9d6..e30716325 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,7 @@ 1.8 2.22.1 2.15.3 - 2.24.10 + 2.25.6 2.15.1 2.1.3 UTF-8 From 6b264fec7dc2d8b88ee701e3b4973b5b0769b953 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 13:04:23 +0100 Subject: [PATCH 153/577] build(deps): bump com.amazonaws:aws-lambda-java-events (#1597) Bumps [com.amazonaws:aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs) from 3.11.2 to 3.11.4. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-events dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core/cdk/app/pom.xml | 2 +- examples/powertools-examples-core/sam/pom.xml | 2 +- examples/powertools-examples-core/serverless/pom.xml | 2 +- examples/powertools-examples-core/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-sqs/pom.xml | 2 +- pom.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index ef28cf2ab..5e3403f4e 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 1.8 1.8 1.2.3 - 3.11.3 + 3.11.4 2.25.6 diff --git a/examples/powertools-examples-core/cdk/app/pom.xml b/examples/powertools-examples-core/cdk/app/pom.xml index 561aae686..4a8383925 100644 --- a/examples/powertools-examples-core/cdk/app/pom.xml +++ b/examples/powertools-examples-core/cdk/app/pom.xml @@ -39,7 +39,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.11.4 org.apache.logging.log4j diff --git a/examples/powertools-examples-core/sam/pom.xml b/examples/powertools-examples-core/sam/pom.xml index 2e95644b6..6ef2c0ecb 100644 --- a/examples/powertools-examples-core/sam/pom.xml +++ b/examples/powertools-examples-core/sam/pom.xml @@ -39,7 +39,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.11.4 org.apache.logging.log4j diff --git a/examples/powertools-examples-core/serverless/pom.xml b/examples/powertools-examples-core/serverless/pom.xml index 59820ffec..ef324056d 100644 --- a/examples/powertools-examples-core/serverless/pom.xml +++ b/examples/powertools-examples-core/serverless/pom.xml @@ -39,7 +39,7 @@ com.amazonaws aws-lambda-java-events - 3.11.2 + 3.11.4 org.apache.logging.log4j diff --git a/examples/powertools-examples-core/terraform/pom.xml b/examples/powertools-examples-core/terraform/pom.xml index 4784dc5e0..8781b70f4 100644 --- a/examples/powertools-examples-core/terraform/pom.xml +++ b/examples/powertools-examples-core/terraform/pom.xml @@ -39,7 +39,7 @@ com.amazonaws aws-lambda-java-events - 3.11.2 + 3.11.4 org.apache.logging.log4j diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 64637be0e..e6d205827 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -52,7 +52,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.11.4 org.apache.logging.log4j diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index e5147acc4..5ef7d69a2 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -31,7 +31,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.11.4 diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 4f2b8ffda..e63ecbc5a 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -31,7 +31,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.11.4 diff --git a/examples/powertools-examples-sqs/pom.xml b/examples/powertools-examples-sqs/pom.xml index 66aca544e..01bbfd8d2 100644 --- a/examples/powertools-examples-sqs/pom.xml +++ b/examples/powertools-examples-sqs/pom.xml @@ -37,7 +37,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.11.4 org.apache.logging.log4j diff --git a/pom.xml b/pom.xml index e30716325..e3f5dad3b 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ 2.1.3 UTF-8 1.2.3 - 3.11.3 + 3.11.4 1.1.5 3.11.0 1.9.7 From 190ad0a5e1cd82e533ee431c9ef382487a2c3f9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Mon, 18 Mar 2024 10:04:25 +0100 Subject: [PATCH 154/577] feat(build): remove java 8 support in v2 (#1606) * split GH actions for 2 versions * Update .github/workflows/publish.yml --- .github/workflows/pr_build.yml | 8 +-- .github/workflows/pr_build_v2.yml | 93 ++++++++++++++++++++++++++ .github/workflows/run-e2e-tests-v2.yml | 58 ++++++++++++++++ .github/workflows/run-e2e-tests.yml | 1 - 4 files changed, 154 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/pr_build_v2.yml create mode 100644 .github/workflows/run-e2e-tests-v2.yml diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 54c2599c3..634a4ee0f 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -4,12 +4,10 @@ on: pull_request: branches: - main - - v2 paths: - 'powertools-batch/**' - 'powertools-cloudformation/**' - - 'powertools-core/**' # not in v2 - - 'powertools-common/**' # v2 only + - 'powertools-core/**' - 'powertools-e2e-tests/**' - 'powertools-idempotency/**' - 'powertools-large-messages/**' @@ -17,8 +15,8 @@ on: - 'powertools-metrics/**' - 'powertools-parameters/**' - 'powertools-serialization/**' - - 'powertools-sqs/**' # not in v2 - - 'powertools-test-suite/**' # not in v2 + - 'powertools-sqs/**' + - 'powertools-test-suite/**' - 'powertools-tracing/**' - 'powertools-validation/**' - 'examples/**' diff --git a/.github/workflows/pr_build_v2.yml b/.github/workflows/pr_build_v2.yml new file mode 100644 index 000000000..3299dc720 --- /dev/null +++ b/.github/workflows/pr_build_v2.yml @@ -0,0 +1,93 @@ +name: Build + +on: + pull_request: + branches: + - v2 + paths: + - 'powertools-batch/**' + - 'powertools-cloudformation/**' + - 'powertools-common/**' + - 'powertools-e2e-tests/**' + - 'powertools-idempotency/**' + - 'powertools-large-messages/**' + - 'powertools-logging/**' + - 'powertools-metrics/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' + - 'powertools-tracing/**' + - 'powertools-validation/**' + - 'examples/**' + - 'pom.xml' + - 'examples/pom.xml' + - '.github/workflows/**' + push: + branches: + - v2 + paths: + - 'powertools-batch/**' + - 'powertools-cloudformation/**' + - 'powertools-common/**' + - 'powertools-e2e-tests/**' + - 'powertools-idempotency/**' + - 'powertools-large-messages/**' + - 'powertools-logging/**' + - 'powertools-metrics/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' + - 'powertools-tracing/**' + - 'powertools-validation/**' + - 'examples/**' + - 'pom.xml' + - 'examples/pom.xml' + - '.github/workflows/**' +jobs: + build-corretto: + runs-on: ubuntu-latest + strategy: + max-parallel: 5 + matrix: + java: [11, 17, 21] + name: Java ${{ matrix.java }} + env: + JAVA: ${{ matrix.java }} + AWS_REGION: eu-west-1 + permissions: + id-token: write # needed to interact with GitHub's OIDC Token endpoint. + contents: read + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Setup java + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + with: + distribution: 'corretto' + java-version: ${{ matrix.java }} + cache: 'maven' + - name: Build with Maven + run: mvn -B install --file pom.xml + - name: Build Gradle Example - Java + working-directory: examples/powertools-examples-core/gradle + run: ./gradlew build + - name: Build Gradle Example - Kotlin + working-directory: examples/powertools-examples-core/kotlin + run: ./gradlew build + - name: Upload coverage to Codecov + uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 + if: ${{ matrix.java == '11' }} # publish results once + with: + files: ./powertools-cloudformation/target/site/jacoco/jacoco.xml,./powertools-core/target/site/jacoco/jacoco.xml,./powertools-idempotency/target/site/jacoco/jacoco.xml,./powertools-logging/target/site/jacoco/jacoco.xml,./powertools-metrics/target/site/jacoco/jacoco.xml,./powertools-parameters/target/site/jacoco/jacoco.xml,./powertools-serialization/target/site/jacoco/jacoco.xml,./powertools-sqs/target/site/jacoco/jacoco.xml,./powertools-tracing/target/site/jacoco/jacoco.xml,./powertools-validation/target/site/jacoco/jacoco.xml,./powertools-large-messages/target/site/jacoco/jacoco.xml,./powertools-batch/target/site/jacoco/jacoco.xml + savepr: + runs-on: ubuntu-latest + name: Save PR number if running on PR by dependabot + if: github.actor == 'dependabot[bot]' + steps: + - name: Create Directory and save issue + run: | + mkdir -p ./pr + echo ${{ github.event.number }} + echo ${{ github.event.number }} > ./pr/NR + - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + name: Upload artifact + with: + name: pr + path: pr/ diff --git a/.github/workflows/run-e2e-tests-v2.yml b/.github/workflows/run-e2e-tests-v2.yml new file mode 100644 index 000000000..255c89cfe --- /dev/null +++ b/.github/workflows/run-e2e-tests-v2.yml @@ -0,0 +1,58 @@ +name: Run end-to-end tests + +on: + workflow_dispatch: + + push: + branches: + - v2 + paths: # add other modules when there are under e2e tests + - 'powertools-e2e-tests/**' + - 'powertools-batch/**' + - 'powertools-core/**' + - 'powertools-common/**' + - 'powertools-idempotency/**' + - 'powertools-large-message/**' + - 'powertools-logging/**' + - 'powertools-metrics/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' + - 'powertools-tracing/**' + - 'pom.xml' + - '.github/workflows/**' + + pull_request: + branches: + - v2 + paths: + - 'powertools-e2e-tests/**' + +jobs: + e2e: + runs-on: ubuntu-latest + strategy: + max-parallel: 4 + matrix: + java: [ 11, 17, 21 ] + name: End-to-end tests java${{ matrix.java }} + env: + AWS_DEFAULT_REGION: eu-west-1 + JAVA_VERSION: ${{ matrix.java }} + permissions: + id-token: write # needed to interact with GitHub's OIDC Token endpoint. + contents: read + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Setup java + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + with: + distribution: 'corretto' + java-version: ${{ matrix.java }} + cache: maven + - name: Setup AWS credentials + uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + - name: Run e2e test with Maven + run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml \ No newline at end of file diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 626268214..77cdea890 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -6,7 +6,6 @@ on: push: branches: - main - - v2 paths: # add other modules when there are under e2e tests - 'powertools-e2e-tests/**' - 'powertools-batch/**' From 4976a5bc4cf32a636c2ee3168990715775c78e65 Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 18 Mar 2024 10:34:15 +0100 Subject: [PATCH 155/577] fix: workflow paths for examples v2 builds --- .github/workflows/pr_build_v2.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_build_v2.yml b/.github/workflows/pr_build_v2.yml index 3299dc720..2079bcb6b 100644 --- a/.github/workflows/pr_build_v2.yml +++ b/.github/workflows/pr_build_v2.yml @@ -66,10 +66,10 @@ jobs: - name: Build with Maven run: mvn -B install --file pom.xml - name: Build Gradle Example - Java - working-directory: examples/powertools-examples-core/gradle + working-directory: examples/powertools-examples-core-utilities/gradle run: ./gradlew build - name: Build Gradle Example - Kotlin - working-directory: examples/powertools-examples-core/kotlin + working-directory: examples/powertools-examples-core-utilities/kotlin run: ./gradlew build - name: Upload coverage to Codecov uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 From 59f9ba4d96ebe0ae017ecf78f2b892f97315e09d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:09:36 +0100 Subject: [PATCH 156/577] build(deps): bump org.junit.jupiter:junit-jupiter-api (#1611) Bumps [org.junit.jupiter:junit-jupiter-api](https://github.com/junit-team/junit5) from 5.9.3 to 5.10.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.3...r5.10.2) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter-api dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 9a9351ea5..dc2bb86b0 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -69,7 +69,7 @@ org.junit.jupiter junit-jupiter-api - 5.9.3 + 5.10.2 test diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 928e56e3a..fe97784d5 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -56,7 +56,7 @@ org.junit.jupiter junit-jupiter-api - 5.9.3 + 5.10.2 test diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 1c39ee8a0..fd0278d78 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -59,7 +59,7 @@ org.junit.jupiter junit-jupiter-api - 5.9.3 + 5.10.2 test From e4e2cd1a8676065b32bd20eb40444ae407c51405 Mon Sep 17 00:00:00 2001 From: Jeroen Reijn Date: Thu, 21 Mar 2024 17:05:47 +0100 Subject: [PATCH 157/577] chore(v2): document use of aws-crt-client (#1092) (#1605) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(v2): document use of aws-crt-client (#1092) * Update docs/FAQs.md Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Update docs/FAQs.md Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * Update docs/FAQs.md Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> * chore(v2): improve documentation based on feedback (#1092) * Update docs/FAQs.md Co-authored-by: Scott Gerring * Update docs/FAQs.md Co-authored-by: Scott Gerring * Update docs/FAQs.md Co-authored-by: Scott Gerring * Update docs/FAQs.md Co-authored-by: Scott Gerring * Update docs/FAQs.md Co-authored-by: Scott Gerring * Update docs/FAQs.md Co-authored-by: Scott Gerring * Update docs/FAQs.md Co-authored-by: Scott Gerring * Update docs/FAQs.md Co-authored-by: Scott Gerring * Update FAQs.md and set version --------- Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> Co-authored-by: Scott Gerring --- docs/FAQs.md | 100 ++++++++++++++++++++++++++++++- docs/utilities/batch.md | 26 ++++---- docs/utilities/large_messages.md | 85 +++++++++++++------------- docs/utilities/parameters.md | 1 + 4 files changed, 155 insertions(+), 57 deletions(-) diff --git a/docs/FAQs.md b/docs/FAQs.md index 99ef40905..88aa81c9f 100644 --- a/docs/FAQs.md +++ b/docs/FAQs.md @@ -6,7 +6,7 @@ description: Frequently Asked Questions ## How can I use Powertools for AWS Lambda (Java) with Lombok? -Poweretools uses `aspectj-maven-plugin` to compile-time weave (CTW) aspects into the project. In case you want to use `Lombok` or other compile-time preprocessor for your project, it is required to change `aspectj-maven-plugin` configuration to enable in-place weaving feature. Otherwise the plugin will ignore changes introduced by `Lombok` and will use `.java` files as a source. +Powertools uses `aspectj-maven-plugin` to compile-time weave (CTW) aspects into the project. In case you want to use `Lombok` or other compile-time preprocessor for your project, it is required to change `aspectj-maven-plugin` configuration to enable in-place weaving feature. Otherwise the plugin will ignore changes introduced by `Lombok` and will use `.java` files as a source. To enable in-place weaving feature you need to use following `aspectj-maven-plugin` configuration: @@ -29,7 +29,7 @@ To enable in-place weaving feature you need to use following `aspectj-maven-plug ## How can I use Powertools for AWS Lambda (Java) with Kotlin projects? -Poweretools uses `aspectj-maven-plugin` to compile-time weave (CTW) aspects into the project. When using it with Kotlin projects, it is required to `forceAjcCompile`. +Powertools uses `aspectj-maven-plugin` to compile-time weave (CTW) aspects into the project. When using it with Kotlin projects, it is required to `forceAjcCompile`. No explicit configuration should be required for gradle projects. To enable `forceAjcCompile` you need to use following `aspectj-maven-plugin` configuration: @@ -47,3 +47,99 @@ To enable `forceAjcCompile` you need to use following `aspectj-maven-plugin` con ``` +## How can I use Powertools for AWS Lambda (Java) with the AWS CRT HTTP Client? + +Powertools uses the `url-connection-client` as the default HTTP client. The `url-connection-client` is a lightweight HTTP client, which keeps the impact on Lambda cold starts to a minimum. +With the [announcement](https://aws.amazon.com/blogs/developer/announcing-availability-of-the-aws-crt-http-client-in-the-aws-sdk-for-java-2-x/) of the `aws-crt-client` a new HTTP client has been released, which offers faster SDK startup time and smaller memory footprint. + +Unfortunately, replacing the `url-connection-client` dependency with the `aws-crt-client` will not immediately improve the lambda cold start performance and memory footprint, +as the default version of the dependency contains native system libraries for all supported runtimes and architectures (Linux, MacOS, Windows, AMD64, ARM64, etc). This makes the CRT client portable, without the user having to consider _where_ their code will run, but comes at the cost of JAR size. + +### Configuring dependencies + +Using the `aws-crt-client` in your project requires the exclusion of the `url-connection-client` transitive dependency from the powertools dependency. + +```xml + + software.amazon.lambda + powertools-parameters + 2.0.0 + + + software.amazon.awssdk + url-connection-client + + + +``` +Next, add the `aws-crt-client` and exclude the "generic" `aws-crt` dependency (contains all runtime libraries). +Instead, set a specific classifier of the `aws-crt` to use the one for your target runtime: either `linux-x86_64` for a Lambda configured for x86 or `linux-aarch_64` for Lambda using arm64. + +!!! note "You will need to add a separate maven profile to build and debug locally when your development environment does not share the target architecture you are using in Lambda." +By specifying the specific target runtime, we prevent other target runtimes from being included in the jar file, resulting in a smaller Lambda package and improved cold start times. + +```xml + + + + software.amazon.awssdk + aws-crt-client + 2.23.21 + + + software.amazon.awssdk.crt + aws-crt + + + + + + software.amazon.awssdk.crt + aws-crt + 0.29.9 + linux-x86_64 + + +``` + +### Explicitly set the AWS CRT HTTP Client +After configuring the dependencies, it's required to explicitly specify the AWS SDK HTTP client. +Depending on the Powertools module, there is a different way to configure the SDK client. + +The following example shows how to use the Lambda Powertools Parameters module while leveraging the AWS CRT Client. + + ```java hl_lines="11-16 19-20 22" + import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import software.amazon.awssdk.services.ssm.SsmClient; + import software.amazon.awssdk.http.crt.AwsCrtHttpClient; + import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; + + public class RequestHandlerWithParams implements RequestHandler { + + // Get an instance of the SSMProvider with a custom HTTP client (aws crt). + SSMProvider ssmProvider = SSMProvider + .builder() + .withClient( + SsmClient.builder() + .httpClient(AwsCrtHttpClient.builder().build()) + .build() + ) + .build(); + + public String handleRequest(String input, Context context) { + // Retrieve a single param + String value = ssmProvider + .get("/my/secret"); + // We might instead want to retrieve multiple parameters at once, returning a Map of key/value pairs + // .getMultiple("/my/secret/path"); + + // Return the result + return value; + } + } + ``` +The `aws-crt-client` was considered for adoption as the default HTTP client in Lambda Powertools for Java as mentioned in [Move SDK http client to CRT](https://github.com/aws-powertools/powertools-lambda-java/issues/1092), +but due to the impact on the developer experience it was decided to stick with the `url-connection-client`. \ No newline at end of file diff --git a/docs/utilities/batch.md b/docs/utilities/batch.md index 6b38b438c..7b571bc6e 100644 --- a/docs/utilities/batch.md +++ b/docs/utilities/batch.md @@ -530,19 +530,19 @@ Handlers can be provided when building the batch processor and are available for For instance for DynamoDB: ```java -BatchMessageHandler handler = new BatchMessageHandlerBuilder() - .withDynamoDbBatchHandler() - .withSuccessHandler((m) -> { - // Success handler receives the raw message - LOGGER.info("Message with sequenceNumber {} was successfully processed", - m.getDynamodb().getSequenceNumber()); - }) - .withFailureHandler((m, e) -> { - // Failure handler receives the raw message and the exception thrown. - LOGGER.info("Message with sequenceNumber {} failed to be processed: {}" - , e.getDynamodb().getSequenceNumber(), e); - }) - .buildWithMessageHander(this::processMessage); + BatchMessageHandler handler = new BatchMessageHandlerBuilder() + .withDynamoDbBatchHandler() + .withSuccessHandler((m) -> { + // Success handler receives the raw message + LOGGER.info("Message with sequenceNumber {} was successfully processed", + m.getDynamodb().getSequenceNumber()); + }) + .withFailureHandler((m, e) -> { + // Failure handler receives the raw message and the exception thrown. + LOGGER.info("Message with sequenceNumber {} failed to be processed: {}" + , e.getDynamodb().getSequenceNumber(), e); + }) + .buildWithMessageHander(this::processMessage); ``` !!! info diff --git a/docs/utilities/large_messages.md b/docs/utilities/large_messages.md index c0c1cd599..2f974c3b5 100644 --- a/docs/utilities/large_messages.md +++ b/docs/utilities/large_messages.md @@ -97,48 +97,49 @@ of amazon-sns-java-extended-client-lib. Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. === "Maven Java 11+" -```xml hl_lines="3-7 16 18 24-27" - -... - -software.amazon.lambda -powertools-large-messages -{{ powertools.version }} - -... - -... - - - -... - -dev.aspectj -aspectj-maven-plugin -1.13.1 - -11 -11 -11 - - -software.amazon.lambda -powertools-large-messages - - - - - - -compile - - - - -... - - -``` + + ```xml hl_lines="3-7 16 18 24-27" + + ... + + software.amazon.lambda + powertools-large-messages + {{ powertools.version }} + + ... + + ... + + + + ... + + dev.aspectj + aspectj-maven-plugin + 1.13.1 + + 11 + 11 + 11 + + + software.amazon.lambda + powertools-large-messages + + + + + + + compile + + + + + ... + + + ``` === "Maven Java 1.8" diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index f72c7704e..46c7e8071 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -544,6 +544,7 @@ To simplify the use of the library, you can chain all method calls before a get. .withTransformation(json) // json is a static import from Transformer.json .withDecryption() // enable decryption of the parameter value .get("/my/param", MyObj.class); // finally get the value + ``` ### Create your own Provider You can create your own custom parameter store provider by implementing a handful of classes: From 56e5f3980595d681a93120aad02a74c0516fcc80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 12:52:13 +0100 Subject: [PATCH 158/577] build(deps): bump jackson.version from 2.16.0 to 2.17.0 (#1615) Bumps `jackson.version` from 2.16.0 to 2.17.0. Updates `com.fasterxml.jackson.core:jackson-databind` from 2.16.0 to 2.17.0 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.core:jackson-core` from 2.16.0 to 2.17.0 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.16.0...jackson-core-2.17.0) Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.16.0 to 2.17.0 --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index aaf7ae002..7d271d8b5 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ 2.20.0 2.22.0 2.0.7 - 2.16.0 + 2.17.0 2.25.6 2.15.1 2.1.3 From adbb7bfc0a2b32ba5e83b377d91897c89281c2ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 12:57:59 +0100 Subject: [PATCH 159/577] build(deps): bump co.elastic.logging:logback-ecs-encoder (#1617) Bumps [co.elastic.logging:logback-ecs-encoder](https://github.com/elastic/ecs-logging-java) from 1.5.0 to 1.6.0. - [Release notes](https://github.com/elastic/ecs-logging-java/releases) - [Commits](https://github.com/elastic/ecs-logging-java/compare/v1.5.0...v1.6.0) --- updated-dependencies: - dependency-name: co.elastic.logging:logback-ecs-encoder dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7d271d8b5..e0d9e631e 100644 --- a/pom.xml +++ b/pom.xml @@ -90,7 +90,7 @@ 5.10.0 1.0.6 0.6.0 - 1.5.0 + 1.6.0 From daec77d18649ec3cb447f9b773aaea1d6b73c739 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 13:27:50 +0200 Subject: [PATCH 160/577] build(deps): bump aws.sdk.version from 2.25.6 to 2.25.21 (#1618) Bumps `aws.sdk.version` from 2.25.6 to 2.25.21. Updates `software.amazon.awssdk:bom` from 2.25.6 to 2.25.21 Updates `software.amazon.awssdk:http-client-spi` from 2.25.6 to 2.25.21 Updates `software.amazon.awssdk:url-connection-client` from 2.24.10 to 2.25.21 Updates `software.amazon.awssdk:dynamodb` from 2.25.6 to 2.25.21 Updates `software.amazon.awssdk:s3` from 2.25.6 to 2.25.21 Updates `software.amazon.awssdk:lambda` from 2.25.6 to 2.25.21 Updates `software.amazon.awssdk:kinesis` from 2.24.10 to 2.25.21 Updates `software.amazon.awssdk:cloudwatch` from 2.25.6 to 2.25.21 Updates `software.amazon.awssdk:xray` from 2.25.6 to 2.25.21 Updates `software.amazon.awssdk:sqs` from 2.24.10 to 2.25.21 Updates `software.amazon.awssdk:cloudformation` from 2.25.6 to 2.25.21 Updates `software.amazon.awssdk:sts` from 2.25.6 to 2.25.21 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 107c8df90..077bab767 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 11 1.2.3 3.11.3 - 2.25.6 + 2.25.21 1.9.20.1 diff --git a/pom.xml b/pom.xml index e0d9e631e..93d9deb8e 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 2.22.0 2.0.7 2.17.0 - 2.25.6 + 2.25.21 2.15.1 2.1.3 UTF-8 From 7d40e6aacc58ff66aa1a5bdb212bf1ad05bfc97e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 13:56:43 +0200 Subject: [PATCH 161/577] build(deps): bump aws.sdk.version from 2.24.10 to 2.25.26 (#1623) Bumps `aws.sdk.version` from 2.24.10 to 2.25.26. Updates `software.amazon.awssdk:url-connection-client` from 2.24.10 to 2.25.26 Updates `software.amazon.awssdk:sdk-core` from 2.24.10 to 2.25.26 Updates `software.amazon.awssdk:kinesis` from 2.24.10 to 2.25.26 Updates `software.amazon.awssdk:sqs` from 2.24.10 to 2.25.26 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.24.10 to 2.25.26 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 70a4a6e3f..4f1eba3c1 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 11 11 1.9.20.1 - 2.24.10 + 2.25.26 From 1a1135d6b7581b41b23cb523a2e23434ca125dfa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:51:36 +0200 Subject: [PATCH 162/577] build(deps): bump ch.qos.logback:logback-classic from 1.3.4 to 1.5.5 (#1626) Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.3.4 to 1.5.5. - [Commits](https://github.com/qos-ch/logback/compare/v_1.3.4...v_1.5.5) --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-logging/powertools-logging-logback/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 99fff3ab9..3ab756334 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -29,7 +29,7 @@ ch.qos.logback logback-classic - 1.3.4 + 1.5.5 provided From 36d82340148acbe3a21bb9c342fba1aea4f73300 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:53:41 +0200 Subject: [PATCH 163/577] build(deps): bump com.github.spotbugs:spotbugs-maven-plugin (#1627) Bumps [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) from 4.7.3.6 to 4.8.4.0. - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.7.3.6...spotbugs-maven-plugin-4.8.4.0) --- updated-dependencies: - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 93d9deb8e..c7d75fa1b 100644 --- a/pom.xml +++ b/pom.xml @@ -517,7 +517,7 @@ com.github.spotbugs spotbugs-maven-plugin - 4.7.3.6 + 4.8.4.0 test From 4cd8f706269dec59f89d3b4a08caf1e05b7e0d2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:56:24 +0200 Subject: [PATCH 164/577] build(deps): bump org.junit:junit-bom from 5.10.0 to 5.10.2 (#1628) Bumps [org.junit:junit-bom](https://github.com/junit-team/junit5) from 5.10.0 to 5.10.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.0...r5.10.2) --- updated-dependencies: - dependency-name: org.junit:junit-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c7d75fa1b..7c2b89c88 100644 --- a/pom.xml +++ b/pom.xml @@ -87,7 +87,7 @@ 3.6.3 3.3.0 3.1.0 - 5.10.0 + 5.10.2 1.0.6 0.6.0 1.6.0 From 34a94f31e136518eb0989b8850a1f888339e8d4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 13:59:35 +0200 Subject: [PATCH 165/577] build(deps): bump log4j.version from 2.20.0 to 2.23.1 (#1630) Bumps `log4j.version` from 2.20.0 to 2.23.1. Updates `org.apache.logging.log4j:log4j-core` from 2.20.0 to 2.23.1 Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.22.0 to 2.23.1 Updates `org.apache.logging.log4j:log4j-slf4j2-impl` from 2.22.0 to 2.23.1 Updates `org.apache.logging.log4j:log4j-api` from 2.20.0 to 2.23.1 Updates `org.apache.logging.log4j:log4j-layout-template-json` from 2.22.0 to 2.23.1 Updates `org.apache.logging.log4j:log4j-jcl` from 2.22.0 to 2.23.1 --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-slf4j-impl dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-slf4j2-impl dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-api dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-layout-template-json dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-jcl dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index f964782e3..cc9643bda 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -11,7 +11,7 @@ jar - 2.20.0 + 2.23.1 11 11 1.9.20.1 diff --git a/pom.xml b/pom.xml index 7c2b89c88..d12ac0c61 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ 1.8 3.1.1 2.20.0 - 2.22.0 + 2.23.1 2.0.7 2.17.0 2.25.21 From 2d9364532bc9950fcb8829a3fc6000aa150f0ded Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:00:00 +0200 Subject: [PATCH 166/577] build(deps): bump aws.sdk.version from 2.25.21 to 2.25.35 (#1631) Bumps `aws.sdk.version` from 2.25.21 to 2.25.35. Updates `software.amazon.awssdk:bom` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:http-client-spi` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:url-connection-client` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:dynamodb` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:s3` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:lambda` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:kinesis` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:cloudwatch` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:xray` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:sqs` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:cloudformation` from 2.25.21 to 2.25.35 Updates `software.amazon.awssdk:sts` from 2.25.21 to 2.25.35 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 077bab767..d675a90c2 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 11 1.2.3 3.11.3 - 2.25.21 + 2.25.35 1.9.20.1 diff --git a/pom.xml b/pom.xml index d12ac0c61..1d0ffe9a7 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 2.23.1 2.0.7 2.17.0 - 2.25.21 + 2.25.35 2.15.1 2.1.3 UTF-8 From e2b43efcc60a5af356967c8ca1cc96b302db4a28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 14:00:22 +0200 Subject: [PATCH 167/577] build(deps): bump dev.aspectj:aspectj-maven-plugin from 1.13.1 to 1.14 (#1632) Bumps [dev.aspectj:aspectj-maven-plugin](https://github.com/dev-aspectj/aspectj-maven-plugin) from 1.13.1 to 1.14. - [Release notes](https://github.com/dev-aspectj/aspectj-maven-plugin/releases) - [Commits](https://github.com/dev-aspectj/aspectj-maven-plugin/compare/aspectj-maven-plugin-1.13.1...aspectj-maven-plugin-1.14) --- updated-dependencies: - dependency-name: dev.aspectj:aspectj-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- examples/powertools-examples-core-utilities/serverless/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 4f1eba3c1..8aab869bb 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -75,7 +75,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index d675a90c2..bbe849c1e 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -87,7 +87,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index cc9643bda..1ad3b9b68 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -66,7 +66,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index c9d90d281..3e495c960 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -52,7 +52,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 32cca9bb4..d899b40de 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -53,7 +53,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 94f79a5fd..66418888a 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -53,7 +53,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index dc2bb86b0..63640be57 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -79,7 +79,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index fe97784d5..e3e3ec9b2 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -78,7 +78,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 96afc3ea0..7858ee2a4 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -49,7 +49,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 true diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index fd0278d78..bf533dab9 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -75,7 +75,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} diff --git a/pom.xml b/pom.xml index 1d0ffe9a7..67dfc340a 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ 1.1.2 3.11.0 1.9.7 - 1.13.1 + 1.14 3.1.2 0.8.10 1.6.13 diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index df6154560..d76137678 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -88,7 +88,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 3ab756334..c43526dd4 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -87,7 +87,7 @@ dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 ${maven.compiler.source} ${maven.compiler.target} From c7b2f7e30b6a08ce568e2ba6c26029a48ee3a4e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 14:00:58 +0200 Subject: [PATCH 168/577] build(deps): bump org.codehaus.mojo:exec-maven-plugin (#1645) Bumps [org.codehaus.mojo:exec-maven-plugin](https://github.com/mojohaus/exec-maven-plugin) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/mojohaus/exec-maven-plugin/releases) - [Commits](https://github.com/mojohaus/exec-maven-plugin/compare/3.2.0...3.3.0) --- updated-dependencies: - dependency-name: org.codehaus.mojo:exec-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 2dd61753a..e7d941ae8 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -25,7 +25,7 @@ org.codehaus.mojo exec-maven-plugin - 3.2.0 + 3.3.0 cdk.CdkApp From 16ad40335926e997f08cdfa857b85eb94b8c308d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:45:24 +0200 Subject: [PATCH 169/577] build(deps): bump org.apache.maven.plugins:maven-deploy-plugin (#1647) Bumps [org.apache.maven.plugins:maven-deploy-plugin](https://github.com/apache/maven-deploy-plugin) from 3.1.1 to 3.1.2. - [Release notes](https://github.com/apache/maven-deploy-plugin/releases) - [Commits](https://github.com/apache/maven-deploy-plugin/compare/maven-deploy-plugin-3.1.1...maven-deploy-plugin-3.1.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-deploy-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- pom.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index f864c3c04..1f985a9cf 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -48,7 +48,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 8aab869bb..8cadd1393 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -136,7 +136,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index bbe849c1e..d7f372002 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -144,7 +144,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 1ad3b9b68..5ac2a89ac 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -132,7 +132,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index e7d941ae8..81bdbe185 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -34,7 +34,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 66418888a..e9dec2e34 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -118,7 +118,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 63640be57..f0f0628c9 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -176,7 +176,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index e3e3ec9b2..340bcbafb 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -108,7 +108,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 7858ee2a4..2f9bf77ef 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -41,7 +41,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index bf533dab9..f2f6e1f08 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -106,7 +106,7 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.1 + 3.1.2 true diff --git a/pom.xml b/pom.xml index 67dfc340a..4af6cdb32 100644 --- a/pom.xml +++ b/pom.xml @@ -66,7 +66,7 @@ 1.8 1.8 - 3.1.1 + 3.1.2 2.20.0 2.23.1 2.0.7 From d38995bf6a7cbc471302e8e6a32a6d55a2f0b4bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:48:34 +0200 Subject: [PATCH 170/577] build(deps): bump org.apache.maven.plugins:maven-shade-plugin (#1648) Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.0 to 3.6.0. - [Release notes](https://github.com/apache/maven-shade-plugin/releases) - [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.0...maven-shade-plugin-3.6.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-shade-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- examples/powertools-examples-core-utilities/serverless/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 8cadd1393..3d94982fd 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -109,7 +109,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.2 + 3.6.0 package diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index d7f372002..0aa8fab83 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -117,7 +117,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.6.0 package diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 5ac2a89ac..f942fe1fa 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -104,7 +104,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.6.0 package diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 3e495c960..75821f851 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -90,7 +90,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.6.0 package diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index d899b40de..a83050b0a 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -91,7 +91,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.6.0 package diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index e9dec2e34..1918b63a9 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -91,7 +91,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.6.0 package diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index f0f0628c9..422a8ebb5 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -150,7 +150,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.0 + 3.6.0 package From 04b9c159144f71ce19684a4ef7f9400ad83d744d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:25:32 +0200 Subject: [PATCH 171/577] build(deps): bump org.apache.maven.plugins:maven-jar-plugin (#1649) Bumps [org.apache.maven.plugins:maven-jar-plugin](https://github.com/apache/maven-jar-plugin) from 3.3.0 to 3.4.1. - [Release notes](https://github.com/apache/maven-jar-plugin/releases) - [Commits](https://github.com/apache/maven-jar-plugin/compare/maven-jar-plugin-3.3.0...maven-jar-plugin-3.4.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-jar-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-idempotency/powertools-idempotency-dynamodb/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index a8f69c468..c0a807ed8 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -79,7 +79,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.3.0 + 3.4.1 From e347e41fe8849e100973d3b3472d7dce2332d159 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:32:17 +0200 Subject: [PATCH 172/577] build(deps): bump org.apache.maven.plugins:maven-compiler-plugin (#1651) Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.11.0 to 3.13.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.11.0...maven-compiler-plugin-3.13.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 81bdbe185..100928618 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -16,7 +16,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.13.0 11 11 diff --git a/pom.xml b/pom.xml index 4af6cdb32..b24608f06 100644 --- a/pom.xml +++ b/pom.xml @@ -78,7 +78,7 @@ 1.2.3 3.11.2 1.1.2 - 3.11.0 + 3.13.0 1.9.7 1.14 3.1.2 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 20679d64f..c3bfca0df 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -192,7 +192,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.13.0 ${maven.compiler.source} ${maven.compiler.target} From a5c22c46b6ca48fc31458920de25be6341709982 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 11:33:15 +0000 Subject: [PATCH 173/577] build(deps): bump org.jacoco:jacoco-maven-plugin from 0.8.10 to 0.8.12 (#1656) Bumps [org.jacoco:jacoco-maven-plugin](https://github.com/jacoco/jacoco) from 0.8.10 to 0.8.12. - [Release notes](https://github.com/jacoco/jacoco/releases) - [Commits](https://github.com/jacoco/jacoco/compare/v0.8.10...v0.8.12) --- updated-dependencies: - dependency-name: org.jacoco:jacoco-maven-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b24608f06..8055c41a8 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ 1.9.7 1.14 3.1.2 - 0.8.10 + 0.8.12 1.6.13 3.6.3 3.3.0 From 12a2f44d3cf1b7e0fbba3937b9e18363c8bde663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Fri, 21 Jun 2024 17:47:22 +0200 Subject: [PATCH 174/577] Update run-e2e-tests.yml remove v2 --- .github/workflows/run-e2e-tests.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index b358fe355..13c84befe 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -24,7 +24,6 @@ on: pull_request: branches: - main - - v2 paths: - 'powertools-e2e-tests/**' @@ -63,4 +62,4 @@ jobs: if: ${{ matrix.java != '8' }} # If not 8 don't exclude the examples directory run: mvn -DskipTests install --file pom.xml - name: Run e2e test with Maven - run: mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml \ No newline at end of file + run: mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml From 471c3a61eba48e8731ba513fd1748b530f198cdb Mon Sep 17 00:00:00 2001 From: Scott Gerring Date: Mon, 24 Jun 2024 09:57:34 +0200 Subject: [PATCH 175/577] feat(v2): publish snapshots (#1655) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial commit * Add distributionManagement back * Switch to environment variables * Enforcer should work * Re-enable GPG * Change user/password for publish * Missing config? * Skip SAM example for deploy * Another missing one * Publish preview docs * Update docs accordingly * Exclude intentional constructor throw from spotbugs * More new spotbugs? * Block new spotbugs rules * Remove PR push triggers * Again but properly --------- Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> --- .github/workflows/docs-v2-snapshot.yml | 40 +++++++++++++++++++ .github/workflows/publish-v2-snapshot.yml | 29 ++++++++++++++ .github/workflows/publish.yml | 4 +- docs/index.md | 8 +++- .../sam/pom.xml | 9 +++++ .../serverless/pom.xml | 9 +++++ mkdocs.yml | 6 +-- pom.xml | 29 ++++++++++++++ .../dynamodb-local-metadata.json | 1 + spotbugs-exclude.xml | 16 ++++++++ 10 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/docs-v2-snapshot.yml create mode 100644 .github/workflows/publish-v2-snapshot.yml create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/dynamodb-local-metadata.json diff --git a/.github/workflows/docs-v2-snapshot.yml b/.github/workflows/docs-v2-snapshot.yml new file mode 100644 index 000000000..55803c737 --- /dev/null +++ b/.github/workflows/docs-v2-snapshot.yml @@ -0,0 +1,40 @@ +name: Docs +on: + push: + branches: + - v2 + workflow_dispatch: {} + +permissions: + id-token: write + contents: write + pages: write + +jobs: + docs: + runs-on: ubuntu-latest + environment: Docs + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Set up Python + uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 + with: + python-version: "3.8" + - name: Capture branch and tag + id: branch_name + run: | + echo "SOURCE_BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV + echo "SOURCE_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV + - name: Build docs website + run: | + make build-docs-website + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef + with: + aws-region: us-east-1 + role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} + - name: Deploy Docs + run: | + aws s3 sync \ + dist \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/preview/ diff --git a/.github/workflows/publish-v2-snapshot.yml b/.github/workflows/publish-v2-snapshot.yml new file mode 100644 index 000000000..d5a683261 --- /dev/null +++ b/.github/workflows/publish-v2-snapshot.yml @@ -0,0 +1,29 @@ +name: Publish v2 +on: + push: + branches: + - v2 + workflow_dispatch: {} +jobs: + publish: + runs-on: ubuntu-latest + environment: snapshot + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Set up Maven Central Repository + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + with: + distribution: 'corretto' + java-version: 11 + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + # TODO: use environments https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment + gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }} # Value of the GPG private key to import + gpg-passphrase: GPG_PASSPHRASE # env variable for GPG private key passphrase + - name: Publish package + run: mvn -Prelease clean validate deploy -DskipTests # We use validate here to run maven enforcer, to make sure we are only publishing SNAPSHOT builds + env: + MAVEN_USERNAME: ${{ secrets.SNAPSHOT_PUBLISH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.SNAPSHOT_PUBLISH_PASSWORD }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 03f04e0f4..d2d47b308 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -27,8 +27,8 @@ jobs: - name: Publish package run: mvn -Prelease clean deploy -DskipTests env: - MAVEN_USERNAME: ${{ secrets.OSSRH_JIRA_USERNAME }} - MAVEN_PASSWORD: ${{ secrets.OSSRH_JIRA_PASSWORD }} + MAVEN_USERNAME: ${{ secrets.SNAPSHOT_PUBLISH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.SNAPSHOT_PUBLISH_PASSWORD }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - name: Close issues related to this release uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 diff --git a/docs/index.md b/docs/index.md index 06c9beb6d..1c5dfac85 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,7 +3,13 @@ title: Homepage description: Powertools for AWS Lambda (Java) --- -![aws provider](https://img.shields.io/badge/provider-AWS-orange?logo=amazon-aws&color=ff9900) ![Build status](https://github.com/aws-powertools/powertools-lambda-java/actions/workflows/build.yml/badge.svg) ![Maven Central](https://img.shields.io/maven-central/v/software.amazon.lambda/powertools-parent) +![aws provider](https://img.shields.io/badge/provider-AWS-orange?logo=amazon-aws&color=ff9900) ![Build status](https://github.com/aws-powertools/powertools-lambda-java/actions/workflows/publish-v2-snapshot.yml/badge.svg) ![Maven Central](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Faws.oss.sonatype.org%2Fcontent%2Frepositories%2Fsnapshots%2Fsoftware%2Famazon%2Flambda%2Fpowertools-parent%2Fmaven-metadata.xml +) + +???+ warning + You are browsing the documentation for Powertools for AWS Lambda (Java) - v2. This is a snapshot release and not stable! + Check out our stable [v1](https://docs.powertools.aws.dev/lambda/java/) documentation if this is not what you wanted. + The v2 maven snapshot repository can be found [here](https://aws.oss.sonatype.org/content/repositories/snapshots/software/amazon/lambda/) . Powertools for AWS Lambda (Java) is a suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 75821f851..86fa52425 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -113,6 +113,15 @@ + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.2 + + true + + diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index a83050b0a..0b5b06152 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -114,6 +114,15 @@ + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.2 + + true + + diff --git a/mkdocs.yml b/mkdocs.yml index b7f793e18..aa7b0e314 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,5 +1,5 @@ -site_name: Powertools for AWS Lambda (Java) -site_description: Powertools for AWS Lambda (Java) +site_name: Powertools for AWS Lambda (Java) Preview +site_description: Powertools for AWS Lambda (Java) Preview site_author: Amazon Web Services site_url: https://docs.powertools.aws.dev/lambda-java/ nav: @@ -85,7 +85,7 @@ extra_javascript: extra: powertools: - version: 2.0.0 # to update after each release (we do not want snapshot version here) + version: 2.0.0-SNAPSHOT repo_url: https://github.com/aws-powertools/powertools-lambda-java edit_uri: edit/main/docs diff --git a/pom.xml b/pom.xml index 8055c41a8..2f4e327e6 100644 --- a/pom.xml +++ b/pom.xml @@ -97,6 +97,13 @@ ${maven.multiModuleProjectDirectory} + + + ossrh + https://aws.oss.sonatype.org/content/repositories/snapshots + + + @@ -457,6 +464,28 @@ release + + org.apache.maven.plugins + maven-enforcer-plugin + 3.5.0 + + + enforce-snapshot-versions + validate + + enforce + + + + + Release build should not have snapshot dependencies! + + + true + + + + org.apache.maven.plugins maven-gpg-plugin diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/dynamodb-local-metadata.json b/powertools-idempotency/powertools-idempotency-dynamodb/dynamodb-local-metadata.json new file mode 100644 index 000000000..c76c2c76d --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-dynamodb/dynamodb-local-metadata.json @@ -0,0 +1 @@ +{"installationId":"e43b8515-8484-485c-8315-bead4568972b","telemetryEnabled":"true"} \ No newline at end of file diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index a4eb3756f..ee44f7b4d 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -8,6 +8,22 @@ https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html --> + + + + + + + + + + + + + + + From 31124c46af235c9f3fa2174f5c6ac4439adf66e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 10:52:58 +0200 Subject: [PATCH 176/577] build(deps): bump org.apache.maven.plugins:maven-gpg-plugin (#1634) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2f4e327e6..ba2ef5dba 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ 1.6.13 3.6.3 3.3.0 - 3.1.0 + 3.2.4 5.10.2 1.0.6 0.6.0 From 598a20746d97807145714c775aac7794c0b70481 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:11:00 +0200 Subject: [PATCH 177/577] build(deps): bump com.amazonaws:aws-lambda-java-serialization (#1636) Bumps [com.amazonaws:aws-lambda-java-serialization](https://github.com/aws/aws-lambda-java-libs) from 1.1.2 to 1.1.5. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ba2ef5dba..d96c51d2f 100644 --- a/pom.xml +++ b/pom.xml @@ -77,7 +77,7 @@ UTF-8 1.2.3 3.11.2 - 1.1.2 + 1.1.5 3.13.0 1.9.7 1.14 From 0d8e2b1166c27d8fcabff80502d8013eae564577 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:35:30 +0200 Subject: [PATCH 178/577] build(deps): bump commons-io:commons-io from 2.15.1 to 2.16.1 (#1635) Bumps commons-io:commons-io from 2.15.1 to 2.16.1. --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index c3bfca0df..f4aaf3715 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -103,7 +103,7 @@ commons-io commons-io - 2.15.1 + 2.16.1 From 5b370d6a778b2c1e12584385cdda395856664acd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 12:05:46 +0200 Subject: [PATCH 179/577] build(deps-dev): bump com.amazonaws:amazon-sqs-java-extended-client-lib (#1650) Bumps [com.amazonaws:amazon-sqs-java-extended-client-lib](https://github.com/awslabs/amazon-sqs-java-extended-client-lib) from 2.0.4 to 2.1.0. --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index f4aaf3715..6eb67d4d5 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -84,7 +84,7 @@ com.amazonaws amazon-sqs-java-extended-client-lib - 2.0.4 + 2.1.0 test From 8a1092185e546af3d33f3afb2c6d9a51ed50f4e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:32:16 +0000 Subject: [PATCH 180/577] build(deps): bump aws.sdk.version from 2.25.26 to 2.26.7 (#1660) Bumps `aws.sdk.version` from 2.25.26 to 2.26.7. Updates `software.amazon.awssdk:url-connection-client` from 2.25.26 to 2.26.7 Updates `software.amazon.awssdk:sdk-core` from 2.25.26 to 2.26.7 Updates `software.amazon.awssdk:kinesis` from 2.25.26 to 2.26.7 Updates `software.amazon.awssdk:sqs` from 2.25.26 to 2.26.7 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.25.26 to 2.26.7 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 3d94982fd..b9a523d04 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 11 11 1.9.20.1 - 2.25.26 + 2.26.7 From 814b3fbae9b3482b61f8a0ae8bacb0c44416bd6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:33:16 +0000 Subject: [PATCH 181/577] build(deps): bump software.amazon.payloadoffloading:payloadoffloading-common (#1661) Bumps [software.amazon.payloadoffloading:payloadoffloading-common](https://github.com/awslabs/payload-offloading-java-common-lib-for-aws) from 2.1.3 to 2.2.0. - [Release notes](https://github.com/awslabs/payload-offloading-java-common-lib-for-aws/releases) - [Commits](https://github.com/awslabs/payload-offloading-java-common-lib-for-aws/compare/v2.1.3...v2.2.0) --- updated-dependencies: - dependency-name: software.amazon.payloadoffloading:payloadoffloading-common dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d96c51d2f..61946007a 100644 --- a/pom.xml +++ b/pom.xml @@ -73,7 +73,7 @@ 2.17.0 2.25.35 2.15.1 - 2.1.3 + 2.2.0 UTF-8 1.2.3 3.11.2 From 1074aab205149b89423e82e1e6738690357c9d98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:34:13 +0000 Subject: [PATCH 182/577] build(deps): bump jackson.version from 2.17.0 to 2.17.1 (#1664) Bumps `jackson.version` from 2.17.0 to 2.17.1. Updates `com.fasterxml.jackson.core:jackson-databind` from 2.17.0 to 2.17.1 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.core:jackson-core` from 2.17.0 to 2.17.1 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.17.0...jackson-core-2.17.1) Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.17.0 to 2.17.1 --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 61946007a..0b51e0086 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ 2.20.0 2.23.1 2.0.7 - 2.17.0 + 2.17.1 2.25.35 2.15.1 2.2.0 From 42b8325b893d2bfe5c413388ed427e76c64f3d29 Mon Sep 17 00:00:00 2001 From: jdoherty Date: Mon, 24 Jun 2024 12:37:04 +0100 Subject: [PATCH 183/577] feat: upgraded embedded metrics library for high resolution metrics (#1550) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * upgraded embedded metrics library and associated tests * Removing LambdaJsonLayout from logging in examples (#1545) * updated formatting and changed assertion for sonar * fix example * do not build on java 8 for v2 (oopsy) * spotbugs fix * update documentation --------- Co-authored-by: ritigupt <102658810+ritigupt@users.noreply.github.com> Co-authored-by: Scott Gerring Co-authored-by: Jerome Van Der Linden Co-authored-by: Jérôme Van Der Linden <117538+jeromevdl@users.noreply.github.com> --- docs/core/metrics.md | 112 ++++++------------ .../sam/src/main/java/helloworld/App.java | 3 + pom.xml | 2 +- .../lambda/powertools/e2e/Function.java | 14 ++- .../amazon/lambda/powertools/e2e/Input.java | 10 ++ .../amazon/lambda/powertools/MetricsE2ET.java | 39 +++++- .../powertools/metrics/MetricsLoggerTest.java | 11 ++ ...rtoolsMetricsTooManyDimensionsHandler.java | 11 +- .../internal/LambdaMetricsAspectTest.java | 6 +- spotbugs-exclude.xml | 4 + 10 files changed, 123 insertions(+), 89 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index e06ab6d10..165c26e1c 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -28,9 +28,7 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar ## Install - Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. - -=== "Maven Java 11+" +=== "Maven" ```xml hl_lines="3-7 16 18 24-27" @@ -75,52 +73,7 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar ``` -=== "Maven Java 1.8" - - ```xml hl_lines="3-7 16 18 24-27" - - ... - - software.amazon.lambda - powertools-metrics - {{ powertools.version }} - - ... - - ... - - - - ... - - org.codehaus.mojo - aspectj-maven-plugin - 1.14.0 - - 1.8 - 1.8 - 1.8 - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - ... - - - ``` - -=== "Gradle Java 11+" +=== "Gradle" ```groovy hl_lines="3 11" plugins { @@ -140,34 +93,14 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar targetCompatibility = 11 ``` -=== "Gradle Java 1.8" - - ```groovy hl_lines="3 11" - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' - } - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' - } - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - ``` - ## Getting started Metric has two global settings that will be used across all metrics emitted: -Setting | Description | Environment variable | Constructor parameter -------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- -**Metric namespace** | Logical container where all metrics will be placed e.g. `ServerlessAirline` | `POWERTOOLS_METRICS_NAMESPACE` | `namespace` -**Service** | Optionally, sets **service** metric dimension across all metrics e.g. `payment` | `POWERTOOLS_SERVICE_NAME` | `service` +| Setting | Description | Environment variable | Constructor parameter | +|----------------------|---------------------------------------------------------------------------------|--------------------------------|-----------------------| +| **Metric namespace** | Logical container where all metrics will be placed e.g. `ServerlessAirline` | `POWERTOOLS_METRICS_NAMESPACE` | `namespace` | +| **Service** | Optionally, sets **service** metric dimension across all metrics e.g. `payment` | `POWERTOOLS_SERVICE_NAME` | `service` | !!! tip "Use your application or main service as the metric namespace to easily group all metrics" @@ -198,7 +131,7 @@ Setting | Description | Environment variable | Constructor parameter @Override @Metrics(namespace = "ExampleApplication", service = "booking") public Object handleRequest(Object input, Context context) { - ... + // ... } } ``` @@ -224,7 +157,7 @@ You can create metrics using `putMetric`, and manually create dimensions for all public Object handleRequest(Object input, Context context) { metricsLogger.putDimensions(DimensionSet.of("environment", "prod")); metricsLogger.putMetric("SuccessfulBooking", 1, Unit.COUNT); - ... + // ... } } ``` @@ -234,6 +167,35 @@ You can create metrics using `putMetric`, and manually create dimensions for all !!! note "Metrics overflow" CloudWatch EMF supports a max of 100 metrics. Metrics utility will flush all metrics when adding the 100th metric while subsequent metrics will be aggregated into a new EMF object, for your convenience. + +### Adding high-resolution metrics + +You can create [high-resolution metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html#high-resolution-metrics) +passing a `storageResolution` to the `putMetric` method: + +=== "HigResMetricsHandler.java" + + ```java hl_lines="3 13" + import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; + import software.amazon.cloudwatchlogs.emf.model.StorageResolution; + + public class MetricsEnabledHandler implements RequestHandler { + + MetricsLogger metricsLogger = MetricsUtils.metricsLogger(); + + @Override + @Metrics(namespace = "ExampleApplication", service = "booking") + public Object handleRequest(Object input, Context context) { + // ... + metricsLogger.putMetric("SuccessfulBooking", 1, Unit.COUNT, StorageResolution.HIGH); + } + } + ``` + +!!! info "When is it useful?" + High-resolution metrics are data with a granularity of one second and are very useful in several situations such as telemetry, time series, real-time incident management, and others. + ### Flushing metrics The `@Metrics` annotation **validates**, **serializes**, and **flushes** all your metrics. During metrics validation, diff --git a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java index b1a701b8f..e7c410042 100644 --- a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java @@ -34,6 +34,7 @@ import org.slf4j.LoggerFactory; import org.slf4j.MDC; import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.StorageResolution; import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.metrics.Metrics; @@ -64,6 +65,8 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); }); + metricsLogger().putMetric("CustomMetric3", 1, Unit.COUNT, StorageResolution.HIGH); + MDC.put("test", "willBeLogged"); APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() diff --git a/pom.xml b/pom.xml index 0b51e0086..168243622 100644 --- a/pom.xml +++ b/pom.xml @@ -88,7 +88,7 @@ 3.3.0 3.2.4 5.10.2 - 1.0.6 + 4.1.2 0.6.0 1.6.0 diff --git a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index d9cf575c3..a86e515f7 100644 --- a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -18,9 +18,15 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.StorageResolution; import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.metrics.Metrics; import software.amazon.lambda.powertools.metrics.MetricsUtils; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; +import java.time.Instant; + public class Function implements RequestHandler { @@ -29,11 +35,17 @@ public class Function implements RequestHandler { @Metrics(captureColdStart = true) public String handleRequest(Input input, Context context) { + Instant currentTimeTruncatedPlusThirty = + LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES).toInstant(ZoneOffset.UTC).plusSeconds(30); + metricsLogger.setTimestamp(currentTimeTruncatedPlusThirty); + DimensionSet dimensionSet = new DimensionSet(); input.getDimensions().forEach((key, value) -> dimensionSet.addDimension(key, value)); metricsLogger.putDimensions(dimensionSet); - input.getMetrics().forEach((key, value) -> metricsLogger.putMetric(key, value, Unit.COUNT)); + input.getMetrics().forEach((key, value) -> metricsLogger.putMetric(key, value, Unit.COUNT, + input.getHighResolution().equalsIgnoreCase("true") ? StorageResolution.HIGH : + StorageResolution.STANDARD)); return "OK"; } diff --git a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java index 18c4eb747..1328ded77 100644 --- a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java +++ b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java @@ -21,6 +21,8 @@ public class Input { private Map dimensions; + private String highResolution; + public Input() { } @@ -32,6 +34,14 @@ public void setMetrics(Map metrics) { this.metrics = metrics; } + public String getHighResolution() { + return highResolution; + } + + public void setHighResolution(String highResolution) { + this.highResolution = highResolution; + } + public Map getDimensions() { return dimensions; } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java index 80673b995..235255dff 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java @@ -18,6 +18,10 @@ import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT; import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.temporal.ChronoUnit; import java.util.Collections; import java.util.List; import java.util.Map; @@ -66,12 +70,20 @@ public static void tearDown() { @Test public void test_recordMetrics() { // GIVEN + + Instant currentTimeTruncatedToMinutes = + LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES).toInstant(ZoneOffset.UTC); + String event1 = - "{ \"metrics\": {\"orders\": 1, \"products\": 4}, \"dimensions\": { \"Environment\": \"test\"} }"; + "{ \"metrics\": {\"orders\": 1, \"products\": 4}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"false\"}"; + String event2 = + "{ \"metrics\": {\"orders\": 1, \"products\": 8}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"true\"}"; // WHEN InvocationResult invocationResult = invokeFunction(functionName, event1); + invokeFunction(functionName, event2); + // THEN MetricsFetcher metricsFetcher = new MetricsFetcher(); List coldStart = @@ -84,18 +96,35 @@ public void test_recordMetrics() { List orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, "orders", Collections.singletonMap("Environment", "test")); - assertThat(orderMetrics.get(0)).isEqualTo(1); + assertThat(orderMetrics.get(0)).isEqualTo(2); List productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, "products", Collections.singletonMap("Environment", "test")); - assertThat(productMetrics.get(0)).isEqualTo(4); + + // When searching across a 1 minute time period with a period of 60 we find both metrics and the sum is 12 + + assertThat(productMetrics.get(0)).isEqualTo(12); + orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, "orders", Collections.singletonMap("Service", service)); - assertThat(orderMetrics.get(0)).isEqualTo(1); + assertThat(orderMetrics.get(0)).isEqualTo(2); productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, "products", Collections.singletonMap("Service", service)); - assertThat(productMetrics.get(0)).isEqualTo(4); + assertThat(productMetrics.get(0)).isEqualTo(12); + + Instant searchStartTime = currentTimeTruncatedToMinutes.plusSeconds(15); + Instant searchEndTime = currentTimeTruncatedToMinutes.plusSeconds(45); + + List productMetricDataResult = + metricsFetcher.fetchMetrics(searchStartTime, searchEndTime, 1, namespace, + "products", Collections.singletonMap("Environment", "test")); + +// We are searching across the time period the metric was created but with a period of 1 second. Only the high resolution metric will be available at this point + + assertThat(productMetricDataResult.get(0)).isEqualTo(8); + + } } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java index 0402e3cc5..26ae41a00 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java @@ -25,6 +25,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Consumer; import org.junit.jupiter.api.AfterEach; @@ -35,6 +37,7 @@ import software.amazon.cloudwatchlogs.emf.config.SystemWrapper; import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.StorageResolution; import software.amazon.cloudwatchlogs.emf.model.Unit; class MetricsLoggerTest { @@ -245,6 +248,7 @@ private void testLogger(Consumer> methodToTest) { { metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1")); metricsLogger.putMetric("Metric1", 1, Unit.COUNT); + metricsLogger.putMetric("Metric2", 1, Unit.COUNT, StorageResolution.HIGH); }); assertThat(out.toString()) @@ -263,6 +267,13 @@ private void testLogger(Consumer> methodToTest) { assertThat(aws.get("CloudWatchMetrics")) .asString() .contains("Namespace=GlobalName"); + + ArrayList cloudWatchMetrics = (ArrayList) aws.get("CloudWatchMetrics"); + LinkedHashMap values = + (java.util.LinkedHashMap) cloudWatchMetrics.get(0); + ArrayList metricArray = (ArrayList) values.get("Metrics"); + LinkedHashMap metricValues = (LinkedHashMap) metricArray.get(1); + assertThat(metricValues).containsEntry("StorageResolution", 1); }); } } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java index bc8a6e949..fd406b9cd 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java @@ -26,13 +26,14 @@ public class PowertoolsMetricsTooManyDimensionsHandler implements RequestHandler { @Override - @Metrics + @Metrics(namespace = "ExampleApplication",service = "booking") public Object handleRequest(Object input, Context context) { MetricsLogger metricsLogger = metricsLogger(); - - metricsLogger.setDimensions(IntStream.range(1, 15) - .mapToObj(value -> DimensionSet.of("Dimension" + value, "DimensionValue" + value)) - .toArray(DimensionSet[]::new)); + DimensionSet dimensionSet = new DimensionSet(); + for (int i = 0; i < 35; i++) { + dimensionSet.addDimension("Dimension" + i, "value" + i); + } + metricsLogger.setDimensions(dimensionSet); return null; } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java index 81e10ed22..d27af1fdf 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java @@ -40,6 +40,7 @@ import org.mockito.Mock; import org.mockito.MockedStatic; import software.amazon.cloudwatchlogs.emf.config.SystemWrapper; +import software.amazon.cloudwatchlogs.emf.exception.DimensionSetExceededException; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.metrics.MetricsUtils; import software.amazon.lambda.powertools.metrics.ValidationException; @@ -389,9 +390,10 @@ public void exceptionWhenTooManyDimensionsSet() { requestHandler = new PowertoolsMetricsTooManyDimensionsHandler(); - assertThatExceptionOfType(ValidationException.class) + assertThatExceptionOfType(DimensionSetExceededException.class) .isThrownBy(() -> requestHandler.handleRequest("input", context)) - .withMessage("Number of Dimensions must be in range of 0-9. Actual size: 14."); + .withMessage( + "Maximum number of dimensions allowed are 30. Account for default dimensions if not using setDimensions."); } } diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index ee44f7b4d..e959204ad 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -233,6 +233,10 @@ + + + + From 1317da4ad623dec472fbadb0f22486980356ee1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:38:26 +0000 Subject: [PATCH 184/577] build(deps): bump aws.xray.recorder.version from 2.15.1 to 2.16.0 (#1662) Bumps `aws.xray.recorder.version` from 2.15.1 to 2.16.0. Updates `com.amazonaws:aws-xray-recorder-sdk-core` from 2.15.1 to 2.16.0 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.15.1...v2.16.0) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core` from 2.15.1 to 2.16.0 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.15.1...v2.16.0) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2` from 2.15.1 to 2.16.0 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.15.1...v2.16.0) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor` from 2.15.1 to 2.16.0 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.15.1...v2.16.0) --- updated-dependencies: - dependency-name: com.amazonaws:aws-xray-recorder-sdk-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 168243622..acfe00fd1 100644 --- a/pom.xml +++ b/pom.xml @@ -72,7 +72,7 @@ 2.0.7 2.17.1 2.25.35 - 2.15.1 + 2.16.0 2.2.0 UTF-8 1.2.3 From adbd75069ca01d8e13ec692d4f648754e21fd999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Wed, 26 Jun 2024 09:17:25 +0000 Subject: [PATCH 185/577] chore(v2): remove java 1.8 relics from the code (#1659) * remove java 1.8 relics --- .github/workflows/pr_build.yml | 2 +- .github/workflows/publish.yml | 2 +- .github/workflows/run-e2e-tests.yml | 7 +- .github/workflows/spotbugs.yml | 2 +- README.md | 88 +------------ docs/core/tracing.md | 72 +---------- docs/index.md | 120 ++---------------- docs/utilities/idempotency.md | 70 +--------- docs/utilities/large_messages.md | 71 +---------- docs/utilities/parameters.md | 80 +----------- docs/utilities/validation.md | 71 +---------- .../kotlin/build.gradle.kts | 2 +- .../powertools-examples-validation/pom.xml | 24 +--- pom.xml | 5 +- powertools-e2e-tests/handlers/pom.xml | 8 +- powertools-e2e-tests/pom.xml | 4 +- .../powertools/testutils/Infrastructure.java | 4 +- .../powertools/testutils/JavaRuntime.java | 2 - .../persistence/BasePersistenceStore.java | 24 ++-- .../powertools-logging-logback/pom.xml | 4 +- 20 files changed, 59 insertions(+), 603 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 634a4ee0f..1ff2dc48b 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -51,7 +51,7 @@ jobs: strategy: max-parallel: 5 matrix: - java: [8, 11, 17, 21] + java: [11, 17, 21] name: Java ${{ matrix.java }} env: JAVA: ${{ matrix.java }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d2d47b308..68c4d2e52 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,7 +13,7 @@ jobs: uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'corretto' - java-version: 8 + java-version: 11 server-id: ossrh server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 13c84befe..86d66156b 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -33,7 +33,7 @@ jobs: strategy: max-parallel: 4 matrix: - java: [ 8, 11, 17, 21 ] + java: [ 11, 17, 21 ] name: End-to-end tests java${{ matrix.java }} env: AWS_DEFAULT_REGION: eu-west-1 @@ -54,12 +54,7 @@ jobs: with: role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} aws-region: ${{ env.AWS_DEFAULT_REGION }} - - - name: Build with Maven Java 8 - if: ${{ matrix.java == '8' }} # If 8 exclude the examples directory - run: mvn -DskipTests install --file pom.xml -pl '!software.amazon.lambda.examples:powertools-examples-idempotency,!software.amazon.lambda.examples:powertools-examples-batch,!software.amazon.lambda.examples:powertools-examples-cloudformation,!software.amazon.lambda.examples:powertools-examples-core-utilities-cdk,!software.amazon.lambda.examples:powertools-examples-core-utilities-sam,!software.amazon.lambda.examples:powertools-examples-core-utilities-serverless,!software.amazon.lambda.examples:powertools-examples-core-utilities-terraform,!software.amazon.lambda.examples:powertools-examples-parameters,!software.amazon.lambda.examples:powertools-examples-serialization,!software.amazon.lambda.examples:powertools-examples-validation,!software.amazon.lambda.examples:cdk,!software.amazon.lambda:powertools-examples' - name: Build with Maven - if: ${{ matrix.java != '8' }} # If not 8 don't exclude the examples directory run: mvn -DskipTests install --file pom.xml - name: Run e2e test with Maven run: mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml diff --git a/.github/workflows/spotbugs.yml b/.github/workflows/spotbugs.yml index f0d50d8c5..a75cba8f1 100644 --- a/.github/workflows/spotbugs.yml +++ b/.github/workflows/spotbugs.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Setup java JDK 1.8 + - name: Setup java JDK 11 uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'corretto' diff --git a/README.md b/README.md index 83b026d15..bf04b54b1 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,10 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your ``` -Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project. A different configuration is needed for projects on Java 8. +Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project.

- Maven - Java 11 and newer + Maven ```xml @@ -52,9 +52,9 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam aspectj-maven-plugin 1.13.1 - 1.8 - 1.8 - 1.8 + 11 + 11 + 11 software.amazon.lambda @@ -85,51 +85,7 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam
-Maven - Java 8 - -```xml - - - ... - - org.codehaus.mojo - aspectj-maven-plugin - 1.14.0 - - 1.8 - 1.8 - 1.8 - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - ... - - -``` -
- -
-Gradle - Java 11+ +Gradle ```groovy @@ -160,38 +116,9 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam ```
-
-Gradle - Java 8 - -```groovy - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' - } - - // the freefair aspect plugins targets gradle 7.6.1 - // https://docs.freefair.io/gradle-plugins/6.6.3/reference/ - wrapper { - gradleVersion = "7.6.1" - } - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' - aspect 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' - aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' - } - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 -``` -
### Java Compatibility -Powertools for AWS Lambda (Java) supports all Java version from 8 up to 21 as well as the +Powertools for AWS Lambda (Java) supports all Java version from 11 up to 21 as well as the [corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). For the modules that provide annotations, Powertools for AWS Lambda (Java) leverages the **aspectj** library. You may need to add the good version of `aspectjrt` to your dependencies based on the JDK used for building your function: @@ -209,7 +136,6 @@ You may need to add the good version of `aspectjrt` to your dependencies based o | JDK version | aspectj version | |-------------|-----------------| -| `1.8` | `1.9.7` | | `11-17` | `1.9.20.1` | | `21` | `1.9.21` | diff --git a/docs/core/tracing.md b/docs/core/tracing.md index 17e81b867..4cb06fc29 100644 --- a/docs/core/tracing.md +++ b/docs/core/tracing.md @@ -17,9 +17,7 @@ a provides functionality to reduce the overhead of performing common tracing tas ## Install -Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. - -=== "Maven Java 11+" +=== "Maven" ```xml hl_lines="3-7 16 18 24-27" @@ -64,52 +62,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl
``` -=== "Maven Java 1.8" - - ```xml hl_lines="3-7 16 18 24-27" - - ... - - software.amazon.lambda - powertools-tracing - {{ powertools.version }} - - ... - - ... - - - - ... - - org.codehaus.mojo - aspectj-maven-plugin - 1.14.0 - - 1.8 - 1.8 - 1.8 - - - software.amazon.lambda - powertools-tracing - - - - - - - compile - - - - - ... - - - ``` - -=== "Gradle Java 11+" +=== "Gradle" ```groovy hl_lines="3 11" plugins { @@ -129,27 +82,6 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl targetCompatibility = 11 ``` -=== "Gradle Java 1.8" - - ```groovy hl_lines="3 11" - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' - } - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' - } - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - ``` - - ## Initialization Before your use this utility, your AWS Lambda function [must have permissions](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html#services-xray-permissions) to send traces to AWS X-Ray. diff --git a/docs/index.md b/docs/index.md index 1c5dfac85..9092adc09 100644 --- a/docs/index.md +++ b/docs/index.md @@ -86,9 +86,7 @@ Powertools for AWS Lambda (Java) dependencies are available in Maven Central. Yo * [Maven](https://maven.apache.org/) * [Gradle](https://gradle.org) -Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. - -=== "Maven Java 11+" +=== "Maven" ```xml @@ -151,70 +149,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl
``` -=== "Maven Java 1.8" - - ```xml - - ... - - software.amazon.lambda - powertools-tracing - {{ powertools.version }} - - - software.amazon.lambda - powertools-logging - {{ powertools.version }} - - - software.amazon.lambda - powertools-metrics - {{ powertools.version }} - - ... - - ... - - - - ... - - org.codehaus.mojo - aspectj-maven-plugin - 1.14.0 - - 1.8 - 1.8 - 1.8 - - - software.amazon.lambda - powertools-tracing - - - software.amazon.lambda - powertools-logging - - - software.amazon.lambda - powertools-metrics - - - - - - - compile - - - - - ... - - - ``` - -=== "Gradle Java 11+" +=== "Gradle" ```groovy @@ -243,36 +178,6 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl targetCompatibility = 11 ``` -=== "Gradle Java 1.8" - - ```groovy - - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' - } - - // the freefair aspect plugins targets gradle 7.6.1 - // https://docs.freefair.io/gradle-plugins/6.6.3/reference/ - wrapper { - gradleVersion = "7.6.1" - } - - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' - aspect 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' - aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' - } - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - ``` - ???+ tip "Why a different configuration?" Powertools for AWS Lambda (Java) is using [AspectJ](https://eclipse.dev/aspectj/doc/released/progguide/starting.html) internally to handle annotations. Recently, in order to support Java 17 we had to move to `dev.aspectj:aspectj-maven-plugin` because @@ -281,7 +186,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl while `dev.aspectj:aspectj-maven-plugin` is based on AspectJ 1.9.8, compiled for Java 11+. ### Java Compatibility -Powertools for AWS Lambda (Java) supports all Java version from 8 up to 21 as well as the +Powertools for AWS Lambda (Java) supports all Java version from 11 up to 21 as well as the [corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). For the following modules, Powertools for AWS Lambda (Java) leverages the **aspectj** library to provide annotations: @@ -308,7 +213,6 @@ Use the following [dependency matrix](https://github.com/eclipse-aspectj/aspectj | JDK version | aspectj version | |-------------|-----------------| -| `1.8` | `1.9.7` | | `11-17` | `1.9.20.1` | | `21` | `1.9.21` | @@ -317,13 +221,13 @@ Use the following [dependency matrix](https://github.com/eclipse-aspectj/aspectj !!! info **Explicit parameters take precedence over environment variables.** -| Environment variable | Description | Utility | -| ------------------------------------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | -| **POWERTOOLS_SERVICE_NAME** | Sets service name used for tracing namespace, metrics dimension and structured logging | All | -| **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics) | -| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logging) | -| **POWERTOOLS_LOG_LEVEL** | Sets logging level | [Logging](./core/logging) | -| **POWERTOOLS_LOGGER_LOG_EVENT** | Enables/Disables whether to log the incoming event when using the aspect | [Logging](./core/logging) | -| **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Enables/Disables tracing mode to capture method response | [Tracing](./core/tracing) | -| **POWERTOOLS_TRACER_CAPTURE_ERROR** | Enables/Disables tracing mode to capture method error | [Tracing](./core/tracing) | +| Environment variable | Description | Utility | +|----------------------------------------|----------------------------------------------------------------------------------------|---------------------------| +| **POWERTOOLS_SERVICE_NAME** | Sets service name used for tracing namespace, metrics dimension and structured logging | All | +| **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics) | +| **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logging) | +| **POWERTOOLS_LOG_LEVEL** | Sets logging level | [Logging](./core/logging) | +| **POWERTOOLS_LOGGER_LOG_EVENT** | Enables/Disables whether to log the incoming event when using the aspect | [Logging](./core/logging) | +| **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Enables/Disables tracing mode to capture method response | [Tracing](./core/tracing) | +| **POWERTOOLS_TRACER_CAPTURE_ERROR** | Enables/Disables tracing mode to capture method error | [Tracing](./core/tracing) | diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index f4defbdfd..240752a55 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -26,9 +26,8 @@ times with the same parameters**. This makes idempotent operations safe to retry ## Getting started ### Installation -Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. -=== "Maven Java 11+" +=== "Maven" ```xml hl_lines="3-7 16 18 24-27" @@ -73,52 +72,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl
``` -=== "Maven Java 1.8" - - ```xml hl_lines="3-7 16 18 24-27" - - ... - - software.amazon.lambda - powertools-idempotency-dynamodb - {{ powertools.version }} - - ... - - ... - - - - ... - - org.codehaus.mojo - aspectj-maven-plugin - 1.14.0 - - 1.8 - 1.8 - 1.8 - - - software.amazon.lambda - powertools-idempotency-dynamodb - - - - - - - compile - - - - - ... - - - ``` - -=== "Gradle Java 11+" +=== "Gradle" ```groovy hl_lines="3 11" plugins { @@ -138,26 +92,6 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl targetCompatibility = 11 // or higher ``` -=== "Gradle Java 1.8" - - ```groovy hl_lines="3 11" - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' - } - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-idempotency-dynamodb:{{ powertools.version }}' - } - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - ``` - ### Required resources Before getting started, you need to create a persistent storage layer where the idempotency utility can store its state - your Lambda functions will need read and write access to it. diff --git a/docs/utilities/large_messages.md b/docs/utilities/large_messages.md index 2f974c3b5..29244de98 100644 --- a/docs/utilities/large_messages.md +++ b/docs/utilities/large_messages.md @@ -94,9 +94,7 @@ of amazon-sns-java-extended-client-lib. ## Install -Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. - -=== "Maven Java 11+" +=== "Maven" ```xml hl_lines="3-7 16 18 24-27" @@ -141,52 +139,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl ``` -=== "Maven Java 1.8" - - ```xml hl_lines="3-7 16 18 24-27" - - ... - - software.amazon.lambda - powertools-large-messages - {{ powertools.version }} - - ... - - ... - - - - ... - - org.codehaus.mojo - aspectj-maven-plugin - 1.14.0 - - 1.8 - 1.8 - 1.8 - - - software.amazon.lambda - powertools-large-messages - - - - - - - compile - - - - - ... - - - ``` - -=== "Gradle Java 11+" +=== "Gradle" ```groovy hl_lines="3 11" plugins { @@ -206,26 +159,6 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl targetCompatibility = 11 // or higher ``` -=== "Gradle Java 1.8" - - ```groovy hl_lines="3 11" - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' - } - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-large-messages:{{ powertools.version }}' - } - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - ``` - ## Permissions As the utility interacts with Amazon S3, the lambda function must have the following permissions diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index 46c7e8071..ab9c04c64 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -26,10 +26,9 @@ package: You can easily mix and match parameter providers within the same project for different needs. -Depending on which Java version you are using, you configuration will differ. Note that you must also provide -the concrete parameters module you want to use below - see the TODOs! +Note that you must provide the concrete parameters module you want to use below - see the TODOs! -=== "Maven Java 11+" +=== "Maven" ```xml hl_lines="4-12 17 24 30-34" @@ -81,59 +80,7 @@ the concrete parameters module you want to use below - see the TODOs! ``` -=== "Maven Java 1.8" - - ```xml hl_lines="4-12 17 24 30-34" - - ... - - software.amazon.lambda - - - powertools-parameters-secrets - powertools-parameters-ssm - powertools-parameters-dynamodb - powertools-parameters-appconfig - - {{ powertools.version }} - - ... - - ... - - - - ... - - org.codehaus.mojo - aspectj-maven-plugin - 1.14.0 - - 1.8 - 1.8 - 1.8 - - - - software.amazon.lambda - powertools-parameters-secrets - - - - - - - compile - - - - - ... - - - ``` - -=== "Gradle Java 11+" +=== "Gradle" ```groovy hl_lines="3 11 12" plugins { @@ -154,27 +101,6 @@ the concrete parameters module you want to use below - see the TODOs! targetCompatibility = 11 // or higher ``` -=== "Gradle Java 1.8" - - ```groovy hl_lines="3 11 12" - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' - } - - repositories { - mavenCentral() - } - - // TODO! Provide an aspectLibrary for each of the parameters module(s) you want to use here - dependencies { - aspect 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}' - } - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - ``` - **IAM Permissions** This utility requires additional permissions to work as expected. See the table below: diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index dfd97e0d4..cc1c71bda 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -12,9 +12,8 @@ This utility provides JSON Schema validation for payloads held within events and * JMESPath support validate only a sub part of the event ## Install -Depending on your version of Java (either Java 1.8 or 11+), the configuration slightly changes. -=== "Maven Java 11+" +=== "Maven" ```xml hl_lines="3-7 16 18 24-27" ... @@ -58,52 +57,7 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl ``` -=== "Maven Java 1.8" - - ```xml hl_lines="3-7 16 18 24-27" - - ... - - software.amazon.lambda - powertools-validation - {{ powertools.version }} - - ... - - ... - - - - ... - - org.codehaus.mojo - aspectj-maven-plugin - 1.14.0 - - 1.8 - 1.8 - 1.8 - - - software.amazon.lambda - powertools-validation - - - - - - - compile - - - - - ... - - - ``` - -=== "Gradle Java 11+" +=== "Gradle" ```groovy hl_lines="3 11" plugins { @@ -123,27 +77,6 @@ Depending on your version of Java (either Java 1.8 or 11+), the configuration sl targetCompatibility = 11 // or higher ``` -=== "Gradle Java 1.8" - - ```groovy hl_lines="3 11" - plugins { - id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '6.6.3' - } - - repositories { - mavenCentral() - } - - dependencies { - aspect 'software.amazon.lambda:powertools-validation:{{ powertools.version }}' - } - - sourceCompatibility = 1.8 - targetCompatibility = 1.8 - ``` - - ## Validating events You can validate inbound and outbound events using `@Validation` annotation. diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index b37ef6d31..3c84ce7f4 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { aspect("software.amazon.lambda:powertools-tracing:2.0.0-SNAPSHOT") aspect("software.amazon.lambda:powertools-logging-log4j:2.0.0-SNAPSHOT") aspect("software.amazon.lambda:powertools-metrics:2.0.0-SNAPSHOT") - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.10") + implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } kotlin { diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index f2f6e1f08..d1973f3df 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -22,8 +22,8 @@ Powertools for AWS Lambda (Java) - Examples - Validation - 1.8 - 1.8 + 11 + 11 1.9.20.1 @@ -113,24 +113,4 @@ - - - - jdk8 - - (,11) - - - 1.9.7 - - - diff --git a/pom.xml b/pom.xml index acfe00fd1..aeb8ba6d4 100644 --- a/pom.xml +++ b/pom.xml @@ -64,8 +64,8 @@ - 1.8 - 1.8 + 11 + 11 3.1.2 2.20.0 2.23.1 @@ -661,7 +661,6 @@ false - com.puppycrawl.tools diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 1bf26f871..b55cf436a 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -12,8 +12,8 @@ 2.0.0-SNAPSHOT UTF-8 - 1.8 - 1.8 + 11 + 11 1.2.2 1.1.2 @@ -192,9 +192,9 @@ - jdk8to16 + jdk11to16 - [1.8,16] + [11,16] 1.9.7 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 6eb67d4d5..5171bb418 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -28,8 +28,8 @@ Powertools for AWS Lambda (Java)End-To-End Tests - 1.8 - 1.8 + 11 + 11 10.3.0 2.130.0 diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java index 28a0f2bb4..bce4bbf98 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java @@ -517,9 +517,7 @@ private JavaRuntime mapRuntimeVersion(String environmentVariableName) { if (javaVersion == null) { throw new IllegalArgumentException(environmentVariableName + " is not set"); } - if (javaVersion.startsWith("8")) { - ret = JavaRuntime.JAVA8AL2; - } else if (javaVersion.startsWith("11")) { + if (javaVersion.startsWith("11")) { ret = JavaRuntime.JAVA11; } else if (javaVersion.startsWith("17")) { ret = JavaRuntime.JAVA17; diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java index c75682949..53d35e86d 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java @@ -17,8 +17,6 @@ import software.amazon.awscdk.services.lambda.Runtime; public enum JavaRuntime { - JAVA8("java8", Runtime.JAVA_8, "1.8"), - JAVA8AL2("java8.al2", Runtime.JAVA_8_CORRETTO, "1.8"), JAVA11("java11", Runtime.JAVA_11, "11"), JAVA17("java17", Runtime.JAVA_17, "17"), JAVA21("java21", Runtime.JAVA_21, "21"); diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java index bafbcbd42..8b08434ba 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java @@ -14,20 +14,12 @@ package software.amazon.lambda.powertools.idempotency.persistence; +import static software.amazon.lambda.powertools.common.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; + import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectWriter; import io.burt.jmespath.Expression; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; -import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; -import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; -import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyKeyException; -import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyValidationException; -import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache; -import software.amazon.lambda.powertools.utilities.JsonConfig; - import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -41,8 +33,15 @@ import java.util.Spliterators; import java.util.stream.Stream; import java.util.stream.StreamSupport; - -import static software.amazon.lambda.powertools.common.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyKeyException; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyValidationException; +import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache; +import software.amazon.lambda.powertools.utilities.JsonConfig; /** * Persistence layer that will store the idempotency result. @@ -315,6 +314,7 @@ String generateHash(JsonNode data) { return String.format("%032x", new BigInteger(1, digest)); } + @SuppressWarnings("java:S4790") // Usage of MessageDigest is OK private MessageDigest getHashAlgorithm() { MessageDigest hashAlgorithm; try { diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index c43526dd4..11fc85b72 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -28,9 +28,7 @@ ch.qos.logback logback-classic - - 1.5.5 - provided + 1.5.5 com.sun.mail From 71109d90fb5297cbea3c693c26ad764899e097c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:04:39 +0000 Subject: [PATCH 186/577] build(deps): bump aws.sdk.version from 2.25.35 to 2.26.12 (#1681) Bumps `aws.sdk.version` from 2.25.35 to 2.26.12. Updates `software.amazon.awssdk:url-connection-client` from 2.25.35 to 2.26.12 Updates `software.amazon.awssdk:sdk-core` from 2.26.7 to 2.26.12 Updates `software.amazon.awssdk:kinesis` from 2.25.35 to 2.26.12 Updates `software.amazon.awssdk:sqs` from 2.25.35 to 2.26.12 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.26.7 to 2.26.12 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index b9a523d04..207040476 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 11 11 1.9.20.1 - 2.26.7 + 2.26.12 From 2285374225c108f8a5336038b468182d81bd7986 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:05:22 +0000 Subject: [PATCH 187/577] build(deps): bump org.apache.maven.plugins:maven-javadoc-plugin (#1683) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.3 to 3.7.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.3...maven-javadoc-plugin-3.7.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index aeb8ba6d4..e685d056c 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ 3.1.2 0.8.12 1.6.13 - 3.6.3 + 3.7.0 3.3.0 3.2.4 5.10.2 From 57f3efff187e8da8c487602d8cef15d6228a2108 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:10:38 +0000 Subject: [PATCH 188/577] build(deps): bump org.sonatype.plugins:nexus-staging-maven-plugin (#1682) Bumps org.sonatype.plugins:nexus-staging-maven-plugin from 1.6.13 to 1.7.0. --- updated-dependencies: - dependency-name: org.sonatype.plugins:nexus-staging-maven-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e685d056c..4ba84d4fc 100644 --- a/pom.xml +++ b/pom.xml @@ -83,7 +83,7 @@ 1.14 3.1.2 0.8.12 - 1.6.13 + 1.7.0 3.7.0 3.3.0 3.2.4 From b4f9ee932ca9794583c59d178c59b13db314215c Mon Sep 17 00:00:00 2001 From: Justin Tay <49700559+justin-tay@users.noreply.github.com> Date: Tue, 2 Jul 2024 19:54:48 +0800 Subject: [PATCH 189/577] build(deps): bump com.networknt:json-schema-validator from 1.0.87 to 1.4.3 (#1674) --- docs/utilities/validation.md | 7 ++++-- .../lambda/powertools/ValidationALBE2ET.java | 4 ++-- .../powertools/ValidationApiGWE2ET.java | 4 ++-- powertools-validation/pom.xml | 2 +- .../validation/ValidationConfig.java | 8 ++++++- .../validation/ValidationUtils.java | 23 ++++++++----------- .../validation/ValidationUtilsTest.java | 4 ++-- .../src/test/resources/schema_v7.json | 2 +- .../src/test/resources/schema_v7_ko.json | 2 +- 9 files changed, 31 insertions(+), 25 deletions(-) diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index cc1c71bda..226e10bb6 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -83,7 +83,9 @@ You can validate inbound and outbound events using `@Validation` annotation. You can also use the `Validator#validate()` methods, if you want more control over the validation process such as handling a validation error. -We support JSON schema version 4, 6, 7 and 201909 (from [jmespath-jackson library](https://github.com/burtcorp/jmespath-java)). +We support JSON schema version 4, 6, 7, 2019-09 and 2020-12 using the [NetworkNT JSON Schema Validator](https://github.com/networknt/json-schema-validator). ([Compatibility with JSON Schema versions](https://github.com/networknt/json-schema-validator/blob/master/doc/compatibility.md)). + +The validator is configured to enable format assertions by default even for 2019-09 and 2020-12. ### Validation annotation @@ -228,7 +230,8 @@ and [function](https://jmespath.org/tutorial.html#functions) expressions, where ## Change the schema version -By default, powertools-validation is configured with [V7](https://json-schema.org/draft-07/json-schema-release-notes.html). +By default, powertools-validation is configured to use [V7](https://json-schema.org/draft-07/json-schema-release-notes.html) as the default dialect if [`$schema`](https://json-schema.org/understanding-json-schema/reference/schema#schema) is not explicitly specified within the schema. If [`$schema`](https://json-schema.org/understanding-json-schema/reference/schema#schema) is explicitly specified within the schema, the validator will use the specified dialect. + You can use the `ValidationConfig` to change that behaviour. === "Handler with custom schema version" diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java index 324c77a34..41696943a 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java @@ -85,7 +85,7 @@ void test_invalidInboundSQSEvent() throws IOException { // THEN // invocation should fail inbound validation and return an error message JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); - assertThat(validJsonNode.get("errorMessage").asText()).contains("$.price: is missing but it is required"); + assertThat(validJsonNode.get("errorMessage").asText()).contains(": required property 'price' not found"); } @Test @@ -99,6 +99,6 @@ void test_invalidOutboundSQSEvent() throws IOException { // THEN // invocation should fail outbound validation and return 400 JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); - assertThat(validJsonNode.get("errorMessage").asText()).contains("$.price: must have an exclusive maximum value of 1000"); + assertThat(validJsonNode.get("errorMessage").asText()).contains("/price: must have an exclusive maximum value of 1000"); } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java index af7c7d87c..425399c95 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java @@ -86,7 +86,7 @@ void test_invalidInboundApiGWEvent() throws IOException { // invocation should fail inbound validation and return 400 JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(400); - assertThat(validJsonNode.get("body").asText()).contains("$.price: is missing but it is required"); + assertThat(validJsonNode.get("body").asText()).contains(": required property 'price' not found"); } @Test @@ -102,6 +102,6 @@ void test_invalidOutboundApiGWEvent() throws IOException { JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(400); assertThat(validJsonNode.get("body").asText()) - .contains("$.price: must have an exclusive maximum value of 1000"); + .contains("/price: must have an exclusive maximum value of 1000"); } } diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 0de38c1c1..fa299b591 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -65,7 +65,7 @@ com.networknt json-schema-validator - 1.0.87 + 1.4.3 com.amazonaws diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java index ccc5a4c2c..3f643ab00 100644 --- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java @@ -47,9 +47,15 @@ public SpecVersion.VersionFlag getSchemaVersion() { } /** - * Set the version of the json schema specifications (default is V7) + * Set the version of the json schema specifications to use if $schema is not + * explicitly specified within the schema (default is V7). If $schema is + * explicitly specified within the schema is explicitly specified within the + * schema, the validator will use the specified dialect. * * @param version May be V4, V6, V7, V201909 or V202012 + * @see Declaring + * a Dialect */ public void setSchemaVersion(SpecVersion.VersionFlag version) { if (version != jsonSchemaVersion) { diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java index 221e5fb1d..35b309f07 100644 --- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationUtils.java @@ -21,18 +21,16 @@ import com.fasterxml.jackson.databind.node.JsonNodeType; import com.fasterxml.jackson.databind.node.NullNode; import com.networknt.schema.JsonSchema; +import com.networknt.schema.SchemaLocation; import com.networknt.schema.SchemaValidatorsConfig; import com.networknt.schema.ValidationMessage; -import com.networknt.schema.uri.URITranslator; import io.burt.jmespath.Expression; import java.io.ByteArrayOutputStream; -import java.io.InputStream; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; -import software.amazon.lambda.powertools.validation.internal.ValidationAspect; /** * Validation utility, used to manually validate Json against Json Schema @@ -255,27 +253,26 @@ public static JsonSchema getJsonSchema(String schema, boolean validateSchema) { private static JsonSchema createJsonSchema(String schema) { JsonSchema jsonSchema; + SchemaValidatorsConfig config = SchemaValidatorsConfig.builder().formatAssertionsEnabled(true) + .preloadJsonSchemaRefMaxNestingDepth(10).build(); if (schema.startsWith(CLASSPATH)) { - String filePath = schema.substring(CLASSPATH.length()); - try (InputStream schemaStream = ValidationAspect.class.getResourceAsStream(filePath)) { - - SchemaValidatorsConfig config = new SchemaValidatorsConfig(); - config.addUriTranslator(URITranslator.prefix("https://json-schema.org", "resource:")); - - jsonSchema = ValidationConfig.get().getFactory().getSchema(schemaStream, config); + try { + jsonSchema = ValidationConfig.get().getFactory().getSchema(SchemaLocation.of(schema), config); } catch (Exception e) { + String filePath = schema.substring(CLASSPATH.length()); throw new IllegalArgumentException( - "'" + schema + "' is invalid, verify '" + filePath + "' is in your classpath"); + "'" + schema + "' is invalid, verify '" + filePath + "' is in your classpath", e); } } else { - jsonSchema = ValidationConfig.get().getFactory().getSchema(schema); + jsonSchema = ValidationConfig.get().getFactory().getSchema(schema, config); } return jsonSchema; } private static void validateSchema(String schema, JsonSchema jsonSchema) { - String schemaId = ValidationConfig.get().getSchemaVersion().getId().replace("https://json-schema.org", ""); + String schemaId = jsonSchema.getValidationContext().getMetaSchema().getIri() + .replace("https://json-schema.org", "").replace("http://json-schema.org", ""); try { validate(jsonSchema.getSchemaNode(), getJsonSchema(CLASSPATH + schemaId)); diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java index d80670669..73c3c6567 100644 --- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationUtilsTest.java @@ -48,7 +48,7 @@ public void testLoadSchemaV7OK() { ValidationConfig.get().setSchemaVersion(SpecVersion.VersionFlag.V7); JsonSchema jsonSchema = getJsonSchema("classpath:/schema_v7.json", true); assertThat(jsonSchema).isNotNull(); - assertThat(jsonSchema.getCurrentUri()).asString().isEqualTo("http://example.com/product.json"); + assertThat(jsonSchema.getId()).isEqualTo("http://example.com/product.json"); } @Test @@ -57,7 +57,7 @@ public void testLoadSchemaV7KO() { assertThatThrownBy(() -> getJsonSchema("classpath:/schema_v7_ko.json", true)) .isInstanceOf(IllegalArgumentException.class) .hasMessage( - "The schema classpath:/schema_v7_ko.json is not valid, it does not respect the specification /draft-07/schema"); + "The schema classpath:/schema_v7_ko.json is not valid, it does not respect the specification /draft-07/schema#"); } @Test diff --git a/powertools-validation/src/test/resources/schema_v7.json b/powertools-validation/src/test/resources/schema_v7.json index f38272f2d..e382b8971 100644 --- a/powertools-validation/src/test/resources/schema_v7.json +++ b/powertools-validation/src/test/resources/schema_v7.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-07/schema", + "$schema": "http://json-schema.org/draft-07/schema#", "$id": "http://example.com/product.json", "type": "object", "title": "Product schema", diff --git a/powertools-validation/src/test/resources/schema_v7_ko.json b/powertools-validation/src/test/resources/schema_v7_ko.json index f54bcb3c7..aed187c34 100644 --- a/powertools-validation/src/test/resources/schema_v7_ko.json +++ b/powertools-validation/src/test/resources/schema_v7_ko.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-07/schema", + "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "title": "Product schema", "description": "JSON schema to validate Products", From 749e9730cc3e5f7f87297c74837ae7f126b30fbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Wed, 3 Jul 2024 13:46:14 +0000 Subject: [PATCH 190/577] chore(v2): remove deprecated code (#1624) * remove deprecated code * fix tests * fix tests * remove v1 workflows * remove sqs example in doc --- .github/workflows/build-docs.yml | 1 - .github/workflows/pr_artifacts_size.yml | 6 +- .github/workflows/pr_build.yml | 18 ++-- .github/workflows/pr_build_v2.yml | 93 ------------------- .github/workflows/pr_iac_lint.yml | 2 - .github/workflows/run-e2e-tests-v2.yml | 58 ------------ .github/workflows/run-e2e-tests.yml | 8 +- .github/workflows/spotbugs.yml | 1 - examples/README.md | 1 - .../powertools/cloudformation/Response.java | 34 ------- .../CloudFormationResponseTest.java | 10 +- .../cloudformation/ResponseTest.java | 16 ++-- .../NoPhysicalResourceIdSetHandler.java | 6 +- .../powertools/metrics/MetricsUtils.java | 32 ------- .../powertools/metrics/MetricsLoggerTest.java | 12 --- powertools-tracing/pom.xml | 5 + .../lambda/powertools/tracing/Tracing.java | 16 ---- .../tracing/internal/LambdaTracingAspect.java | 10 +- ...erToolEnabledWithNoMetaDataDeprecated.java | 28 ------ .../internal/LambdaTracingAspectTest.java | 67 ++++++++----- 20 files changed, 78 insertions(+), 346 deletions(-) delete mode 100644 .github/workflows/pr_build_v2.yml delete mode 100644 .github/workflows/run-e2e-tests-v2.yml delete mode 100644 powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaDataDeprecated.java diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index a4ab6e7de..a75c13b52 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -3,7 +3,6 @@ name: Build Docs on: pull_request: branches: - - main - v2 paths: - 'docs/**' diff --git a/.github/workflows/pr_artifacts_size.yml b/.github/workflows/pr_artifacts_size.yml index e7e3158e3..c4d29205b 100644 --- a/.github/workflows/pr_artifacts_size.yml +++ b/.github/workflows/pr_artifacts_size.yml @@ -3,13 +3,11 @@ name: Artifacts Size on: pull_request: branches: - - main - v2 paths: - 'powertools-batch/**' - 'powertools-cloudformation/**' - - 'powertools-core/**' # not in v2 - - 'powertools-common/**' # v2 only + - 'powertools-common/**' - 'powertools-e2e-tests/**' - 'powertools-idempotency-core/**' - 'powertools-idempotency-dynamodb/**' @@ -18,8 +16,6 @@ on: - 'powertools-metrics/**' - 'powertools-parameters/**' - 'powertools-serialization/**' - - 'powertools-sqs/**' # not in v2 - - 'powertools-test-suite/**' # not in v2 - 'powertools-tracing/**' - 'powertools-validation/**' - 'pom.xml' diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 1ff2dc48b..2079bcb6b 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -3,11 +3,11 @@ name: Build on: pull_request: branches: - - main + - v2 paths: - 'powertools-batch/**' - 'powertools-cloudformation/**' - - 'powertools-core/**' + - 'powertools-common/**' - 'powertools-e2e-tests/**' - 'powertools-idempotency/**' - 'powertools-large-messages/**' @@ -15,8 +15,6 @@ on: - 'powertools-metrics/**' - 'powertools-parameters/**' - 'powertools-serialization/**' - - 'powertools-sqs/**' - - 'powertools-test-suite/**' - 'powertools-tracing/**' - 'powertools-validation/**' - 'examples/**' @@ -25,11 +23,11 @@ on: - '.github/workflows/**' push: branches: - - main + - v2 paths: - 'powertools-batch/**' - 'powertools-cloudformation/**' - - 'powertools-core/**' + - 'powertools-common/**' - 'powertools-e2e-tests/**' - 'powertools-idempotency/**' - 'powertools-large-messages/**' @@ -37,8 +35,6 @@ on: - 'powertools-metrics/**' - 'powertools-parameters/**' - 'powertools-serialization/**' - - 'powertools-sqs/**' - - 'powertools-test-suite/**' - 'powertools-tracing/**' - 'powertools-validation/**' - 'examples/**' @@ -70,12 +66,10 @@ jobs: - name: Build with Maven run: mvn -B install --file pom.xml - name: Build Gradle Example - Java - if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 - working-directory: examples/powertools-examples-core/gradle + working-directory: examples/powertools-examples-core-utilities/gradle run: ./gradlew build - name: Build Gradle Example - Kotlin - if: ${{ matrix.java == '8' }} # Gradle example can only be built on Java 8 - working-directory: examples/powertools-examples-core/kotlin + working-directory: examples/powertools-examples-core-utilities/kotlin run: ./gradlew build - name: Upload coverage to Codecov uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 diff --git a/.github/workflows/pr_build_v2.yml b/.github/workflows/pr_build_v2.yml deleted file mode 100644 index 2079bcb6b..000000000 --- a/.github/workflows/pr_build_v2.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: Build - -on: - pull_request: - branches: - - v2 - paths: - - 'powertools-batch/**' - - 'powertools-cloudformation/**' - - 'powertools-common/**' - - 'powertools-e2e-tests/**' - - 'powertools-idempotency/**' - - 'powertools-large-messages/**' - - 'powertools-logging/**' - - 'powertools-metrics/**' - - 'powertools-parameters/**' - - 'powertools-serialization/**' - - 'powertools-tracing/**' - - 'powertools-validation/**' - - 'examples/**' - - 'pom.xml' - - 'examples/pom.xml' - - '.github/workflows/**' - push: - branches: - - v2 - paths: - - 'powertools-batch/**' - - 'powertools-cloudformation/**' - - 'powertools-common/**' - - 'powertools-e2e-tests/**' - - 'powertools-idempotency/**' - - 'powertools-large-messages/**' - - 'powertools-logging/**' - - 'powertools-metrics/**' - - 'powertools-parameters/**' - - 'powertools-serialization/**' - - 'powertools-tracing/**' - - 'powertools-validation/**' - - 'examples/**' - - 'pom.xml' - - 'examples/pom.xml' - - '.github/workflows/**' -jobs: - build-corretto: - runs-on: ubuntu-latest - strategy: - max-parallel: 5 - matrix: - java: [11, 17, 21] - name: Java ${{ matrix.java }} - env: - JAVA: ${{ matrix.java }} - AWS_REGION: eu-west-1 - permissions: - id-token: write # needed to interact with GitHub's OIDC Token endpoint. - contents: read - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Setup java - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 - with: - distribution: 'corretto' - java-version: ${{ matrix.java }} - cache: 'maven' - - name: Build with Maven - run: mvn -B install --file pom.xml - - name: Build Gradle Example - Java - working-directory: examples/powertools-examples-core-utilities/gradle - run: ./gradlew build - - name: Build Gradle Example - Kotlin - working-directory: examples/powertools-examples-core-utilities/kotlin - run: ./gradlew build - - name: Upload coverage to Codecov - uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 - if: ${{ matrix.java == '11' }} # publish results once - with: - files: ./powertools-cloudformation/target/site/jacoco/jacoco.xml,./powertools-core/target/site/jacoco/jacoco.xml,./powertools-idempotency/target/site/jacoco/jacoco.xml,./powertools-logging/target/site/jacoco/jacoco.xml,./powertools-metrics/target/site/jacoco/jacoco.xml,./powertools-parameters/target/site/jacoco/jacoco.xml,./powertools-serialization/target/site/jacoco/jacoco.xml,./powertools-sqs/target/site/jacoco/jacoco.xml,./powertools-tracing/target/site/jacoco/jacoco.xml,./powertools-validation/target/site/jacoco/jacoco.xml,./powertools-large-messages/target/site/jacoco/jacoco.xml,./powertools-batch/target/site/jacoco/jacoco.xml - savepr: - runs-on: ubuntu-latest - name: Save PR number if running on PR by dependabot - if: github.actor == 'dependabot[bot]' - steps: - - name: Create Directory and save issue - run: | - mkdir -p ./pr - echo ${{ github.event.number }} - echo ${{ github.event.number }} > ./pr/NR - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - name: Upload artifact - with: - name: pr - path: pr/ diff --git a/.github/workflows/pr_iac_lint.yml b/.github/workflows/pr_iac_lint.yml index 09ba5f02b..531ccbbcb 100644 --- a/.github/workflows/pr_iac_lint.yml +++ b/.github/workflows/pr_iac_lint.yml @@ -3,11 +3,9 @@ name: Validate IaC on: push: branches: - - main - v2 pull_request: branches: - - main - v2 paths: - 'examples/**' diff --git a/.github/workflows/run-e2e-tests-v2.yml b/.github/workflows/run-e2e-tests-v2.yml deleted file mode 100644 index 255c89cfe..000000000 --- a/.github/workflows/run-e2e-tests-v2.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Run end-to-end tests - -on: - workflow_dispatch: - - push: - branches: - - v2 - paths: # add other modules when there are under e2e tests - - 'powertools-e2e-tests/**' - - 'powertools-batch/**' - - 'powertools-core/**' - - 'powertools-common/**' - - 'powertools-idempotency/**' - - 'powertools-large-message/**' - - 'powertools-logging/**' - - 'powertools-metrics/**' - - 'powertools-parameters/**' - - 'powertools-serialization/**' - - 'powertools-tracing/**' - - 'pom.xml' - - '.github/workflows/**' - - pull_request: - branches: - - v2 - paths: - - 'powertools-e2e-tests/**' - -jobs: - e2e: - runs-on: ubuntu-latest - strategy: - max-parallel: 4 - matrix: - java: [ 11, 17, 21 ] - name: End-to-end tests java${{ matrix.java }} - env: - AWS_DEFAULT_REGION: eu-west-1 - JAVA_VERSION: ${{ matrix.java }} - permissions: - id-token: write # needed to interact with GitHub's OIDC Token endpoint. - contents: read - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Setup java - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 - with: - distribution: 'corretto' - java-version: ${{ matrix.java }} - cache: maven - - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 - with: - role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: Run e2e test with Maven - run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml \ No newline at end of file diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 86d66156b..255c89cfe 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -5,7 +5,7 @@ on: push: branches: - - main + - v2 paths: # add other modules when there are under e2e tests - 'powertools-e2e-tests/**' - 'powertools-batch/**' @@ -23,7 +23,7 @@ on: pull_request: branches: - - main + - v2 paths: - 'powertools-e2e-tests/**' @@ -54,7 +54,5 @@ jobs: with: role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: Build with Maven - run: mvn -DskipTests install --file pom.xml - name: Run e2e test with Maven - run: mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml + run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml \ No newline at end of file diff --git a/.github/workflows/spotbugs.yml b/.github/workflows/spotbugs.yml index a75cba8f1..106905a70 100644 --- a/.github/workflows/spotbugs.yml +++ b/.github/workflows/spotbugs.yml @@ -3,7 +3,6 @@ name: SpotBugs on: pull_request: branches: - - main - v2 paths: - 'powertools-cloudformation/**' diff --git a/examples/README.md b/examples/README.md index 2e34513db..41640b5ad 100644 --- a/examples/README.md +++ b/examples/README.md @@ -14,7 +14,6 @@ Each example can be copied from its subdirectory and used independently of the r * [powertools-examples-idempotency](powertools-examples-idempotency) - An idempotent HTTP API * [powertools-examples-parameters](powertools-examples-parameters) - Uses the parameters module to provide runtime parameters to a function * [powertools-examples-serialization](powertools-examples-serialization) - Uses the serialization module to serialize and deserialize API Gateway & SQS payloads -* [powertools-examples-sqs](powertools-examples-sqs) - Processes SQS batch requests (**Deprecated** - will be replaced by `powertools-examples-batch` in version 2 of this library) * [powertools-examples-validation](powertools-examples-validation) - Uses the validation module to validate user requests received via API Gateway * [powertools-examples-cloudformation](powertools-examples-cloudformation) - Deploys a Cloudformation custom resource * [powertools-examples-batch](powertools-examples-batch) - Examples for each of the different batch processing deployments diff --git a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java index fe18000d4..215151d44 100644 --- a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java +++ b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java @@ -47,23 +47,6 @@ public static Builder builder() { return new Builder(); } - /** - * Creates a failed Response with no physicalResourceId set. Powertools for AWS Lambda (Java) will set the physicalResourceId to the - * Lambda LogStreamName - *

- * The value returned for a PhysicalResourceId can change custom resource update operations. If the value returned - * is the same, it is considered a normal update. If the value returned is different, AWS CloudFormation recognizes - * the update as a replacement and sends a delete request to the old resource. For more information, - * see AWS::CloudFormation::CustomResource. - * - * @return a failed Response with no value. - * @deprecated this method is not safe. Provide a physicalResourceId. - */ - @Deprecated - public static Response failed() { - return new Response(null, Status.FAILED, null, false); - } - /** * Creates a failed Response with a given physicalResourceId. * @@ -80,23 +63,6 @@ public static Response failed(String physicalResourceId) { return new Response(null, Status.FAILED, physicalResourceId, false); } - /** - * Creates a successful Response with no physicalResourceId set. Powertools for AWS Lambda (Java) will set the physicalResourceId to the - * Lambda LogStreamName - *

- * The value returned for a PhysicalResourceId can change custom resource update operations. If the value returned - * is the same, it is considered a normal update. If the value returned is different, AWS CloudFormation recognizes - * the update as a replacement and sends a delete request to the old resource. For more information, - * see AWS::CloudFormation::CustomResource. - * - * @return a success Response with no physicalResourceId value. - * @deprecated this method is not safe. Provide a physicalResourceId. - */ - @Deprecated - public static Response success() { - return new Response(null, Status.SUCCESS, null, false); - } - /** * Creates a successful Response with a given physicalResourceId. * diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java index 51f0e95f9..0701c98fe 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java @@ -38,7 +38,7 @@ import software.amazon.awssdk.utils.StringInputStream; import software.amazon.lambda.powertools.cloudformation.CloudFormationResponse.ResponseBody; -public class CloudFormationResponseTest { +class CloudFormationResponseTest { /** * Creates a mock CloudFormationCustomResourceEvent with a non-null response URL. @@ -215,7 +215,7 @@ void reasonIncludesLogStreamName() { } @Test - public void sendWithNoResponseData() throws Exception { + void sendWithNoResponseData() throws Exception { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); Context context = mock(Context.class); CloudFormationResponse cfnResponse = testableCloudFormationResponse(); @@ -237,7 +237,7 @@ public void sendWithNoResponseData() throws Exception { } @Test - public void sendWithNonNullResponseData() throws Exception { + void sendWithNonNullResponseData() throws Exception { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); Context context = mock(Context.class); CloudFormationResponse cfnResponse = testableCloudFormationResponse(); @@ -289,7 +289,7 @@ void responseBodyStreamSuccessResponse() throws Exception { Context context = mock(Context.class); CloudFormationResponse cfnResponse = testableCloudFormationResponse(); - StringInputStream stream = cfnResponse.responseBodyStream(event, context, Response.success()); + StringInputStream stream = cfnResponse.responseBodyStream(event, context, Response.success(null)); String expectedJson = "{" + "\"Status\":\"SUCCESS\"," + @@ -310,7 +310,7 @@ void responseBodyStreamFailedResponse() throws Exception { Context context = mock(Context.class); CloudFormationResponse cfnResponse = testableCloudFormationResponse(); - StringInputStream stream = cfnResponse.responseBodyStream(event, context, Response.failed()); + StringInputStream stream = cfnResponse.responseBodyStream(event, context, Response.failed(null)); String expectedJson = "{" + "\"Status\":\"FAILED\"," + diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java index 37fe73d0f..e577aecca 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java @@ -22,7 +22,7 @@ import java.util.Map; import org.junit.jupiter.api.Test; -public class ResponseTest { +class ResponseTest { @Test void defaultValues() { @@ -92,7 +92,7 @@ void jsonMapValueWithDefaultObjectMapper() { String expected = "{\"foo\":\"bar\"}"; assertThat(response.getJsonNode()).isNotNull(); - assertThat(response.getJsonNode().toString()).isEqualTo(expected); + assertThat(response.getJsonNode()).hasToString(expected); assertThat(response.toString()).contains("JSON = " + expected); } @@ -105,7 +105,7 @@ void jsonObjectValueWithDefaultObjectMapper() { .build(); String expected = "{\"PropertyWithLongName\":\"test\"}"; - assertThat(response.getJsonNode().toString()).isEqualTo(expected); + assertThat(response.getJsonNode()).hasToString(expected); assertThat(response.toString()).contains("JSON = " + expected); } @@ -119,7 +119,7 @@ void jsonObjectValueWithNullObjectMapper() { .build(); String expected = "{\"PropertyWithLongName\":\"test\"}"; - assertThat(response.getJsonNode().toString()).isEqualTo(expected); + assertThat(response.getJsonNode()).hasToString(expected); assertThat(response.toString()).contains("JSON = " + expected); } @@ -135,7 +135,7 @@ void jsonObjectValueWithCustomObjectMapper() { .build(); String expected = "{\"property-with-long-name\":10}"; - assertThat(response.getJsonNode().toString()).isEqualTo(expected); + assertThat(response.getJsonNode()).hasToString(expected); assertThat(response.toString()).contains("JSON = " + expected); } @@ -154,13 +154,13 @@ void jsonObjectValueWithPostConfiguredObjectMapper() { customMapper.setPropertyNamingStrategy(PropertyNamingStrategies.UPPER_CAMEL_CASE); String expected = "{\"property-with-long-name\":10}"; - assertThat(response.getJsonNode().toString()).isEqualTo(expected); + assertThat(response.getJsonNode()).hasToString(expected); assertThat(response.toString()).contains("JSON = " + expected); } @Test void successFactoryMethod() { - Response response = Response.success(); + Response response = Response.success(null); assertThat(response).isNotNull(); assertThat(response.getStatus()).isEqualTo(Response.Status.SUCCESS); @@ -168,7 +168,7 @@ void successFactoryMethod() { @Test void failedFactoryMethod() { - Response response = Response.failed(); + Response response = Response.failed(null); assertThat(response).isNotNull(); assertThat(response.getStatus()).isEqualTo(Response.Status.FAILED); diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java index 2bbda309f..e55abca03 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java @@ -23,16 +23,16 @@ public class NoPhysicalResourceIdSetHandler extends AbstractCustomResourceHandle @Override protected Response create(CloudFormationCustomResourceEvent event, Context context) { - return Response.success(); + return Response.success(null); } @Override protected Response update(CloudFormationCustomResourceEvent event, Context context) { - return Response.success(); + return Response.success(null); } @Override protected Response delete(CloudFormationCustomResourceEvent event, Context context) { - return Response.success(); + return Response.success(null); } } diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java index ba53bad1f..6c3a89a65 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java @@ -14,7 +14,6 @@ package software.amazon.lambda.powertools.metrics; -import static java.util.Objects.requireNonNull; import static java.util.Optional.ofNullable; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; import static software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect.REQUEST_ID_PROPERTY; @@ -63,23 +62,6 @@ public static void defaultDimensions(final DimensionSet... dimensionSets) { MetricsUtils.defaultDimensions = dimensionSets; } - /** - * Configure default dimension to be used by logger. - * By default, @{@link Metrics} annotation captures configured service as a dimension Service - * - * @param dimensionSet Default value of dimension set for logger - * @deprecated use {@link #defaultDimensions(DimensionSet...)} instead - */ - @Deprecated - public static void defaultDimensionSet(final DimensionSet dimensionSet) { - requireNonNull(dimensionSet, "Null dimension set not allowed"); - - if (dimensionSet.getDimensionKeys().size() > 0) { - defaultDimensions(dimensionSet); - } - } - - /** * Add and immediately flush a single metric. It will use the default namespace * specified either on {@link Metrics} annotation or via POWERTOOLS_METRICS_NAMESPACE env var. @@ -146,20 +128,6 @@ public static void withMetricsLogger(final Consumer logger) { } } - /** - * Provide and immediately flush a {@link MetricsLogger}. It uses the default namespace - * specified either on {@link Metrics} annotation or via POWERTOOLS_METRICS_NAMESPACE env var. - * It by default captures function_request_id as property if used together with {@link Metrics} annotation. It will also - * capture xray_trace_id as property if tracing is enabled. - * - * @param logger the MetricsLogger - * @deprecated use {@link MetricsUtils#withMetricsLogger} instead - */ - @Deprecated - public static void withMetricLogger(final Consumer logger) { - withMetricsLogger(logger); - } - public static DimensionSet[] getDefaultDimensions() { return Arrays.copyOf(defaultDimensions, defaultDimensions.length); } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java index 26ae41a00..518e11739 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java @@ -188,18 +188,6 @@ void metricsLoggerCaptureUtilityWithDefaultNameSpace() { testLogger(MetricsUtils::withMetricsLogger); } - @Test - void deprecatedMetricLoggerCaptureUtilityWithDefaultNameSpace() { - testLogger(MetricsUtils::withMetricLogger); - } - - @Test - void shouldThrowExceptionWhenDefaultDimensionIsNull() { - assertThatNullPointerException() - .isThrownBy(() -> MetricsUtils.defaultDimensionSet(null)) - .withMessage("Null dimension set not allowed"); - } - @Test void shouldUseTraceIdFromSystemPropertyIfEnvVarNotPresent() { try (MockedStatic mocked = mockStatic(SystemWrapper.class); diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 9d60d4f40..345f14194 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -78,6 +78,11 @@ junit-jupiter-engine test + + org.junit-pioneer + junit-pioneer + test + org.apache.commons commons-lang3 diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/Tracing.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/Tracing.java index 6f17a2e33..432e475a3 100644 --- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/Tracing.java +++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/Tracing.java @@ -50,22 +50,6 @@ public @interface Tracing { String namespace() default ""; - /** - * @deprecated As of release 1.2.0, replaced by captureMode() - * in order to support different modes and support via - * environment variables - */ - @Deprecated - boolean captureResponse() default true; - - /** - * @deprecated As of release 1.2.0, replaced by captureMode() - * in order to support different modes and support via - * environment variables - */ - @Deprecated - boolean captureError() default true; - String segmentName() default ""; CaptureMode captureMode() default CaptureMode.ENVIRONMENT_VAR; diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java index 198cb7f34..a4a48532c 100644 --- a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java +++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspect.java @@ -83,9 +83,8 @@ public Object around(ProceedingJoinPoint pjp, private boolean captureResponse(Tracing powerToolsTracing) { switch (powerToolsTracing.captureMode()) { case ENVIRONMENT_VAR: - boolean captureResponse = environmentVariable("POWERTOOLS_TRACER_CAPTURE_RESPONSE"); - return isEnvironmentVariableSet("POWERTOOLS_TRACER_CAPTURE_RESPONSE") ? captureResponse : - powerToolsTracing.captureResponse(); + return isEnvironmentVariableSet("POWERTOOLS_TRACER_CAPTURE_RESPONSE") + && environmentVariable("POWERTOOLS_TRACER_CAPTURE_RESPONSE"); case RESPONSE: case RESPONSE_AND_ERROR: return true; @@ -98,9 +97,8 @@ private boolean captureResponse(Tracing powerToolsTracing) { private boolean captureError(Tracing powerToolsTracing) { switch (powerToolsTracing.captureMode()) { case ENVIRONMENT_VAR: - boolean captureError = environmentVariable("POWERTOOLS_TRACER_CAPTURE_ERROR"); - return isEnvironmentVariableSet("POWERTOOLS_TRACER_CAPTURE_ERROR") ? captureError : - powerToolsTracing.captureError(); + return isEnvironmentVariableSet("POWERTOOLS_TRACER_CAPTURE_ERROR") + && environmentVariable("POWERTOOLS_TRACER_CAPTURE_ERROR"); case ERROR: case RESPONSE_AND_ERROR: return true; diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaDataDeprecated.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaDataDeprecated.java deleted file mode 100644 index c13f28df0..000000000 --- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/handlers/PowerTracerToolEnabledWithNoMetaDataDeprecated.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.tracing.handlers; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import software.amazon.lambda.powertools.tracing.Tracing; - -public class PowerTracerToolEnabledWithNoMetaDataDeprecated implements RequestHandler { - - @Override - @Tracing(captureResponse = false, captureError = false) - public Object handleRequest(Object input, Context context) { - return null; - } -} diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java index a676bf683..4aefdec9c 100644 --- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java +++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java @@ -33,6 +33,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetEnvironmentVariable; import org.mockito.Mock; import org.mockito.MockedStatic; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; @@ -47,7 +48,6 @@ import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledForStreamWithNoMetaData; import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledWithException; import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledWithNoMetaData; -import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledWithNoMetaDataDeprecated; import software.amazon.lambda.powertools.tracing.nonhandler.PowerToolNonHandler; class LambdaTracingAspectTest { @@ -114,6 +114,28 @@ void shouldCaptureNonHandlerMethodWithCustomSegmentName() { void shouldCaptureTraces() { requestHandler.handleRequest(new Object(), context); + assertThat(AWSXRay.getTraceEntity()) + .isNotNull(); + + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) + .hasSize(1) + .allSatisfy(subsegment -> + { + assertThat(subsegment.getAnnotations()) + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); + + assertThat(subsegment.getMetadata()) + .hasSize(0); + }); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_RESPONSE", value = "true") + void shouldCaptureTracesWithResponseMetadata() { + requestHandler.handleRequest(new Object(), context); + assertThat(AWSXRay.getTraceEntity()) .isNotNull(); @@ -133,6 +155,7 @@ void shouldCaptureTraces() { } @Test + @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_ERROR", value = "true") void shouldCaptureTracesWithExceptionMetaData() { requestHandler = new PowerTracerToolEnabledWithException(); @@ -164,6 +187,25 @@ void shouldCaptureTracesWithExceptionMetaData() { void shouldCaptureTracesForStream() throws IOException { streamHandler.handleRequest(new ByteArrayInputStream("test".getBytes()), new ByteArrayOutputStream(), context); + assertThat(AWSXRay.getTraceEntity()) + .isNotNull(); + + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) + .hasSize(1) + .allSatisfy(subsegment -> + { + assertThat(subsegment.getAnnotations()) + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "streamHandler"); + }); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_RESPONSE", value = "true") + void shouldCaptureTracesForStreamWithResponseMetadata() throws IOException { + streamHandler.handleRequest(new ByteArrayInputStream("test".getBytes()), new ByteArrayOutputStream(), context); + assertThat(AWSXRay.getTraceEntity()) .isNotNull(); @@ -246,29 +288,6 @@ void shouldCaptureTracesForStreamWithNoMetadata() throws IOException { }); } - @Test - void shouldCaptureTracesWithNoMetadataDeprecated() { - requestHandler = new PowerTracerToolEnabledWithNoMetaDataDeprecated(); - - requestHandler.handleRequest(new Object(), context); - - assertThat(AWSXRay.getTraceEntity()) - .isNotNull(); - - assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) - .hasSize(1) - .allSatisfy(subsegment -> - { - assertThat(subsegment.getAnnotations()) - .hasSize(2) - .containsEntry("ColdStart", true) - .containsEntry("Service", "service_undefined"); - - assertThat(subsegment.getMetadata()) - .isEmpty(); - }); - } - @Test void shouldNotCaptureTracesIfDisabledViaEnvironmentVariable() { try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { From 1fa11c138529ee7d49f6d24415a5de6223330aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Van=20Der=20Linden?= <117538+jeromevdl@users.noreply.github.com> Date: Wed, 3 Jul 2024 13:47:05 +0000 Subject: [PATCH 191/577] feat(v2): parallel batch processing (#1620) * implement parallel processing * test parallel processing * document parallel processing * code review * sqs // batch processing example * rollback to AtomicBoolean * complete sqs batch example with logs and traces annotations * update doc * update doc * update doc --- docs/utilities/batch.md | 94 ++-- .../deploy/sqs/template.yml | 63 ++- examples/powertools-examples-batch/pom.xml | 11 + .../batch/sqs/AbstractSqsBatchHandler.java | 70 +++ .../org/demo/batch/sqs/SqsBatchHandler.java | 15 +- .../org/demo/batch/sqs/SqsBatchSender.java | 25 +- .../batch/sqs/SqsParallelBatchHandler.java | 48 ++ .../src/main/resources/LogLayout.json | 75 +++ .../src/main/resources/log4j2.xml | 3 +- powertools-batch/pom.xml | 16 + .../batch/handler/BatchMessageHandler.java | 17 +- .../handler/DynamoDbBatchMessageHandler.java | 77 +++- .../KinesisStreamsBatchMessageHandler.java | 93 ++-- .../batch/handler/SqsBatchMessageHandler.java | 105 +++-- .../batch/internal/MultiThreadMDC.java | 47 ++ .../batch/DdbBatchProcessorTest.java | 88 +++- .../batch/KinesisBatchProcessorTest.java | 92 +++- .../batch/SQSBatchProcessorTest.java | 89 +++- .../src/test/resources/dynamo_event_big.json | 376 +++++++++++++++ .../src/test/resources/kinesis_event_big.json | 224 +++++++++ .../src/test/resources/sqs_event_big.json | 429 ++++++++++++++++++ 21 files changed, 1877 insertions(+), 180 deletions(-) create mode 100644 examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java create mode 100644 examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsParallelBatchHandler.java create mode 100644 examples/powertools-examples-batch/src/main/resources/LogLayout.json create mode 100644 powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/MultiThreadMDC.java create mode 100644 powertools-batch/src/test/resources/dynamo_event_big.json create mode 100644 powertools-batch/src/test/resources/kinesis_event_big.json create mode 100644 powertools-batch/src/test/resources/sqs_event_big.json diff --git a/docs/utilities/batch.md b/docs/utilities/batch.md index 7b571bc6e..7693ac98f 100644 --- a/docs/utilities/batch.md +++ b/docs/utilities/batch.md @@ -30,6 +30,7 @@ stateDiagram-v2 * Reports batch item failures to reduce number of retries for a record upon errors * Simple interface to process each batch record +* Parallel processing of batches * Integrates with Java Events library and the deserialization module * Build your own batch processor by extending primitives @@ -110,16 +111,9 @@ You can use your preferred deployment framework to set the correct configuration while the `powertools-batch` module handles generating the response, which simply needs to be returned as the result of your Lambda handler. -A complete [Serverless Application Model](https://aws.amazon.com/serverless/sam/) example can be found -[here](https://github.com/aws-powertools/powertools-lambda-java/tree/main/examples/powertools-examples-batch) covering -all of the batch sources. - -For more information on configuring `ReportBatchItemFailures`, -see the details for [SQS](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting), -[Kinesis](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html#services-kinesis-batchfailurereporting),and -[DynamoDB Streams](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html#services-ddb-batchfailurereporting). - +A complete [Serverless Application Model](https://aws.amazon.com/serverless/sam/) example can be found [here](https://github.com/aws-powertools/powertools-lambda-java/tree/main/examples/powertools-examples-batch) covering all the batch sources. +For more information on configuring `ReportBatchItemFailures`, see the details for [SQS](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting), [Kinesis](https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html#services-kinesis-batchfailurereporting), and [DynamoDB Streams](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html#services-ddb-batchfailurereporting). !!! note "You do not need any additional IAM permissions to use this utility, except for what each event source requires." @@ -150,12 +144,10 @@ see the details for [SQS](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs. public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { return handler.processBatch(sqsEvent, context); } - - + private void processMessage(Product p, Context c) { // Process the product } - } ``` @@ -276,7 +268,6 @@ see the details for [SQS](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs. private void processMessage(Product p, Context c) { // process the product } - } ``` @@ -475,6 +466,51 @@ see the details for [SQS](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs. } ``` +## Parallel processing +You can choose to process batch items in parallel using the `BatchMessageHandler#processBatchInParallel()` +instead of `BatchMessageHandler#processBatch()`. Partial batch failure works the same way but items are processed +in parallel rather than sequentially. + +This feature is available for SQS, Kinesis and DynamoDB Streams but cannot be +used with SQS FIFO. In that case, an `UnsupportedOperationException` is thrown. + +!!! warning + Note that parallel processing is not always better than sequential processing, + and you should benchmark your code to determine the best approach for your use case. + +!!! info + To get more threads available (more vCPUs), you need to increase the amount of memory allocated to your Lambda function. + While it is possible to increase the number of threads using Java options or custom thread pools, + in most cases the defaults work well, and changing them is more likely to decrease performance + (see [here](https://www.baeldung.com/java-when-to-use-parallel-stream#fork-join-framework) + and [here](https://dzone.com/articles/be-aware-of-forkjoinpoolcommonpool)). + In situations where this may be useful - such as performing IO-bound work in parallel - make sure to measure before and after! + + +=== "Example with SQS" + + ```java hl_lines="13" + public class SqsBatchHandler implements RequestHandler { + + private final BatchMessageHandler handler; + + public SqsBatchHandler() { + handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithMessageHandler(this::processMessage, Product.class); + } + + @Override + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + return handler.processBatchInParallel(sqsEvent, context); + } + + private void processMessage(Product p, Context c) { + // Process the product + } + } + ``` + ## Handling Messages @@ -490,7 +526,7 @@ In general, the deserialized message handler should be used unless you need acce === "Raw Message Handler" - ```java + ```java hl_lines="4 7" public void setup() { BatchMessageHandler handler = new BatchMessageHandlerBuilder() .withSqsBatchHandler() @@ -505,7 +541,7 @@ In general, the deserialized message handler should be used unless you need acce === "Deserialized Message Handler" - ```java + ```java hl_lines="4 7" public void setup() { BatchMessageHandler handler = new BatchMessageHandlerBuilder() .withSqsBatchHandler() @@ -529,20 +565,20 @@ provide a custom failure handler. Handlers can be provided when building the batch processor and are available for all event sources. For instance for DynamoDB: -```java - BatchMessageHandler handler = new BatchMessageHandlerBuilder() - .withDynamoDbBatchHandler() - .withSuccessHandler((m) -> { - // Success handler receives the raw message - LOGGER.info("Message with sequenceNumber {} was successfully processed", - m.getDynamodb().getSequenceNumber()); - }) - .withFailureHandler((m, e) -> { - // Failure handler receives the raw message and the exception thrown. - LOGGER.info("Message with sequenceNumber {} failed to be processed: {}" - , e.getDynamodb().getSequenceNumber(), e); - }) - .buildWithMessageHander(this::processMessage); +```java hl_lines="3 8" +BatchMessageHandler handler = new BatchMessageHandlerBuilder() + .withDynamoDbBatchHandler() + .withSuccessHandler((m) -> { + // Success handler receives the raw message + LOGGER.info("Message with sequenceNumber {} was successfully processed", + m.getDynamodb().getSequenceNumber()); + }) + .withFailureHandler((m, e) -> { + // Failure handler receives the raw message and the exception thrown. + LOGGER.info("Message with sequenceNumber {} failed to be processed: {}" + , e.getDynamodb().getSequenceNumber(), e); + }) + .buildWithMessageHander(this::processMessage); ``` !!! info diff --git a/examples/powertools-examples-batch/deploy/sqs/template.yml b/examples/powertools-examples-batch/deploy/sqs/template.yml index 764ba4863..2f1d6c363 100644 --- a/examples/powertools-examples-batch/deploy/sqs/template.yml +++ b/examples/powertools-examples-batch/deploy/sqs/template.yml @@ -7,12 +7,10 @@ Globals: Function: Timeout: 20 Runtime: java11 - MemorySize: 512 - Tracing: Active + MemorySize: 5400 Environment: Variables: POWERTOOLS_LOG_LEVEL: INFO - POWERTOOLS_LOGGER_SAMPLE_RATE: 1.0 POWERTOOLS_LOGGER_LOG_EVENT: true Resources: @@ -45,6 +43,9 @@ Resources: AliasName: alias/powertools-batch-sqs-demo TargetKeyId: !Ref CustomerKey + Bucket: + Type: AWS::S3::Bucket + DemoDlqSqsQueue: Type: AWS::SQS::Queue Properties: @@ -96,11 +97,57 @@ Resources: DemoSQSConsumerFunction: Type: AWS::Serverless::Function Properties: + Tracing: Active CodeUri: ../.. Handler: org.demo.batch.sqs.SqsBatchHandler::handleRequest Environment: Variables: POWERTOOLS_SERVICE_NAME: sqs-demo + BUCKET: !Ref Bucket + Policies: + - Statement: + - Sid: SQSDeleteGetAttribute + Effect: Allow + Action: + - sqs:DeleteMessageBatch + - sqs:GetQueueAttributes + Resource: !GetAtt DemoSqsQueue.Arn + - Sid: SQSSendMessageBatch + Effect: Allow + Action: + - sqs:SendMessageBatch + - sqs:SendMessage + Resource: !GetAtt DemoDlqSqsQueue.Arn + - Sid: SQSKMSKey + Effect: Allow + Action: + - kms:GenerateDataKey + - kms:Decrypt + Resource: !GetAtt CustomerKey.Arn + - Sid: WriteToS3 + Effect: Allow + Action: + - s3:PutObject + Resource: !Sub ${Bucket.Arn}/* + +# Events: +# MySQSEvent: +# Type: SQS +# Properties: +# Queue: !GetAtt DemoSqsQueue.Arn +# BatchSize: 100 +# MaximumBatchingWindowInSeconds: 60 + + DemoSQSParallelConsumerFunction: + Type: AWS::Serverless::Function + Properties: + Tracing: Active + CodeUri: ../.. + Handler: org.demo.batch.sqs.SqsParallelBatchHandler::handleRequest + Environment: + Variables: + POWERTOOLS_SERVICE_NAME: sqs-demo + BUCKET: !Ref Bucket Policies: - Statement: - Sid: SQSDeleteGetAttribute @@ -121,13 +168,19 @@ Resources: - kms:GenerateDataKey - kms:Decrypt Resource: !GetAtt CustomerKey.Arn + - Sid: WriteToS3 + Effect: Allow + Action: + - s3:PutObject + Resource: !Sub ${Bucket.Arn}/* + Events: MySQSEvent: Type: SQS Properties: Queue: !GetAtt DemoSqsQueue.Arn - BatchSize: 2 - MaximumBatchingWindowInSeconds: 300 + BatchSize: 100 + MaximumBatchingWindowInSeconds: 60 Outputs: DemoSqsQueue: diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 207040476..6eb548937 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -42,6 +42,17 @@ software.amazon.awssdk sdk-core ${sdk.version} + + + org.slf4j + slf4j-api + + + + + software.amazon.awssdk + s3 + ${sdk.version} software.amazon.awssdk diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java new file mode 100644 index 000000000..25dba47bb --- /dev/null +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java @@ -0,0 +1,70 @@ +/* + * Copyright 2024 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.demo.batch.sqs; + +import com.amazonaws.services.lambda.runtime.Context; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Random; +import org.demo.batch.model.Product; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.tracing.TracingUtils; + +public class AbstractSqsBatchHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSqsBatchHandler.class); + private final ObjectMapper mapper = new ObjectMapper(); + private final String bucket = System.getenv("BUCKET"); + private final S3Client s3 = S3Client.builder().httpClient(UrlConnectionHttpClient.create()).build(); + private final Random r = new Random(); + + /** + * Simulate some processing (I/O + S3 put request) + * @param p deserialized product + * @param context Lambda context + */ + @Logging + @Tracing + protected void processMessage(Product p, Context context) { + TracingUtils.putAnnotation("productId", p.getId()); + TracingUtils.putAnnotation("Thread", Thread.currentThread().getName()); + MDC.put("product", String.valueOf(p.getId())); + LOGGER.info("Processing product {}", p); + + char c = (char)(r.nextInt(26) + 'a'); + char[] chars = new char[1024 * 1000]; + Arrays.fill(chars, c); + p.setName(new String(chars)); + try { + File file = new File("/tmp/"+p.getId()+".json"); + mapper.writeValue(file, p); + s3.putObject( + PutObjectRequest.builder().bucket(bucket).key(p.getId()+".json").build(), RequestBody.fromFile(file)); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + MDC.remove("product"); + } + } +} diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandler.java index 27689485c..bc0f57cb8 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandler.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandler.java @@ -4,13 +4,15 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import org.demo.batch.model.Product; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.demo.batch.model.Product; import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder; import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.tracing.Tracing; -public class SqsBatchHandler implements RequestHandler { +public class SqsBatchHandler extends AbstractSqsBatchHandler implements RequestHandler { private static final Logger LOGGER = LoggerFactory.getLogger(SqsBatchHandler.class); private final BatchMessageHandler handler; @@ -20,14 +22,11 @@ public SqsBatchHandler() { .buildWithMessageHandler(this::processMessage, Product.class); } + @Logging + @Tracing @Override public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + LOGGER.info("Processing batch of {} messages", sqsEvent.getRecords().size()); return handler.processBatch(sqsEvent, context); } - - - private void processMessage(Product p, Context c) { - LOGGER.info("Processing product " + p); - } - } diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchSender.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchSender.java index 4050ab98b..58b24d735 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchSender.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchSender.java @@ -10,14 +10,13 @@ import java.security.SecureRandom; import java.util.List; import java.util.stream.IntStream; +import org.demo.batch.model.Product; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.demo.batch.model.Product; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.services.sqs.SqsClient; import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry; -import software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse; /** @@ -45,16 +44,12 @@ public SqsBatchSender() { public String handleRequest(ScheduledEvent scheduledEvent, Context context) { String queueUrl = System.getenv("QUEUE_URL"); - LOGGER.info("handleRequest"); - - // Push 5 messages on each invoke. - List batchRequestEntries = IntStream.range(0, 5) + List batchRequestEntries = IntStream.range(0, 50) .mapToObj(value -> { - long id = random.nextLong(); - float price = random.nextFloat(); + long id = Math.abs(random.nextLong()); + float price = Math.abs(random.nextFloat() * 3465); Product product = new Product(id, "product-" + id, price); try { - return SendMessageBatchRequestEntry.builder() .id(scheduledEvent.getId() + value) .messageBody(objectMapper.writeValueAsString(product)) @@ -65,12 +60,12 @@ public String handleRequest(ScheduledEvent scheduledEvent, Context context) { } }).collect(toList()); - SendMessageBatchResponse sendMessageBatchResponse = sqsClient.sendMessageBatch(SendMessageBatchRequest.builder() - .queueUrl(queueUrl) - .entries(batchRequestEntries) - .build()); - - LOGGER.info("Sent Message {}", sendMessageBatchResponse); + for (int i = 0; i < 50; i += 10) { + sqsClient.sendMessageBatch(SendMessageBatchRequest.builder() + .queueUrl(queueUrl) + .entries(batchRequestEntries.subList(i, i + 10)) + .build()); + } return "Success"; } diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsParallelBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsParallelBatchHandler.java new file mode 100644 index 000000000..0151c0a32 --- /dev/null +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsParallelBatchHandler.java @@ -0,0 +1,48 @@ +/* + * Copyright 2024 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.demo.batch.sqs; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import org.demo.batch.model.Product; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder; +import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.tracing.Tracing; + +public class SqsParallelBatchHandler extends AbstractSqsBatchHandler implements RequestHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(SqsParallelBatchHandler.class); + private final BatchMessageHandler handler; + + public SqsParallelBatchHandler() { + handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithMessageHandler(this::processMessage, Product.class); + } + + @Logging + @Tracing + @Override + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + LOGGER.info("Processing batch of {} messages", sqsEvent.getRecords().size()); + MDC.put("requestId", context.getAwsRequestId()); // should be propagated to other threads + return handler.processBatchInParallel(sqsEvent, context); + } +} diff --git a/examples/powertools-examples-batch/src/main/resources/LogLayout.json b/examples/powertools-examples-batch/src/main/resources/LogLayout.json new file mode 100644 index 000000000..60f102e09 --- /dev/null +++ b/examples/powertools-examples-batch/src/main/resources/LogLayout.json @@ -0,0 +1,75 @@ +{ + "level": { + "$resolver": "level", + "field": "name" + }, + "message": { + "$resolver": "message" + }, + "error": { + "message": { + "$resolver": "exception", + "field": "message" + }, + "name": { + "$resolver": "exception", + "field": "className" + }, + "stack": { + "$resolver": "exception", + "field": "stackTrace", + "stackTrace": { + "stringified": true + } + } + }, + "cold_start": { + "$resolver": "powertools", + "field": "cold_start" + }, + "thread": { + "$resolver": "thread", + "field": "name" + }, + "function_arn": { + "$resolver": "powertools", + "field": "function_arn" + }, + "function_memory_size": { + "$resolver": "powertools", + "field": "function_memory_size" + }, + "function_name": { + "$resolver": "powertools", + "field": "function_name" + }, + "function_request_id": { + "$resolver": "powertools", + "field": "function_request_id" + }, + "function_version": { + "$resolver": "powertools", + "field": "function_version" + }, + "sampling_rate": { + "$resolver": "powertools", + "field": "sampling_rate" + }, + "service": { + "$resolver": "powertools", + "field": "service" + }, + "timestamp": { + "$resolver": "timestamp", + "pattern": { + "format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" + } + }, + "xray_trace_id": { + "$resolver": "powertools", + "field": "xray_trace_id" + }, + "": { + "$resolver": "powertools" + } +} \ No newline at end of file diff --git a/examples/powertools-examples-batch/src/main/resources/log4j2.xml b/examples/powertools-examples-batch/src/main/resources/log4j2.xml index ea3ecf474..c48ca3ef4 100644 --- a/examples/powertools-examples-batch/src/main/resources/log4j2.xml +++ b/examples/powertools-examples-batch/src/main/resources/log4j2.xml @@ -2,7 +2,8 @@ - + + diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 1886f56e6..66a5e3087 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -21,6 +21,16 @@ true + + org.apache.maven.plugins + maven-surefire-plugin + + + + -Djava.util.concurrent.ForkJoinPool.common.parallelism=4 + + + @@ -47,6 +57,12 @@ junit-jupiter-api test + + org.slf4j + slf4j-simple + 2.0.7 + test + org.assertj assertj-core diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/BatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/BatchMessageHandler.java index 730211feb..18d74bb25 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/BatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/BatchMessageHandler.java @@ -33,6 +33,21 @@ public interface BatchMessageHandler { * @param context The lambda context * @return A partial batch response */ - public abstract R processBatch(E event, Context context); + R processBatch(E event, Context context); + /** + * Processes the given batch in parallel returning a partial batch + * response indicating the success and failure of individual + * messages within the batch.
+ * Note that parallel processing is not always better than sequential processing, + * and you should benchmark your code to determine the best approach for your use case.
+ * Also note that to get more threads available (more vCPUs), + * you need to increase the amount of memory allocated to your Lambda function.
+ + * + * @param event The Lambda event containing the batch to process + * @param context The lambda context + * @return A partial batch response + */ + R processBatchInParallel(E event, Context context); } diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java index 83a8bf7dd..4b03d0947 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java @@ -17,12 +17,14 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; -import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.batch.internal.MultiThreadMDC; /** * A batch message processor for DynamoDB Streams batches. @@ -46,35 +48,60 @@ public DynamoDbBatchMessageHandler(Consumer @Override public StreamsEventResponse processBatch(DynamodbEvent event, Context context) { - List batchFailures = new ArrayList<>(); + List batchItemFailures = event.getRecords() + .stream() + .map(eventRecord -> processBatchItem(eventRecord, context)) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList()); - for (DynamodbEvent.DynamodbStreamRecord record : event.getRecords()) { - try { + return StreamsEventResponse.builder().withBatchItemFailures(batchItemFailures).build(); + } - rawMessageHandler.accept(record, context); - // Report success if we have a handler - if (this.successHandler != null) { - this.successHandler.accept(record); - } - } catch (Throwable t) { - String sequenceNumber = record.getDynamodb().getSequenceNumber(); - LOGGER.error("Error while processing record with id {}: {}, adding it to batch item failures", - sequenceNumber, t.getMessage()); - LOGGER.error("Error was", t); - batchFailures.add(new StreamsEventResponse.BatchItemFailure(sequenceNumber)); + @Override + public StreamsEventResponse processBatchInParallel(DynamodbEvent event, Context context) { + MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + + List batchItemFailures = event.getRecords() + .parallelStream() // Parallel processing + .map(eventRecord -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + return processBatchItem(eventRecord, context); + }) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList()); + + return StreamsEventResponse.builder().withBatchItemFailures(batchItemFailures).build(); + } - // Report failure if we have a handler - if (this.failureHandler != null) { - // A failing failure handler is no reason to fail the batch - try { - this.failureHandler.accept(record, t); - } catch (Throwable t2) { - LOGGER.warn("failureHandler threw handling failure", t2); - } + private Optional processBatchItem(DynamodbEvent.DynamodbStreamRecord streamRecord, Context context) { + try { + LOGGER.debug("Processing item {}", streamRecord.getEventID()); + + rawMessageHandler.accept(streamRecord, context); + + // Report success if we have a handler + if (this.successHandler != null) { + this.successHandler.accept(streamRecord); + } + return Optional.empty(); + } catch (Throwable t) { + String sequenceNumber = streamRecord.getDynamodb().getSequenceNumber(); + LOGGER.error("Error while processing record with id {}: {}, adding it to batch item failures", + sequenceNumber, t.getMessage()); + LOGGER.error("Error was", t); + + // Report failure if we have a handler + if (this.failureHandler != null) { + // A failing failure handler is no reason to fail the batch + try { + this.failureHandler.accept(streamRecord, t); + } catch (Throwable t2) { + LOGGER.warn("failureHandler threw handling failure", t2); } } + return Optional.of(StreamsEventResponse.BatchItemFailure.builder().withItemIdentifier(sequenceNumber).build()); } - - return new StreamsEventResponse(batchFailures); } } diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java index ad1dd302d..7b4179de7 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java @@ -18,12 +18,14 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.KinesisEvent; import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; -import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.batch.internal.MultiThreadMDC; import software.amazon.lambda.powertools.utilities.EventDeserializer; /** @@ -57,42 +59,67 @@ public KinesisStreamsBatchMessageHandler(BiConsumer batchFailures = new ArrayList<>(); - - for (KinesisEvent.KinesisEventRecord record : event.getRecords()) { - try { - if (this.rawMessageHandler != null) { - rawMessageHandler.accept(record, context); - } else { - M messageDeserialized = EventDeserializer.extractDataFrom(record).as(messageClass); - messageHandler.accept(messageDeserialized, context); - } + List batchItemFailures = event.getRecords() + .stream() + .map(eventRecord -> processBatchItem(eventRecord, context)) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList()); - // Report success if we have a handler - if (this.successHandler != null) { - this.successHandler.accept(record); - } - } catch (Throwable t) { - String sequenceNumber = record.getEventID(); - LOGGER.error("Error while processing record with eventID {}: {}, adding it to batch item failures", - sequenceNumber, t.getMessage()); - LOGGER.error("Error was", t); - - batchFailures.add(new StreamsEventResponse.BatchItemFailure(record.getKinesis().getSequenceNumber())); - - // Report failure if we have a handler - if (this.failureHandler != null) { - // A failing failure handler is no reason to fail the batch - try { - this.failureHandler.accept(record, t); - } catch (Throwable t2) { - LOGGER.warn("failureHandler threw handling failure", t2); - } + return StreamsEventResponse.builder().withBatchItemFailures(batchItemFailures).build(); + } + + @Override + public StreamsEventResponse processBatchInParallel(KinesisEvent event, Context context) { + MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + + List batchItemFailures = event.getRecords() + .parallelStream() // Parallel processing + .map(eventRecord -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + return processBatchItem(eventRecord, context); + }) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList()); + + return StreamsEventResponse.builder().withBatchItemFailures(batchItemFailures).build(); + } + + private Optional processBatchItem(KinesisEvent.KinesisEventRecord eventRecord, Context context) { + try { + LOGGER.debug("Processing item {}", eventRecord.getEventID()); + + if (this.rawMessageHandler != null) { + rawMessageHandler.accept(eventRecord, context); + } else { + M messageDeserialized = EventDeserializer.extractDataFrom(eventRecord).as(messageClass); + messageHandler.accept(messageDeserialized, context); + } + + // Report success if we have a handler + if (this.successHandler != null) { + this.successHandler.accept(eventRecord); + } + return Optional.empty(); + } catch (Throwable t) { + String sequenceNumber = eventRecord.getEventID(); + LOGGER.error("Error while processing record with eventID {}: {}, adding it to batch item failures", + sequenceNumber, t.getMessage()); + LOGGER.error("Error was", t); + + // Report failure if we have a handler + if (this.failureHandler != null) { + // A failing failure handler is no reason to fail the batch + try { + this.failureHandler.accept(eventRecord, t); + } catch (Throwable t2) { + LOGGER.warn("failureHandler threw handling failure", t2); } } - } - return new StreamsEventResponse(batchFailures); + return Optional.of(StreamsEventResponse.BatchItemFailure.builder().withItemIdentifier(eventRecord.getKinesis().getSequenceNumber()).build()); + } } } diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java index b634f9b62..2dfb0a28e 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java @@ -18,10 +18,15 @@ import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.batch.internal.MultiThreadMDC; import software.amazon.lambda.powertools.utilities.EventDeserializer; /** @@ -61,57 +66,27 @@ public SQSBatchResponse processBatch(SQSEvent event, Context context) { // If we are working on a FIFO queue, when any message fails we should stop processing and return the // rest of the batch as failed too. We use this variable to track when that has happened. // https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting - boolean failWholeBatch = false; + final AtomicBoolean failWholeBatch = new AtomicBoolean(false); int messageCursor = 0; - for (; messageCursor < event.getRecords().size() && !failWholeBatch; messageCursor++) { + for (; messageCursor < event.getRecords().size() && !failWholeBatch.get(); messageCursor++) { SQSEvent.SQSMessage message = event.getRecords().get(messageCursor); String messageGroupId = message.getAttributes() != null ? message.getAttributes().get(MESSAGE_GROUP_ID_KEY) : null; - try { - if (this.rawMessageHandler != null) { - rawMessageHandler.accept(message, context); - } else { - M messageDeserialized = EventDeserializer.extractDataFrom(message).as(messageClass); - messageHandler.accept(messageDeserialized, context); - } - - // Report success if we have a handler - if (this.successHandler != null) { - this.successHandler.accept(message); - } - - } catch (Throwable t) { - LOGGER.error("Error while processing message with messageId {}: {}, adding it to batch item failures", - message.getMessageId(), t.getMessage()); - LOGGER.error("Error was", t); - - response.getBatchItemFailures() - .add(SQSBatchResponse.BatchItemFailure.builder().withItemIdentifier(message.getMessageId()) - .build()); + processBatchItem(message, context).ifPresent(batchItemFailure -> { + response.getBatchItemFailures().add(batchItemFailure); if (messageGroupId != null) { - failWholeBatch = true; + failWholeBatch.set(true); LOGGER.info( "A message in a batch with messageGroupId {} and messageId {} failed; failing the rest of the batch too" , messageGroupId, message.getMessageId()); } - - // Report failure if we have a handler - if (this.failureHandler != null) { - // A failing failure handler is no reason to fail the batch - try { - this.failureHandler.accept(message, t); - } catch (Throwable t2) { - LOGGER.warn("failureHandler threw handling failure", t2); - } - } - - } + }); } - if (failWholeBatch) { + if (failWholeBatch.get()) { // Add the remaining messages to the batch item failures event.getRecords() .subList(messageCursor, event.getRecords().size()) @@ -121,4 +96,60 @@ public SQSBatchResponse processBatch(SQSEvent event, Context context) { } return response; } + + @Override + public SQSBatchResponse processBatchInParallel(SQSEvent event, Context context) { + if (!event.getRecords().isEmpty() && event.getRecords().get(0).getAttributes().get(MESSAGE_GROUP_ID_KEY) != null) { + throw new UnsupportedOperationException("FIFO queues are not supported in parallel mode, use the processBatch method instead"); + } + + MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + List batchItemFailures = event.getRecords() + .parallelStream() // Parallel processing + .map(sqsMessage -> { + + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + return processBatchItem(sqsMessage, context); + }) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toList()); + + return SQSBatchResponse.builder().withBatchItemFailures(batchItemFailures).build(); + } + + private Optional processBatchItem(SQSEvent.SQSMessage message, Context context) { + try { + LOGGER.debug("Processing message {}", message.getMessageId()); + + if (this.rawMessageHandler != null) { + rawMessageHandler.accept(message, context); + } else { + M messageDeserialized = EventDeserializer.extractDataFrom(message).as(messageClass); + messageHandler.accept(messageDeserialized, context); + } + + // Report success if we have a handler + if (this.successHandler != null) { + this.successHandler.accept(message); + } + return Optional.empty(); + } catch (Throwable t) { + LOGGER.error("Error while processing message with messageId {}: {}, adding it to batch item failures", + message.getMessageId(), t.getMessage()); + LOGGER.error("Error was", t); + + // Report failure if we have a handler + if (this.failureHandler != null) { + // A failing failure handler is no reason to fail the batch + try { + this.failureHandler.accept(message, t); + } catch (Throwable t2) { + LOGGER.warn("failureHandler threw handling failure", t2); + } + } + return Optional.of(SQSBatchResponse.BatchItemFailure.builder().withItemIdentifier(message.getMessageId()) + .build()); + } + } } diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/MultiThreadMDC.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/MultiThreadMDC.java new file mode 100644 index 000000000..df1c2e7a0 --- /dev/null +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/MultiThreadMDC.java @@ -0,0 +1,47 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.batch.internal; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +/** + * MDC (SLF4J) is not passed to other threads (ThreadLocal). + * This class permits to manually copy the MDC to a given thread. + */ +public class MultiThreadMDC { + + private static final Logger LOGGER = LoggerFactory.getLogger(MultiThreadMDC.class); + + private final List mdcAwareThreads = new ArrayList<>(); + private final Map contextMap; + + public MultiThreadMDC() { + mdcAwareThreads.add("main"); + contextMap = MDC.getCopyOfContextMap(); + } + + public void copyMDCToThread(String thread) { + if (!mdcAwareThreads.contains(thread)) { + LOGGER.debug("Copy MDC to thread {}", thread); + MDC.setContextMap(contextMap); + mdcAwareThreads.add(thread); + } + } +} diff --git a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/DdbBatchProcessorTest.java b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/DdbBatchProcessorTest.java index 9e2c211e2..6bb247323 100644 --- a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/DdbBatchProcessorTest.java +++ b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/DdbBatchProcessorTest.java @@ -20,16 +20,27 @@ import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; import com.amazonaws.services.lambda.runtime.tests.annotations.Event; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.params.ParameterizedTest; import org.mockito.Mock; import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; -public class DdbBatchProcessorTest { +class DdbBatchProcessorTest { @Mock private Context context; + private final List threadList = Collections.synchronizedList(new ArrayList<>()); + + @AfterEach + public void clear() { + threadList.clear(); + } + private void processMessageSucceeds(DynamodbEvent.DynamodbStreamRecord record, Context context) { // Great success } @@ -40,9 +51,36 @@ private void processMessageFailsForFixedMessage(DynamodbEvent.DynamodbStreamReco } } + private void processMessageInParallelSucceeds(DynamodbEvent.DynamodbStreamRecord record, Context context) { + String thread = Thread.currentThread().getName(); + if (!threadList.contains(thread)) { + threadList.add(thread); + } + try { + Thread.sleep(500); // simulate some processing + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + private void processMessageInParallelFailsForFixedMessage(DynamodbEvent.DynamodbStreamRecord record, Context context) { + String thread = Thread.currentThread().getName(); + if (!threadList.contains(thread)) { + threadList.add(thread); + } + try { + Thread.sleep(500); // simulate some processing + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + if (record.getDynamodb().getSequenceNumber().equals("4421584500000000017450439091")) { + throw new RuntimeException("fake exception"); + } + } + @ParameterizedTest @Event(value = "dynamo_event.json", type = DynamodbEvent.class) - public void batchProcessingSucceedsAndReturns(DynamodbEvent event) { + void batchProcessingSucceedsAndReturns(DynamodbEvent event) { // Arrange BatchMessageHandler handler = new BatchMessageHandlerBuilder() .withDynamoDbBatchHandler() @@ -52,12 +90,28 @@ public void batchProcessingSucceedsAndReturns(DynamodbEvent event) { StreamsEventResponse dynamodbBatchResponse = handler.processBatch(event, context); // Assert - assertThat(dynamodbBatchResponse.getBatchItemFailures()).hasSize(0); + assertThat(dynamodbBatchResponse.getBatchItemFailures()).isEmpty(); + } + + @ParameterizedTest + @Event(value = "dynamo_event_big.json", type = DynamodbEvent.class) + void parallelBatchProcessingSucceedsAndReturns(DynamodbEvent event) { + // Arrange + BatchMessageHandler handler = new BatchMessageHandlerBuilder() + .withDynamoDbBatchHandler() + .buildWithRawMessageHandler(this::processMessageInParallelSucceeds); + + // Act + StreamsEventResponse dynamodbBatchResponse = handler.processBatchInParallel(event, context); + + // Assert + assertThat(dynamodbBatchResponse.getBatchItemFailures()).isEmpty(); + assertThat(threadList).hasSizeGreaterThan(1); } @ParameterizedTest @Event(value = "dynamo_event.json", type = DynamodbEvent.class) - public void shouldAddMessageToBatchFailure_whenException_withMessage(DynamodbEvent event) { + void shouldAddMessageToBatchFailure_whenException_withMessage(DynamodbEvent event) { // Arrange BatchMessageHandler handler = new BatchMessageHandlerBuilder() .withDynamoDbBatchHandler() @@ -72,9 +126,27 @@ public void shouldAddMessageToBatchFailure_whenException_withMessage(DynamodbEve assertThat(batchItemFailure.getItemIdentifier()).isEqualTo("4421584500000000017450439091"); } + @ParameterizedTest + @Event(value = "dynamo_event_big.json", type = DynamodbEvent.class) + void parallelBatchProcessing_shouldAddMessageToBatchFailure_whenException_withMessage(DynamodbEvent event) { + // Arrange + BatchMessageHandler handler = new BatchMessageHandlerBuilder() + .withDynamoDbBatchHandler() + .buildWithRawMessageHandler(this::processMessageInParallelFailsForFixedMessage); + + // Act + StreamsEventResponse dynamodbBatchResponse = handler.processBatchInParallel(event, context); + + // Assert + assertThat(dynamodbBatchResponse.getBatchItemFailures()).hasSize(1); + StreamsEventResponse.BatchItemFailure batchItemFailure = dynamodbBatchResponse.getBatchItemFailures().get(0); + assertThat(batchItemFailure.getItemIdentifier()).isEqualTo("4421584500000000017450439091"); + assertThat(threadList).hasSizeGreaterThan(1); + } + @ParameterizedTest @Event(value = "dynamo_event.json", type = DynamodbEvent.class) - public void failingFailureHandlerShouldntFailBatch(DynamodbEvent event) { + void failingFailureHandlerShouldntFailBatch(DynamodbEvent event) { // Arrange AtomicBoolean wasCalledAndFailed = new AtomicBoolean(false); BatchMessageHandler handler = new BatchMessageHandlerBuilder() @@ -92,7 +164,7 @@ public void failingFailureHandlerShouldntFailBatch(DynamodbEvent event) { // Assert assertThat(dynamodbBatchResponse).isNotNull(); - assertThat(dynamodbBatchResponse.getBatchItemFailures().size()).isEqualTo(1); + assertThat(dynamodbBatchResponse.getBatchItemFailures()).hasSize(1); assertThat(wasCalledAndFailed.get()).isTrue(); StreamsEventResponse.BatchItemFailure batchItemFailure = dynamodbBatchResponse.getBatchItemFailures().get(0); assertThat(batchItemFailure.getItemIdentifier()).isEqualTo("4421584500000000017450439091"); @@ -100,7 +172,7 @@ public void failingFailureHandlerShouldntFailBatch(DynamodbEvent event) { @ParameterizedTest @Event(value = "dynamo_event.json", type = DynamodbEvent.class) - public void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(DynamodbEvent event) { + void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(DynamodbEvent event) { // Arrange AtomicBoolean wasCalledAndFailed = new AtomicBoolean(false); BatchMessageHandler handler = new BatchMessageHandlerBuilder() @@ -118,7 +190,7 @@ public void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(DynamodbE // Assert assertThat(dynamodbBatchResponse).isNotNull(); - assertThat(dynamodbBatchResponse.getBatchItemFailures().size()).isEqualTo(1); + assertThat(dynamodbBatchResponse.getBatchItemFailures()).hasSize(1); assertThat(wasCalledAndFailed.get()).isTrue(); StreamsEventResponse.BatchItemFailure batchItemFailure = dynamodbBatchResponse.getBatchItemFailures().get(0); assertThat(batchItemFailure.getItemIdentifier()).isEqualTo("4421584500000000017450439091"); diff --git a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/KinesisBatchProcessorTest.java b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/KinesisBatchProcessorTest.java index d78638e1d..059a4d2d0 100644 --- a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/KinesisBatchProcessorTest.java +++ b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/KinesisBatchProcessorTest.java @@ -20,17 +20,28 @@ import com.amazonaws.services.lambda.runtime.events.KinesisEvent; import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; import com.amazonaws.services.lambda.runtime.tests.annotations.Event; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.params.ParameterizedTest; import org.mockito.Mock; import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; import software.amazon.lambda.powertools.batch.model.Product; -public class KinesisBatchProcessorTest { +class KinesisBatchProcessorTest { @Mock private Context context; + private final List threadList = Collections.synchronizedList(new ArrayList<>()); + + @AfterEach + public void clear() { + threadList.clear(); + } + private void processMessageSucceeds(KinesisEvent.KinesisEventRecord record, Context context) { // Great success } @@ -42,6 +53,34 @@ private void processMessageFailsForFixedMessage(KinesisEvent.KinesisEventRecord } } + private void processMessageInParallelSucceeds(KinesisEvent.KinesisEventRecord record, Context context) { + String thread = Thread.currentThread().getName(); + if (!threadList.contains(thread)) { + threadList.add(thread); + } + try { + Thread.sleep(500); // simulate some processing + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + private void processMessageInParallelFailsForFixedMessage(KinesisEvent.KinesisEventRecord record, Context context) { + String thread = Thread.currentThread().getName(); + if (!threadList.contains(thread)) { + threadList.add(thread); + } + try { + Thread.sleep(500); // simulate some processing + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + if (record.getKinesis().getSequenceNumber() + .equals("49545115243490985018280067714973144582180062593244200961")) { + throw new RuntimeException("fake exception"); + } + } + // A handler that throws an exception for _one_ of the deserialized products in the same messages public void processMessageFailsForFixedProduct(Product product, Context context) { if (product.getId() == 1234) { @@ -51,7 +90,7 @@ public void processMessageFailsForFixedProduct(Product product, Context context) @ParameterizedTest @Event(value = "kinesis_event.json", type = KinesisEvent.class) - public void batchProcessingSucceedsAndReturns(KinesisEvent event) { + void batchProcessingSucceedsAndReturns(KinesisEvent event) { // Arrange BatchMessageHandler handler = new BatchMessageHandlerBuilder() .withKinesisBatchHandler() @@ -61,12 +100,28 @@ public void batchProcessingSucceedsAndReturns(KinesisEvent event) { StreamsEventResponse kinesisBatchResponse = handler.processBatch(event, context); // Assert - assertThat(kinesisBatchResponse.getBatchItemFailures()).hasSize(0); + assertThat(kinesisBatchResponse.getBatchItemFailures()).isEmpty(); + } + + @ParameterizedTest + @Event(value = "kinesis_event_big.json", type = KinesisEvent.class) + void batchProcessingInParallelSucceedsAndReturns(KinesisEvent event) { + // Arrange + BatchMessageHandler handler = new BatchMessageHandlerBuilder() + .withKinesisBatchHandler() + .buildWithRawMessageHandler(this::processMessageInParallelSucceeds); + + // Act + StreamsEventResponse kinesisBatchResponse = handler.processBatchInParallel(event, context); + + // Assert + assertThat(kinesisBatchResponse.getBatchItemFailures()).isEmpty(); + assertThat(threadList).hasSizeGreaterThan(1); } @ParameterizedTest @Event(value = "kinesis_event.json", type = KinesisEvent.class) - public void shouldAddMessageToBatchFailure_whenException_withMessage(KinesisEvent event) { + void shouldAddMessageToBatchFailure_whenException_withMessage(KinesisEvent event) { // Arrange BatchMessageHandler handler = new BatchMessageHandlerBuilder() .withKinesisBatchHandler() @@ -82,9 +137,28 @@ public void shouldAddMessageToBatchFailure_whenException_withMessage(KinesisEven "49545115243490985018280067714973144582180062593244200961"); } + @ParameterizedTest + @Event(value = "kinesis_event_big.json", type = KinesisEvent.class) + void batchProcessingInParallel_shouldAddMessageToBatchFailure_whenException_withMessage(KinesisEvent event) { + // Arrange + BatchMessageHandler handler = new BatchMessageHandlerBuilder() + .withKinesisBatchHandler() + .buildWithRawMessageHandler(this::processMessageInParallelFailsForFixedMessage); + + // Act + StreamsEventResponse kinesisBatchResponse = handler.processBatchInParallel(event, context); + + // Assert + assertThat(kinesisBatchResponse.getBatchItemFailures()).hasSize(1); + StreamsEventResponse.BatchItemFailure batchItemFailure = kinesisBatchResponse.getBatchItemFailures().get(0); + assertThat(batchItemFailure.getItemIdentifier()).isEqualTo( + "49545115243490985018280067714973144582180062593244200961"); + assertThat(threadList).hasSizeGreaterThan(1); + } + @ParameterizedTest @Event(value = "kinesis_event.json", type = KinesisEvent.class) - public void shouldAddMessageToBatchFailure_whenException_withProduct(KinesisEvent event) { + void shouldAddMessageToBatchFailure_whenException_withProduct(KinesisEvent event) { // Arrange BatchMessageHandler handler = new BatchMessageHandlerBuilder() .withKinesisBatchHandler() @@ -102,7 +176,7 @@ public void shouldAddMessageToBatchFailure_whenException_withProduct(KinesisEven @ParameterizedTest @Event(value = "kinesis_event.json", type = KinesisEvent.class) - public void failingFailureHandlerShouldntFailBatch(KinesisEvent event) { + void failingFailureHandlerShouldntFailBatch(KinesisEvent event) { // Arrange AtomicBoolean wasCalled = new AtomicBoolean(false); BatchMessageHandler handler = new BatchMessageHandlerBuilder() @@ -118,7 +192,7 @@ public void failingFailureHandlerShouldntFailBatch(KinesisEvent event) { // Assert assertThat(kinesisBatchResponse).isNotNull(); - assertThat(kinesisBatchResponse.getBatchItemFailures().size()).isEqualTo(1); + assertThat(kinesisBatchResponse.getBatchItemFailures()).hasSize(1); assertThat(wasCalled.get()).isTrue(); StreamsEventResponse.BatchItemFailure batchItemFailure = kinesisBatchResponse.getBatchItemFailures().get(0); assertThat(batchItemFailure.getItemIdentifier()).isEqualTo( @@ -127,7 +201,7 @@ public void failingFailureHandlerShouldntFailBatch(KinesisEvent event) { @ParameterizedTest @Event(value = "kinesis_event.json", type = KinesisEvent.class) - public void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(KinesisEvent event) { + void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(KinesisEvent event) { // Arrange AtomicBoolean wasCalledAndFailed = new AtomicBoolean(false); BatchMessageHandler handler = new BatchMessageHandlerBuilder() @@ -146,7 +220,7 @@ public void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(KinesisEv // Assert assertThat(kinesisBatchResponse).isNotNull(); - assertThat(kinesisBatchResponse.getBatchItemFailures().size()).isEqualTo(1); + assertThat(kinesisBatchResponse.getBatchItemFailures()).hasSize(1); assertThat(wasCalledAndFailed.get()).isTrue(); StreamsEventResponse.BatchItemFailure batchItemFailure = kinesisBatchResponse.getBatchItemFailures().get(0); assertThat(batchItemFailure.getItemIdentifier()).isEqualTo( diff --git a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/SQSBatchProcessorTest.java b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/SQSBatchProcessorTest.java index 2f9429fa3..7dd51374e 100644 --- a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/SQSBatchProcessorTest.java +++ b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/SQSBatchProcessorTest.java @@ -20,20 +20,43 @@ import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.amazonaws.services.lambda.runtime.tests.annotations.Event; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.params.ParameterizedTest; import org.mockito.Mock; import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; import software.amazon.lambda.powertools.batch.model.Product; -public class SQSBatchProcessorTest { +class SQSBatchProcessorTest { @Mock private Context context; + private final List threadList = Collections.synchronizedList(new ArrayList<>()); + + @AfterEach + public void clear() { + threadList.clear(); + } + // A handler that works private void processMessageSucceeds(SQSEvent.SQSMessage sqsMessage) { } + private void processMessageInParallelSucceeds(SQSEvent.SQSMessage sqsMessage) { + String thread = Thread.currentThread().getName(); + if (!threadList.contains(thread)) { + threadList.add(thread); + } + try { + Thread.sleep(500); // simulate some processing + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + // A handler that throws an exception for _one_ of the sample messages private void processMessageFailsForFixedMessage(SQSEvent.SQSMessage message, Context context) { if (message.getMessageId().equals("e9144555-9a4f-4ec3-99a0-34ce359b4b54")) { @@ -41,8 +64,23 @@ private void processMessageFailsForFixedMessage(SQSEvent.SQSMessage message, Con } } + private void processMessageInParallelFailsForFixedMessage(SQSEvent.SQSMessage message, Context context) { + String thread = Thread.currentThread().getName(); + if (!threadList.contains(thread)) { + threadList.add(thread); + } + try { + Thread.sleep(500); // simulate some processing + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + if (message.getMessageId().equals("e9144555-9a4f-4ec3-99a0-34ce359b4b54")) { + throw new RuntimeException("fake exception"); + } + } + // A handler that throws an exception for _one_ of the deserialized products in the same messages - public void processMessageFailsForFixedProduct(Product product, Context context) { + private void processMessageFailsForFixedProduct(Product product, Context context) { if (product.getId() == 12345) { throw new RuntimeException("fake exception"); } @@ -50,7 +88,7 @@ public void processMessageFailsForFixedProduct(Product product, Context context) @ParameterizedTest @Event(value = "sqs_event.json", type = SQSEvent.class) - public void batchProcessingSucceedsAndReturns(SQSEvent event) { + void batchProcessingSucceedsAndReturns(SQSEvent event) { // Arrange BatchMessageHandler handler = new BatchMessageHandlerBuilder() .withSqsBatchHandler() @@ -60,13 +98,28 @@ public void batchProcessingSucceedsAndReturns(SQSEvent event) { SQSBatchResponse sqsBatchResponse = handler.processBatch(event, context); // Assert - assertThat(sqsBatchResponse.getBatchItemFailures()).hasSize(0); + assertThat(sqsBatchResponse.getBatchItemFailures()).isEmpty(); } + @ParameterizedTest + @Event(value = "sqs_event_big.json", type = SQSEvent.class) + void parallelBatchProcessingSucceedsAndReturns(SQSEvent event) { + // Arrange + BatchMessageHandler handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithRawMessageHandler(this::processMessageInParallelSucceeds); + + // Act + SQSBatchResponse sqsBatchResponse = handler.processBatchInParallel(event, context); + + // Assert + assertThat(sqsBatchResponse.getBatchItemFailures()).isEmpty(); + assertThat(threadList).hasSizeGreaterThan(1); + } @ParameterizedTest @Event(value = "sqs_event.json", type = SQSEvent.class) - public void shouldAddMessageToBatchFailure_whenException_withMessage(SQSEvent event) { + void shouldAddMessageToBatchFailure_whenException_withMessage(SQSEvent event) { // Arrange BatchMessageHandler handler = new BatchMessageHandlerBuilder() .withSqsBatchHandler() @@ -81,9 +134,27 @@ public void shouldAddMessageToBatchFailure_whenException_withMessage(SQSEvent ev assertThat(batchItemFailure.getItemIdentifier()).isEqualTo("e9144555-9a4f-4ec3-99a0-34ce359b4b54"); } + @ParameterizedTest + @Event(value = "sqs_event_big.json", type = SQSEvent.class) + void parallelBatchProcessing_shouldAddMessageToBatchFailure_whenException_withMessage(SQSEvent event) { + // Arrange + BatchMessageHandler handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithRawMessageHandler(this::processMessageInParallelFailsForFixedMessage); + + // Act + SQSBatchResponse sqsBatchResponse = handler.processBatchInParallel(event, context); + + // Assert + assertThat(sqsBatchResponse.getBatchItemFailures()).hasSize(1); + SQSBatchResponse.BatchItemFailure batchItemFailure = sqsBatchResponse.getBatchItemFailures().get(0); + assertThat(batchItemFailure.getItemIdentifier()).isEqualTo("e9144555-9a4f-4ec3-99a0-34ce359b4b54"); + assertThat(threadList).hasSizeGreaterThan(1); + } + @ParameterizedTest @Event(value = "sqs_fifo_event.json", type = SQSEvent.class) - public void shouldAddMessageToBatchFailure_whenException_withSQSFIFO(SQSEvent event) { + void shouldAddMessageToBatchFailure_whenException_withSQSFIFO(SQSEvent event) { // Arrange BatchMessageHandler handler = new BatchMessageHandlerBuilder() .withSqsBatchHandler() @@ -103,7 +174,7 @@ public void shouldAddMessageToBatchFailure_whenException_withSQSFIFO(SQSEvent ev @ParameterizedTest @Event(value = "sqs_event.json", type = SQSEvent.class) - public void shouldAddMessageToBatchFailure_whenException_withProduct(SQSEvent event) { + void shouldAddMessageToBatchFailure_whenException_withProduct(SQSEvent event) { // Arrange BatchMessageHandler handler = new BatchMessageHandlerBuilder() @@ -121,7 +192,7 @@ public void shouldAddMessageToBatchFailure_whenException_withProduct(SQSEvent ev @ParameterizedTest @Event(value = "sqs_event.json", type = SQSEvent.class) - public void failingFailureHandlerShouldntFailBatch(SQSEvent event) { + void failingFailureHandlerShouldntFailBatch(SQSEvent event) { // Arrange AtomicBoolean wasCalled = new AtomicBoolean(false); BatchMessageHandler handler = new BatchMessageHandlerBuilder() @@ -144,7 +215,7 @@ public void failingFailureHandlerShouldntFailBatch(SQSEvent event) { @ParameterizedTest @Event(value = "sqs_event.json", type = SQSEvent.class) - public void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(SQSEvent event) { + void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(SQSEvent event) { // Arrange AtomicBoolean wasCalledAndFailed = new AtomicBoolean(false); BatchMessageHandler handler = new BatchMessageHandlerBuilder() diff --git a/powertools-batch/src/test/resources/dynamo_event_big.json b/powertools-batch/src/test/resources/dynamo_event_big.json new file mode 100644 index 000000000..fa0a75c24 --- /dev/null +++ b/powertools-batch/src/test/resources/dynamo_event_big.json @@ -0,0 +1,376 @@ +{ + "Records": [ + { + "eventID": "c4ca4238a0b923820dcc509a6f75849b", + "eventName": "INSERT", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439001", + "SizeBytes": 26, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", + "userIdentity": { + "principalId": "dynamodb.amazonaws.com", + "type": "Service" + } + }, + { + "eventID": "c81e728d9d4c2f636f067f89cc14862c", + "eventName": "MODIFY", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "OldImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439092", + "SizeBytes": 59, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899" + }, + { + "eventID": "eccbc87e4b5ce2fe28308fd9f2a7baf3", + "eventName": "REMOVE", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "OldImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439093", + "SizeBytes": 38, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899" + }, + { + "eventID": "c4ca4238a0b923820dcc509a6f75849b", + "eventName": "INSERT", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439031", + "SizeBytes": 26, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", + "userIdentity": { + "principalId": "dynamodb.amazonaws.com", + "type": "Service" + } + }, + { + "eventID": "c81e728d9d4c2f636f067f89cc14862c", + "eventName": "MODIFY", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "OldImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439092", + "SizeBytes": 59, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899" + }, + { + "eventID": "eccbc87e4b5ce2fe28308fd9f2a7baf3", + "eventName": "REMOVE", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "OldImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439093", + "SizeBytes": 38, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899" + }, + { + "eventID": "c4ca4238a0b923820dcc509a6f75849b", + "eventName": "INSERT", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439001", + "SizeBytes": 26, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", + "userIdentity": { + "principalId": "dynamodb.amazonaws.com", + "type": "Service" + } + }, + { + "eventID": "c81e728d9d4c2f636f067f89cc14862c", + "eventName": "MODIFY", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "OldImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439092", + "SizeBytes": 59, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899" + }, + { + "eventID": "eccbc87e4b5ce2fe28308fd9f2a7baf3", + "eventName": "REMOVE", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "OldImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439093", + "SizeBytes": 38, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899" + }, + { + "eventID": "c4ca4238a0b923820dcc509a6f75849b", + "eventName": "INSERT", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439031", + "SizeBytes": 26, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899", + "userIdentity": { + "principalId": "dynamodb.amazonaws.com", + "type": "Service" + } + }, + { + "eventID": "c81e728d9d4c2f636f067f89cc14862c", + "eventName": "MODIFY", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "NewImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "OldImage": { + "Message": { + "S": "New item!" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439091", + "SizeBytes": 59, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899" + }, + { + "eventID": "eccbc87e4b5ce2fe28308fd9f2a7baf3", + "eventName": "REMOVE", + "eventVersion": "1.1", + "eventSource": "aws:dynamodb", + "awsRegion": "eu-central-1", + "dynamodb": { + "Keys": { + "Id": { + "N": "101" + } + }, + "OldImage": { + "Message": { + "S": "This item has changed" + }, + "Id": { + "N": "101" + } + }, + "ApproximateCreationDateTime": 1428537600, + "SequenceNumber": "4421584500000000017450439093", + "SizeBytes": 38, + "StreamViewType": "NEW_AND_OLD_IMAGES" + }, + "eventSourceARN": "arn:aws:dynamodb:eu-central-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899" + } + ] +} \ No newline at end of file diff --git a/powertools-batch/src/test/resources/kinesis_event_big.json b/powertools-batch/src/test/resources/kinesis_event_big.json new file mode 100644 index 000000000..57f702d27 --- /dev/null +++ b/powertools-batch/src/test/resources/kinesis_event_big.json @@ -0,0 +1,224 @@ +{ + "Records": [ + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNCwgIm5hbWUiOiJwcm9kdWN0IiwgInByaWNlIjo0Mn0=", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200962", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200962", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNDUsICJuYW1lIjoicHJvZHVjdDUiLCAicHJpY2UiOjQ1fQ==", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200963", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200963", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNCwgIm5hbWUiOiJwcm9kdWN0IiwgInByaWNlIjo0Mn0=", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200964", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200964", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNDUsICJuYW1lIjoicHJvZHVjdDUiLCAicHJpY2UiOjQ1fQ==", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200965", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200965", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + },{ + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNCwgIm5hbWUiOiJwcm9kdWN0IiwgInByaWNlIjo0Mn0=", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200966", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200966", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNDUsICJuYW1lIjoicHJvZHVjdDUiLCAicHJpY2UiOjQ1fQ==", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200961", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNCwgIm5hbWUiOiJwcm9kdWN0IiwgInByaWNlIjo0Mn0=", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200967", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200967", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNCwgIm5hbWUiOiJwcm9kdWN0IiwgInByaWNlIjo0Mn0=", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200968", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200968", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNDUsICJuYW1lIjoicHJvZHVjdDUiLCAicHJpY2UiOjQ1fQ==", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200969", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200969", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNCwgIm5hbWUiOiJwcm9kdWN0IiwgInByaWNlIjo0Mn0=", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200971", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200971", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNCwgIm5hbWUiOiJwcm9kdWN0IiwgInByaWNlIjo0Mn0=", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200981", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200981", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNDUsICJuYW1lIjoicHJvZHVjdDUiLCAicHJpY2UiOjQ1fQ==", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200992", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200992", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "eyJpZCI6MTIzNCwgIm5hbWUiOiJwcm9kdWN0IiwgInByaWNlIjo0Mn0=", + "sequenceNumber": "49545115243490985018280067714973144582180062593244210961", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244210961", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + } + ] +} \ No newline at end of file diff --git a/powertools-batch/src/test/resources/sqs_event_big.json b/powertools-batch/src/test/resources/sqs_event_big.json new file mode 100644 index 000000000..f5c83f442 --- /dev/null +++ b/powertools-batch/src/test/resources/sqs_event_big.json @@ -0,0 +1,429 @@ +{ + "Records": [ + { + "messageId": "d9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "13e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1234,\n \"name\": \"product\",\n \"price\": 42\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "13e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "f9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "14e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1235,\n \"name\": \"product\",\n \"price\": 43\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "14e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "g9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "15e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1236,\n \"name\": \"product\",\n \"price\": 44\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "15e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "c9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "16e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1237,\n \"name\": \"product\",\n \"price\": 45\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "16e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "b4144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "13e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1238,\n \"name\": \"product\",\n \"price\": 486\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "13e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "a2144552-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "14e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1239,\n \"name\": \"product\",\n \"price\": 430\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "14e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "32144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "15e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1240,\n \"name\": \"product\",\n \"price\": 445\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "15e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "a9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "16e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1241,\n \"name\": \"product\",\n \"price\": 45\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "16e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "d9144555-9a4f-4ec3-99a0-34ce359b354", + "receiptHandle": "13e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1242,\n \"name\": \"product\",\n \"price\": 42\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "13e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "e9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "14e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1243,\n \"name\": \"product\",\n \"price\": 43\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "14e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "19144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "15e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1244,\n \"name\": \"product\",\n \"price\": 44\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "15e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "c9144555-9a4f-4ec3-99a0-34ce3a9b4b54", + "receiptHandle": "16e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1245,\n \"name\": \"product\",\n \"price\": 45\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "16e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "b4144555-9a4f-4ec3-99a5-34ce359b4b54", + "receiptHandle": "13e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1247,\n \"name\": \"product\",\n \"price\": 486\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "13e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "a2144555-9a4f-4ec3-97a0-34ce359b4b54", + "receiptHandle": "14e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1248,\n \"name\": \"product\",\n \"price\": 430\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "14e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "3k144555-9a4f-4ec2-99a0-34ce359b4b54", + "receiptHandle": "15e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1249,\n \"name\": \"product\",\n \"price\": 445\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "15e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "h9144555-9aaf-4ec3-99a0-34ce359b4b54", + "receiptHandle": "16e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1250,\n \"name\": \"product\",\n \"price\": 45\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "16e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "d9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "13e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1234,\n \"name\": \"product\",\n \"price\": 42\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "13e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "f9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "14e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1235,\n \"name\": \"product\",\n \"price\": 43\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "14e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "g9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "15e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1236,\n \"name\": \"product\",\n \"price\": 44\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "15e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "c9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "16e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1237,\n \"name\": \"product\",\n \"price\": 45\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "16e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "b4144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "13e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1238,\n \"name\": \"product\",\n \"price\": 486\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "13e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "a2144552-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "14e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1239,\n \"name\": \"product\",\n \"price\": 430\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "14e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "32144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "15e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1240,\n \"name\": \"product\",\n \"price\": 445\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "15e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "a9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "16e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1241,\n \"name\": \"product\",\n \"price\": 45\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "16e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "d9144555-9a4f-4ec3-99a0-34ce359b354", + "receiptHandle": "13e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{\n \"id\": 1242,\n \"name\": \"product\",\n \"price\": 42\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "13e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + } + ] +} \ No newline at end of file From 754454a92cfe4e6c69eed86ddf5fedf1d59bf4c7 Mon Sep 17 00:00:00 2001 From: Jerome Van Der Linden Date: Thu, 4 Jul 2024 10:03:24 +0200 Subject: [PATCH 192/577] improve tracing doc for xray --- docs/core/tracing.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/core/tracing.md b/docs/core/tracing.md index 4cb06fc29..7ad896462 100644 --- a/docs/core/tracing.md +++ b/docs/core/tracing.md @@ -308,8 +308,24 @@ under a subsegment, or you are doing multithreaded programming. Refer examples b ## Instrumenting SDK clients and HTTP calls -User should make sure to instrument the SDK clients explicitly based on the function dependency. Refer details on -[how to instrument SDK client with Xray](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-awssdkclients.html) and [outgoing http calls](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-httpclients.html). +Powertools for Lambda (Java) cannot intercept SDK clients instantiation to add X-Ray instrumentation. You should make sure to instrument the SDK clients explicitly. Refer details on +[how to instrument SDK client with Xray](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java.html#xray-sdk-java-awssdkclients) +and [outgoing http calls](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java.html#xray-sdk-java-httpclients). For example: + +=== "LambdaHandler.java" + + ```java hl_lines="1 2 7" + import com.amazonaws.xray.AWSXRay; + import com.amazonaws.xray.handlers.TracingHandler; + + public class LambdaHandler { + private AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard() + .withRegion(Regions.fromName(System.getenv("AWS_REGION"))) + .withRequestHandlers(new TracingHandler(AWSXRay.getGlobalRecorder())) + .build(); + // ... + } + ``` ## Testing your code From 8cb9f0a50b38ebd616b8c789259e9a4520d6787b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 12:01:37 +0000 Subject: [PATCH 193/577] build(deps): bump org.assertj:assertj-core from 3.25.3 to 3.26.3 (#1695) Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.25.3 to 3.26.3. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.25.3...assertj-build-3.26.3) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4ba84d4fc..81aa226d7 100644 --- a/pom.xml +++ b/pom.xml @@ -298,7 +298,7 @@ org.assertj assertj-core - 3.25.3 + 3.26.3 test From e5ce29901aff6d0cd041144b20eaab53643234b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:10:23 +0200 Subject: [PATCH 194/577] build(deps): bump com.networknt:json-schema-validator (#1705) Bumps [com.networknt:json-schema-validator](https://github.com/networknt/json-schema-validator) from 1.4.3 to 1.5.1. - [Release notes](https://github.com/networknt/json-schema-validator/releases) - [Changelog](https://github.com/networknt/json-schema-validator/blob/master/CHANGELOG.md) - [Commits](https://github.com/networknt/json-schema-validator/compare/1.4.3...1.5.1) --- updated-dependencies: - dependency-name: com.networknt:json-schema-validator dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-validation/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index fa299b591..c1521f1c7 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -65,7 +65,7 @@ com.networknt json-schema-validator - 1.4.3 + 1.5.1 com.amazonaws From 2c087103bda1671414c2b5c37d6c801ff2337a8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 15:34:59 +0200 Subject: [PATCH 195/577] build(deps): bump jackson.version from 2.17.1 to 2.17.2 (#1688) Bumps `jackson.version` from 2.17.1 to 2.17.2. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 81aa226d7..eccaf3d2d 100644 --- a/pom.xml +++ b/pom.xml @@ -70,7 +70,7 @@ 2.20.0 2.23.1 2.0.7 - 2.17.1 + 2.17.2 2.25.35 2.16.0 2.2.0 From 4a49c2a87426f13edf97bec902c4495b5d44df32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 15:42:57 +0200 Subject: [PATCH 196/577] build(deps): bump org.apache.commons:commons-lang3 from 3.13.0 to 3.15.0 (#1699) Bumps org.apache.commons:commons-lang3 from 3.13.0 to 3.15.0. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index eccaf3d2d..fe421442a 100644 --- a/pom.xml +++ b/pom.xml @@ -286,7 +286,7 @@ org.apache.commons commons-lang3 - 3.13.0 + 3.15.0 test From 97e7c49080ddafabd335dec3672bcbdb2572ecf0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 15:43:37 +0200 Subject: [PATCH 197/577] build(deps): bump aws.sdk.version from 2.25.35 to 2.26.28 (#1707) Bumps `aws.sdk.version` from 2.25.35 to 2.26.28. Updates `software.amazon.awssdk:bom` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:http-client-spi` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:url-connection-client` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:dynamodb` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:s3` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:lambda` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:kinesis` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:cloudwatch` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:xray` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:sqs` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:cloudformation` from 2.25.35 to 2.26.28 Updates `software.amazon.awssdk:sts` from 2.25.35 to 2.26.28 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 0aa8fab83..fa6a9136c 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 11 1.2.3 3.11.3 - 2.25.35 + 2.26.28 1.9.20.1 diff --git a/pom.xml b/pom.xml index fe421442a..b19520867 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 2.23.1 2.0.7 2.17.2 - 2.25.35 + 2.26.28 2.16.0 2.2.0 UTF-8 From 91cfec235c7ab273d206c7cc677dbbad68cb2d69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 13:20:12 +0200 Subject: [PATCH 198/577] build(deps): bump ch.qos.logback:logback-classic from 1.5.5 to 1.5.7 (#1718) Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.5.5 to 1.5.7. - [Commits](https://github.com/qos-ch/logback/compare/v_1.5.5...v_1.5.7) --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-logging/powertools-logging-logback/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 11fc85b72..f723be91b 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -28,7 +28,7 @@ ch.qos.logback logback-classic - 1.5.5 + 1.5.7 com.sun.mail From 39828b3bad357e1b825f612bd387d50277df4f5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 13:52:30 +0200 Subject: [PATCH 199/577] build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1723) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.130.0 to 2.154.1. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.130.0...v2.154.1) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 100928618..5c96f3ec4 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ 2.0.0-SNAPSHOT UTF-8 - 2.130.0 + 2.154.1 [10.0.0,11.0.0) 5.10.0 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 5171bb418..f66c5959a 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ 11 11 10.3.0 - 2.130.0 + 2.154.1 From c091a83d0a1b9d5d058da4040d2aa1ff889d81c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 13:58:30 +0200 Subject: [PATCH 200/577] build(deps): bump aws.xray.recorder.version from 2.16.0 to 2.18.1 (#1727) Bumps `aws.xray.recorder.version` from 2.16.0 to 2.18.1. Updates `com.amazonaws:aws-xray-recorder-sdk-core` from 2.16.0 to 2.18.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.16.0...v2.18.1) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core` from 2.16.0 to 2.18.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.16.0...v2.18.1) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2` from 2.16.0 to 2.18.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.16.0...v2.18.1) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor` from 2.16.0 to 2.18.1 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.16.0...v2.18.1) --- updated-dependencies: - dependency-name: com.amazonaws:aws-xray-recorder-sdk-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b19520867..cd58d3b7b 100644 --- a/pom.xml +++ b/pom.xml @@ -72,7 +72,7 @@ 2.0.7 2.17.2 2.26.28 - 2.16.0 + 2.18.1 2.2.0 UTF-8 1.2.3 From e74afda303fc8017c6c7342d6b33e821855df540 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 13:59:07 +0200 Subject: [PATCH 201/577] build(deps): bump com.puppycrawl.tools:checkstyle (#1728) Bumps [com.puppycrawl.tools:checkstyle](https://github.com/checkstyle/checkstyle) from 10.12.3 to 10.18.1. - [Release notes](https://github.com/checkstyle/checkstyle/releases) - [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-10.12.3...checkstyle-10.18.1) --- updated-dependencies: - dependency-name: com.puppycrawl.tools:checkstyle dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cd58d3b7b..e43691536 100644 --- a/pom.xml +++ b/pom.xml @@ -665,7 +665,7 @@ com.puppycrawl.tools checkstyle - 10.12.3 + 10.18.1 From aa65755fd95251b9e214affa191c57f1504d3fbb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 14:06:27 +0200 Subject: [PATCH 202/577] build(deps): bump aws.sdk.version from 2.26.28 to 2.27.17 (#1729) Bumps `aws.sdk.version` from 2.26.28 to 2.27.17. Updates `software.amazon.awssdk:bom` from 2.26.28 to 2.27.17 Updates `software.amazon.awssdk:http-client-spi` from 2.26.28 to 2.27.17 Updates `software.amazon.awssdk:url-connection-client` from 2.26.12 to 2.27.17 Updates `software.amazon.awssdk:dynamodb` from 2.26.28 to 2.27.17 Updates `software.amazon.awssdk:s3` from 2.26.12 to 2.27.17 Updates `software.amazon.awssdk:lambda` from 2.26.28 to 2.27.17 Updates `software.amazon.awssdk:kinesis` from 2.26.12 to 2.27.17 Updates `software.amazon.awssdk:cloudwatch` from 2.26.28 to 2.27.17 Updates `software.amazon.awssdk:xray` from 2.26.28 to 2.27.17 Updates `software.amazon.awssdk:sqs` from 2.26.12 to 2.27.17 Updates `software.amazon.awssdk:cloudformation` from 2.26.28 to 2.27.17 Updates `software.amazon.awssdk:sts` from 2.26.28 to 2.27.17 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index fa6a9136c..699f2b000 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 11 1.2.3 3.11.3 - 2.26.28 + 2.27.17 1.9.20.1 diff --git a/pom.xml b/pom.xml index e43691536..84908a341 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 2.23.1 2.0.7 2.17.2 - 2.26.28 + 2.27.17 2.18.1 2.2.0 UTF-8 From a925f4887ba0a12771b67497382e23677700d0eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:35:42 +0200 Subject: [PATCH 203/577] build(deps): bump aws.sdk.version from 2.27.17 to 2.27.21 (#1733) Bumps `aws.sdk.version` from 2.27.17 to 2.27.21. Updates `software.amazon.awssdk:bom` from 2.27.17 to 2.27.21 Updates `software.amazon.awssdk:http-client-spi` from 2.27.17 to 2.27.21 Updates `software.amazon.awssdk:url-connection-client` from 2.26.12 to 2.27.21 Updates `software.amazon.awssdk:dynamodb` from 2.27.17 to 2.27.21 Updates `software.amazon.awssdk:s3` from 2.26.12 to 2.27.21 Updates `software.amazon.awssdk:lambda` from 2.27.17 to 2.27.21 Updates `software.amazon.awssdk:kinesis` from 2.26.12 to 2.27.21 Updates `software.amazon.awssdk:cloudwatch` from 2.27.17 to 2.27.21 Updates `software.amazon.awssdk:xray` from 2.27.17 to 2.27.21 Updates `software.amazon.awssdk:sqs` from 2.26.12 to 2.27.21 Updates `software.amazon.awssdk:cloudformation` from 2.27.17 to 2.27.21 Updates `software.amazon.awssdk:sts` from 2.27.17 to 2.27.21 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 699f2b000..d0dd57188 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 11 1.2.3 3.11.3 - 2.27.17 + 2.27.21 1.9.20.1 diff --git a/pom.xml b/pom.xml index 84908a341..8266aedd4 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 2.23.1 2.0.7 2.17.2 - 2.27.17 + 2.27.21 2.18.1 2.2.0 UTF-8 From c9c4d0513134fa6edb154295382016d5db9b6a36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:43:00 +0200 Subject: [PATCH 204/577] build(deps): bump aws.sdk.version from 2.27.21 to 2.28.1 (#1736) Bumps `aws.sdk.version` from 2.27.21 to 2.28.1. Updates `software.amazon.awssdk:bom` from 2.27.21 to 2.28.1 Updates `software.amazon.awssdk:http-client-spi` from 2.27.21 to 2.28.1 Updates `software.amazon.awssdk:url-connection-client` from 2.26.12 to 2.28.1 Updates `software.amazon.awssdk:dynamodb` from 2.27.21 to 2.28.1 Updates `software.amazon.awssdk:s3` from 2.26.12 to 2.28.1 Updates `software.amazon.awssdk:lambda` from 2.27.21 to 2.28.1 Updates `software.amazon.awssdk:kinesis` from 2.26.12 to 2.28.1 Updates `software.amazon.awssdk:cloudwatch` from 2.27.21 to 2.28.1 Updates `software.amazon.awssdk:xray` from 2.27.21 to 2.28.1 Updates `software.amazon.awssdk:sqs` from 2.26.12 to 2.28.1 Updates `software.amazon.awssdk:cloudformation` from 2.27.21 to 2.28.1 Updates `software.amazon.awssdk:sts` from 2.27.21 to 2.28.1 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index d0dd57188..782162029 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ 11 1.2.3 3.11.3 - 2.27.21 + 2.28.1 1.9.20.1 diff --git a/pom.xml b/pom.xml index 8266aedd4..c17c88736 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 2.23.1 2.0.7 2.17.2 - 2.27.21 + 2.28.1 2.18.1 2.2.0 UTF-8 From c6e41b4702ad604ffde803428a3c7db3698b9841 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:43:22 +0200 Subject: [PATCH 205/577] build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1737) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.154.1 to 2.158.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.154.1...v2.158.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 5c96f3ec4..6ab3a7601 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ 2.0.0-SNAPSHOT UTF-8 - 2.154.1 + 2.158.0 [10.0.0,11.0.0) 5.10.0 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index f66c5959a..1a147922b 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ 11 11 10.3.0 - 2.154.1 + 2.158.0 From a22dc0cafa507bed88001b29f8c195c2ee8c1f8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:02:56 +0200 Subject: [PATCH 206/577] build(deps): bump org.junit.jupiter:junit-jupiter-api (#1743) Bumps [org.junit.jupiter:junit-jupiter-api](https://github.com/junit-team/junit5) from 5.10.2 to 5.11.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.2...r5.11.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter-api dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 422a8ebb5..2a866fa82 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -69,7 +69,7 @@ org.junit.jupiter junit-jupiter-api - 5.10.2 + 5.11.1 test diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index 340bcbafb..cb0fc4474 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -56,7 +56,7 @@ org.junit.jupiter junit-jupiter-api - 5.10.2 + 5.11.1 test diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index d1973f3df..c021572f8 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -59,7 +59,7 @@ org.junit.jupiter junit-jupiter-api - 5.10.2 + 5.11.1 test From 95a91302aabe304f14f0d6b0a2c9056c7fdf93f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:04:13 +0200 Subject: [PATCH 207/577] build(deps-dev): bump org.junit.jupiter:junit-jupiter (#1744) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit5) from 5.10.0 to 5.11.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.0...r5.11.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 6ab3a7601..2cd4c6043 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -9,7 +9,7 @@ UTF-8 2.158.0 [10.0.0,11.0.0) - 5.10.0 + 5.11.1 From 697f176d9d8e3e43e0cb1a5ac0a95f9d1dd6966a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:49:47 +0200 Subject: [PATCH 208/577] build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib (#1749) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.158.0 to 2.162.1. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/v2.162.1/CHANGELOG.v2.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.158.0...v2.162.1) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 2cd4c6043..fca756921 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ 2.0.0-SNAPSHOT UTF-8 - 2.158.0 + 2.162.1 [10.0.0,11.0.0) 5.11.1 diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 1a147922b..1bf6310f4 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ 11 11 10.3.0 - 2.158.0 + 2.162.1 From 72cac418c2136d7956dbc4690051c97bddc8b674 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 10:20:38 +0100 Subject: [PATCH 209/577] build(deps): bump log4j.version from 2.23.1 to 2.24.3 (#1783) Bumps `log4j.version` from 2.23.1 to 2.24.3. Updates `org.apache.logging.log4j:log4j-core` from 2.23.1 to 2.24.3 Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.23.1 to 2.24.3 Updates `org.apache.logging.log4j:log4j-slf4j2-impl` from 2.23.1 to 2.24.3 Updates `org.apache.logging.log4j:log4j-api` from 2.23.1 to 2.24.3 Updates `org.apache.logging.log4j:log4j-layout-template-json` from 2.23.1 to 2.24.3 Updates `org.apache.logging.log4j:log4j-jcl` from 2.23.1 to 2.24.3 --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-slf4j-impl dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-slf4j2-impl dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-api dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-layout-template-json dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-jcl dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index f942fe1fa..22a1b0d32 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -11,7 +11,7 @@ jar - 2.23.1 + 2.24.3 11 11 1.9.20.1 diff --git a/pom.xml b/pom.xml index c17c88736..d07005c70 100644 --- a/pom.xml +++ b/pom.xml @@ -68,7 +68,7 @@ 11 3.1.2 2.20.0 - 2.23.1 + 2.24.3 2.0.7 2.17.2 2.28.1 From cef1ef17c28577d20d42716bbbd60e68a0905bfc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 10:20:58 +0100 Subject: [PATCH 210/577] build(deps): bump aws.sdk.version from 2.26.12 to 2.30.31 (#1782) Bumps `aws.sdk.version` from 2.26.12 to 2.30.31. Updates `software.amazon.awssdk:url-connection-client` from 2.26.12 to 2.30.31 Updates `software.amazon.awssdk:sdk-core` from 2.26.12 to 2.30.31 Updates `software.amazon.awssdk:s3` from 2.26.12 to 2.30.31 Updates `software.amazon.awssdk:kinesis` from 2.26.12 to 2.30.31 Updates `software.amazon.awssdk:sqs` from 2.26.12 to 2.30.31 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.26.12 to 2.30.31 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 6eb548937..b8b50b77f 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ 11 11 1.9.20.1 - 2.26.12 + 2.30.31 From 26f8b10ddcd85b9339d9543c771873d8805bddb9 Mon Sep 17 00:00:00 2001 From: RR <5737258+rr-on-gh@users.noreply.github.com> Date: Thu, 13 Mar 2025 14:14:39 +0100 Subject: [PATCH 211/577] feat(v2): Add GraalVM reachability metadata for core utilities (#1753) Provides GraalVM Reachability Metadata files and respective Maven configurations / profiles for building a native-image for all core-utilities. Also refactors all unit tests to use Junit Pioneer for mocking environment variables. --------- Co-authored-by: Philipp Page --- GraalVM.md | 60 + docs/FAQs.md | 111 +- docs/core/logging.md | 6 +- .../sam-graalvm/Dockerfile | 14 + .../sam-graalvm/Makefile | 6 + .../sam-graalvm/README.md | 64 + .../sam-graalvm/events/event.json | 63 + .../sam-graalvm/pom.xml | 186 +++ .../sam-graalvm/src/main/config/bootstrap | 4 + .../src/main/java/helloworld/App.java | 111 ++ .../aws-lambda-java-core/reflect-config.json | 13 + .../reflect-config.json | 35 + .../jni-config.json | 11 + .../native-image.properties | 1 + .../reflect-config.json | 34 + .../resource-config.json | 19 + .../reflect-config.json | 25 + .../helloworld/native-image.properties | 1 + .../helloworld/reflect-config.json | 11 + .../helloworld/resource-config.json | 7 + .../sam-graalvm/src/main/resources/log4j2.xml | 16 + .../sam-graalvm/template.yaml | 52 + pom.xml | 1 - powertools-common/pom.xml | 102 ++ .../internal/UserAgentConfigurator.java | 12 +- .../powertools-common/jni-config.json | 22 + .../powertools-common/reflect-config.json | 189 +++ .../powertools-common/resource-config.json | 21 + .../internal/LambdaHandlerProcessorTest.java | 60 +- .../internal/UserAgentConfiguratorTest.java | 36 +- .../src/test/resources/unreadable.properties | 2 - powertools-logging/pom.xml | 102 +- .../powertools-logging-log4j/pom.xml | 102 +- .../powertools-logging-log4j/jni-config.json | 26 + .../reflect-config.json | 1225 +++++++++++++++++ .../resource-config.json | 95 ++ .../json/resolver/PowertoolsResolverTest.java | 15 +- .../powertools-logging-logback/pom.xml | 96 ++ .../jni-config.json | 26 + .../reflect-config.json | 290 ++++ .../resource-config.json | 29 + .../powertools-logging/jni-config.json | 26 + .../powertools-logging/reflect-config.json | 669 +++++++++ .../powertools-logging/resource-config.json | 23 + .../internal/LambdaLoggingAspectTest.java | 66 +- powertools-metrics/pom.xml | 104 +- .../powertools-metrics/jni-config.json | 22 + .../powertools-metrics/reflect-config.json | 285 ++++ .../powertools-metrics/resource-config.json | 19 + .../powertools/metrics/MetricsLoggerTest.java | 339 ++--- .../internal/LambdaMetricsAspectTest.java | 527 ++++--- powertools-serialization/pom.xml | 96 +- .../powertools-serialization/jni-config.json | 18 + .../reflect-config.json | 470 +++++++ .../resource-config.json | 85 ++ powertools-tracing/pom.xml | 97 ++ .../powertools-tracing/jni-config.json | 26 + .../powertools-tracing/reflect-config.json | 365 +++++ .../powertools-tracing/resource-config.json | 31 + .../internal/LambdaTracingAspectTest.java | 261 ++-- 60 files changed, 6086 insertions(+), 744 deletions(-) create mode 100644 GraalVM.md create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/Dockerfile create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/Makefile create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/README.md create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/events/event.json create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/pom.xml create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/config/bootstrap create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/java/helloworld/App.java create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/log4j2.xml create mode 100644 examples/powertools-examples-core-utilities/sam-graalvm/template.yaml create mode 100644 powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/jni-config.json create mode 100644 powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/reflect-config.json create mode 100644 powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/resource-config.json delete mode 100644 powertools-common/src/test/resources/unreadable.properties create mode 100644 powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/jni-config.json create mode 100644 powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json create mode 100644 powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json create mode 100644 powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/jni-config.json create mode 100644 powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json create mode 100644 powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/resource-config.json create mode 100644 powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/jni-config.json create mode 100644 powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json create mode 100644 powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json create mode 100644 powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/jni-config.json create mode 100644 powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json create mode 100644 powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json create mode 100644 powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/jni-config.json create mode 100644 powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json create mode 100644 powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json diff --git a/GraalVM.md b/GraalVM.md new file mode 100644 index 000000000..56c72d96f --- /dev/null +++ b/GraalVM.md @@ -0,0 +1,60 @@ +# GraalVM Compatibility for AWS Lambda Powertools Java + +## Table of Contents +- [Overview](#overview) +- [Prerequisites](#prerequisites) +- [General Implementation Steps](#general-implementation-steps) +- [Known Issues and Solutions](#known-issues-and-solutions) +- [Reference Implementation](#reference-implementation) + +## Overview +This documentation provides guidance for adding GraalVM support for AWS Lambda Powertools Java modules and using the modules in Lambda functions. + +## Prerequisites +- GraalVM 21+ installation +- Maven 3.x + +## General Implementation Steps +GraalVM native image compilation requires complete knowledge of an application's dynamic features at build time. The GraalVM reachability metadata (GRM) JSON files are essential because Java applications often use features that are determined at runtime, such as reflection, dynamic proxy classes, resource loading, and JNI (Java Native Interface). The metadata files tell GraalVM which classes need reflection access, which resources need to be included in the native image, and which proxy classes need to be generated. + +In order to generate the metadata reachability files for Powertools for Lambda, follow these general steps. + +1. **Add Maven Profiles** + - Add profile for generating GraalVM reachability metadata files. You can find an example of this in profile `generate-graalvm-files` of this [pom.xml](powertools-common/pom.xml). + - Add another profile for running the tests in the native image. You can find and example of this in profile `graalvm-native` of this [pom.xml](powertools-common/pom.xml). + +2. **Generate Reachability Metadata** + - Set the `JAVA_HOME` environment variable to use GraalVM + - Run tests with `-Pgenerate-graalvm-files` profile. +```shell +mvn -Pgenerate-graalvm-files clean test +``` + +3. **Validate Native Image Tests** + - Set the `JAVA_HOME` environment variable to use GraalVM + - Run tests with `-Pgraalvm-native` profile. This will build a GraalVM native image and run the JUnit tests. +```shell +mvn -Pgraalvm-native clean test +``` + +4. **Clean Up Metadata** + - GraalVM metadata reachability files generated in Step 2 contains references to the test scoped dependencies as well. + - Remove the references in generated metadata files for the following (and any other references to test scoped resources and classes): + - JUnit + - Mockito + - ByteBuddy + +## Known Issues and Solutions +1. **Mockito Compatibility** + - Powertools uses Mockito 5.x which uses “inline mock maker” as the default. This mock maker does not play well with GraalVM. Mockito [recommends](https://github.com/mockito/mockito/releases/tag/v5.0.0) using subclass mock maker with GraalVM. Therefore `generate-graalvm-files` profile uses subclass mock maker instead of inline mock maker. + - Subclass mock maker does not support testing static methods. Tests have therefore been modified to use [JUnit Pioneer](https://junit-pioneer.org/docs/environment-variables/) to inject the environment variables in the scope of the test's execution. + +2. **Log4j Compatibility** + - Version 2.22.1 fails with this error +``` +java.lang.InternalError: com.oracle.svm.core.jdk.UnsupportedFeatureError: Defining hidden classes at runtime is not supported. +``` + - This has been [fixed](https://github.com/apache/logging-log4j2/discussions/2364#discussioncomment-8950077) in Log4j 2.24.x. PT has been updated to use this version of Log4j + +## Reference Implementation +Working example is available in the [examples](examples/powertools-examples-core-utilities/sam-graalvm). diff --git a/docs/FAQs.md b/docs/FAQs.md index 88aa81c9f..b42302239 100644 --- a/docs/FAQs.md +++ b/docs/FAQs.md @@ -142,4 +142,113 @@ The following example shows how to use the Lambda Powertools Parameters module w } ``` The `aws-crt-client` was considered for adoption as the default HTTP client in Lambda Powertools for Java as mentioned in [Move SDK http client to CRT](https://github.com/aws-powertools/powertools-lambda-java/issues/1092), -but due to the impact on the developer experience it was decided to stick with the `url-connection-client`. \ No newline at end of file +but due to the impact on the developer experience it was decided to stick with the `url-connection-client`. + +## How can I use Powertools for AWS Lambda (Java) with GraalVM? + +Powertools core utilities, i.e. [logging](./core/logging.md), [metrics](./core/metrics.md) and [tracing](./core/tracing.md), include the [GraalVM Reachability Metadata (GRM)](https://www.graalvm.org/latest/reference-manual/native-image/metadata/) in the `META-INF` directories of the respective JARs. You can find a working example of Serverless Application Model (SAM) based application in the [examples](../examples/powertools-examples-core-utilities/sam-graalvm/README.md) directory. + +Below, you find typical steps you need to follow in a Maven based Java project: + +### Set the environment to use GraalVM + +```shell +export JAVA_HOME= +``` + +### Use log4j `>2.24.0` +Log4j version `2.24.0` adds [support for GraalVM](https://github.com/apache/logging-log4j2/issues/1539#issuecomment-2106766878). Depending on your project's dependency hierarchy, older version of log4j might be included in the final dependency graph. Make sure version `>2.24.0` of these dependencies are used by your Maven project: + +```xml + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + org.apache.logging.log4j + log4j-slf4j2-impl + ${log4j.version} + + + org.apache.logging.log4j + log4j-layout-template-json + ${log4j.version} + + + +``` + +### Add the AWS Lambda Java Runtime Interface Client dependency + +The Runtime Interface Client allows your function to receive invocation events from Lambda, send the response back to Lambda, and report errors to the Lambda service. Add the below dependency to your Maven project: + +```xml + + com.amazonaws + aws-lambda-java-runtime-interface-client + 2.1.1 + +``` + +Also include the AWS Lambda GRM files by copying the `com.amazonaws` [directory](../examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/) in your project's `META-INF/native-image` directory + +### Build the native image + +Use the `native-maven-plugin` to build the native image. You can do this by adding the plugin to your `pom.xml` and creating a build profile called `native-image` that can build the native image of your Lambda function: + +```xml + + + native-image + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.1 + true + + + build-native + + build + + package + + + + your-project-name + com.amazonaws.services.lambda.runtime.api.client.AWSLambda + + + --enable-url-protocols=http + --add-opens java.base/java.util=ALL-UNNAMED + + + + + + + +``` + +Create a Docker image using a `Dockerfile` like [this](../examples/powertools-examples-core-utilities/sam-graalvm/Dockerfile) to create an x86 based build image. + +```shell +docker build --platform linux/amd64 . -t your-org/your-app-graalvm-builder +``` + +Create the native image of you Lambda function using the Docker command below. + +```shell +docker run --platform linux/amd64 -it -v `pwd`:`pwd` -w `pwd` -v ~/.m2:/root/.m2 your-org/your-app-graalvm-builder mvn clean -Pnative-image package + +``` +The native image is created in the `target/` directory. diff --git a/docs/core/logging.md b/docs/core/logging.md index 5306c55df..b5dd38ccf 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -444,7 +444,7 @@ we provide [built-in JMESPath expressions](#built-in-correlation-id-expressions) #### Custom keys -** Using StructuredArguments ** +**Using StructuredArguments** To append additional keys in your logs, you can use the `StructuredArguments` class: @@ -624,7 +624,7 @@ To append additional keys in your logs, you can use the `StructuredArguments` cl } ``` -** Using MDC ** +**Using MDC** Mapped Diagnostic Context (MDC) is essentially a Key-Value store. It is supported by the [SLF4J API](https://www.slf4j.org/manual.html#mdc){target="_blank"}, [logback](https://logback.qos.ch/manual/mdc.html){target="_blank"} and log4j (known as [ThreadContext](https://logging.apache.org/log4j/2.x/manual/thread-context.html){target="_blank"}). You can use the following standard: @@ -1048,4 +1048,4 @@ Use the `LambdaEcsEncoder` rather than the `LambdaJsonEncoder` when configuring - ``` \ No newline at end of file + ``` diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/Dockerfile b/examples/powertools-examples-core-utilities/sam-graalvm/Dockerfile new file mode 100644 index 000000000..a690606ad --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/Dockerfile @@ -0,0 +1,14 @@ +#Use the official AWS SAM base image for Java 21 +FROM public.ecr.aws/sam/build-java21:latest + +#Install GraalVM dependencies +RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz +RUN mv graalvm-jdk-21.* /usr/lib/graalvm + +#Make native image and mvn available on CLI +RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image +RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn + +#Set GraalVM as default +ENV JAVA_HOME=/usr/lib/graalvm +ENV PATH=/usr/lib/graalvm/bin:$PATH diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/Makefile b/examples/powertools-examples-core-utilities/sam-graalvm/Makefile new file mode 100644 index 000000000..f8abe6870 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/Makefile @@ -0,0 +1,6 @@ +build-HelloWorldFunction: + mvn clean package -P native-image + chmod +x target/hello-world + cp target/hello-world $(ARTIFACTS_DIR) # (ARTIFACTS_DIR --> https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/custom_make/DESIGN.md#implementation) + chmod +x src/main/config/bootstrap + cp src/main/config/bootstrap $(ARTIFACTS_DIR) diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/README.md b/examples/powertools-examples-core-utilities/sam-graalvm/README.md new file mode 100644 index 000000000..5572684ad --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/README.md @@ -0,0 +1,64 @@ +# Powertools for AWS Lambda (Java) - Core Utilities Example with SAM on GraalVM + +This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) running as a GraalVM native image. + +For general information on the deployed example itself, you can refer to the parent [README](../README.md) + +## Configuration + +- SAM uses [template.yaml](template.yaml) to define the application's AWS resources. + This file defines the Lambda function to be deployed as well as API Gateway for it. + +- Set the environment to use GraalVM + +```shell +export JAVA_HOME= +``` + +## Build the sample application + +- Build the Docker image that will be used as the environment for SAM build: + +```shell +docker build --platform linux/amd64 . -t powertools-examples-core-sam-graalvm +``` + +- Build the SAM project using the docker image + +```shell +sam build --use-container --build-image powertools-examples-core-sam-graalvm +``` + +#### [Optional] Building with -SNAPSHOT versions of PowerTools + +- If you are testing the example with a -SNAPSHOT version of PowerTools, the maven build inside the docker image will fail. This is because the -SNAPSHOT version of the PowerTools library that you are working on is still not available in maven central/snapshot repository. + To get around this, follow these steps: + - Create the native image using the `docker` command below on your development machine. The native image is created in the `target` directory. + - `` docker run --platform linux/amd64 -it -v `pwd`:`pwd` -w `pwd` -v ~/.m2:/root/.m2 powertools-examples-core-sam-graalvm mvn clean -Pnative-image package -DskipTests `` + - Edit the [`Makefile`](Makefile) remove this line + - `mvn clean package -P native-image` + - Build the SAM project using the docker image + - `sam build --use-container --build-image powertools-examples-core-sam-graalvm` + +## Deploy the sample application + +- SAM deploy + +```shell +sam deploy +``` + +To deploy the example, check out the instructions for getting +started with SAM in [the examples directory](../../README.md) + +## Additional notes + +You can watch the trace information or log information using the SAM CLI: + +```bash +# Tail the logs +sam logs --tail $MY_STACK + +# Tail the traces +sam traces --tail +``` diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/events/event.json b/examples/powertools-examples-core-utilities/sam-graalvm/events/event.json new file mode 100644 index 000000000..3822fadaa --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/events/event.json @@ -0,0 +1,63 @@ +{ + "body": "{\"message\": \"hello world\"}", + "resource": "/{proxy+}", + "path": "/path/to/resource", + "httpMethod": "POST", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/path/to/resource", + "resourcePath": "/{proxy+}", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } + } + \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml new file mode 100644 index 000000000..4ba4db943 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -0,0 +1,186 @@ + + 4.0.0 + + Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM + software.amazon.lambda.examples + 2.0.0-SNAPSHOT + powertools-examples-core-utilitiessam-graalvm + jar + + + 2.24.0 + 21 + 21 + 1.9.22.1 + + + + + software.amazon.lambda + powertools-tracing + ${project.version} + + + software.amazon.lambda + powertools-logging-log4j + ${project.version} + + + software.amazon.lambda + powertools-metrics + ${project.version} + + + com.amazonaws + aws-lambda-java-core + 1.2.3 + + + com.amazonaws + aws-lambda-java-events + 3.11.3 + + + org.aspectj + aspectjrt + ${aspectj.version} + + + com.amazonaws + aws-lambda-java-runtime-interface-client + 2.1.1 + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + org.apache.logging.log4j + log4j-slf4j2-impl + ${log4j.version} + + + org.apache.logging.log4j + log4j-layout-template-json + ${log4j.version} + + + + + + + org.codehaus.mojo + aspectj-maven-plugin + 1.15.0 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-tracing + + + software.amazon.lambda + powertools-logging + + + software.amazon.lambda + powertools-metrics + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + false + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.2 + + true + + + + + + + native-image + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.1 + true + + + build-native + + build + + package + + + + hello-world + com.amazonaws.services.lambda.runtime.api.client.AWSLambda + + + --enable-url-protocols=http + --add-opens java.base/java.util=ALL-UNNAMED + + + + + + + + diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/config/bootstrap b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/config/bootstrap new file mode 100644 index 000000000..8e7928cd3 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/config/bootstrap @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +./hello-world $_HANDLER \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/java/helloworld/App.java new file mode 100644 index 000000000..e7c410042 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/java/helloworld/App.java @@ -0,0 +1,111 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; +import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; +import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; +import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.StorageResolution; +import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.tracing.CaptureMode; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.tracing.TracingUtils; + +/** + * Handler for requests to Lambda function. + */ +public class App implements RequestHandler { + private static final Logger log = LoggerFactory.getLogger(App.class); + + @Logging(logEvent = true, samplingRate = 0.7) + @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + Map headers = new HashMap<>(); + + headers.put("Content-Type", "application/json"); + headers.put("X-Custom-Header", "application/json"); + + metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + + withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> + { + metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); + metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); + }); + + metricsLogger().putMetric("CustomMetric3", 1, Unit.COUNT, StorageResolution.HIGH); + + MDC.put("test", "willBeLogged"); + + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() + .withHeaders(headers); + try { + final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); + log.info("", entry("ip", pageContents)); + TracingUtils.putAnnotation("Test", "New"); + String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); + + TracingUtils.withSubsegment("loggingResponse", subsegment -> + { + String sampled = "log something out"; + log.info(sampled); + log.info(output); + }); + + log.info("After output"); + return response + .withStatusCode(200) + .withBody(output); + } catch (RuntimeException | IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + @Tracing + private void log() { + log.info("inside threaded logging for function"); + } + + @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + putMetadata("getPageContents", address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..d30696750 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..106edef38 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,34 @@ +[ + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields":[{"name":"logger"}] + }, + { + "name":"java.lang.Void", + "methods":[{"name":"","parameterTypes":[] }] + }, + { + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] + }, + { + "name":"jdk.internal.module.IllegalAccessLogger", + "fields":[{"name":"logger"}] + }, + { + "name":"sun.misc.Unsafe", + "fields":[{"name":"theUnsafe"}] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..7cc78a494 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qaarch64/aws-lambda-runtime-interface-client.glibc.so\\E" + }, + { + "pattern": "\\Qaarch64/aws-lambda-runtime-interface-client.musl.so\\E" + }, + { + "pattern": "\\Qx86_64/aws-lambda-runtime-interface-client.glibc.so\\E" + }, + { + "pattern": "\\Qx86_64/aws-lambda-runtime-interface-client.musl.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties new file mode 100644 index 000000000..db5ebaa55 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties @@ -0,0 +1 @@ +Args = --enable-url-protocols=http,https \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json new file mode 100644 index 000000000..06ea9ce2f --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json @@ -0,0 +1,11 @@ +[ + { + "name": "helloworld.App", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/log4j2.xml b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/log4j2.xml new file mode 100644 index 000000000..60975d487 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/template.yaml b/examples/powertools-examples-core-utilities/sam-graalvm/template.yaml new file mode 100644 index 000000000..feb55743b --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-graalvm/template.yaml @@ -0,0 +1,52 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + CoreUtilities + +# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst +Globals: + Function: + Timeout: 20 + MemorySize: 512 + Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html + Environment: + Variables: + # Powertools for AWS Lambda (Java) env vars: https://docs.powertools.aws.dev/lambda/java/#environment-variables + POWERTOOLS_LOG_LEVEL: INFO + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 + POWERTOOLS_LOGGER_LOG_EVENT: true + POWERTOOLS_METRICS_NAMESPACE: Coreutilities + +Resources: + HelloWorldFunction: + Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + Properties: + CodeUri: . + Handler: helloworld.App::handleRequest + Runtime: provided.al2023 + MemorySize: 512 + Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object + Variables: + POWERTOOLS_SERVICE_NAME: hello + Events: + HelloWorld: + Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api + Properties: + Path: /hello + Method: get + Metadata: + BuildMethod: makefile + +Outputs: + # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function + # Find out more about other implicit resources you can reference within SAM + # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api + HelloWorldApi: + Description: "API Gateway endpoint URL for Prod stage for Hello World function" + Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" + HelloWorldFunction: + Description: "Hello World Lambda Function ARN" + Value: !GetAtt HelloWorldFunction.Arn + HelloWorldFunctionIamRole: + Description: "Implicit IAM Role created for Hello World function" + Value: !GetAtt HelloWorldFunctionRole.Arn diff --git a/pom.xml b/pom.xml index d07005c70..01ca81458 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,6 @@ 11 11 3.1.2 - 2.20.0 2.24.3 2.0.7 2.17.2 diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 15409e1f6..2a04688fb 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -56,6 +56,11 @@ junit-jupiter-engine test + + org.junit-pioneer + junit-pioneer + test + org.apache.commons commons-lang3 @@ -72,6 +77,99 @@ test + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-common + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + + + + + + + @@ -79,6 +177,10 @@ src/main/resources-filtered true + + + src/main/resources + diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java index 8ae10ad62..d2e592902 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java @@ -16,9 +16,8 @@ import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; -import java.io.FileInputStream; import java.io.IOException; -import java.net.URL; +import java.io.InputStream; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,11 +65,12 @@ static String getProjectVersion() { */ static String getVersionFromProperties(String propertyFileName, String versionKey) { - URL propertiesFileURI = Thread.currentThread().getContextClassLoader().getResource(propertyFileName); - if (propertiesFileURI != null) { - try (FileInputStream fis = new FileInputStream(propertiesFileURI.getPath())) { + InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(propertyFileName); + + if (is != null) { + try { Properties properties = new Properties(); - properties.load(fis); + properties.load(is); String version = properties.getProperty(versionKey); if (version != null && !version.isEmpty()) { return version; diff --git a/powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/jni-config.json b/powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/jni-config.json new file mode 100644 index 000000000..8ea90d67f --- /dev/null +++ b/powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/jni-config.json @@ -0,0 +1,22 @@ +[ +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"org.apache.maven.surefire.booter.ForkedBooter", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"sun.instrument.InstrumentationImpl", + "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/reflect-config.json b/powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/reflect-config.json new file mode 100644 index 000000000..54afdb74e --- /dev/null +++ b/powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/reflect-config.json @@ -0,0 +1,189 @@ +[ +{ + "name":"com.amazonaws.services.lambda.runtime.Context", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"java.io.Closeable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.io.Flushable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.io.InputStream", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"available","parameterTypes":[] }, {"name":"close","parameterTypes":[] }, {"name":"mark","parameterTypes":["int"] }, {"name":"markSupported","parameterTypes":[] }, {"name":"read","parameterTypes":[] }, {"name":"read","parameterTypes":["byte[]"] }, {"name":"read","parameterTypes":["byte[]","int","int"] }, {"name":"readAllBytes","parameterTypes":[] }, {"name":"readNBytes","parameterTypes":["int"] }, {"name":"readNBytes","parameterTypes":["byte[]","int","int"] }, {"name":"reset","parameterTypes":[] }, {"name":"skip","parameterTypes":["long"] }, {"name":"skipNBytes","parameterTypes":["long"] }, {"name":"transferTo","parameterTypes":["java.io.OutputStream"] }] +}, +{ + "name":"java.io.OutputStream", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"close","parameterTypes":[] }, {"name":"flush","parameterTypes":[] }, {"name":"write","parameterTypes":["int"] }, {"name":"write","parameterTypes":["byte[]"] }, {"name":"write","parameterTypes":["byte[]","int","int"] }] +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.AutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessEnvironment", + "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"org.aspectj.lang.JoinPoint", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getArgs","parameterTypes":[] }, {"name":"getKind","parameterTypes":[] }, {"name":"getSignature","parameterTypes":[] }, {"name":"getSourceLocation","parameterTypes":[] }, {"name":"getStaticPart","parameterTypes":[] }, {"name":"getTarget","parameterTypes":[] }, {"name":"getThis","parameterTypes":[] }, {"name":"toLongString","parameterTypes":[] }, {"name":"toShortString","parameterTypes":[] }] +}, +{ + "name":"org.aspectj.lang.ProceedingJoinPoint", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"proceed","parameterTypes":[] }, {"name":"proceed","parameterTypes":["java.lang.Object[]"] }, {"name":"set$AroundClosure","parameterTypes":["org.aspectj.runtime.internal.AroundClosure"] }, {"name":"stack$AroundClosure","parameterTypes":["org.aspectj.runtime.internal.AroundClosure"] }] +}, +{ + "name":"org.aspectj.lang.Signature", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getDeclaringType","parameterTypes":[] }, {"name":"getDeclaringTypeName","parameterTypes":[] }, {"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"toLongString","parameterTypes":[] }, {"name":"toShortString","parameterTypes":[] }] +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +} +] diff --git a/powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/resource-config.json b/powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/resource-config.json new file mode 100644 index 000000000..6fb5eb95e --- /dev/null +++ b/powertools-common/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common/resource-config.json @@ -0,0 +1,21 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }, { + "pattern":"\\Qversion.properties\\E" + }]}, + "bundles":[] +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index 4ad170600..15d7bccdb 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -17,20 +17,21 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; -import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import java.io.InputStream; import java.io.OutputStream; import java.util.Optional; + import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; +import org.junitpioneer.jupiter.ClearEnvironmentVariable; +import org.junitpioneer.jupiter.SetEnvironmentVariable; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; class LambdaHandlerProcessorTest { @@ -139,27 +140,23 @@ void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidContextArg() { } @Test + @SetEnvironmentVariable(key = LambdaConstants.X_AMZN_TRACE_ID, value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\"") void getXrayTraceId_present() { String traceID = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""; - try (MockedStatic mockedSystemWrapper = mockStatic(SystemWrapper.class)) { - mockedSystemWrapper.when(() -> getenv(LambdaConstants.X_AMZN_TRACE_ID)).thenReturn(traceID); - Optional xRayTraceId = LambdaHandlerProcessor.getXrayTraceId(); + Optional xRayTraceId = LambdaHandlerProcessor.getXrayTraceId(); - assertThat(xRayTraceId.isPresent()).isTrue(); - assertThat(traceID.split(";")[0].replace(LambdaConstants.ROOT_EQUALS, "")).isEqualTo(xRayTraceId.get()); - } + assertThat(xRayTraceId.isPresent()).isTrue(); + assertThat(traceID.split(";")[0].replace(LambdaConstants.ROOT_EQUALS, "")).isEqualTo(xRayTraceId.get()); } @Test + @ClearEnvironmentVariable(key = LambdaConstants.X_AMZN_TRACE_ID) void getXrayTraceId_notPresent() { - try (MockedStatic mockedSystemWrapper = mockStatic(SystemWrapper.class)) { - mockedSystemWrapper.when(() -> getenv(LambdaConstants.X_AMZN_TRACE_ID)).thenReturn(null); - boolean isXRayTraceIdPresent = LambdaHandlerProcessor.getXrayTraceId().isPresent(); + boolean isXRayTraceIdPresent = LambdaHandlerProcessor.getXrayTraceId().isPresent(); - assertThat(isXRayTraceIdPresent).isFalse(); - } + assertThat(isXRayTraceIdPresent).isFalse(); } @Test @@ -209,37 +206,28 @@ void isColdStart_coldStartDone() { } @Test + @SetEnvironmentVariable(key = LambdaConstants.AWS_SAM_LOCAL, value = "true") void isSamLocal() { - try (MockedStatic mockedSystemWrapper = mockStatic(SystemWrapper.class)) { - mockedSystemWrapper.when(() -> getenv(LambdaConstants.AWS_SAM_LOCAL)).thenReturn("true"); - boolean isSamLocal = LambdaHandlerProcessor.isSamLocal(); + boolean isSamLocal = LambdaHandlerProcessor.isSamLocal(); - assertThat(isSamLocal).isTrue(); - } + assertThat(isSamLocal).isTrue(); } @Test + @SetEnvironmentVariable(key = LambdaConstants.POWERTOOLS_SERVICE_NAME, value = "MyService") void serviceName() { - try (MockedStatic mockedSystemWrapper = mockStatic(SystemWrapper.class)) { - String expectedServiceName = "MyService"; - mockedSystemWrapper.when(() -> getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME)) - .thenReturn(expectedServiceName); + String expectedServiceName = "MyService"; + String actualServiceName = LambdaHandlerProcessor.serviceName(); - String actualServiceName = LambdaHandlerProcessor.serviceName(); - - assertThat(actualServiceName).isEqualTo(expectedServiceName); - } + assertThat(actualServiceName).isEqualTo(expectedServiceName); } @Test + @ClearEnvironmentVariable(key = LambdaConstants.POWERTOOLS_SERVICE_NAME) void serviceName_Undefined() { LambdaHandlerProcessor.resetServiceName(); - try (MockedStatic mockedSystemWrapper = mockStatic(SystemWrapper.class)) { - mockedSystemWrapper.when(() -> getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME)).thenReturn(null); - - assertThat(LambdaHandlerProcessor.serviceName()).isEqualTo(LambdaConstants.SERVICE_UNDEFINED); - } + assertThat(LambdaHandlerProcessor.serviceName()).isEqualTo(LambdaConstants.SERVICE_UNDEFINED); } private ProceedingJoinPoint mockRequestHandlerPjp(Class handlerClass, Object[] handlerArgs) { @@ -248,4 +236,4 @@ private ProceedingJoinPoint mockRequestHandlerPjp(Class handlerClass, Object[] h when(pjpMock.getSignature()).thenReturn(signature); return pjpMock; } -} \ No newline at end of file +} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java index 9e4d26504..0c7935a55 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java @@ -15,19 +15,19 @@ package software.amazon.lambda.powertools.common.internal; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mockStatic; import static software.amazon.lambda.powertools.common.internal.UserAgentConfigurator.AWS_EXECUTION_ENV; import static software.amazon.lambda.powertools.common.internal.UserAgentConfigurator.VERSION_KEY; import static software.amazon.lambda.powertools.common.internal.UserAgentConfigurator.VERSION_PROPERTIES_FILENAME; import static software.amazon.lambda.powertools.common.internal.UserAgentConfigurator.getVersionFromProperties; -import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; - import java.io.File; -import java.util.Objects; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.regex.Pattern; + import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; +import org.junitpioneer.jupiter.SetEnvironmentVariable; class UserAgentConfiguratorTest { @@ -64,14 +64,18 @@ void testGetVersionFromProperties_FileNotExist() { } @Test - void testGetVersionFromProperties_InvalidFile() { - File f = new File(Objects.requireNonNull(Thread.currentThread().getContextClassLoader() - .getResource("unreadable.properties")).getPath()); + void testGetVersionFromProperties_InvalidFile() throws IOException { + Path tempFile = Files.createTempFile("unreadable", ".properties"); + File f = tempFile.toFile(); f.setReadable(false); - String version = getVersionFromProperties("unreadable.properties", VERSION_KEY); + String version = getVersionFromProperties(f.getName(), VERSION_KEY); assertThat(version).isEqualTo("NA"); + + // Cleanup + f.setReadable(true); + Files.deleteIfExists(tempFile); } @Test @@ -110,15 +114,13 @@ void testGetUserAgent_NullFeature() { } @Test + @SetEnvironmentVariable(key = AWS_EXECUTION_ENV, value = "AWS_Lambda_java8") void testGetUserAgent_SetAWSExecutionEnv() { - try (MockedStatic mockedSystemWrapper = mockStatic(SystemWrapper.class)) { - mockedSystemWrapper.when(() -> getenv(AWS_EXECUTION_ENV)).thenReturn("AWS_Lambda_java8"); - String userAgent = UserAgentConfigurator.getUserAgent("test-feature"); - - assertThat(userAgent) - .isNotNull() - .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/AWS_Lambda_java8"); - } + String userAgent = UserAgentConfigurator.getUserAgent("test-feature"); + + assertThat(userAgent) + .isNotNull() + .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/AWS_Lambda_java8"); } } diff --git a/powertools-common/src/test/resources/unreadable.properties b/powertools-common/src/test/resources/unreadable.properties deleted file mode 100644 index 42ff4693f..000000000 --- a/powertools-common/src/test/resources/unreadable.properties +++ /dev/null @@ -1,2 +0,0 @@ -# This is intentionally left empty -# It used during testing and is set to un-readable to fulfil the test purposes. \ No newline at end of file diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index a1148a9cd..86aeadd28 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -67,6 +67,11 @@ junit-jupiter-engine test + + org.junit-pioneer + junit-pioneer + test + org.apache.commons commons-lang3 @@ -98,8 +103,103 @@ test - + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-logging + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + + + + + + + + + + + src/main/resources + + org.apache.maven.plugins diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index d76137678..5f176bb46 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -51,6 +51,11 @@ junit-jupiter-engine test + + org.junit-pioneer + junit-pioneer + test + org.apache.commons commons-lang3 @@ -82,8 +87,103 @@ test - + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-logging-log4j + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + + + + + + + + + + + src/main/resources + + dev.aspectj diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/jni-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/jni-config.json new file mode 100644 index 000000000..2c4de0562 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/jni-config.json @@ -0,0 +1,26 @@ +[ +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"org.apache.maven.surefire.booter.ForkedBooter", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"sun.instrument.InstrumentationImpl", + "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json new file mode 100644 index 000000000..9b2afe183 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json @@ -0,0 +1,1225 @@ +[ +{ + "name":"[Lorg.apache.logging.log4j.core.Appender;" +}, +{ + "name":"[Lorg.apache.logging.log4j.core.config.AppenderRef;" +}, +{ + "name":"[Lorg.apache.logging.log4j.core.config.LoggerConfig;" +}, +{ + "name":"[Lorg.apache.logging.log4j.core.config.Property;" +}, +{ + "name":"[Lorg.apache.logging.log4j.layout.template.json.JsonTemplateLayout$EventTemplateAdditionalField;" +}, +{ + "name":"com.amazonaws.services.lambda.runtime.Context", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.RequestHandler", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SQSEvent$MessageAttribute", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getBinaryListValues","parameterTypes":[] }, {"name":"getBinaryValue","parameterTypes":[] }, {"name":"getDataType","parameterTypes":[] }, {"name":"getStringListValues","parameterTypes":[] }, {"name":"getStringValue","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SQSEvent$SQSMessage", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getAttributes","parameterTypes":[] }, {"name":"getAwsRegion","parameterTypes":[] }, {"name":"getBody","parameterTypes":[] }, {"name":"getEventSource","parameterTypes":[] }, {"name":"getEventSourceArn","parameterTypes":[] }, {"name":"getMd5OfBody","parameterTypes":[] }, {"name":"getMd5OfMessageAttributes","parameterTypes":[] }, {"name":"getMessageAttributes","parameterTypes":[] }, {"name":"getMessageId","parameterTypes":[] }, {"name":"getReceiptHandle","parameterTypes":[] }] +}, +{ + "name":"com.fasterxml.jackson.core.JsonParser" +}, +{ + "name":"com.fasterxml.jackson.databind.JsonNode" +}, +{ + "name":"com.fasterxml.jackson.databind.ObjectMapper" +}, +{ + "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.fasterxml.jackson.dataformat.yaml.YAMLFactory" +}, +{ + "name":"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"jakarta.servlet.Servlet" +}, +{ + "name":"java.io.Serializable", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Cloneable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Comparable", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"java.lang.Enum", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessEnvironment", + "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.Thread", + "fields":[{"name":"threadLocalRandomProbe"}] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.constant.Constable", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.sql.Date" +}, +{ + "name":"java.sql.Time" +}, +{ + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.Striped64", + "fields":[{"name":"base"}, {"name":"cellsBusy"}] +}, +{ + "name":"java.util.function.Consumer", + "queryAllPublicMethods":true +}, +{ + "name":"javax.servlet.Servlet" +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apache.logging.log4j.core.appender.AbstractAppender$Builder", + "allDeclaredFields":true +}, +{ + "name":"org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender$Builder", + "allDeclaredFields":true +}, +{ + "name":"org.apache.logging.log4j.core.appender.AppenderSet" +}, +{ + "name":"org.apache.logging.log4j.core.appender.AsyncAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.ConsoleAppender", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newBuilder","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.appender.ConsoleAppender$Builder", + "allDeclaredFields":true +}, +{ + "name":"org.apache.logging.log4j.core.appender.CountingNoOpAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.FailoverAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.FailoversPlugin" +}, +{ + "name":"org.apache.logging.log4j.core.appender.FileAppender", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newBuilder","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.appender.FileAppender$Builder", + "allDeclaredFields":true +}, +{ + "name":"org.apache.logging.log4j.core.appender.HttpAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.MemoryMappedFileAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.NullAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.OutputStreamAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.RandomAccessFileAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.RollingFileAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.RollingRandomAccessFileAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.ScriptAppenderSelector" +}, +{ + "name":"org.apache.logging.log4j.core.appender.SmtpAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.SocketAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.SyslogAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.WriterAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.db.ColumnMapping" +}, +{ + "name":"org.apache.logging.log4j.core.appender.db.jdbc.ColumnConfig" +}, +{ + "name":"org.apache.logging.log4j.core.appender.db.jdbc.DataSourceConnectionSource" +}, +{ + "name":"org.apache.logging.log4j.core.appender.db.jdbc.DriverManagerConnectionSource" +}, +{ + "name":"org.apache.logging.log4j.core.appender.db.jdbc.FactoryMethodConnectionSource" +}, +{ + "name":"org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.mom.JmsAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.mom.jeromq.JeroMqAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.mom.kafka.KafkaAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.nosql.NoSqlAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rewrite.LoggerNameLevelRewritePolicy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rewrite.MapRewritePolicy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rewrite.PropertiesRewritePolicy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rewrite.RewriteAppender" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.CronTriggeringPolicy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.DirectWriteRolloverStrategy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.NoOpTriggeringPolicy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.OnStartupTriggeringPolicy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.DeleteAction" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.IfAccumulatedFileCount" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.IfAccumulatedFileSize" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.IfAll" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.IfAny" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.IfFileName" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.IfLastModified" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.IfNot" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.PathSortByModificationTime" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.PosixViewAttributeAction" +}, +{ + "name":"org.apache.logging.log4j.core.appender.rolling.action.ScriptCondition" +}, +{ + "name":"org.apache.logging.log4j.core.appender.routing.IdlePurgePolicy" +}, +{ + "name":"org.apache.logging.log4j.core.appender.routing.Route" +}, +{ + "name":"org.apache.logging.log4j.core.appender.routing.Routes" +}, +{ + "name":"org.apache.logging.log4j.core.appender.routing.RoutingAppender" +}, +{ + "name":"org.apache.logging.log4j.core.async.ArrayBlockingQueueFactory" +}, +{ + "name":"org.apache.logging.log4j.core.async.AsyncLoggerConfig" +}, +{ + "name":"org.apache.logging.log4j.core.async.AsyncLoggerConfig$RootLogger" +}, +{ + "name":"org.apache.logging.log4j.core.async.AsyncWaitStrategyFactoryConfig" +}, +{ + "name":"org.apache.logging.log4j.core.async.DisruptorBlockingQueueFactory" +}, +{ + "name":"org.apache.logging.log4j.core.async.JCToolsBlockingQueueFactory" +}, +{ + "name":"org.apache.logging.log4j.core.async.LinkedTransferQueueFactory" +}, +{ + "name":"org.apache.logging.log4j.core.config.AppenderControlArraySet", + "fields":[{"name":"appenderArray"}] +}, +{ + "name":"org.apache.logging.log4j.core.config.AppenderRef", + "queryAllDeclaredMethods":true, + "methods":[{"name":"createAppenderRef","parameterTypes":["java.lang.String","org.apache.logging.log4j.Level","org.apache.logging.log4j.core.Filter"] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.AppendersPlugin", + "queryAllDeclaredMethods":true, + "methods":[{"name":"createAppenders","parameterTypes":["org.apache.logging.log4j.core.Appender[]"] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.CustomLevelConfig" +}, +{ + "name":"org.apache.logging.log4j.core.config.CustomLevels" +}, +{ + "name":"org.apache.logging.log4j.core.config.DefaultAdvertiser" +}, +{ + "name":"org.apache.logging.log4j.core.config.HttpWatcher" +}, +{ + "name":"org.apache.logging.log4j.core.config.LoggerConfig", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newBuilder","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.LoggerConfig$Builder", + "allDeclaredFields":true +}, +{ + "name":"org.apache.logging.log4j.core.config.LoggerConfig$RootLogger", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newRootBuilder","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.LoggerConfig$RootLogger$Builder", + "allDeclaredFields":true +}, +{ + "name":"org.apache.logging.log4j.core.config.LoggersPlugin", + "queryAllDeclaredMethods":true, + "methods":[{"name":"createLoggers","parameterTypes":["org.apache.logging.log4j.core.config.LoggerConfig[]"] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.PropertiesPlugin" +}, +{ + "name":"org.apache.logging.log4j.core.config.Property" +}, +{ + "name":"org.apache.logging.log4j.core.config.ScriptsPlugin" +}, +{ + "name":"org.apache.logging.log4j.core.config.arbiters.ClassArbiter" +}, +{ + "name":"org.apache.logging.log4j.core.config.arbiters.DefaultArbiter" +}, +{ + "name":"org.apache.logging.log4j.core.config.arbiters.EnvironmentArbiter" +}, +{ + "name":"org.apache.logging.log4j.core.config.arbiters.ScriptArbiter" +}, +{ + "name":"org.apache.logging.log4j.core.config.arbiters.SelectArbiter" +}, +{ + "name":"org.apache.logging.log4j.core.config.arbiters.SystemPropertyArbiter" +}, +{ + "name":"org.apache.logging.log4j.core.config.json.JsonConfigurationFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$BigDecimalConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$BigIntegerConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$BooleanConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$ByteArrayConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$ByteConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$CharArrayConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$CharacterConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$CharsetConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$ClassConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$CronExpressionConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$DoubleConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$DurationConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$FileConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$FloatConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$InetAddressConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$IntegerConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$LevelConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$LongConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$PathConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$PatternConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$SecurityProviderConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$ShortConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$StringConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$UriConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$UrlConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$UuidConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.validation.validators.RequiredValidator", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.visitors.PluginAttributeVisitor", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.visitors.PluginBuilderAttributeVisitor", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.visitors.PluginConfigurationVisitor", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.plugins.visitors.PluginElementVisitor", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.properties.PropertiesConfigurationFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.config.yaml.YamlConfigurationFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.filter.AbstractFilterable$Builder", + "allDeclaredFields":true +}, +{ + "name":"org.apache.logging.log4j.core.filter.BurstFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.CompositeFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.DenyAllFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.DynamicThresholdFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.LevelMatchFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.LevelRangeFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.MapFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.MarkerFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.MutableThreadContextMapFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.NoMarkerFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.RegexFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.ScriptFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.StringMatchFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.StructuredDataFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.ThreadContextMapFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.ThresholdFilter" +}, +{ + "name":"org.apache.logging.log4j.core.filter.TimeFilter" +}, +{ + "name":"org.apache.logging.log4j.core.layout.CsvLogEventLayout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.CsvParameterLayout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.GelfLayout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.HtmlLayout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.JsonLayout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.LevelPatternSelector" +}, +{ + "name":"org.apache.logging.log4j.core.layout.LoggerFields" +}, +{ + "name":"org.apache.logging.log4j.core.layout.MarkerPatternSelector" +}, +{ + "name":"org.apache.logging.log4j.core.layout.MessageLayout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.PatternLayout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.PatternMatch" +}, +{ + "name":"org.apache.logging.log4j.core.layout.Rfc5424Layout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.ScriptPatternSelector" +}, +{ + "name":"org.apache.logging.log4j.core.layout.SerializedLayout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.SyslogLayout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.XmlLayout" +}, +{ + "name":"org.apache.logging.log4j.core.layout.YamlLayout" +}, +{ + "name":"org.apache.logging.log4j.core.lookup.ContextMapLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.DateLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.EnvironmentLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.EventLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.JavaLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.JndiLookup" +}, +{ + "name":"org.apache.logging.log4j.core.lookup.Log4jLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.LowerLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.MainMapLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.MapLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.MarkerLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.ResourceBundleLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.StructuredDataLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.SystemPropertiesLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.lookup.UpperLookup", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.net.MulticastDnsAdvertiser" +}, +{ + "name":"org.apache.logging.log4j.core.net.SocketAddress" +}, +{ + "name":"org.apache.logging.log4j.core.net.SocketOptions" +}, +{ + "name":"org.apache.logging.log4j.core.net.SocketPerformancePreferences" +}, +{ + "name":"org.apache.logging.log4j.core.net.ssl.KeyStoreConfiguration" +}, +{ + "name":"org.apache.logging.log4j.core.net.ssl.SslConfiguration" +}, +{ + "name":"org.apache.logging.log4j.core.net.ssl.TrustStoreConfiguration" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Black" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Blue" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Cyan" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Green" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Magenta" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Red" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$White" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.AbstractStyleNameConverter$Yellow" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.ClassNamePatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.DatePatternConverter", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newInstance","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"org.apache.logging.log4j.core.pattern.EncodingPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.EndOfBatchPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.EqualsIgnoreCaseReplacementConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.EqualsReplacementConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.FileDatePatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.FileLocationPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.FullLocationPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.HighlightConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.IntegerPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.LevelPatternConverter", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newInstance","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"org.apache.logging.log4j.core.pattern.LineLocationPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.LineSeparatorPatternConverter", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newInstance","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"org.apache.logging.log4j.core.pattern.LoggerFqcnPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.LoggerPatternConverter", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newInstance","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"org.apache.logging.log4j.core.pattern.MapPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.MarkerPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.MarkerSimpleNamePatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.MaxLengthConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.MdcPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.MessagePatternConverter", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newInstance","parameterTypes":["org.apache.logging.log4j.core.config.Configuration","java.lang.String[]"] }] +}, +{ + "name":"org.apache.logging.log4j.core.pattern.MethodLocationPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.NanoTimePatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.NdcPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.ProcessIdPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.RegexReplacement" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.RegexReplacementConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.RelativeTimePatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.RepeatPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.RootThrowablePatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.SequenceNumberPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.StyleConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.ThreadIdPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.ThreadNamePatternConverter", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newInstance","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"org.apache.logging.log4j.core.pattern.ThreadPriorityPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.ThrowablePatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.UuidPatternConverter" +}, +{ + "name":"org.apache.logging.log4j.core.pattern.VariablesNotEmptyReplacementConverter" +}, +{ + "name":"org.apache.logging.log4j.core.script.Script" +}, +{ + "name":"org.apache.logging.log4j.core.script.ScriptFile" +}, +{ + "name":"org.apache.logging.log4j.core.script.ScriptRef" +}, +{ + "name":"org.apache.logging.log4j.core.util.KeyValuePair" +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.JsonTemplateLayout", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newBuilder","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$Builder", + "allDeclaredFields":true +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.JsonTemplateLayout$EventTemplateAdditionalField" +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.CaseConverterResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.CounterResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.EndOfBatchResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.EventAdditionalFieldInterceptor", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.EventRootObjectKeyInterceptor", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.ExceptionResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.ExceptionRootCauseResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.LevelResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.LoggerResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.MainMapResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.MapResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.MarkerResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.MessageParameterResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.MessageResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.PatternResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.PowerToolsResolverFactoryTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"cleanUp","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"shouldLogInEcsFormat","parameterTypes":[] }, {"name":"shouldLogInJsonFormat","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.PowertoolsResolverArgumentsTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"cleanUp","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"shouldLogArgumentsAsJsonWhenUsingKeyValue","parameterTypes":[] }, {"name":"shouldLogArgumentsAsJsonWhenUsingRawJson","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.PowertoolsResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.ThreadContextDataResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.ThreadContextStackResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.ThreadResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.resolver.TimestampResolverFactory", + "queryAllDeclaredMethods":true, + "methods":[{"name":"getInstance","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.layout.template.json.util.RecyclerFactoryConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"org.aspectj.runtime.internal.AroundClosure", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.jctools.queues.MpmcArrayQueue" +}, +{ + "name":"org.osgi.framework.FrameworkUtil" +}, +{ + "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", + "fields":[{"name":"IS_COLD_START"}] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.Log4jLoggingManagerTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getLogLevel_shouldReturnConfiguredLogLevel","parameterTypes":[] }, {"name":"resetLogLevel","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent$SQSMessage","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments$ArgumentFormat", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +} +] diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json new file mode 100644 index 000000000..aca0e0356 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json @@ -0,0 +1,95 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QLambdaEcsLayout.json\\E" + }, { + "pattern":"\\QLambdaJsonLayout.json\\E" + }, { + "pattern":"\\QMETA-INF/log4j-provider.properties\\E" + }, { + "pattern":"\\QMETA-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat\\E" + }, { + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.InetAddressResolverProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/javax.xml.parsers.DocumentBuilderFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.logging.log4j.core.util.ContextDataProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.logging.log4j.core.util.WatchEventService\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.logging.log4j.spi.Provider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.logging.log4j.util.PropertySource\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" + }, { + "pattern":"\\QStackTraceElementLayout.json\\E" + }, { + "pattern":"\\Qlog4j2-test.jsn\\E" + }, { + "pattern":"\\Qlog4j2-test.json\\E" + }, { + "pattern":"\\Qlog4j2-test.properties\\E" + }, { + "pattern":"\\Qlog4j2-test.xml\\E" + }, { + "pattern":"\\Qlog4j2-test.yaml\\E" + }, { + "pattern":"\\Qlog4j2-test.yml\\E" + }, { + "pattern":"\\Qlog4j2-test18b4aac2.jsn\\E" + }, { + "pattern":"\\Qlog4j2-test18b4aac2.json\\E" + }, { + "pattern":"\\Qlog4j2-test18b4aac2.properties\\E" + }, { + "pattern":"\\Qlog4j2-test18b4aac2.xml\\E" + }, { + "pattern":"\\Qlog4j2-test18b4aac2.yaml\\E" + }, { + "pattern":"\\Qlog4j2-test18b4aac2.yml\\E" + }, { + "pattern":"\\Qlog4j2.StatusLogger.properties\\E" + }, { + "pattern":"\\Qlog4j2.component.properties\\E" + }, { + "pattern":"\\Qlog4j2.jsn\\E" + }, { + "pattern":"\\Qlog4j2.json\\E" + }, { + "pattern":"\\Qlog4j2.properties\\E" + }, { + "pattern":"\\Qlog4j2.system.properties\\E" + }, { + "pattern":"\\Qlog4j2.xml\\E" + }, { + "pattern":"\\Qlog4j2.yaml\\E" + }, { + "pattern":"\\Qlog4j2.yml\\E" + }, { + "pattern":"\\Qlog4j218b4aac2.jsn\\E" + }, { + "pattern":"\\Qlog4j218b4aac2.json\\E" + }, { + "pattern":"\\Qlog4j218b4aac2.properties\\E" + }, { + "pattern":"\\Qlog4j218b4aac2.xml\\E" + }, { + "pattern":"\\Qlog4j218b4aac2.yaml\\E" + }, { + "pattern":"\\Qlog4j218b4aac2.yml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java index 073cd7026..d1b9fec83 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverTest.java @@ -16,8 +16,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.Mockito.mockStatic; -import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; @@ -32,8 +30,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import org.mockito.MockedStatic; -import software.amazon.lambda.powertools.common.internal.SystemWrapper; +import org.junitpioneer.jupiter.SetEnvironmentVariable; import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; class PowertoolsResolverTest { @@ -79,14 +76,10 @@ void unknownField_shouldThrowException() { } @Test + @SetEnvironmentVariable(key = "AWS_REGION", value = "eu-central-2") void shouldResolveRegion() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> getenv("AWS_REGION")) - .thenReturn("eu-central-2"); - - String result = resolveField("region", "dummy, will use the env var"); - assertThat(result).isEqualTo("\"eu-central-2\""); - } + String result = resolveField("region", "dummy, will use the env var"); + assertThat(result).isEqualTo("\"eu-central-2\""); } private static String resolveField(String field, String value) { diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index f723be91b..8fde683b4 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -80,7 +80,103 @@ + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + + true + Standard + + powertools-logging-logback + + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + + + + + + + + + + + + src/main/resources + + dev.aspectj diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json new file mode 100644 index 000000000..2c4de0562 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json @@ -0,0 +1,26 @@ +[ +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"org.apache.maven.surefire.booter.ForkedBooter", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"sun.instrument.InstrumentationImpl", + "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json new file mode 100644 index 000000000..0d3bdbe7e --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json @@ -0,0 +1,290 @@ +[ +{ + "name":"ch.qos.logback.classic.joran.SerializedModelConfigurator", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.util.DefaultJoranConfigurator", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.core.FileAppender", + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setFile","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"ch.qos.logback.core.OutputStreamAppender", + "methods":[{"name":"setEncoder","parameterTypes":["ch.qos.logback.core.encoder.Encoder"] }] +}, +{ + "name":"ch.qos.logback.core.encoder.Encoder", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.Context", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SQSEvent$MessageAttribute", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getBinaryListValues","parameterTypes":[] }, {"name":"getBinaryValue","parameterTypes":[] }, {"name":"getDataType","parameterTypes":[] }, {"name":"getStringListValues","parameterTypes":[] }, {"name":"getStringValue","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SQSEvent$SQSMessage", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getAttributes","parameterTypes":[] }, {"name":"getAwsRegion","parameterTypes":[] }, {"name":"getBody","parameterTypes":[] }, {"name":"getEventSource","parameterTypes":[] }, {"name":"getEventSourceArn","parameterTypes":[] }, {"name":"getMd5OfBody","parameterTypes":[] }, {"name":"getMd5OfMessageAttributes","parameterTypes":[] }, {"name":"getMessageAttributes","parameterTypes":[] }, {"name":"getMessageId","parameterTypes":[] }, {"name":"getReceiptHandle","parameterTypes":[] }] +}, +{ + "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"java.io.FilePermission" +}, +{ + "name":"java.io.IOException" +}, +{ + "name":"java.io.InputStream" +}, +{ + "name":"java.io.OutputStream" +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Cloneable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.RuntimePermission" +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.net.NetPermission" +}, +{ + "name":"java.net.SocketPermission" +}, +{ + "name":"java.net.URLPermission", + "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.security.AllPermission" +}, +{ + "name":"java.security.SecurityPermission" +}, +{ + "name":"java.util.PropertyPermission" +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"javax.smartcardio.CardPermission" +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", + "fields":[{"name":"IS_COLD_START"}] +}, +{ + "name":"software.amazon.lambda.powertools.logging.LogbackLoggingManagerTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getLogLevel_shouldReturnConfiguredLogLevel","parameterTypes":[] }, {"name":"resetLogLevel","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.LambdaEcsEncoderTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"cleanUp","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"shouldLogException","parameterTypes":[] }, {"name":"shouldLogInEcsFormat","parameterTypes":[] }, {"name":"shouldNotLogCloudInfo","parameterTypes":[] }, {"name":"shouldNotLogFunctionInfo","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.LambdaJsonEncoderTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"cleanUp","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"shouldLogArgumentsAsJsonWhenUsingKeyValue","parameterTypes":[] }, {"name":"shouldLogArgumentsAsJsonWhenUsingRawJson","parameterTypes":[] }, {"name":"shouldLogEventAsStringForStreamHandler","parameterTypes":[] }, {"name":"shouldLogEventForHandlerWhenEnvVariableSetToTrue","parameterTypes":[] }, {"name":"shouldLogEventForHandlerWithLogEventAnnotation","parameterTypes":[] }, {"name":"shouldLogException","parameterTypes":[] }, {"name":"shouldLogInJsonFormat","parameterTypes":[] }, {"name":"shouldLogResponseForHandlerWhenEnvVariableSetToTrue","parameterTypes":[] }, {"name":"shouldLogResponseForHandlerWithLogResponseAnnotation","parameterTypes":[] }, {"name":"shouldLogResponseForStreamHandler","parameterTypes":[] }, {"name":"shouldLogStructuredArgumentsAsNewEntries","parameterTypes":[] }, {"name":"shouldLogThreadInfo","parameterTypes":[] }, {"name":"shouldLogTimestampDifferently","parameterTypes":[] }, {"name":"shouldNotLogEventForHandlerWhenEnvVariableSetToFalse","parameterTypes":[] }, {"name":"shouldNotLogPowertoolsInfo","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments", + "methods":[{"name":"handleRequest","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent$SQSMessage","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEvent", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEventDisabled", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEventForStream", + "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogResponse", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogResponseForStream", + "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.logback.LambdaEcsEncoder", + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder", + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +} +] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json new file mode 100644 index 000000000..dea71883a --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json @@ -0,0 +1,29 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\E" + }, { + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/javax.xml.parsers.SAXParserFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" + }, { + "pattern":"\\Qlogback-test.scmo\\E" + }, { + "pattern":"\\Qlogback-test.xml\\E" + }, { + "pattern":"\\Qlogback.scmo\\E" + }]}, + "bundles":[] +} diff --git a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/jni-config.json b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/jni-config.json new file mode 100644 index 000000000..2c4de0562 --- /dev/null +++ b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/jni-config.json @@ -0,0 +1,26 @@ +[ +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"org.apache.maven.surefire.booter.ForkedBooter", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"sun.instrument.InstrumentationImpl", + "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json new file mode 100644 index 000000000..7347b8400 --- /dev/null +++ b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json @@ -0,0 +1,669 @@ +[ +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.KeyDeserializers;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiators;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers;" +}, +{ + "name":"[Lsoftware.amazon.lambda.powertools.logging.model.Product;" +}, +{ + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.Context", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.RequestHandler", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.RequestStreamHandler", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getBody","parameterTypes":[] }, {"name":"getHeaders","parameterTypes":[] }, {"name":"getHttpMethod","parameterTypes":[] }, {"name":"getIsBase64Encoded","parameterTypes":[] }, {"name":"getMultiValueHeaders","parameterTypes":[] }, {"name":"getMultiValueQueryStringParameters","parameterTypes":[] }, {"name":"getPath","parameterTypes":[] }, {"name":"getPathParameters","parameterTypes":[] }, {"name":"getQueryStringParameters","parameterTypes":[] }, {"name":"getRequestContext","parameterTypes":[] }, {"name":"getResource","parameterTypes":[] }, {"name":"getStageVariables","parameterTypes":[] }, {"name":"getVersion","parameterTypes":[] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setHttpMethod","parameterTypes":["java.lang.String"] }, {"name":"setIsBase64Encoded","parameterTypes":["java.lang.Boolean"] }, {"name":"setMultiValueHeaders","parameterTypes":["java.util.Map"] }, {"name":"setMultiValueQueryStringParameters","parameterTypes":["java.util.Map"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setPathParameters","parameterTypes":["java.util.Map"] }, {"name":"setQueryStringParameters","parameterTypes":["java.util.Map"] }, {"name":"setRequestContext","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext"] }, {"name":"setResource","parameterTypes":["java.lang.String"] }, {"name":"setStageVariables","parameterTypes":["java.util.Map"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getAccountId","parameterTypes":[] }, {"name":"getApiId","parameterTypes":[] }, {"name":"getAuthorizer","parameterTypes":[] }, {"name":"getDomainName","parameterTypes":[] }, {"name":"getDomainPrefix","parameterTypes":[] }, {"name":"getExtendedRequestId","parameterTypes":[] }, {"name":"getHttpMethod","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getOperationName","parameterTypes":[] }, {"name":"getPath","parameterTypes":[] }, {"name":"getProtocol","parameterTypes":[] }, {"name":"getRequestId","parameterTypes":[] }, {"name":"getRequestTime","parameterTypes":[] }, {"name":"getRequestTimeEpoch","parameterTypes":[] }, {"name":"getResourceId","parameterTypes":[] }, {"name":"getResourcePath","parameterTypes":[] }, {"name":"getStage","parameterTypes":[] }, {"name":"setHttpMethod","parameterTypes":["java.lang.String"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setRequestId","parameterTypes":["java.lang.String"] }, {"name":"setResourcePath","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getBody","parameterTypes":[] }, {"name":"getCookies","parameterTypes":[] }, {"name":"getHeaders","parameterTypes":[] }, {"name":"getIsBase64Encoded","parameterTypes":[] }, {"name":"getPathParameters","parameterTypes":[] }, {"name":"getQueryStringParameters","parameterTypes":[] }, {"name":"getRawPath","parameterTypes":[] }, {"name":"getRawQueryString","parameterTypes":[] }, {"name":"getRequestContext","parameterTypes":[] }, {"name":"getRouteKey","parameterTypes":[] }, {"name":"getStageVariables","parameterTypes":[] }, {"name":"getVersion","parameterTypes":[] }, {"name":"setCookies","parameterTypes":["java.util.List"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setIsBase64Encoded","parameterTypes":["boolean"] }, {"name":"setRawPath","parameterTypes":["java.lang.String"] }, {"name":"setRawQueryString","parameterTypes":["java.lang.String"] }, {"name":"setRequestContext","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext"] }, {"name":"setRouteKey","parameterTypes":["java.lang.String"] }, {"name":"setVersion","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getAccountId","parameterTypes":[] }, {"name":"getApiId","parameterTypes":[] }, {"name":"getAuthorizer","parameterTypes":[] }, {"name":"getDomainName","parameterTypes":[] }, {"name":"getDomainPrefix","parameterTypes":[] }, {"name":"getHttp","parameterTypes":[] }, {"name":"getRequestId","parameterTypes":[] }, {"name":"getRouteKey","parameterTypes":[] }, {"name":"getStage","parameterTypes":[] }, {"name":"getTime","parameterTypes":[] }, {"name":"getTimeEpoch","parameterTypes":[] }, {"name":"setAccountId","parameterTypes":["java.lang.String"] }, {"name":"setApiId","parameterTypes":["java.lang.String"] }, {"name":"setDomainName","parameterTypes":["java.lang.String"] }, {"name":"setDomainPrefix","parameterTypes":["java.lang.String"] }, {"name":"setHttp","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$Http"] }, {"name":"setRequestId","parameterTypes":["java.lang.String"] }, {"name":"setRouteKey","parameterTypes":["java.lang.String"] }, {"name":"setStage","parameterTypes":["java.lang.String"] }, {"name":"setTime","parameterTypes":["java.lang.String"] }, {"name":"setTimeEpoch","parameterTypes":["long"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$Authorizer", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$Authorizer$JWT", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$CognitoIdentity", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$Http", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getMethod","parameterTypes":[] }, {"name":"getPath","parameterTypes":[] }, {"name":"getProtocol","parameterTypes":[] }, {"name":"getSourceIp","parameterTypes":[] }, {"name":"getUserAgent","parameterTypes":[] }, {"name":"setMethod","parameterTypes":["java.lang.String"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setProtocol","parameterTypes":["java.lang.String"] }, {"name":"setSourceIp","parameterTypes":["java.lang.String"] }, {"name":"setUserAgent","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$IAM", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getBody","parameterTypes":[] }, {"name":"getHeaders","parameterTypes":[] }, {"name":"getHttpMethod","parameterTypes":[] }, {"name":"getIsBase64Encoded","parameterTypes":[] }, {"name":"getMultiValueHeaders","parameterTypes":[] }, {"name":"getMultiValueQueryStringParameters","parameterTypes":[] }, {"name":"getPath","parameterTypes":[] }, {"name":"getQueryStringParameters","parameterTypes":[] }, {"name":"getRequestContext","parameterTypes":[] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setHttpMethod","parameterTypes":["java.lang.String"] }, {"name":"setIsBase64Encoded","parameterTypes":["boolean"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setQueryStringParameters","parameterTypes":["java.util.Map"] }, {"name":"setRequestContext","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent$RequestContext"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent$Elb", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getTargetGroupArn","parameterTypes":[] }, {"name":"setTargetGroupArn","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent$RequestContext", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getElb","parameterTypes":[] }, {"name":"setElb","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent$Elb"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.tests.EventArgumentsProvider", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.tests.annotations.Event", + "queryAllPublicMethods":true +}, +{ + "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"double", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.io.IOException" +}, +{ + "name":"java.io.InputStream" +}, +{ + "name":"java.io.OutputStream" +}, +{ + "name":"java.io.Serializable", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Boolean" +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Cloneable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Comparable", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"java.lang.Enum", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessEnvironment", + "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.constant.Constable", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] +}, +{ + "name":"java.util.Map" +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.function.Consumer", + "queryAllPublicMethods":true +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"org.aspectj.runtime.internal.AroundClosure", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.joda.time.DateTime" +}, +{ + "name":"org.slf4j.ILoggerFactory", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.slf4j.Logger", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.slf4j.helpers.AbstractLogger", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.slf4j.helpers.LegacyAbstractLogger", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.slf4j.spi.SLF4JServiceProvider", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.slf4j.test.OutputChoice", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.slf4j.test.OutputChoice$OutputChoiceType", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.slf4j.test.TestLogger", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.slf4j.test.TestLoggerConfiguration", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.slf4j.test.TestLoggerFactory", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"org.slf4j.test.TestServiceProvider", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", + "fields":[{"name":"IS_COLD_START"}, {"name":"SERVICE_NAME"}] +}, +{ + "name":"software.amazon.lambda.powertools.logging.argument.StructuredArgumentsTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"arrayArgument","parameterTypes":[] }, {"name":"jsonArgument","parameterTypes":[] }, {"name":"keyValueArgument","parameterTypes":[] }, {"name":"mapArgument","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayRestApiCorrelationId", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayRestApiCorrelationId$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAppSyncCorrelationId", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAppSyncCorrelationId$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogClearState", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.util.Map","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogClearState$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogDisabled", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogDisabledForStream", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabled", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"anotherMethod","parameterTypes":[] }, {"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabled$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabled$AjcClosure3", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabledForStream", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabledForStream$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogError", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogError$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEvent", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEvent$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventBridgeCorrelationId", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventBridgeCorrelationId$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventEnvVar", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventEnvVar$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventForStream", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventForStream$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponse", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponse$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponseForStream", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponseForStream$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogSamplingDisabled", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogSamplingDisabled$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogSamplingEnabled", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogSamplingEnabled$AjcClosure1", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.LambdaLoggingAspect", + "fields":[{"name":"LEVEL_AT_INITIALISATION"}], + "methods":[{"name":"setLogLevels","parameterTypes":["org.slf4j.event.Level"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.LoggingConstants", + "fields":[{"name":"LAMBDA_LOG_LEVEL"}, {"name":"POWERTOOLS_LOG_EVENT"}, {"name":"POWERTOOLS_LOG_LEVEL"}, {"name":"POWERTOOLS_SAMPLING_RATE"}] +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.LoggingManager", + "allDeclaredClasses":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.internal.TestLoggingManager", + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.logging.model.Basket", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getProducts","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.model.Product", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getId","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPrice","parameterTypes":[] }] +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +} +] diff --git a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/resource-config.json b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/resource-config.json new file mode 100644 index 000000000..ca77675e0 --- /dev/null +++ b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/resource-config.json @@ -0,0 +1,23 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" + }, { + "pattern":"\\Qcom/amazonaws/lambda/thirdparty/org/joda/time/tz/data/Europe/Berlin\\E" + }, { + "pattern":"\\Qcom/amazonaws/lambda/thirdparty/org/joda/time/tz/data/ZoneInfoMap\\E" + }]}, + "bundles":[] +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index 28e20aadd..557c6c893 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -18,11 +18,8 @@ import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.openMocks; -import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getProperty; -import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; @@ -32,15 +29,6 @@ import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_VERSION; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SERVICE; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; -import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import com.amazonaws.services.lambda.runtime.tests.annotations.Event; -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -58,19 +46,32 @@ import java.util.Collections; import java.util.List; import java.util.Map; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junitpioneer.jupiter.ClearEnvironmentVariable; +import org.junitpioneer.jupiter.SetEnvironmentVariable; +import org.junitpioneer.jupiter.SetSystemProperty; import org.mockito.Mock; -import org.mockito.MockedStatic; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.slf4j.event.Level; import org.slf4j.test.TestLogger; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; +import com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import com.amazonaws.services.lambda.runtime.tests.annotations.Event; +import com.fasterxml.jackson.databind.ObjectMapper; + import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; -import software.amazon.lambda.powertools.common.internal.SystemWrapper; import software.amazon.lambda.powertools.logging.argument.KeyValueArgument; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId; @@ -426,40 +427,31 @@ void shouldLogServiceNameWhenEnvVarSet() throws IllegalAccessException { } @Test + @ClearEnvironmentVariable(key = "_X_AMZN_TRACE_ID") + @SetSystemProperty(key = "com.amazonaws.xray.traceHeader", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") void shouldLogxRayTraceIdSystemPropertySet() { String xRayTraceId = "1-5759e988-bd862e3fe1be46a994272793"; - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn(null); - mocked.when(() -> getProperty("com.amazonaws.xray.traceHeader")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); - - requestHandler.handleRequest(new Object(), context); + requestHandler.handleRequest(new Object(), context); - assertThat(MDC.getCopyOfContextMap()) - .hasSize(EXPECTED_CONTEXT_SIZE + 1) - .containsEntry("xray_trace_id", xRayTraceId); - } + assertThat(MDC.getCopyOfContextMap()) + .hasSize(EXPECTED_CONTEXT_SIZE + 1) + .containsEntry("xray_trace_id", xRayTraceId); } @Test + @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") void shouldLogxRayTraceIdEnvVarSet() { // GIVEN String xRayTraceId = "1-5759e988-bd862e3fe1be46a994272793"; - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); - - // WHEN - requestHandler.handleRequest(new Object(), context); + // WHEN + requestHandler.handleRequest(new Object(), context); - // THEN - assertThat(MDC.getCopyOfContextMap()) - .hasSize(EXPECTED_CONTEXT_SIZE + 1) - .containsEntry(FUNCTION_TRACE_ID.getName(), xRayTraceId); - } + // THEN + assertThat(MDC.getCopyOfContextMap()) + .hasSize(EXPECTED_CONTEXT_SIZE + 1) + .containsEntry(FUNCTION_TRACE_ID.getName(), xRayTraceId); } @Test @@ -791,4 +783,4 @@ private void resetLogLevel(Level level) setLogLevels.invoke(null, level); writeStaticField(LambdaLoggingAspect.class, "LEVEL_AT_INITIALISATION", level, true); } -} \ No newline at end of file +} diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 0daa49664..1211a02c1 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -77,6 +77,11 @@ junit-jupiter-engine test + + org.junit-pioneer + junit-pioneer + test + org.apache.commons commons-lang3 @@ -94,7 +99,104 @@ + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-metrics + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + + + + + + + + + + + + src/main/resources + + org.apache.maven.plugins @@ -102,4 +204,4 @@ - \ No newline at end of file + diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/jni-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/jni-config.json new file mode 100644 index 000000000..8ea90d67f --- /dev/null +++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/jni-config.json @@ -0,0 +1,22 @@ +[ +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"org.apache.maven.surefire.booter.ForkedBooter", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"sun.instrument.InstrumentationImpl", + "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json new file mode 100644 index 000000000..bf67fc97b --- /dev/null +++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json @@ -0,0 +1,285 @@ +[ +{ + "name":"com.amazonaws.services.lambda.runtime.Context", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] +}, +{ + "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"java.io.InputStream" +}, +{ + "name":"java.io.OutputStream" +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Comparable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Double", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Number", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessEnvironment", + "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.constant.Constable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.constant.ConstantDesc", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.cloudwatchlogs.emf.logger.MetricsLogger", + "fields":[{"name":"context"}] +}, +{ + "name":"software.amazon.cloudwatchlogs.emf.model.Metadata", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getCloudWatchMetrics","parameterTypes":[] }, {"name":"getCustomMetadata","parameterTypes":[] }, {"name":"getTimestamp","parameterTypes":[] }] +}, +{ + "name":"software.amazon.cloudwatchlogs.emf.model.MetricDefinition", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getName","parameterTypes":[] }, {"name":"getStorageResolution","parameterTypes":[] }, {"name":"getUnit","parameterTypes":[] }] +}, +{ + "name":"software.amazon.cloudwatchlogs.emf.model.MetricDirective", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getAllDimensionKeys","parameterTypes":[] }, {"name":"getAllMetrics","parameterTypes":[] }, {"name":"getNamespace","parameterTypes":[] }] +}, +{ + "name":"software.amazon.cloudwatchlogs.emf.model.RootNode", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getAws","parameterTypes":[] }, {"name":"getTargetMembers","parameterTypes":[] }] +}, +{ + "name":"software.amazon.cloudwatchlogs.emf.serializers.InstantSerializer", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"software.amazon.cloudwatchlogs.emf.serializers.StorageResolutionFilter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"software.amazon.cloudwatchlogs.emf.serializers.StorageResolutionSerializer", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"software.amazon.cloudwatchlogs.emf.serializers.UnitSerializer", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", + "fields":[{"name":"IS_COLD_START"}] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.MetricsLoggerTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"metricsLoggerCaptureUtilityWithDefaultNameSpace","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"shouldUseTraceIdFromSystemPropertyIfEnvVarNotPresent","parameterTypes":[] }, {"name":"singleMetricsCaptureUtility","parameterTypes":[] }, {"name":"singleMetricsCaptureUtilityWithDefaultDimension","parameterTypes":[] }, {"name":"singleMetricsCaptureUtilityWithDefaultNameSpace","parameterTypes":[] }, {"name":"singleMetricsCaptureUtilityWithNullNamespace","parameterTypes":[] }, {"name":"tearDown","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsColdStartEnabledHandler", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledDefaultDimensionHandler", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledDefaultNoDimensionHandler", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledHandler", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledStreamHandler", + "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsExceptionWhenNoMetricsHandler", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsNoDimensionsHandler", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsNoExceptionWhenNoMetricsHandler", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsTooManyDimensionsHandler", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsWithExceptionInHandler", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"allowWhenNoDimensionsSet","parameterTypes":[] }, {"name":"exceptionWhenNoMetricsEmitted","parameterTypes":[] }, {"name":"exceptionWhenTooManyDimensionsSet","parameterTypes":[] }, {"name":"metricsPublishedEvenHandlerThrowsException","parameterTypes":[] }, {"name":"metricsWithColdStart","parameterTypes":[] }, {"name":"metricsWithDefaultDimensionSpecified","parameterTypes":[] }, {"name":"metricsWithDefaultNoDimensionSpecified","parameterTypes":[] }, {"name":"metricsWithStreamHandler","parameterTypes":[] }, {"name":"metricsWithoutColdStart","parameterTypes":[] }, {"name":"noColdStartMetricsWhenColdStartDone","parameterTypes":[] }, {"name":"noExceptionWhenNoMetricsEmitted","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"tearDown","parameterTypes":[] }] +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +} +] diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json new file mode 100644 index 000000000..dd8fabec3 --- /dev/null +++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }]}, + "bundles":[] +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java index 518e11739..5f99c950a 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java @@ -16,43 +16,34 @@ import static java.util.Collections.emptyMap; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatNullPointerException; -import static org.mockito.Mockito.mockStatic; -import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getProperty; -import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; import java.util.function.Consumer; + import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import software.amazon.cloudwatchlogs.emf.config.SystemWrapper; +import org.junitpioneer.jupiter.SetEnvironmentVariable; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; import software.amazon.cloudwatchlogs.emf.model.DimensionSet; import software.amazon.cloudwatchlogs.emf.model.StorageResolution; import software.amazon.cloudwatchlogs.emf.model.Unit; +@SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") class MetricsLoggerTest { private final ByteArrayOutputStream out = new ByteArrayOutputStream(); private final PrintStream originalOut = System.out; private final ObjectMapper mapper = new ObjectMapper(); - @BeforeAll - static void beforeAll() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - } - } - @BeforeEach void setUp() { System.setOut(new PrintStream(out)); @@ -64,206 +55,170 @@ void tearDown() { } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") + @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") void singleMetricsCaptureUtilityWithDefaultDimension() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); - - MetricsUtils.defaultDimensions(DimensionSet.of("Service", "Booking")); - - MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, "test", - metricsLogger -> - { - }); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "Booking") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); - }); - } + MetricsUtils.defaultDimensions(DimensionSet.of("Service", "Booking")); + + MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, "test", + metricsLogger -> + { + }); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("Service", "Booking") + .containsKey("_aws") + .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") + @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") void singleMetricsCaptureUtility() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); - - MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, "test", - metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Dimension1", "Value1") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=test"); - }); - } + MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, "test", + metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("Dimension1", "Value1") + .containsKey("_aws") + .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); + + Map aws = (Map) logAsJson.get("_aws"); + + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=test"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") void singleMetricsCaptureUtilityWithNullNamespace() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - // POWERTOOLS_METRICS_NAMESPACE is not defined - - MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, - metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=aws-embedded-metrics"); - }); - } + // POWERTOOLS_METRICS_NAMESPACE is not defined + + MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, + metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + + Map aws = (Map) logAsJson.get("_aws"); + + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=aws-embedded-metrics"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "GlobalName") + @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") void singleMetricsCaptureUtilityWithDefaultNameSpace() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName"); - internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); - - MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, - metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Dimension1", "Value1") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=GlobalName"); - }); - } + MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, + metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("Dimension1", "Value1") + .containsKey("_aws") + .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); + + Map aws = (Map) logAsJson.get("_aws"); + + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=GlobalName"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "GlobalName") + @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") void metricsLoggerCaptureUtilityWithDefaultNameSpace() { testLogger(MetricsUtils::withMetricsLogger); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "GlobalName") + @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") void shouldUseTraceIdFromSystemPropertyIfEnvVarNotPresent() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName"); - internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn(null); - internalWrapper.when(() -> getProperty("com.amazonaws.xray.traceHeader")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); - - MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, - metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Dimension1", "Value1") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=GlobalName"); - }); - } + MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, + metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("Dimension1", "Value1") + .containsKey("_aws") + .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); + + Map aws = (Map) logAsJson.get("_aws"); + + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=GlobalName"); + }); } private void testLogger(Consumer> methodToTest) { - try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE")).thenReturn("GlobalName"); - internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); - - methodToTest.accept(metricsLogger -> - { - metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1")); - metricsLogger.putMetric("Metric1", 1, Unit.COUNT); - metricsLogger.putMetric("Metric2", 1, Unit.COUNT, StorageResolution.HIGH); - }); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Dimension1", "Value1") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=GlobalName"); - - ArrayList cloudWatchMetrics = (ArrayList) aws.get("CloudWatchMetrics"); - LinkedHashMap values = - (java.util.LinkedHashMap) cloudWatchMetrics.get(0); - ArrayList metricArray = (ArrayList) values.get("Metrics"); - LinkedHashMap metricValues = (LinkedHashMap) metricArray.get(1); - assertThat(metricValues).containsEntry("StorageResolution", 1); - }); - } + methodToTest.accept(metricsLogger -> + { + metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1")); + metricsLogger.putMetric("Metric1", 1, Unit.COUNT); + metricsLogger.putMetric("Metric2", 1, Unit.COUNT, StorageResolution.HIGH); + }); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("Dimension1", "Value1") + .containsKey("_aws") + .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); + + Map aws = (Map) logAsJson.get("_aws"); + + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=GlobalName"); + + ArrayList cloudWatchMetrics = (ArrayList) aws.get("CloudWatchMetrics"); + LinkedHashMap values = + (java.util.LinkedHashMap) cloudWatchMetrics.get(0); + ArrayList metricArray = (ArrayList) values.get("Metrics"); + LinkedHashMap metricValues = (LinkedHashMap) metricArray.get(1); + assertThat(metricValues).containsEntry("StorageResolution", 1); + }); } private Map readAsJson(String s) { @@ -274,4 +229,4 @@ private Map readAsJson(String s) { } return emptyMap(); } -} \ No newline at end of file +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java index d27af1fdf..5df6003c8 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java @@ -18,28 +18,27 @@ import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.openMocks; -import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.Map; + import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetEnvironmentVariable; import org.mockito.Mock; -import org.mockito.MockedStatic; -import software.amazon.cloudwatchlogs.emf.config.SystemWrapper; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + import software.amazon.cloudwatchlogs.emf.exception.DimensionSetExceededException; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.metrics.MetricsUtils; @@ -55,6 +54,7 @@ import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsTooManyDimensionsHandler; import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsWithExceptionInHandler; +@SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") public class LambdaMetricsAspectTest { private final ByteArrayOutputStream out = new ByteArrayOutputStream(); private final PrintStream originalOut = System.out; @@ -63,14 +63,6 @@ public class LambdaMetricsAspectTest { private Context context; private RequestHandler requestHandler; - - @BeforeAll - static void beforeAll() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - } - } - @BeforeEach void setUp() throws IllegalAccessException { openMocks(this); @@ -85,341 +77,292 @@ void tearDown() { } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") + @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") public void metricsWithoutColdStart() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { - - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); - - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsEnabledHandler(); - requestHandler.handleRequest("input", context); - - assertThat(out.toString().split("\n")) - .hasSize(2) - .satisfies(s -> - { - Map logAsJson = readAsJson(s[0]); - - assertThat(logAsJson) - .containsEntry("Metric2", 1.0) - .containsEntry("Dimension1", "Value1") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793") - .containsEntry("function_request_id", "123ABC"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=ExampleApplication"); - - logAsJson = readAsJson(s[1]); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); - } + + MetricsUtils.defaultDimensions(null); + requestHandler = new PowertoolsMetricsEnabledHandler(); + requestHandler.handleRequest("input", context); + + assertThat(out.toString().split("\n")) + .hasSize(2) + .satisfies(s -> + { + Map logAsJson = readAsJson(s[0]); + + assertThat(logAsJson) + .containsEntry("Metric2", 1.0) + .containsEntry("Dimension1", "Value1") + .containsKey("_aws") + .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793") + .containsEntry("function_request_id", "123ABC"); + + Map aws = (Map) logAsJson.get("_aws"); + + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=ExampleApplication"); + + logAsJson = readAsJson(s[1]); + + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("Service", "booking") + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") + @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") public void metricsWithDefaultDimensionSpecified() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { - - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); + requestHandler = new PowertoolsMetricsEnabledDefaultDimensionHandler(); - requestHandler = new PowertoolsMetricsEnabledDefaultDimensionHandler(); + requestHandler.handleRequest("input", context); - requestHandler.handleRequest("input", context); + assertThat(out.toString().split("\n")) + .hasSize(2) + .satisfies(s -> + { + Map logAsJson = readAsJson(s[0]); - assertThat(out.toString().split("\n")) - .hasSize(2) - .satisfies(s -> - { - Map logAsJson = readAsJson(s[0]); + assertThat(logAsJson) + .containsEntry("Metric2", 1.0) + .containsEntry("CustomDimension", "booking") + .containsKey("_aws") + .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793") + .containsEntry("function_request_id", "123ABC"); - assertThat(logAsJson) - .containsEntry("Metric2", 1.0) - .containsEntry("CustomDimension", "booking") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793") - .containsEntry("function_request_id", "123ABC"); + Map aws = (Map) logAsJson.get("_aws"); - Map aws = (Map) logAsJson.get("_aws"); + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=ExampleApplication"); - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=ExampleApplication"); + logAsJson = readAsJson(s[1]); - logAsJson = readAsJson(s[1]); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("CustomDimension", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); - } + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("CustomDimension", "booking") + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") + @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") public void metricsWithDefaultNoDimensionSpecified() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class); - MockedStatic internalWrapper = mockStatic( - software.amazon.lambda.powertools.common.internal.SystemWrapper.class)) { - - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - internalWrapper.when(() -> getenv("_X_AMZN_TRACE_ID")) - .thenReturn("Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"); + requestHandler = new PowertoolsMetricsEnabledDefaultNoDimensionHandler(); - requestHandler = new PowertoolsMetricsEnabledDefaultNoDimensionHandler(); + requestHandler.handleRequest("input", context); - requestHandler.handleRequest("input", context); + assertThat(out.toString().split("\n")) + .hasSize(2) + .satisfies(s -> + { + Map logAsJson = readAsJson(s[0]); - assertThat(out.toString().split("\n")) - .hasSize(2) - .satisfies(s -> - { - Map logAsJson = readAsJson(s[0]); + assertThat(logAsJson) + .containsEntry("Metric2", 1.0) + .containsKey("_aws") + .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793") + .containsEntry("function_request_id", "123ABC"); - assertThat(logAsJson) - .containsEntry("Metric2", 1.0) - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793") - .containsEntry("function_request_id", "123ABC"); + Map aws = (Map) logAsJson.get("_aws"); - Map aws = (Map) logAsJson.get("_aws"); + assertThat(aws.get("CloudWatchMetrics")) + .asString() + .contains("Namespace=ExampleApplication"); - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=ExampleApplication"); + logAsJson = readAsJson(s[1]); - logAsJson = readAsJson(s[1]); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); - } + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") public void metricsWithColdStart() { - - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsColdStartEnabledHandler(); - - requestHandler.handleRequest("input", context); - - assertThat(out.toString().split("\n")) - .hasSize(2) - .satisfies(s -> - { - Map logAsJson = readAsJson(s[0]); - - assertThat(logAsJson) - .doesNotContainKey("Metric1") - .containsEntry("ColdStart", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - - logAsJson = readAsJson(s[1]); - - assertThat(logAsJson) - .doesNotContainKey("ColdStart") - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); - } + MetricsUtils.defaultDimensions(null); + requestHandler = new PowertoolsMetricsColdStartEnabledHandler(); + + requestHandler.handleRequest("input", context); + + assertThat(out.toString().split("\n")) + .hasSize(2) + .satisfies(s -> + { + Map logAsJson = readAsJson(s[0]); + + assertThat(logAsJson) + .doesNotContainKey("Metric1") + .containsEntry("ColdStart", 1.0) + .containsEntry("Service", "booking") + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + + logAsJson = readAsJson(s[1]); + + assertThat(logAsJson) + .doesNotContainKey("ColdStart") + .containsEntry("Metric1", 1.0) + .containsEntry("Service", "booking") + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") public void noColdStartMetricsWhenColdStartDone() { - - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsColdStartEnabledHandler(); - - requestHandler.handleRequest("input", context); - requestHandler.handleRequest("input", context); - - assertThat(out.toString().split("\n")) - .hasSize(3) - .satisfies(s -> - { - Map logAsJson = readAsJson(s[0]); - - assertThat(logAsJson) - .doesNotContainKey("Metric1") - .containsEntry("ColdStart", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - - logAsJson = readAsJson(s[1]); - - assertThat(logAsJson) - .doesNotContainKey("ColdStart") - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - - logAsJson = readAsJson(s[2]); - - assertThat(logAsJson) - .doesNotContainKey("ColdStart") - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); - } + MetricsUtils.defaultDimensions(null); + requestHandler = new PowertoolsMetricsColdStartEnabledHandler(); + + requestHandler.handleRequest("input", context); + requestHandler.handleRequest("input", context); + + assertThat(out.toString().split("\n")) + .hasSize(3) + .satisfies(s -> + { + Map logAsJson = readAsJson(s[0]); + + assertThat(logAsJson) + .doesNotContainKey("Metric1") + .containsEntry("ColdStart", 1.0) + .containsEntry("Service", "booking") + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + + logAsJson = readAsJson(s[1]); + + assertThat(logAsJson) + .doesNotContainKey("ColdStart") + .containsEntry("Metric1", 1.0) + .containsEntry("Service", "booking") + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + + logAsJson = readAsJson(s[2]); + + assertThat(logAsJson) + .doesNotContainKey("ColdStart") + .containsEntry("Metric1", 1.0) + .containsEntry("Service", "booking") + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") public void metricsWithStreamHandler() throws IOException { - - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - - MetricsUtils.defaultDimensions(null); - RequestStreamHandler streamHandler = new PowertoolsMetricsEnabledStreamHandler(); - - streamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), context); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); - } + MetricsUtils.defaultDimensions(null); + RequestStreamHandler streamHandler = new PowertoolsMetricsEnabledStreamHandler(); + + streamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), context); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + + assertThat(logAsJson) + .containsEntry("Metric1", 1.0) + .containsEntry("Service", "booking") + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") public void exceptionWhenNoMetricsEmitted() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsExceptionWhenNoMetricsHandler(); + MetricsUtils.defaultDimensions(null); + requestHandler = new PowertoolsMetricsExceptionWhenNoMetricsHandler(); - assertThatExceptionOfType(ValidationException.class) - .isThrownBy(() -> requestHandler.handleRequest("input", context)) - .withMessage("No metrics captured, at least one metrics must be emitted"); - } + assertThatExceptionOfType(ValidationException.class) + .isThrownBy(() -> requestHandler.handleRequest("input", context)) + .withMessage("No metrics captured, at least one metrics must be emitted"); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") public void noExceptionWhenNoMetricsEmitted() { + MetricsUtils.defaultDimensions(null); + requestHandler = new PowertoolsMetricsNoExceptionWhenNoMetricsHandler(); - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsNoExceptionWhenNoMetricsHandler(); - - requestHandler.handleRequest("input", context); + requestHandler.handleRequest("input", context); - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); - assertThat(logAsJson) - .containsEntry("Service", "booking") - .doesNotContainKey("_aws"); - }); - } + assertThat(logAsJson) + .containsEntry("Service", "booking") + .doesNotContainKey("_aws"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") public void allowWhenNoDimensionsSet() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - MetricsUtils.defaultDimensions(null); - - requestHandler = new PowertoolsMetricsNoDimensionsHandler(); - requestHandler.handleRequest("input", context); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - assertThat(logAsJson) - .containsEntry("CoolMetric", 1.0) - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); - } + MetricsUtils.defaultDimensions(null); + + requestHandler = new PowertoolsMetricsNoDimensionsHandler(); + requestHandler.handleRequest("input", context); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + assertThat(logAsJson) + .containsEntry("CoolMetric", 1.0) + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + }); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") public void exceptionWhenTooManyDimensionsSet() { + MetricsUtils.defaultDimensions(null); - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - - MetricsUtils.defaultDimensions(null); + requestHandler = new PowertoolsMetricsTooManyDimensionsHandler(); - requestHandler = new PowertoolsMetricsTooManyDimensionsHandler(); - - assertThatExceptionOfType(DimensionSetExceededException.class) - .isThrownBy(() -> requestHandler.handleRequest("input", context)) - .withMessage( - "Maximum number of dimensions allowed are 30. Account for default dimensions if not using setDimensions."); - } + assertThatExceptionOfType(DimensionSetExceededException.class) + .isThrownBy(() -> requestHandler.handleRequest("input", context)) + .withMessage( + "Maximum number of dimensions allowed are 30. Account for default dimensions if not using setDimensions."); } @Test + @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") public void metricsPublishedEvenHandlerThrowsException() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("AWS_EMF_ENVIRONMENT")).thenReturn("Lambda"); - - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsWithExceptionInHandler(); - - assertThatExceptionOfType(IllegalStateException.class) - .isThrownBy(() -> requestHandler.handleRequest("input", context)) - .withMessage("Whoops, unexpected exception"); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - assertThat(logAsJson) - .containsEntry("CoolMetric", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); - } + MetricsUtils.defaultDimensions(null); + requestHandler = new PowertoolsMetricsWithExceptionInHandler(); + + assertThatExceptionOfType(IllegalStateException.class) + .isThrownBy(() -> requestHandler.handleRequest("input", context)) + .withMessage("Whoops, unexpected exception"); + + assertThat(out.toString()) + .satisfies(s -> + { + Map logAsJson = readAsJson(s); + assertThat(logAsJson) + .containsEntry("CoolMetric", 1.0) + .containsEntry("Service", "booking") + .containsEntry("function_request_id", "123ABC") + .containsKey("_aws"); + }); } private void setupContext() { diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 454b30d3e..ee2d7db3d 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -67,8 +67,102 @@ test - + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization,experimental-class-define-support + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + + true + Standard + + powertools-serialization + + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + + + + + + + + + + + src/main/resources + + dev.aspectj diff --git a/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/jni-config.json b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/jni-config.json new file mode 100644 index 000000000..079c02a4d --- /dev/null +++ b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/jni-config.json @@ -0,0 +1,18 @@ +[ +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"org.apache.maven.surefire.booter.ForkedBooter", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json new file mode 100644 index 000000000..1a4f89735 --- /dev/null +++ b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json @@ -0,0 +1,470 @@ +[ +{ + "name":"[B" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.KeyDeserializers;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiators;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers;" +}, +{ + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setHttpMethod","parameterTypes":["java.lang.String"] }, {"name":"setIsBase64Encoded","parameterTypes":["java.lang.Boolean"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setPathParameters","parameterTypes":["java.util.Map"] }, {"name":"setQueryStringParameters","parameterTypes":["java.util.Map"] }, {"name":"setRequestContext","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext"] }, {"name":"setResource","parameterTypes":["java.lang.String"] }, {"name":"setStageVariables","parameterTypes":["java.util.Map"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setAccountId","parameterTypes":["java.lang.String"] }, {"name":"setApiId","parameterTypes":["java.lang.String"] }, {"name":"setHttpMethod","parameterTypes":["java.lang.String"] }, {"name":"setIdentity","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setProtocol","parameterTypes":["java.lang.String"] }, {"name":"setRequestId","parameterTypes":["java.lang.String"] }, {"name":"setRequestTime","parameterTypes":["java.lang.String"] }, {"name":"setRequestTimeEpoch","parameterTypes":["java.lang.Long"] }, {"name":"setResourceId","parameterTypes":["java.lang.String"] }, {"name":"setResourcePath","parameterTypes":["java.lang.String"] }, {"name":"setStage","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setAccessKey","parameterTypes":["java.lang.String"] }, {"name":"setAccountId","parameterTypes":["java.lang.String"] }, {"name":"setCaller","parameterTypes":["java.lang.String"] }, {"name":"setCognitoAuthenticationProvider","parameterTypes":["java.lang.String"] }, {"name":"setCognitoAuthenticationType","parameterTypes":["java.lang.String"] }, {"name":"setCognitoIdentityId","parameterTypes":["java.lang.String"] }, {"name":"setCognitoIdentityPoolId","parameterTypes":["java.lang.String"] }, {"name":"setSourceIp","parameterTypes":["java.lang.String"] }, {"name":"setUser","parameterTypes":["java.lang.String"] }, {"name":"setUserAgent","parameterTypes":["java.lang.String"] }, {"name":"setUserArn","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setCookies","parameterTypes":["java.util.List"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setIsBase64Encoded","parameterTypes":["boolean"] }, {"name":"setPathParameters","parameterTypes":["java.util.Map"] }, {"name":"setQueryStringParameters","parameterTypes":["java.util.Map"] }, {"name":"setRawPath","parameterTypes":["java.lang.String"] }, {"name":"setRawQueryString","parameterTypes":["java.lang.String"] }, {"name":"setRequestContext","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext"] }, {"name":"setRouteKey","parameterTypes":["java.lang.String"] }, {"name":"setStageVariables","parameterTypes":["java.util.Map"] }, {"name":"setVersion","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setAccountId","parameterTypes":["java.lang.String"] }, {"name":"setApiId","parameterTypes":["java.lang.String"] }, {"name":"setDomainName","parameterTypes":["java.lang.String"] }, {"name":"setDomainPrefix","parameterTypes":["java.lang.String"] }, {"name":"setHttp","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$Http"] }, {"name":"setRouteKey","parameterTypes":["java.lang.String"] }, {"name":"setStage","parameterTypes":["java.lang.String"] }, {"name":"setTime","parameterTypes":["java.lang.String"] }, {"name":"setTimeEpoch","parameterTypes":["long"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$Authorizer", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$Authorizer$JWT", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$CognitoIdentity", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$Http", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setMethod","parameterTypes":["java.lang.String"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setProtocol","parameterTypes":["java.lang.String"] }, {"name":"setSourceIp","parameterTypes":["java.lang.String"] }, {"name":"setUserAgent","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent$RequestContext$IAM", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.ActiveMQEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setEventSource","parameterTypes":["java.lang.String"] }, {"name":"setEventSourceArn","parameterTypes":["java.lang.String"] }, {"name":"setMessages","parameterTypes":["java.util.List"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.ActiveMQEvent$ActiveMQMessage", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setBrokerInTime","parameterTypes":["long"] }, {"name":"setBrokerOutTime","parameterTypes":["long"] }, {"name":"setData","parameterTypes":["java.lang.String"] }, {"name":"setDeliveryMode","parameterTypes":["int"] }, {"name":"setDestination","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ActiveMQEvent$Destination"] }, {"name":"setExpiration","parameterTypes":["long"] }, {"name":"setMessageID","parameterTypes":["java.lang.String"] }, {"name":"setMessageType","parameterTypes":["java.lang.String"] }, {"name":"setPriority","parameterTypes":["int"] }, {"name":"setProperties","parameterTypes":["java.util.Map"] }, {"name":"setRedelivered","parameterTypes":["boolean"] }, {"name":"setReplyTo","parameterTypes":["java.lang.String"] }, {"name":"setTimestamp","parameterTypes":["long"] }, {"name":"setType","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.ActiveMQEvent$Destination", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setPhysicalName","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setHttpMethod","parameterTypes":["java.lang.String"] }, {"name":"setIsBase64Encoded","parameterTypes":["boolean"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setQueryStringParameters","parameterTypes":["java.util.Map"] }, {"name":"setRequestContext","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent$RequestContext"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent$Elb", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setTargetGroupArn","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent$RequestContext", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setElb","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent$Elb"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setLogicalResourceId","parameterTypes":["java.lang.String"] }, {"name":"setOldResourceProperties","parameterTypes":["java.util.Map"] }, {"name":"setRequestId","parameterTypes":["java.lang.String"] }, {"name":"setRequestType","parameterTypes":["java.lang.String"] }, {"name":"setResourceProperties","parameterTypes":["java.util.Map"] }, {"name":"setResourceType","parameterTypes":["java.lang.String"] }, {"name":"setServiceToken","parameterTypes":["java.lang.String"] }, {"name":"setStackId","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.CloudWatchLogsEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setAwsLogs","parameterTypes":["com.amazonaws.services.lambda.runtime.events.CloudWatchLogsEvent$AWSLogs"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.CloudWatchLogsEvent$AWSLogs", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setData","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KafkaEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setBootstrapServers","parameterTypes":["java.lang.String"] }, {"name":"setEventSource","parameterTypes":["java.lang.String"] }, {"name":"setEventSourceArn","parameterTypes":["java.lang.String"] }, {"name":"setRecords","parameterTypes":["java.util.Map"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KafkaEvent$KafkaEventRecord", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setOffset","parameterTypes":["long"] }, {"name":"setPartition","parameterTypes":["int"] }, {"name":"setTimestamp","parameterTypes":["long"] }, {"name":"setTimestampType","parameterTypes":["java.lang.String"] }, {"name":"setTopic","parameterTypes":["java.lang.String"] }, {"name":"setValue","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsFirehoseInputPreprocessingEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setApplicationArn","parameterTypes":["java.lang.String"] }, {"name":"setInvocationId","parameterTypes":["java.lang.String"] }, {"name":"setRecords","parameterTypes":["java.util.List"] }, {"name":"setStreamArn","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsFirehoseInputPreprocessingEvent$Record", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setData","parameterTypes":["java.nio.ByteBuffer"] }, {"name":"setKinesisFirehoseRecordMetadata","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsFirehoseInputPreprocessingEvent$Record$KinesisFirehoseRecordMetadata"] }, {"name":"setRecordId","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsFirehoseInputPreprocessingEvent$Record$KinesisFirehoseRecordMetadata", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setApproximateArrivalTimestamp","parameterTypes":["java.lang.Long"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsStreamsInputPreprocessingEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setApplicationArn","parameterTypes":["java.lang.String"] }, {"name":"setInvocationId","parameterTypes":["java.lang.String"] }, {"name":"setRecords","parameterTypes":["java.util.List"] }, {"name":"setStreamArn","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsStreamsInputPreprocessingEvent$Record", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setData","parameterTypes":["java.nio.ByteBuffer"] }, {"name":"setKinesisStreamRecordMetadata","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsStreamsInputPreprocessingEvent$Record$KinesisStreamRecordMetadata"] }, {"name":"setRecordId","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsStreamsInputPreprocessingEvent$Record$KinesisStreamRecordMetadata", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setApproximateArrivalTimestamp","parameterTypes":["java.lang.Long"] }, {"name":"setPartitionKey","parameterTypes":["java.lang.String"] }, {"name":"setSequenceNumber","parameterTypes":["java.lang.String"] }, {"name":"setShardId","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setRecords","parameterTypes":["java.util.List"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisEvent$KinesisEventRecord", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setAwsRegion","parameterTypes":["java.lang.String"] }, {"name":"setEventID","parameterTypes":["java.lang.String"] }, {"name":"setEventName","parameterTypes":["java.lang.String"] }, {"name":"setEventSource","parameterTypes":["java.lang.String"] }, {"name":"setEventSourceARN","parameterTypes":["java.lang.String"] }, {"name":"setEventVersion","parameterTypes":["java.lang.String"] }, {"name":"setInvokeIdentityArn","parameterTypes":["java.lang.String"] }, {"name":"setKinesis","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisEvent$Record"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisEvent$Record", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setKinesisSchemaVersion","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setDeliveryStreamArn","parameterTypes":["java.lang.String"] }, {"name":"setInvocationId","parameterTypes":["java.lang.String"] }, {"name":"setRecords","parameterTypes":["java.util.List"] }, {"name":"setRegion","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent$Record", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setApproximateArrivalTimestamp","parameterTypes":["java.lang.Long"] }, {"name":"setData","parameterTypes":["java.nio.ByteBuffer"] }, {"name":"setRecordId","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.RabbitMQEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setEventSource","parameterTypes":["java.lang.String"] }, {"name":"setEventSourceArn","parameterTypes":["java.lang.String"] }, {"name":"setRmqMessagesByQueue","parameterTypes":["java.util.Map"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.RabbitMQEvent$BasicProperties", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setAppId","parameterTypes":["java.lang.String"] }, {"name":"setBodySize","parameterTypes":["int"] }, {"name":"setClusterId","parameterTypes":["java.lang.String"] }, {"name":"setContentEncoding","parameterTypes":["java.lang.String"] }, {"name":"setContentType","parameterTypes":["java.lang.String"] }, {"name":"setCorrelationId","parameterTypes":["java.lang.String"] }, {"name":"setDeliveryMode","parameterTypes":["int"] }, {"name":"setExpiration","parameterTypes":["int"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setMessageId","parameterTypes":["java.lang.String"] }, {"name":"setPriority","parameterTypes":["int"] }, {"name":"setReplyTo","parameterTypes":["java.lang.String"] }, {"name":"setTimestamp","parameterTypes":["java.lang.String"] }, {"name":"setType","parameterTypes":["java.lang.String"] }, {"name":"setUserId","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.RabbitMQEvent$RabbitMessage", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setBasicProperties","parameterTypes":["com.amazonaws.services.lambda.runtime.events.RabbitMQEvent$BasicProperties"] }, {"name":"setData","parameterTypes":["java.lang.String"] }, {"name":"setRedelivered","parameterTypes":["boolean"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SNSEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setRecords","parameterTypes":["java.util.List"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SNSEvent$MessageAttribute", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setType","parameterTypes":["java.lang.String"] }, {"name":"setValue","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SNSEvent$SNS", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setMessage","parameterTypes":["java.lang.String"] }, {"name":"setMessageAttributes","parameterTypes":["java.util.Map"] }, {"name":"setMessageId","parameterTypes":["java.lang.String"] }, {"name":"setSignature","parameterTypes":["java.lang.String"] }, {"name":"setSignatureVersion","parameterTypes":["java.lang.String"] }, {"name":"setSigningCertUrl","parameterTypes":["java.lang.String"] }, {"name":"setSubject","parameterTypes":["java.lang.String"] }, {"name":"setTimestamp","parameterTypes":["org.joda.time.DateTime"] }, {"name":"setTopicArn","parameterTypes":["java.lang.String"] }, {"name":"setType","parameterTypes":["java.lang.String"] }, {"name":"setUnsubscribeUrl","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SNSEvent$SNSRecord", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setEventSource","parameterTypes":["java.lang.String"] }, {"name":"setEventSubscriptionArn","parameterTypes":["java.lang.String"] }, {"name":"setEventVersion","parameterTypes":["java.lang.String"] }, {"name":"setSns","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SNSEvent$SNS"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SQSEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setRecords","parameterTypes":["java.util.List"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SQSEvent$MessageAttribute", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.SQSEvent$SQSMessage", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setAttributes","parameterTypes":["java.util.Map"] }, {"name":"setAwsRegion","parameterTypes":["java.lang.String"] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setEventSource","parameterTypes":["java.lang.String"] }, {"name":"setEventSourceArn","parameterTypes":["java.lang.String"] }, {"name":"setMd5OfBody","parameterTypes":["java.lang.String"] }, {"name":"setMessageAttributes","parameterTypes":["java.util.Map"] }, {"name":"setMessageId","parameterTypes":["java.lang.String"] }, {"name":"setReceiptHandle","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.ScheduledEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setAccount","parameterTypes":["java.lang.String"] }, {"name":"setDetail","parameterTypes":["java.util.Map"] }, {"name":"setDetailType","parameterTypes":["java.lang.String"] }, {"name":"setId","parameterTypes":["java.lang.String"] }, {"name":"setRegion","parameterTypes":["java.lang.String"] }, {"name":"setResources","parameterTypes":["java.util.List"] }, {"name":"setSource","parameterTypes":["java.lang.String"] }, {"name":"setTime","parameterTypes":["org.joda.time.DateTime"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.models.kinesis.Record", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"setApproximateArrivalTimestamp","parameterTypes":["java.util.Date"] }, {"name":"setData","parameterTypes":["java.nio.ByteBuffer"] }, {"name":"setEncryptionType","parameterTypes":["java.lang.String"] }, {"name":"setPartitionKey","parameterTypes":["java.lang.String"] }, {"name":"setSequenceNumber","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.serialization.events.mixins.CloudFormationCustomResourceEventMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.serialization.events.mixins.CloudWatchLogsEventMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.serialization.events.mixins.KinesisEventMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.serialization.events.mixins.KinesisEventMixin$RecordMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.serialization.events.mixins.SNSEventMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.serialization.events.mixins.SNSEventMixin$SNSRecordMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.serialization.events.mixins.SQSEventMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.serialization.events.mixins.SQSEventMixin$SQSMessageMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.serialization.events.mixins.ScheduledEventMixin", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.tests.EventArgumentsProvider", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.tests.annotations.Event", + "queryAllPublicMethods":true +}, +{ + "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Cloneable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Object", + "allDeclaredFields":true +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.function.Consumer", + "queryAllPublicMethods":true +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"org.joda.time.DateTime", + "methods":[{"name":"parse","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"software.amazon.lambda.powertools.utilities.EventDeserializerTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"testDeserializeALBEventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent"] }, {"name":"testDeserializeAMQEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ActiveMQEvent"] }, {"name":"testDeserializeAPIGWEventBodyAsObject_shouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent"] }, {"name":"testDeserializeAPIGatewayEventAsList_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent"] }, {"name":"testDeserializeAPIGatewayMapEventAsList_shouldThrowException","parameterTypes":["java.util.Map"] }, {"name":"testDeserializeAPIGatewayNoBodyAsList_shouldThrowException","parameterTypes":[] }, {"name":"testDeserializeAPIGatewayNoBody_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent"] }, {"name":"testDeserializeApiGWV2EventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent"] }, {"name":"testDeserializeCWLEventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.CloudWatchLogsEvent"] }, {"name":"testDeserializeCfcrEventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent"] }, {"name":"testDeserializeEmptyEventAsList_shouldThrowException","parameterTypes":[] }, {"name":"testDeserializeKFEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent"] }, {"name":"testDeserializeKafipEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsFirehoseInputPreprocessingEvent"] }, {"name":"testDeserializeKafkaEventMessageAsList_shouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KafkaEvent"] }, {"name":"testDeserializeKasipEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsStreamsInputPreprocessingEvent"] }, {"name":"testDeserializeKinesisEventMessageAsList_shouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisEvent"] }, {"name":"testDeserializeMapAsObject_shouldReturnObject","parameterTypes":[] }, {"name":"testDeserializeProductAsProduct_shouldReturnProduct","parameterTypes":[] }, {"name":"testDeserializeRabbitMQEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.RabbitMQEvent"] }, {"name":"testDeserializeSNSEventMessageAsObject_shouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SNSEvent"] }, {"name":"testDeserializeSQSEventMessageAsList_shouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent"] }, {"name":"testDeserializeSQSEventMessageAsObject_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent"] }, {"name":"testDeserializeSQSEventNoBody_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent"] }, {"name":"testDeserializeScheduledEventMessageAsObject_shouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ScheduledEvent"] }, {"name":"testDeserializeStringArrayAsList_shouldReturnList","parameterTypes":[] }, {"name":"testDeserializeStringAsList_shouldThrowException","parameterTypes":[] }, {"name":"testDeserializeStringAsObject_shouldReturnObject","parameterTypes":[] }, {"name":"testDeserializeStringAsString_shouldReturnString","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.utilities.jmespath.Base64FunctionTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"testPowertoolsBase64","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunctionTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"testBase64GzipDecompressNull","parameterTypes":[] }, {"name":"testConstructor","parameterTypes":[] }, {"name":"testPowertoolsGzip","parameterTypes":[] }, {"name":"testPowertoolsGzipEmptyJsonAttribute","parameterTypes":[] }, {"name":"testPowertoolsGzipNotCompressedJsonAttribute","parameterTypes":[] }, {"name":"testPowertoolsGzipWrongArgumentType","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.utilities.jmespath.JsonFunctionTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"testJsonFunction","parameterTypes":[] }, {"name":"testJsonFunctionChild","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.utilities.model.Product", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setId","parameterTypes":["long"] }, {"name":"setName","parameterTypes":["java.lang.String"] }, {"name":"setPrice","parameterTypes":["double"] }] +} +] diff --git a/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json new file mode 100644 index 000000000..d5bd7e14c --- /dev/null +++ b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json @@ -0,0 +1,85 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.engine.TestEngine\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherDiscoveryListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherSessionListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.PostDiscoveryFilter\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.TestExecutionListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qalb_event.json\\E" + }, { + "pattern":"\\Qamq_event.json\\E" + }, { + "pattern":"\\Qapigw_event.json\\E" + }, { + "pattern":"\\Qapigw_event_no_body.json\\E" + }, { + "pattern":"\\Qapigwv2_event.json\\E" + }, { + "pattern":"\\Qcfcr_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/lambda/thirdparty/org/joda/time/tz/data/Europe/Berlin\\E" + }, { + "pattern":"\\Qcom/amazonaws/lambda/thirdparty/org/joda/time/tz/data/ZoneInfoMap\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/alb_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/amq_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/apigw_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/apigw_event_no_body.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/apigwv2_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/cfcr_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/custom_event_map.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/cwl_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/kafip_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/kafka_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/kasip_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/kf_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/kinesis_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/rabbitmq_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/scheduled_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/sns_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/sqs_event.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/sqs_event_no_body.json\\E" + }, { + "pattern":"\\Qorg/joda/time/tz/data/Europe/Berlin\\E" + }, { + "pattern":"\\Qorg/joda/time/tz/data/ZoneInfoMap\\E" + }, { + "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }]}, + "bundles":[] +} diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 345f14194..59bb596db 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -100,6 +100,103 @@
+ + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-tracing + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --enable-url-protocols=http + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + -H:IncludeResources=version.properties + -H:IncludeResources=unreadable.properties + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + + + + + + + + diff --git a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/jni-config.json b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/jni-config.json new file mode 100644 index 000000000..2c4de0562 --- /dev/null +++ b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/jni-config.json @@ -0,0 +1,26 @@ +[ +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"org.apache.maven.surefire.booter.ForkedBooter", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"sun.instrument.InstrumentationImpl", + "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json new file mode 100644 index 000000000..94a514dee --- /dev/null +++ b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json @@ -0,0 +1,365 @@ +[ +{ + "name":"[Lcom.fasterxml.jackson.databind.deser.Deserializers;" +}, +{ + "name":"[Lcom.fasterxml.jackson.databind.ser.BeanSerializerModifier;" +}, +{ + "name":"[Lcom.fasterxml.jackson.databind.ser.Serializers;" +}, +{ + "name":"[Ljava.lang.StackTraceElement;" +}, +{ + "name":"[Ljava.lang.Throwable;" +}, +{ + "name":"com.amazonaws.services.lambda.runtime.Context", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.entities.Cause", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.xray.entities.Entity", + "queryAllDeclaredMethods":true +}, +{ + "name":"com.amazonaws.xray.entities.EntityImpl", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"getAnnotations","parameterTypes":[] }, {"name":"getAws","parameterTypes":[] }, {"name":"getCause","parameterTypes":[] }, {"name":"getEndTime","parameterTypes":[] }, {"name":"getHttp","parameterTypes":[] }, {"name":"getId","parameterTypes":[] }, {"name":"getMetadata","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getNamespace","parameterTypes":[] }, {"name":"getParentId","parameterTypes":[] }, {"name":"getSql","parameterTypes":[] }, {"name":"getStartTime","parameterTypes":[] }, {"name":"getSubsegments","parameterTypes":[] }, {"name":"getTraceId","parameterTypes":[] }, {"name":"isError","parameterTypes":[] }, {"name":"isFault","parameterTypes":[] }, {"name":"isInProgress","parameterTypes":[] }, {"name":"isThrottle","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.entities.Segment", + "queryAllDeclaredMethods":true +}, +{ + "name":"com.amazonaws.xray.entities.SegmentImpl", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getOrigin","parameterTypes":[] }, {"name":"getResourceArn","parameterTypes":[] }, {"name":"getService","parameterTypes":[] }, {"name":"getUser","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.entities.Subsegment", + "queryAllDeclaredMethods":true +}, +{ + "name":"com.amazonaws.xray.entities.SubsegmentImpl", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getNamespace","parameterTypes":[] }, {"name":"getPrecursorIds","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.strategy.sampling.manifest.SamplingRuleManifest", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setDefaultRule","parameterTypes":["com.amazonaws.xray.strategy.sampling.rule.SamplingRule"] }, {"name":"setRules","parameterTypes":["java.util.List"] }, {"name":"setVersion","parameterTypes":["int"] }] +}, +{ + "name":"com.amazonaws.xray.strategy.sampling.reservoir.Reservoir", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.xray.strategy.sampling.rule.SamplingRule", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setFixedTarget","parameterTypes":["int"] }, {"name":"setRate","parameterTypes":["float"] }] +}, +{ + "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.fasterxml.jackson.databind.ser.std.ToStringSerializer", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"double", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.io.InputStream" +}, +{ + "name":"java.io.OutputStream" +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "fields":[{"name":"handleRequest response"}] +}, +{ + "name":"java.lang.AutoCloseable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Exception", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "fields":[{"name":"handleRequest response"}], + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"getHandleRequest response","parameterTypes":[] }, {"name":"isHandleRequest response","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessEnvironment", + "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.RuntimeException", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.StackTraceElement", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.Thread", + "fields":[{"name":"threadLocalRandomProbe"}], + "methods":[{"name":"getContextClassLoader","parameterTypes":[] }] +}, +{ + "name":"java.lang.Throwable", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"getCause","parameterTypes":[] }, {"name":"getLocalizedMessage","parameterTypes":[] }, {"name":"getMessage","parameterTypes":[] }, {"name":"getStackTrace","parameterTypes":[] }, {"name":"getSuppressed","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.util.AbstractMap", + "fields":[{"name":"handleRequest response"}], + "methods":[{"name":"getHandleRequest response","parameterTypes":[] }, {"name":"isHandleRequest response","parameterTypes":[] }] +}, +{ + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] +}, +{ + "name":"java.util.Map", + "fields":[{"name":"handleRequest response"}] +}, +{ + "name":"java.util.concurrent.ConcurrentHashMap", + "fields":[{"name":"handleRequest response"}], + "methods":[{"name":"getHandleRequest response","parameterTypes":[] }, {"name":"isHandleRequest response","parameterTypes":[] }] +}, +{ + "name":"java.util.concurrent.ConcurrentMap", + "fields":[{"name":"handleRequest response"}] +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.Striped64", + "fields":[{"name":"base"}, {"name":"cellsBusy"}] +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, + +{ + "name":"org.apache.commons.logging.LogFactory" +}, +{ + "name":"org.apache.commons.logging.impl.Jdk14Logger", + "methods":[{"name":"","parameterTypes":["java.lang.String"] }, {"name":"setLogFactory","parameterTypes":["org.apache.commons.logging.LogFactory"] }] +}, +{ + "name":"org.apache.commons.logging.impl.Log4JLogger" +}, +{ + "name":"org.apache.commons.logging.impl.LogFactoryImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.logging.impl.WeakHashtable", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", + "fields":[{"name":"IS_COLD_START"}] +}, +{ + "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabled", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledExplicitlyForResponseAndError", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledForError", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledForResponse", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledForResponseWithCustomMapper", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledForResponseWithCustomMapper$ParentClass", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true +}, +{ + "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledForStream", + "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledForStreamWithNoMetaData", + "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledWithException", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, +{ + "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledWithNoMetaData", + "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] +}, + +{ + "name":"software.amazon.lambda.powertools.tracing.nonhandler.PowerToolNonHandler", + "methods":[{"name":"doSomething","parameterTypes":[] }, {"name":"doSomethingCustomName","parameterTypes":[] }] +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +} +] diff --git a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json new file mode 100644 index 000000000..2ac72d18f --- /dev/null +++ b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json @@ -0,0 +1,31 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/com.fasterxml.jackson.databind.Module\\E" + }, { + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.commons.logging.LogFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qcom/amazonaws/xray/sdk.properties\\E" + }, { + "pattern":"\\Qcom/amazonaws/xray/strategy/sampling/DefaultSamplingRules.json\\E" + }, { + "pattern":"\\Qcommons-logging.properties\\E" + }, { + "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }]}, + "bundles":[] +} diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java index 4aefdec9c..1d108ed5f 100644 --- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java +++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java @@ -18,24 +18,24 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNoException; import static org.assertj.core.api.Assertions.catchThrowable; -import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.openMocks; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.amazonaws.xray.AWSXRay; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; + import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.SetEnvironmentVariable; import org.mockito.Mock; -import org.mockito.MockedStatic; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.amazonaws.xray.AWSXRay; + import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.tracing.handlers.PowerToolDisabled; import software.amazon.lambda.powertools.tracing.handlers.PowerToolDisabledForStream; @@ -50,6 +50,9 @@ import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledWithNoMetaData; import software.amazon.lambda.powertools.tracing.nonhandler.PowerToolNonHandler; + +@SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_RESPONSE", value = "false") +@SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_ERROR", value = "false") class LambdaTracingAspectTest { private RequestHandler requestHandler; private RequestStreamHandler streamHandler; @@ -58,16 +61,6 @@ class LambdaTracingAspectTest { @Mock private Context context; - @BeforeAll - static void beforeAll() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_TRACER_CAPTURE_RESPONSE")).thenReturn(null); - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_TRACER_CAPTURE_ERROR")).thenReturn(null); - mocked.when(() -> SystemWrapper.containsKey("POWERTOOLS_TRACER_CAPTURE_RESPONSE")).thenReturn(false); - mocked.when(() -> SystemWrapper.containsKey("POWERTOOLS_TRACER_CAPTURE_ERROR")).thenReturn(false); - } - } - @BeforeEach void setUp() throws IllegalAccessException { openMocks(this); @@ -289,56 +282,50 @@ void shouldCaptureTracesForStreamWithNoMetadata() throws IOException { } @Test + @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_RESPONSE", value = "false") void shouldNotCaptureTracesIfDisabledViaEnvironmentVariable() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.containsKey("POWERTOOLS_TRACER_CAPTURE_RESPONSE")).thenReturn(true); - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_TRACER_CAPTURE_RESPONSE")).thenReturn("false"); - - requestHandler.handleRequest(new Object(), context); - - assertThat(AWSXRay.getTraceEntity()) - .isNotNull(); - - assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) - .hasSize(1) - .allSatisfy(subsegment -> - { - assertThat(subsegment.getAnnotations()) - .hasSize(2) - .containsEntry("ColdStart", true) - .containsEntry("Service", "lambdaHandler"); - - assertThat(subsegment.getMetadata()) - .isEmpty(); - }); - } + requestHandler.handleRequest(new Object(), context); + + assertThat(AWSXRay.getTraceEntity()) + .isNotNull(); + + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) + .hasSize(1) + .allSatisfy(subsegment -> + { + assertThat(subsegment.getAnnotations()) + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); + + assertThat(subsegment.getMetadata()) + .isEmpty(); + }); } @Test + @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_RESPONSE", value = "false") void shouldCaptureTracesIfExplicitlyEnabledAndEnvironmentVariableIsDisabled() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_TRACER_CAPTURE_RESPONSE")).thenReturn("false"); - requestHandler = new PowerTracerToolEnabledForResponse(); - - requestHandler.handleRequest(new Object(), context); - - assertThat(AWSXRay.getTraceEntity()) - .isNotNull(); - - assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) - .hasSize(1) - .allSatisfy(subsegment -> - { - assertThat(subsegment.getAnnotations()) - .hasSize(2) - .containsEntry("ColdStart", true) - .containsEntry("Service", "lambdaHandler"); - - assertThat(subsegment.getMetadata()) - .hasSize(1) - .containsKey("lambdaHandler"); - }); - } + requestHandler = new PowerTracerToolEnabledForResponse(); + + requestHandler.handleRequest(new Object(), context); + + assertThat(AWSXRay.getTraceEntity()) + .isNotNull(); + + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) + .hasSize(1) + .allSatisfy(subsegment -> + { + assertThat(subsegment.getAnnotations()) + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); + + assertThat(subsegment.getMetadata()) + .hasSize(1) + .containsKey("lambdaHandler"); + }); } @Test @@ -369,95 +356,85 @@ void shouldCaptureTracesForSelfReferencingReturnTypesViaCustomMapper() { } @Test + @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_RESPONSE", value = "false") + @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_ERROR", value = "false") void shouldCaptureTracesIfExplicitlyEnabledBothAndEnvironmentVariableIsDisabled() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.containsKey("POWERTOOLS_TRACER_CAPTURE_RESPONSE")).thenReturn(true); - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_TRACER_CAPTURE_RESPONSE")).thenReturn("false"); - mocked.when(() -> SystemWrapper.containsKey("POWERTOOLS_TRACER_CAPTURE_ERROR")).thenReturn(true); - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_TRACER_CAPTURE_ERROR")).thenReturn("false"); - requestHandler = new PowerTracerToolEnabledExplicitlyForResponseAndError(); - - requestHandler.handleRequest(new Object(), context); - - assertThat(AWSXRay.getTraceEntity()) - .isNotNull(); - - assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) - .hasSize(1) - .allSatisfy(subsegment -> - { - assertThat(subsegment.getAnnotations()) - .hasSize(2) - .containsEntry("ColdStart", true) - .containsEntry("Service", "lambdaHandler"); - - assertThat(subsegment.getMetadata()) - .hasSize(1) - .containsKey("lambdaHandler"); - }); - } + requestHandler = new PowerTracerToolEnabledExplicitlyForResponseAndError(); + + requestHandler.handleRequest(new Object(), context); + + assertThat(AWSXRay.getTraceEntity()) + .isNotNull(); + + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) + .hasSize(1) + .allSatisfy(subsegment -> + { + assertThat(subsegment.getAnnotations()) + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); + + assertThat(subsegment.getMetadata()) + .hasSize(1) + .containsKey("lambdaHandler"); + }); } @Test + @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_ERROR", value = "false") void shouldNotCaptureTracesWithExceptionMetaDataIfDisabledViaEnvironmentVariable() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.containsKey("POWERTOOLS_TRACER_CAPTURE_ERROR")).thenReturn(true); - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_TRACER_CAPTURE_ERROR")).thenReturn("false"); - requestHandler = new PowerTracerToolEnabledWithException(); - - Throwable throwable = catchThrowable(() -> requestHandler.handleRequest(new Object(), context)); - - assertThat(throwable) - .isInstanceOf(RuntimeException.class); - - assertThat(AWSXRay.getTraceEntity()) - .isNotNull(); - - assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) - .hasSize(1) - .allSatisfy(subsegment -> - { - assertThat(subsegment.getAnnotations()) - .hasSize(2) - .containsEntry("ColdStart", true) - .containsEntry("Service", "lambdaHandler"); - - assertThat(subsegment.getMetadata()) - .isEmpty(); - }); - } + requestHandler = new PowerTracerToolEnabledWithException(); + + Throwable throwable = catchThrowable(() -> requestHandler.handleRequest(new Object(), context)); + + assertThat(throwable) + .isInstanceOf(RuntimeException.class); + + assertThat(AWSXRay.getTraceEntity()) + .isNotNull(); + + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) + .hasSize(1) + .allSatisfy(subsegment -> + { + assertThat(subsegment.getAnnotations()) + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); + + assertThat(subsegment.getMetadata()) + .isEmpty(); + }); } @Test + @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_ERROR", value = "false") void shouldCaptureTracesWithExceptionMetaDataEnabledExplicitlyAndEnvironmentVariableDisabled() { - try (MockedStatic mocked = mockStatic(SystemWrapper.class)) { - mocked.when(() -> SystemWrapper.getenv("POWERTOOLS_TRACER_CAPTURE_ERROR")).thenReturn("false"); - - requestHandler = new PowerTracerToolEnabledForError(); - - Throwable exception = catchThrowable(() -> requestHandler.handleRequest(new Object(), context)); - - assertThat(AWSXRay.getTraceEntity()) - .isNotNull(); - - assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) - .hasSize(1) - .allSatisfy(subsegment -> - { - assertThat(subsegment.getAnnotations()) - .hasSize(2) - .containsEntry("ColdStart", true) - .containsEntry("Service", "lambdaHandler"); - - assertThat(subsegment.getMetadata()) - .hasSize(1) - .containsKey("lambdaHandler"); - - assertThat(subsegment.getMetadata().get("lambdaHandler")) - .satisfies(stringObjectMap -> assertThat(stringObjectMap) - .containsEntry("handleRequest error", exception)); - }); - } + requestHandler = new PowerTracerToolEnabledForError(); + + Throwable exception = catchThrowable(() -> requestHandler.handleRequest(new Object(), context)); + + assertThat(AWSXRay.getTraceEntity()) + .isNotNull(); + + assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) + .hasSize(1) + .allSatisfy(subsegment -> + { + assertThat(subsegment.getAnnotations()) + .hasSize(2) + .containsEntry("ColdStart", true) + .containsEntry("Service", "lambdaHandler"); + + assertThat(subsegment.getMetadata()) + .hasSize(1) + .containsKey("lambdaHandler"); + + assertThat(subsegment.getMetadata().get("lambdaHandler")) + .satisfies(stringObjectMap -> assertThat(stringObjectMap) + .containsEntry("handleRequest error", exception)); + }); } private void setupContext() { From 8479a7f584759dd90e1106024631b6767b79bf0e Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 24 Mar 2025 13:04:56 +0100 Subject: [PATCH 212/577] feat(cfn-custom-resource): Add optional 'reason' field for detailed failure reporting (#1810) --- .../CloudFormationResponse.java | 5 ++- .../powertools/cloudformation/Response.java | 39 +++++++++++++++++++ .../CloudFormationResponseTest.java | 23 +++++++++++ .../cloudformation/ResponseTest.java | 23 +++++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java index 2f020aa25..404137802 100644 --- a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java +++ b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java @@ -36,6 +36,7 @@ import software.amazon.awssdk.http.SdkHttpMethod; import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.utils.StringInputStream; +import software.amazon.awssdk.utils.StringUtils; /** * Client for sending responses to AWS CloudFormation custom resources by way of a response URL, which is an Amazon S3 @@ -148,7 +149,9 @@ StringInputStream responseBodyStream(CloudFormationCustomResourceEvent event, ObjectNode node = body.toObjectNode(null); return new StringInputStream(node.toString()); } else { - + if (!StringUtils.isBlank(resp.getReason())) { + reason = resp.getReason(); + } String physicalResourceId = resp.getPhysicalResourceId() != null ? resp.getPhysicalResourceId() : event.getPhysicalResourceId() != null ? event.getPhysicalResourceId() : context.getLogStreamName(); diff --git a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java index 215151d44..8c782d957 100644 --- a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java +++ b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/Response.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; +import software.amazon.awssdk.utils.StringUtils; /** * Models the arbitrary data to be sent to the custom resource in response to a CloudFormation event. This object @@ -30,12 +31,22 @@ public class Response { private final Status status; private final String physicalResourceId; private final boolean noEcho; + private final String reason; private Response(JsonNode jsonNode, Status status, String physicalResourceId, boolean noEcho) { this.jsonNode = jsonNode; this.status = status; this.physicalResourceId = physicalResourceId; this.noEcho = noEcho; + this.reason = null; + } + + private Response(JsonNode jsonNode, Status status, String physicalResourceId, boolean noEcho, String reason) { + this.jsonNode = jsonNode; + this.status = status; + this.physicalResourceId = physicalResourceId; + this.noEcho = noEcho; + this.reason = reason; } /** @@ -115,6 +126,15 @@ public boolean isNoEcho() { return noEcho; } + /** + * The reason for the failure. + * + * @return a potentially null reason + */ + public String getReason() { + return reason; + } + /** * Includes all Response attributes, including its value in JSON format * @@ -127,6 +147,7 @@ public String toString() { attributes.put("Status", status); attributes.put("PhysicalResourceId", physicalResourceId); attributes.put("NoEcho", noEcho); + attributes.put("Reason", reason); return attributes.entrySet().stream() .map(entry -> entry.getKey() + " = " + entry.getValue()) .collect(Collectors.joining(",", "[", "]")); @@ -148,6 +169,7 @@ public static class Builder { private Status status; private String physicalResourceId; private boolean noEcho; + private String reason; private Builder() { } @@ -229,6 +251,20 @@ public Builder noEcho(boolean noEcho) { return this; } + /** + * Reason for the response. + * Reason is optional for Success responses, but required for Failed responses. + * If not provided it will be replaced with cloudwatch log stream name. + * + * @param reason if null, the default reason will be used + * @return a reference to this builder + */ + + public Builder reason(String reason) { + this.reason = reason; + return this; + } + /** * Builds a Response object for the value. * @@ -243,6 +279,9 @@ public Response build() { node = mapper.valueToTree(value); } Status responseStatus = this.status != null ? this.status : Status.SUCCESS; + if (StringUtils.isNotBlank(this.reason)) { + return new Response(node, responseStatus, physicalResourceId, noEcho, reason); + } return new Response(node, responseStatus, physicalResourceId, noEcho); } } diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java index 0701c98fe..9da18790c 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java @@ -324,4 +324,27 @@ void responseBodyStreamFailedResponse() throws Exception { "}"; assertThat(stream.getString()).isEqualTo(expectedJson); } + + @Test + void responseBodyStreamFailedResponseWithReason() throws Exception { + CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); + Context context = mock(Context.class); + CloudFormationResponse cfnResponse = testableCloudFormationResponse(); + String failureReason = "Failed test reason"; + Response failedResponseWithReason = Response.builder(). + status(Response.Status.FAILED).reason(failureReason).build(); + StringInputStream stream = cfnResponse.responseBodyStream(event, context, failedResponseWithReason); + + String expectedJson = "{" + + "\"Status\":\"FAILED\"," + + "\"Reason\":\"" + failureReason + "\"," + + "\"PhysicalResourceId\":null," + + "\"StackId\":null," + + "\"RequestId\":null," + + "\"LogicalResourceId\":null," + + "\"NoEcho\":false," + + "\"Data\":null" + + "}"; + assertThat(stream.getString()).isEqualTo(expectedJson); + } } diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java index e577aecca..3e2930541 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java @@ -33,11 +33,13 @@ void defaultValues() { assertThat(response.getStatus()).isEqualTo(Response.Status.SUCCESS); assertThat(response.getPhysicalResourceId()).isNull(); assertThat(response.isNoEcho()).isFalse(); + assertThat(response.getReason()).isNull(); assertThat(response.toString()).contains("JSON = null"); assertThat(response.toString()).contains("Status = SUCCESS"); assertThat(response.toString()).contains("PhysicalResourceId = null"); assertThat(response.toString()).contains("NoEcho = false"); + assertThat(response.toString()).contains("Reason = null"); } @Test @@ -61,6 +63,27 @@ void explicitNullValues() { assertThat(response.toString()).contains("NoEcho = false"); } + @Test + void explicitReasonWithDefaultValues() { + String reason = "test"; + Response response = Response.builder() + .reason(reason) + .build(); + assertThat(response).isNotNull(); + assertThat(response.getJsonNode()).isNull(); + assertThat(response.getStatus()).isEqualTo(Response.Status.SUCCESS); + assertThat(response.getPhysicalResourceId()).isNull(); + assertThat(response.isNoEcho()).isFalse(); + assertThat(response.getReason()).isNotNull(); + assertThat(response.getReason()).isEqualTo(reason); + + assertThat(response.toString()).contains("JSON = null"); + assertThat(response.toString()).contains("Status = SUCCESS"); + assertThat(response.toString()).contains("PhysicalResourceId = null"); + assertThat(response.toString()).contains("NoEcho = false"); + assertThat(response.toString()).contains("Reason = "+reason); + } + @Test void customNonJsonRelatedValues() { Response response = Response.builder() From 0358d649badbebd40b56d61f9c1f85ed60e4ba04 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 28 Mar 2025 15:49:40 +0100 Subject: [PATCH 213/577] feat(idempotency): Add response hook feature (#1814) * Add responseHook definition to IdempotencyConfig and call from IdempotencyHandler. Update idempotency example with an example use-case modifying API GW headers. * Make debug log message more concise in IdempotencyHandler.java. * Add unit test for idempotency response hook. * Document idempotency response hook feature. * Update examples/powertools-examples-idempotency/src/main/java/helloworld/App.java Co-authored-by: Leandro Damascena --------- Co-authored-by: Leandro Damascena --- docs/utilities/idempotency.md | 60 +++++- .../src/main/java/helloworld/App.java | 42 +++-- .../idempotency/IdempotencyConfig.java | 85 +++++++-- .../internal/IdempotencyHandler.java | 47 +++-- .../internal/IdempotencyAspectTest.java | 174 +++++++++++++----- 5 files changed, 312 insertions(+), 96 deletions(-) diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index 240752a55..a6da0e37e 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -55,7 +55,7 @@ times with the same parameters**. This makes idempotent operations safe to retry software.amazon.lambda - powertools-idempotency-dynamodb + powertools-idempotency-core @@ -584,6 +584,7 @@ IdempotencyConfig.builder() .withUseLocalCache(true) .withLocalCacheMaxItems(432) .withHashFunction("SHA-256") + .withResponseHook((responseData, dataRecord) -> responseData) .build() ``` @@ -591,13 +592,14 @@ These are the available options for further configuration: | Parameter | Default | Description | |---------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------| -| **EventKeyJMESPath** | `""` | JMESPath expression to extract the idempotency key from the event record. See available [built-in functions](serialization) | +| **EventKeyJMESPath** | `""` | JMESPath expression to extract the idempotency key from the event record. See available [built-in functions](serialization) | | **PayloadValidationJMESPath** | `""` | JMESPath expression to validate whether certain parameters have changed in the event | -| **ThrowOnNoIdempotencyKey** | `False` | Throw exception if no idempotency key was found in the request | +| **ThrowOnNoIdempotencyKey** | `false` | Throw exception if no idempotency key was found in the request | | **ExpirationInSeconds** | 3600 | The number of seconds to wait before a record is expired | | **UseLocalCache** | `false` | Whether to locally cache idempotency results (LRU cache) | | **LocalCacheMaxItems** | 256 | Max number of items to store in local cache | | **HashFunction** | `MD5` | Algorithm to use for calculating hashes, as supported by `java.security.MessageDigest` (eg. SHA-1, SHA-256, ...) | +| **ResponseHook** | `null` | Response hook to apply modifications to idempotent responses | These features are detailed below. @@ -855,6 +857,58 @@ You can extend the `BasePersistenceStore` class and implement the abstract metho For example, the `putRecord` method needs to throw an exception if a non-expired record already exists in the data store with a matching key. +### Manipulating the Idempotent Response + +You can set up a response hook in the Idempotency configuration to manipulate the returned data when an operation is idempotent. The hook function will be called with the current de-serialized response `Object` and the Idempotency `DataRecord`. + +The example below shows how to append an HTTP header to an `APIGatewayProxyResponseEvent`. + +=== "Using an Idempotent Response Hook" + + ```java hl_lines="3-20" + Idempotency.config().withConfig( + IdempotencyConfig.builder() + .withResponseHook((responseData, dataRecord) -> { + if (responseData instanceof APIGatewayProxyResponseEvent) { + APIGatewayProxyResponseEvent proxyResponse = + (APIGatewayProxyResponseEvent) responseData; + final Map headers = new HashMap<>(); + headers.putAll(proxyResponse.getHeaders()); + // Append idempotency headers + headers.put("x-idempotency-response", "true"); + headers.put("x-idempotency-expiration", + String.valueOf(dataRecord.getExpiryTimestamp())); + + proxyResponse.setHeaders(headers); + + return proxyResponse; + } + + return responseData; + }) + .build()) + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withTableName(System.getenv("IDEMPOTENCY_TABLE")) + .build()) + .configure(); + ``` + +???+ info "Info: Using custom de-serialization?" + + The response hook is called after de-serialization so the payload you process will be the de-serialized Java object. + +#### Being a good citizen + +When using response hooks to manipulate returned data from idempotent operations, it's important to follow best practices to avoid introducing complexity or issues. Keep these guidelines in mind: + +1. **Response hook works exclusively when operations are idempotent.** The hook will not be called when an operation is not idempotent, or when the idempotent logic fails. + +2. **Catch and Handle Exceptions.** Your response hook code should catch and handle any exceptions that may arise from your logic. Unhandled exceptions will cause the Lambda function to fail unexpectedly. + +3. **Keep Hook Logic Simple** Response hooks should consist of minimal and straightforward logic for manipulating response data. Avoid complex conditional branching and aim for hooks that are easy to reason about. + + ## Compatibility with other utilities ### Validation utility diff --git a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java index 0c4693230..029877c73 100644 --- a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java @@ -45,20 +45,36 @@ public App() { public App(DynamoDbClient client) { Idempotency.config().withConfig( - IdempotencyConfig.builder() - .withEventKeyJMESPath( - "powertools_json(body).address") // will retrieve the address field in the body which is a string transformed to json with `powertools_json` - .build()) + IdempotencyConfig.builder() + .withEventKeyJMESPath("powertools_json(body).address") + .withResponseHook((responseData, dataRecord) -> { + if (responseData instanceof APIGatewayProxyResponseEvent) { + APIGatewayProxyResponseEvent proxyResponse = (APIGatewayProxyResponseEvent) responseData; + final Map headers = new HashMap<>(); + headers.putAll(proxyResponse.getHeaders()); + headers.put("x-idempotency-response", "true"); + headers.put("x-idempotency-expiration", + String.valueOf(dataRecord.getExpiryTimestamp())); + + proxyResponse.setHeaders(headers); + + return proxyResponse; + } + + return responseData; + }) + .build()) .withPersistenceStore( DynamoDBPersistenceStore.builder() .withDynamoDbClient(client) .withTableName(System.getenv("IDEMPOTENCY_TABLE")) - .build() - ).configure(); + .build()) + .configure(); } /** - * This is our Lambda event handler. It accepts HTTP POST requests from API gateway and returns the contents of the given URL. Requests are made idempotent + * This is your Lambda event handler. It accepts HTTP POST requests from API gateway and returns the contents of the + * given URL. Requests are made idempotent * by the idempotency library, and results are cached for the default 1h expiry time. *

* You can test the endpoint like this: @@ -67,8 +83,10 @@ public App(DynamoDbClient client) { * curl -X POST https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/helloidem/ -H "Content-Type: application/json" -d '{"address": "https://checkip.amazonaws.com"}' *

*
    - *
  • First call will execute the handleRequest normally, and store the response in the idempotency table (Look into DynamoDB)
  • - *
  • Second call (and next ones) will retrieve from the cache (if cache is enabled, which is by default) or from the store, the handler won't be called. Until the expiration happens (by default 1 hour).
  • + *
  • First call will execute the handleRequest normally, and store the response in the idempotency table (Look + * into DynamoDB)
  • + *
  • Second call (and next ones) will retrieve from the cache (if cache is enabled, which is by default) or from + * the store, the handler won't be called. Until the expiration happens (by default 1 hour).
  • *
*/ @Idempotent // The magic is here! @@ -101,14 +119,14 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv } } - /** * Helper to retrieve the contents of the given URL and return them as a string. *

* We could also put the @Idempotent annotation here if we only wanted this sub-operation to be idempotent. Putting * it on the handler, however, reduces total execution time and saves us time! * - * @param address The URL to fetch + * @param address + * The URL to fetch * @return The contents of the given URL * @throws IOException */ @@ -118,4 +136,4 @@ private String getPageContents(String address) throws IOException { return br.lines().collect(Collectors.joining(System.lineSeparator())); } } -} \ No newline at end of file +} diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java index 2b22cac51..9d5c66cac 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java @@ -14,10 +14,13 @@ package software.amazon.lambda.powertools.idempotency; +import java.time.Duration; +import java.util.function.BiFunction; + import com.amazonaws.services.lambda.runtime.Context; -import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache; -import java.time.Duration; +import software.amazon.lambda.powertools.idempotency.internal.cache.LRUCache; +import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; /** * Configuration of the idempotency feature. Use the {@link Builder} to create an instance. @@ -30,11 +33,12 @@ public class IdempotencyConfig { private final String payloadValidationJMESPath; private final boolean throwOnNoIdempotencyKey; private final String hashFunction; + private final BiFunction responseHook; private Context lambdaContext; private IdempotencyConfig(String eventKeyJMESPath, String payloadValidationJMESPath, - boolean throwOnNoIdempotencyKey, boolean useLocalCache, int localCacheMaxItems, - long expirationInSeconds, String hashFunction) { + boolean throwOnNoIdempotencyKey, boolean useLocalCache, int localCacheMaxItems, + long expirationInSeconds, String hashFunction, BiFunction responseHook) { this.localCacheMaxItems = localCacheMaxItems; this.useLocalCache = useLocalCache; this.expirationInSeconds = expirationInSeconds; @@ -42,6 +46,7 @@ private IdempotencyConfig(String eventKeyJMESPath, String payloadValidationJMESP this.payloadValidationJMESPath = payloadValidationJMESPath; this.throwOnNoIdempotencyKey = throwOnNoIdempotencyKey; this.hashFunction = hashFunction; + this.responseHook = responseHook; } /** @@ -89,6 +94,10 @@ public void setLambdaContext(Context lambdaContext) { this.lambdaContext = lambdaContext; } + public BiFunction getResponseHook() { + return responseHook; + } + public static class Builder { private int localCacheMaxItems = 256; @@ -98,14 +107,18 @@ public static class Builder { private String payloadValidationJMESPath; private boolean throwOnNoIdempotencyKey = false; private String hashFunction = "MD5"; + private BiFunction responseHook; /** * Initialize and return an instance of {@link IdempotencyConfig}.
* Example:
+ * *

          * IdempotencyConfig.builder().withUseLocalCache().build();
          * 
+ * * This instance must then be passed to the {@link Idempotency.Config}: + * *
          * Idempotency.config().withConfig(config).configure();
          * 
@@ -120,13 +133,15 @@ public IdempotencyConfig build() { useLocalCache, localCacheMaxItems, expirationInSeconds, - hashFunction); + hashFunction, + responseHook); } /** * A JMESPath expression to extract the idempotency key from the event record.
* See https://jmespath.org/ for more details.
- * Common paths are:
    + * Common paths are: + *
      *
    • powertools_json(body) for APIGatewayProxyRequestEvent and APIGatewayV2HTTPEvent
    • *
    • Records[*].powertools_json(body) for SQSEvent
    • *
    • Records[0].Sns.Message | powertools_json(@) for SNSEvent
    • @@ -136,7 +151,8 @@ public IdempotencyConfig build() { *
    • ...
    • *
    * - * @param eventKeyJMESPath path of the key in the Lambda event + * @param eventKeyJMESPath + * path of the key in the Lambda event * @return the instance of the builder (to chain operations) */ public Builder withEventKeyJMESPath(String eventKeyJMESPath) { @@ -147,7 +163,8 @@ public Builder withEventKeyJMESPath(String eventKeyJMESPath) { /** * Set the maximum number of items to store in local cache, by default 256 * - * @param localCacheMaxItems maximum number of items to store in local cache + * @param localCacheMaxItems + * maximum number of items to store in local cache * @return the instance of the builder (to chain operations) */ public Builder withLocalCacheMaxItems(int localCacheMaxItems) { @@ -158,8 +175,9 @@ public Builder withLocalCacheMaxItems(int localCacheMaxItems) { /** * Whether to locally cache idempotency results, by default false * - * @param useLocalCache boolean that indicate if a local cache must be used in addition to the persistence store. - * If set to true, will use the {@link LRUCache} + * @param useLocalCache + * boolean that indicate if a local cache must be used in addition to the persistence store. + * If set to true, will use the {@link LRUCache} * @return the instance of the builder (to chain operations) */ public Builder withUseLocalCache(boolean useLocalCache) { @@ -170,7 +188,8 @@ public Builder withUseLocalCache(boolean useLocalCache) { /** * The number of seconds to wait before a record is expired * - * @param expiration expiration of the record in the store + * @param expiration + * expiration of the record in the store * @return the instance of the builder (to chain operations) */ public Builder withExpiration(Duration expiration) { @@ -182,7 +201,8 @@ public Builder withExpiration(Duration expiration) { * A JMESPath expression to extract the payload to be validated from the event record.
    * See https://jmespath.org/ for more details. * - * @param payloadValidationJMESPath JMES Path of a part of the payload to be used for validation + * @param payloadValidationJMESPath + * JMES Path of a part of the payload to be used for validation * @return the instance of the builder (to chain operations) */ public Builder withPayloadValidationJMESPath(String payloadValidationJMESPath) { @@ -193,8 +213,9 @@ public Builder withPayloadValidationJMESPath(String payloadValidationJMESPath) { /** * Whether to throw an exception if no idempotency key was found in the request, by default false * - * @param throwOnNoIdempotencyKey boolean to indicate if we must throw an Exception when - * idempotency key could not be found in the payload. + * @param throwOnNoIdempotencyKey + * boolean to indicate if we must throw an Exception when idempotency key could not be found in the + * payload. * @return the instance of the builder (to chain operations) */ public Builder withThrowOnNoIdempotencyKey(boolean throwOnNoIdempotencyKey) { @@ -215,15 +236,43 @@ public Builder withThrowOnNoIdempotencyKey() { /** * Function to use for calculating hashes, by default MD5. * - * @param hashFunction Can be any algorithm supported by {@link java.security.MessageDigest}, most commons are
      - *
    • MD5
    • - *
    • SHA-1
    • - *
    • SHA-256
    + * @param hashFunction + * Can be any algorithm supported by {@link java.security.MessageDigest}, most commons are + *
      + *
    • MD5
    • + *
    • SHA-1
    • + *
    • SHA-256
    • + *
    * @return the instance of the builder (to chain operations) */ public Builder withHashFunction(String hashFunction) { this.hashFunction = hashFunction; return this; } + + /** + * Response hook that will be called for each idempotent response. This hook will receive the de-serialized + * response data from the persistence store as first argument and the original DataRecord from the persistence + * store as second argument. + * + * Usage: + * + *
    +         * IdempotencyConfig.builder().withResponseHook((responseData, dataRecord) -> {
    +         *     // do something with the response data, for example:
    +         *     if(responseData instanceof APIGatewayProxyRequestEvent) {
    +         *         ((APIGatewayProxyRequestEvent) responseData).setHeaders(Map.of("x-idempotency-response", "true")
    +         *     }
    +         *     return responseData;
    +         * })
    +         * 
    + * + * @param responseHook + * @return + */ + public Builder withResponseHook(BiFunction responseHook) { + this.responseHook = responseHook; + return this; + } } } diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java index 7982d911a..38196b5d2 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java @@ -14,12 +14,21 @@ package software.amazon.lambda.powertools.idempotency.internal; -import com.amazonaws.services.lambda.runtime.Context; -import com.fasterxml.jackson.databind.JsonNode; +import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.EXPIRED; +import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS; + +import java.time.Instant; +import java.util.OptionalInt; +import java.util.function.BiFunction; + import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.Context; +import com.fasterxml.jackson.databind.JsonNode; + import software.amazon.lambda.powertools.idempotency.Idempotency; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyAlreadyInProgressException; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyInconsistentStateException; @@ -32,14 +41,9 @@ import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; import software.amazon.lambda.powertools.utilities.JsonConfig; -import java.time.Instant; -import java.util.OptionalInt; - -import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.EXPIRED; -import static software.amazon.lambda.powertools.idempotency.persistence.DataRecord.Status.INPROGRESS; - /** - * Internal class that will handle the Idempotency, and use the {@link software.amazon.lambda.powertools.idempotency.persistence.PersistenceStore} + * Internal class that will handle the Idempotency, and use the + * {@link software.amazon.lambda.powertools.idempotency.persistence.PersistenceStore} * to store the result of previous calls. */ public class IdempotencyHandler { @@ -106,7 +110,8 @@ private Object processIdempotency() throws Throwable { /** * Tries to determine the remaining time available for the current lambda invocation. - * Currently, it only works if the idempotent handler decorator is used or using {@link Idempotency#registerLambdaContext(Context)} + * Currently, it only works if the idempotent handler decorator is used or using + * {@link Idempotency#registerLambdaContext(Context)} * * @return the remaining time in milliseconds or empty if the context was not provided/found */ @@ -144,7 +149,8 @@ private DataRecord getIdempotencyRecord() { /** * Take appropriate action based on data_record's status * - * @param record DataRecord + * @param record + * DataRecord * @return Function's response previously used for this idempotency key, if it has successfully executed already. */ private Object handleForStatus(DataRecord record) { @@ -167,10 +173,25 @@ private Object handleForStatus(DataRecord record) { try { LOG.debug("Response for key '{}' retrieved from idempotency store, skipping the function", record.getIdempotencyKey()); + + final BiFunction responseHook = Idempotency.getInstance().getConfig() + .getResponseHook(); + final Object responseData; + if (returnType.equals(String.class)) { - return record.getResponseData(); + // Primitive String data will be returned raw and not de-serialized from JSON. + responseData = record.getResponseData(); + } else { + responseData = JsonConfig.get().getObjectMapper().reader().readValue(record.getResponseData(), + returnType); } - return JsonConfig.get().getObjectMapper().reader().readValue(record.getResponseData(), returnType); + + if (responseHook != null) { + LOG.debug("Applying user-defined response hook to idempotency data before returning."); + return responseHook.apply(responseData, record); + } + + return responseData; } catch (Exception e) { throw new IdempotencyPersistenceLayerException( "Unable to get function response as " + returnType.getSimpleName(), e); diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java index e5f45aef7..a434bcdc0 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java @@ -14,15 +14,32 @@ package software.amazon.lambda.powertools.idempotency.internal; -import com.amazonaws.services.lambda.runtime.Context; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; +import static java.time.temporal.ChronoUnit.SECONDS; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import java.time.Instant; +import java.util.OptionalInt; +import java.util.OptionalLong; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.SetEnvironmentVariable; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; + +import com.amazonaws.services.lambda.runtime.Context; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; + import software.amazon.lambda.powertools.idempotency.Constants; import software.amazon.lambda.powertools.idempotency.Idempotency; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; @@ -43,21 +60,6 @@ import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; import software.amazon.lambda.powertools.utilities.JsonConfig; -import java.time.Instant; -import java.util.OptionalInt; -import java.util.OptionalLong; - -import static java.time.temporal.ChronoUnit.SECONDS; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; - public class IdempotencyAspectTest { @Mock @@ -77,8 +79,8 @@ public void firstCall_shouldPutInStore() { .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder() .withEventKeyJMESPath("id") - .build() - ).configure(); + .build()) + .configure(); IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); @@ -103,6 +105,45 @@ public void firstCall_shouldPutInStore() { assertThat(resultCaptor.getValue()).isEqualTo(basket); } + @Test + public void firstCall_shouldPutInStoreAndNotApplyResponseHook() { + Idempotency.config() + .withPersistenceStore(store) + .withConfig(IdempotencyConfig.builder() + .withEventKeyJMESPath("id") + // This hook will add a second product to the basket. It should not run here. Only for + // idempotent responses. + .withResponseHook((responseData, dataRecord) -> { + final Basket basket = (Basket) responseData; + basket.add(new Product(42, "fake product 2", 12)); + return basket; + }) + .build()) + .configure(); + + IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); + + when(context.getRemainingTimeInMillis()).thenReturn(30000); + + Product p = new Product(42, "fake product", 12); + Basket basket = function.handleRequest(p, context); + assertThat(basket.getProducts()).hasSize(1); // Size should be 1 because response hook should not run + assertThat(function.handlerCalled()).isTrue(); + + ArgumentCaptor nodeCaptor = ArgumentCaptor.forClass(JsonNode.class); + ArgumentCaptor expiryCaptor = ArgumentCaptor.forClass(OptionalInt.class); + verify(store).saveInProgress(nodeCaptor.capture(), any(), expiryCaptor.capture()); + assertThat(nodeCaptor.getValue().get("id").asLong()).isEqualTo(p.getId()); + assertThat(nodeCaptor.getValue().get("name").asText()).isEqualTo(p.getName()); + assertThat(nodeCaptor.getValue().get("price").asDouble()).isEqualTo(p.getPrice()); + + assertThat(expiryCaptor.getValue().orElse(-1)).isEqualTo(30000); + + ArgumentCaptor resultCaptor = ArgumentCaptor.forClass(Basket.class); + verify(store).saveSuccess(any(), resultCaptor.capture(), any()); + assertThat(resultCaptor.getValue()).isEqualTo(basket); + } + @Test public void secondCall_notExpired_shouldGetFromStore() throws JsonProcessingException { // GIVEN @@ -110,20 +151,20 @@ public void secondCall_notExpired_shouldGetFromStore() throws JsonProcessingExce .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder() .withEventKeyJMESPath("id") - .build() - ).configure(); + .build()) + .configure(); doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); Product p = new Product(42, "fake product", 12); Basket b = new Basket(p); - DataRecord record = new DataRecord( + DataRecord dr = new DataRecord( "42", DataRecord.Status.COMPLETED, Instant.now().plus(356, SECONDS).getEpochSecond(), JsonConfig.get().getObjectMapper().writer().writeValueAsString(b), null); - doReturn(record).when(store).getRecord(any(), any()); + doReturn(dr).when(store).getRecord(any(), any()); // WHEN IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); @@ -141,19 +182,19 @@ public void secondCall_notExpired_shouldGetStringFromStore() { .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder() .withEventKeyJMESPath("id") - .build() - ).configure(); + .build()) + .configure(); doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); Product p = new Product(42, "fake product", 12); - DataRecord record = new DataRecord( + DataRecord dr = new DataRecord( "42", DataRecord.Status.COMPLETED, Instant.now().plus(356, SECONDS).getEpochSecond(), p.getName(), null); - doReturn(record).when(store).getRecord(any(), any()); + doReturn(dr).when(store).getRecord(any(), any()); // WHEN IdempotencyStringFunction function = new IdempotencyStringFunction(); @@ -164,6 +205,41 @@ public void secondCall_notExpired_shouldGetStringFromStore() { assertThat(function.handlerCalled()).isFalse(); } + @Test + public void secondCall_notExpired_shouldGetStringFromStoreWithResponseHook() { + // GIVEN + final String RESPONSE_HOOK_SUFFIX = " ResponseHook"; + Idempotency.config() + .withPersistenceStore(store) + .withConfig(IdempotencyConfig.builder() + .withEventKeyJMESPath("id") + .withResponseHook((responseData, dataRecord) -> { + responseData += RESPONSE_HOOK_SUFFIX; + return responseData; + }) + .build()) + .configure(); + + doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); + + Product p = new Product(42, "fake product", 12); + DataRecord dr = new DataRecord( + "42", + DataRecord.Status.COMPLETED, + Instant.now().plus(356, SECONDS).getEpochSecond(), + p.getName(), + null); + doReturn(dr).when(store).getRecord(any(), any()); + + // WHEN + IdempotencyStringFunction function = new IdempotencyStringFunction(); + String name = function.handleRequest(p, context); + + // THEN + assertThat(name).isEqualTo(p.getName() + RESPONSE_HOOK_SUFFIX); + assertThat(function.handlerCalled()).isFalse(); + } + @Test public void secondCall_inProgress_shouldThrowIdempotencyAlreadyInProgressException() throws JsonProcessingException { @@ -172,23 +248,23 @@ public void secondCall_inProgress_shouldThrowIdempotencyAlreadyInProgressExcepti .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder() .withEventKeyJMESPath("id") - .build() - ).configure(); + .build()) + .configure(); doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); Product p = new Product(42, "fake product", 12); Basket b = new Basket(p); - OptionalLong timestampInFuture = - OptionalLong.of(Instant.now().toEpochMilli() + 1000); // timeout not expired (in 1sec) - DataRecord record = new DataRecord( + OptionalLong timestampInFuture = OptionalLong.of(Instant.now().toEpochMilli() + 1000); // timeout not expired + // (in 1sec) + DataRecord dr = new DataRecord( "42", DataRecord.Status.INPROGRESS, Instant.now().plus(356, SECONDS).getEpochSecond(), JsonConfig.get().getObjectMapper().writer().writeValueAsString(b), null, timestampInFuture); - doReturn(record).when(store).getRecord(any(), any()); + doReturn(dr).when(store).getRecord(any(), any()); // THEN IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); @@ -204,23 +280,23 @@ public void secondCall_inProgress_lambdaTimeout_timeoutExpired_shouldThrowIncons .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder() .withEventKeyJMESPath("id") - .build() - ).configure(); + .build()) + .configure(); doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); Product p = new Product(42, "fake product", 12); Basket b = new Basket(p); - OptionalLong timestampInThePast = - OptionalLong.of(Instant.now().toEpochMilli() - 100); // timeout expired 100ms ago - DataRecord record = new DataRecord( + OptionalLong timestampInThePast = OptionalLong.of(Instant.now().toEpochMilli() - 100); // timeout expired 100ms + // ago + DataRecord dr = new DataRecord( "42", DataRecord.Status.INPROGRESS, Instant.now().plus(356, SECONDS).getEpochSecond(), JsonConfig.get().getObjectMapper().writer().writeValueAsString(b), null, timestampInThePast); - doReturn(record).when(store).getRecord(any(), any()); + doReturn(dr).when(store).getRecord(any(), any()); // THEN IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); @@ -235,8 +311,8 @@ public void functionThrowException_shouldDeleteRecord_andThrowFunctionException( .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder() .withEventKeyJMESPath("id") - .build() - ).configure(); + .build()) + .configure(); // WHEN / THEN IdempotencyWithErrorFunction function = new IdempotencyWithErrorFunction(); @@ -256,8 +332,8 @@ public void testIdempotencyDisabled_shouldJustRunTheFunction() { .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder() .withEventKeyJMESPath("id") - .build() - ).configure(); + .build()) + .configure(); // WHEN IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); @@ -340,13 +416,13 @@ public void idempotencyOnSubMethodAnnotated_secondCall_notExpired_shouldGetFromS Product p = new Product(42, "fake product", 12); Basket b = new Basket(p); - DataRecord record = new DataRecord( + DataRecord dr = new DataRecord( "fake", DataRecord.Status.COMPLETED, Instant.now().plus(356, SECONDS).getEpochSecond(), JsonConfig.get().getObjectMapper().writer().writeValueAsString(b), null); - doReturn(record).when(store).getRecord(any(), any()); + doReturn(dr).when(store).getRecord(any(), any()); // WHEN IdempotencyInternalFunction function = new IdempotencyInternalFunction(false); @@ -405,8 +481,7 @@ public void idempotencyOnSubMethodAnnotated_keyJMESPathArray_shouldPutInStoreWit public void idempotencyOnSubMethodNotAnnotated_shouldThrowException() { Idempotency.config() .withPersistenceStore(store) - .withConfig(IdempotencyConfig.builder().build() - ).configure(); + .withConfig(IdempotencyConfig.builder().build()).configure(); // WHEN IdempotencyInternalFunctionInvalid function = new IdempotencyInternalFunctionInvalid(); @@ -421,8 +496,7 @@ public void idempotencyOnSubMethodNotAnnotated_shouldThrowException() { public void idempotencyOnSubMethodVoid_shouldThrowException() { Idempotency.config() .withPersistenceStore(store) - .withConfig(IdempotencyConfig.builder().build() - ).configure(); + .withConfig(IdempotencyConfig.builder().build()).configure(); // WHEN IdempotencyInternalFunctionVoid function = new IdempotencyInternalFunctionVoid(); From 7f604e4c67d838d6f72ad340c5f4af7492f1e624 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 7 Apr 2025 10:48:27 +0200 Subject: [PATCH 214/577] ci: Fix infrastructure deployment and assertions in end-to-end tests. (#1816) * Fix CDK Stack creation in e2e tests. * Fix timezone problem in MetricsE2ET.java. * Fix tracing E2E tests. * Consistently use UTC time in MetricsE2ET. * Fix LargeMessageE2ET. Initialize ExtendedSQSClient with correct region and use Autoclosable. --- .../lambda/powertools/e2e/Function.java | 2 +- powertools-e2e-tests/pom.xml | 6 +- .../lambda/powertools/LargeMessageE2ET.java | 99 ++++++++++--------- .../amazon/lambda/powertools/MetricsE2ET.java | 67 ++++++------- .../amazon/lambda/powertools/TracingE2ET.java | 66 ++++++++----- .../powertools/testutils/Infrastructure.java | 99 ++++++++++--------- .../testutils/metrics/MetricsFetcher.java | 13 ++- 7 files changed, 186 insertions(+), 166 deletions(-) diff --git a/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index 397e34a85..0f140a20d 100644 --- a/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -52,4 +52,4 @@ private String buildMessage(String message, String funcName) { } return String.format("%s (%s)", message, funcName); } -} \ No newline at end of file +} diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 1bf6310f4..03b6fe413 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -30,8 +30,8 @@ 11 11 - 10.3.0 - 2.162.1 + 10.4.2 + 2.186.0 @@ -231,4 +231,4 @@ - \ No newline at end of file + diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java index 548a710b8..d9c3ef749 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java @@ -3,8 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT; -import com.amazon.sqs.javamessaging.AmazonSQSExtendedClient; -import com.amazon.sqs.javamessaging.ExtendedClientConfiguration; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; @@ -14,6 +12,7 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; + import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; @@ -22,6 +21,10 @@ import org.junit.jupiter.api.Timeout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import com.amazon.sqs.javamessaging.AmazonSQSExtendedClient; +import com.amazon.sqs.javamessaging.ExtendedClientConfiguration; + import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.regions.Region; @@ -101,21 +104,20 @@ public void reset() { @Test public void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException, InterruptedException { // given - final ExtendedClientConfiguration extendedClientConfig = - new ExtendedClientConfiguration() - .withPayloadSupportEnabled(s3Client, bucketName); - AmazonSQSExtendedClient client = - new AmazonSQSExtendedClient(SqsClient.builder().httpClient(httpClient).build(), extendedClientConfig); - InputStream inputStream = this.getClass().getResourceAsStream("/large_sqs_message.txt"); - String bigMessage = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - // when - client.sendMessage(SendMessageRequest - .builder() - .queueUrl(queueUrl) - .messageBody(bigMessage) - .build()); - + final ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration() + .withPayloadSupportEnabled(s3Client, bucketName); + try (AmazonSQSExtendedClient client = new AmazonSQSExtendedClient( + SqsClient.builder().region(region).httpClient(httpClient).build(), extendedClientConfig)) { + InputStream inputStream = this.getClass().getResourceAsStream("/large_sqs_message.txt"); + String bigMessage = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + + // when + client.sendMessage(SendMessageRequest + .builder() + .queueUrl(queueUrl) + .messageBody(bigMessage) + .build()); + } Thread.sleep(30000); // wait for function to be executed // then @@ -137,36 +139,37 @@ public void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException, In @Test public void smallSQSMessage_shouldNotReadFromS3() throws IOException, InterruptedException { // given - final ExtendedClientConfiguration extendedClientConfig = - new ExtendedClientConfiguration() - .withPayloadSupportEnabled(s3Client, bucketName); - AmazonSQSExtendedClient client = - new AmazonSQSExtendedClient(SqsClient.builder().httpClient(httpClient).build(), extendedClientConfig); - String message = "Hello World"; - - // when - client.sendMessage(SendMessageRequest - .builder() - .queueUrl(queueUrl) - .messageBody(message) - .build()); - - Thread.sleep(30000); // wait for function to be executed - - // then - QueryRequest request = QueryRequest - .builder() - .tableName(tableName) - .keyConditionExpression("functionName = :func") - .expressionAttributeValues( - Collections.singletonMap(":func", AttributeValue.builder().s(functionName).build())) - .build(); - QueryResponse response = dynamoDbClient.query(request); - List> items = response.items(); - assertThat(items).hasSize(1); - messageId = items.get(0).get("id").s(); - assertThat(Integer.valueOf(items.get(0).get("bodySize").n())).isEqualTo( - message.getBytes(StandardCharsets.UTF_8).length); - assertThat(items.get(0).get("bodyMD5").s()).isEqualTo("b10a8db164e0754105b7a99be72e3fe5"); + final ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration() + .withPayloadSupportEnabled(s3Client, bucketName); + try (AmazonSQSExtendedClient client = new AmazonSQSExtendedClient( + SqsClient.builder().region(region).httpClient(httpClient).build(), + extendedClientConfig)) { + String message = "Hello World"; + + // when + client.sendMessage(SendMessageRequest + .builder() + .queueUrl(queueUrl) + .messageBody(message) + .build()); + + Thread.sleep(30000); // wait for function to be executed + + // then + QueryRequest request = QueryRequest + .builder() + .tableName(tableName) + .keyConditionExpression("functionName = :func") + .expressionAttributeValues( + Collections.singletonMap(":func", AttributeValue.builder().s(functionName).build())) + .build(); + QueryResponse response = dynamoDbClient.query(request); + List> items = response.items(); + assertThat(items).hasSize(1); + messageId = items.get(0).get("id").s(); + assertThat(Integer.valueOf(items.get(0).get("bodySize").n())).isEqualTo( + message.getBytes(StandardCharsets.UTF_8).length); + assertThat(items.get(0).get("bodyMD5").s()).isEqualTo("b10a8db164e0754105b7a99be72e3fe5"); + } } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java index 235255dff..2765e0e70 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java @@ -18,9 +18,8 @@ import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT; import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction; +import java.time.Clock; import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; import java.util.Collections; import java.util.List; @@ -29,10 +28,12 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; + import software.amazon.lambda.powertools.testutils.Infrastructure; import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; import software.amazon.lambda.powertools.testutils.metrics.MetricsFetcher; @@ -51,9 +52,9 @@ public static void setup() { .pathToFunction("metrics") .environmentVariables( Stream.of(new String[][] { - {"POWERTOOLS_METRICS_NAMESPACE", namespace}, - {"POWERTOOLS_SERVICE_NAME", service} - }) + { "POWERTOOLS_METRICS_NAMESPACE", namespace }, + { "POWERTOOLS_SERVICE_NAME", service } + }) .collect(Collectors.toMap(data -> data[0], data -> data[1]))) .build(); Map outputs = infrastructure.deploy(); @@ -71,14 +72,10 @@ public static void tearDown() { public void test_recordMetrics() { // GIVEN - Instant currentTimeTruncatedToMinutes = - LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES).toInstant(ZoneOffset.UTC); + Instant currentTimeTruncatedToMinutes = Instant.now(Clock.systemUTC()).truncatedTo(ChronoUnit.MINUTES); + String event1 = "{ \"metrics\": {\"orders\": 1, \"products\": 4}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"false\"}"; - String event1 = - "{ \"metrics\": {\"orders\": 1, \"products\": 4}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"false\"}"; - - String event2 = - "{ \"metrics\": {\"orders\": 1, \"products\": 8}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"true\"}"; + String event2 = "{ \"metrics\": {\"orders\": 1, \"products\": 8}, \"dimensions\": { \"Environment\": \"test\"}, \"highResolution\": \"true\"}"; // WHEN InvocationResult invocationResult = invokeFunction(functionName, event1); @@ -86,45 +83,43 @@ public void test_recordMetrics() { // THEN MetricsFetcher metricsFetcher = new MetricsFetcher(); - List coldStart = - metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, - "ColdStart", Stream.of(new String[][] { - {"FunctionName", functionName}, - {"Service", service}} - ).collect(Collectors.toMap(data -> data[0], data -> data[1]))); + List coldStart = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, + namespace, + "ColdStart", Stream.of(new String[][] { + { "FunctionName", functionName }, + { "Service", service } }).collect(Collectors.toMap(data -> data[0], data -> data[1]))); assertThat(coldStart.get(0)).isEqualTo(1); - List orderMetrics = - metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, - "orders", Collections.singletonMap("Environment", "test")); + List orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), + 60, namespace, + "orders", Collections.singletonMap("Environment", "test")); assertThat(orderMetrics.get(0)).isEqualTo(2); - List productMetrics = - metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, - "products", Collections.singletonMap("Environment", "test")); + List productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), + invocationResult.getEnd(), 60, namespace, + "products", Collections.singletonMap("Environment", "test")); - // When searching across a 1 minute time period with a period of 60 we find both metrics and the sum is 12 + // When searching across a 1 minute time period with a period of 60 we find both metrics and the sum is 12 assertThat(productMetrics.get(0)).isEqualTo(12); - orderMetrics = - metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, - "orders", Collections.singletonMap("Service", service)); + orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, + namespace, + "orders", Collections.singletonMap("Service", service)); assertThat(orderMetrics.get(0)).isEqualTo(2); - productMetrics = - metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, namespace, - "products", Collections.singletonMap("Service", service)); + productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, + namespace, + "products", Collections.singletonMap("Service", service)); assertThat(productMetrics.get(0)).isEqualTo(12); Instant searchStartTime = currentTimeTruncatedToMinutes.plusSeconds(15); Instant searchEndTime = currentTimeTruncatedToMinutes.plusSeconds(45); - List productMetricDataResult = - metricsFetcher.fetchMetrics(searchStartTime, searchEndTime, 1, namespace, - "products", Collections.singletonMap("Environment", "test")); + List productMetricDataResult = metricsFetcher.fetchMetrics(searchStartTime, searchEndTime, 1, namespace, + "products", Collections.singletonMap("Environment", "test")); -// We are searching across the time period the metric was created but with a period of 1 second. Only the high resolution metric will be available at this point + // We are searching across the time period the metric was created but with a period of 1 second. Only the high + // resolution metric will be available at this point assertThat(productMetricDataResult.get(0)).isEqualTo(8); - } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java index 0827d91ae..d2a5ceed1 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java @@ -18,14 +18,15 @@ import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT; import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction; -import java.util.Collections; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; + import software.amazon.lambda.powertools.testutils.Infrastructure; import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; import software.amazon.lambda.powertools.testutils.tracing.SegmentDocument.SubSegment; @@ -45,7 +46,9 @@ public static void setup() { .testName(TracingE2ET.class.getSimpleName()) .pathToFunction("tracing") .tracing(true) - .environmentVariables(Collections.singletonMap("POWERTOOLS_SERVICE_NAME", service)) + .environmentVariables( + Map.of("POWERTOOLS_SERVICE_NAME", service, + "POWERTOOLS_TRACER_CAPTURE_RESPONSE", "true")) .build(); Map outputs = infrastructure.deploy(); functionName = outputs.get(FUNCTION_NAME_OUTPUT); @@ -61,45 +64,58 @@ public static void tearDown() { @Test public void test_tracing() { // GIVEN - String message = "Hello World"; - String event = String.format("{\"message\":\"%s\"}", message); - String result = String.format("%s (%s)", message, functionName); + final String message = "Hello World"; + final String event = String.format("{\"message\":\"%s\"}", message); + final String result = String.format("%s (%s)", message, functionName); // WHEN - InvocationResult invocationResult = invokeFunction(functionName, event); + final InvocationResult invocationResult = invokeFunction(functionName, event); // THEN - Trace trace = TraceFetcher.builder() + final Trace trace = TraceFetcher.builder() .start(invocationResult.getStart()) .end(invocationResult.getEnd()) .functionName(functionName) .build() .fetchTrace(); - assertThat(trace.getSubsegments()).hasSize(1); - SubSegment handleRequest = trace.getSubsegments().get(0); - assertThat(handleRequest.getName()).isEqualTo("## handleRequest"); - assertThat(handleRequest.getAnnotations()).hasSize(2); - assertThat(handleRequest.getAnnotations().get("ColdStart")).isEqualTo(true); - assertThat(handleRequest.getAnnotations().get("Service")).isEqualTo(service); - assertThat(handleRequest.getMetadata()).hasSize(1); - Map metadata = (Map) handleRequest.getMetadata().get(service); - assertThat(metadata.get("handleRequest response")).isEqualTo(result); - assertThat(handleRequest.getSubsegments()).hasSize(2); - - SubSegment sub = handleRequest.getSubsegments().get(0); + assertThat(trace.getSubsegments()).hasSize(2); + + // We need to filter segments based on name because they are not returned in-order from the X-Ray API + // The Init segment is created by default for Lambda functions in X-Ray + final SubSegment initSegment = trace.getSubsegments().stream() + .filter(subSegment -> subSegment.getName().equals("Init")) + .findFirst().orElse(null); + assertThat(initSegment.getName()).isEqualTo("Init"); + assertThat(initSegment.getAnnotations()).isNull(); + + final SubSegment handleRequestSegment = trace.getSubsegments().stream() + .filter(subSegment -> subSegment.getName().equals("## handleRequest")) + .findFirst().orElse(null); + assertThat(handleRequestSegment.getName()).isEqualTo("## handleRequest"); + assertThat(handleRequestSegment.getAnnotations()).hasSize(2); + assertThat(handleRequestSegment.getAnnotations()).containsEntry("ColdStart", true); + assertThat(handleRequestSegment.getAnnotations()).containsEntry("Service", service); + assertThat(handleRequestSegment.getMetadata()).hasSize(1); + final Map metadata = (Map) handleRequestSegment.getMetadata().get(service); + assertThat(metadata).containsEntry("handleRequest response", result); + assertThat(handleRequestSegment.getSubsegments()).hasSize(2); + + SubSegment sub = handleRequestSegment.getSubsegments().get(0); assertThat(sub.getName()).isIn("## internal_stuff", "## buildMessage"); - sub = handleRequest.getSubsegments().get(1); + sub = handleRequestSegment.getSubsegments().get(1); assertThat(sub.getName()).isIn("## internal_stuff", "## buildMessage"); - SubSegment buildMessage = handleRequest.getSubsegments().stream() - .filter(subSegment -> subSegment.getName().equals("## buildMessage")).findFirst().orElse(null); + SubSegment buildMessage = handleRequestSegment.getSubsegments().stream() + .filter(subSegment -> subSegment.getName().equals("## buildMessage")) + .findFirst().orElse(null); assertThat(buildMessage).isNotNull(); assertThat(buildMessage.getAnnotations()).hasSize(1); - assertThat(buildMessage.getAnnotations().get("message")).isEqualTo(message); + assertThat(buildMessage.getAnnotations()).containsEntry("message", message); assertThat(buildMessage.getMetadata()).hasSize(1); - metadata = (Map) buildMessage.getMetadata().get(service); - assertThat(metadata.get("buildMessage response")).isEqualTo(result); + final Map buildMessageSegmentMetadata = (Map) buildMessage.getMetadata() + .get(service); + assertThat(buildMessageSegmentMetadata).containsEntry("buildMessage response", result); } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java index bce4bbf98..143409989 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java @@ -16,7 +16,6 @@ import static java.util.Collections.singletonList; -import com.fasterxml.jackson.databind.JsonNode; import java.io.File; import java.io.IOException; import java.nio.file.Paths; @@ -27,13 +26,18 @@ import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; + +import com.fasterxml.jackson.databind.JsonNode; + import software.amazon.awscdk.App; import software.amazon.awscdk.BundlingOptions; import software.amazon.awscdk.BundlingOutput; import software.amazon.awscdk.CfnOutput; +import software.amazon.awscdk.DefaultStackSynthesizer; import software.amazon.awscdk.DockerVolume; import software.amazon.awscdk.Duration; import software.amazon.awscdk.RemovalPolicy; @@ -45,7 +49,11 @@ import software.amazon.awscdk.services.appconfig.CfnDeploymentStrategy; import software.amazon.awscdk.services.appconfig.CfnEnvironment; import software.amazon.awscdk.services.appconfig.CfnHostedConfigurationVersion; -import software.amazon.awscdk.services.dynamodb.*; +import software.amazon.awscdk.services.dynamodb.Attribute; +import software.amazon.awscdk.services.dynamodb.AttributeType; +import software.amazon.awscdk.services.dynamodb.BillingMode; +import software.amazon.awscdk.services.dynamodb.StreamViewType; +import software.amazon.awscdk.services.dynamodb.Table; import software.amazon.awscdk.services.iam.PolicyStatement; import software.amazon.awscdk.services.kinesis.Stream; import software.amazon.awscdk.services.kinesis.StreamMode; @@ -89,7 +97,8 @@ * CloudWatch log groups, ... *
    * It uses the Cloud Development Kit (CDK) to define required resources. The CDK stack is then synthesized to retrieve - * the CloudFormation templates and the assets (function jars). Assets are uploaded to S3 (with the SDK `PutObjectRequest`) + * the CloudFormation templates and the assets (function jars). Assets are uploaded to S3 (with the SDK + * `PutObjectRequest`) * and the CloudFormation stack is created (with the SDK `createStack`) */ public class Infrastructure { @@ -174,11 +183,11 @@ public Map deploy() { .onFailure(OnFailure.ROLLBACK) .capabilities(Capability.CAPABILITY_IAM) .build()); - WaiterResponse waiterResponse = - cfn.waiter().waitUntilStackCreateComplete(DescribeStacksRequest.builder().stackName(stackName).build()); + WaiterResponse waiterResponse = cfn.waiter() + .waitUntilStackCreateComplete(DescribeStacksRequest.builder().stackName(stackName).build()); if (waiterResponse.matched().response().isPresent()) { - software.amazon.awssdk.services.cloudformation.model.Stack deployedStack = - waiterResponse.matched().response().get().stacks().get(0); + software.amazon.awssdk.services.cloudformation.model.Stack deployedStack = waiterResponse.matched() + .response().get().stacks().get(0); LOG.info("Stack " + deployedStack.stackName() + " successfully deployed"); Map outputs = new HashMap<>(); deployedStack.outputs().forEach(output -> outputs.put(output.outputKey(), output.outputValue())); @@ -203,7 +212,11 @@ public void destroy() { */ private Stack createStackWithLambda() { boolean createTableForAsyncTests = false; - Stack stack = new Stack(app, stackName); + final Stack e2eStack = Stack.Builder.create(app, stackName) + .synthesizer(DefaultStackSynthesizer.Builder.create() + .generateBootstrapVersionRule(false) // Disable bootstrap version check + .build()) + .build(); List packagingInstruction = Arrays.asList( "/bin/sh", @@ -213,8 +226,7 @@ private Stack createStackWithLambda() { " -Dmaven.test.skip=true " + " -Dmaven.compiler.source=" + runtime.getMvnProperty() + " -Dmaven.compiler.target=" + runtime.getMvnProperty() + - " && cp /asset-input/" + pathToFunction + "/target/function.jar /asset-output/" - ); + " && cp /asset-input/" + pathToFunction + "/target/function.jar /asset-output/"); BundlingOptions.Builder builderOptions = BundlingOptions.builder() .command(packagingInstruction) @@ -224,20 +236,19 @@ private Stack createStackWithLambda() { DockerVolume.builder() .hostPath(System.getProperty("user.home") + "/.m2/") .containerPath("/root/.m2/") - .build() - )) + .build())) .user("root") .outputType(BundlingOutput.ARCHIVED); functionName = stackName + "-function"; - CfnOutput.Builder.create(stack, FUNCTION_NAME_OUTPUT) + CfnOutput.Builder.create(e2eStack, FUNCTION_NAME_OUTPUT) .value(functionName) .build(); LOG.debug("Building Lambda function with command " + packagingInstruction.stream().collect(Collectors.joining(" ", "[", "]"))); Function function = Function.Builder - .create(stack, functionName) + .create(e2eStack, functionName) .code(Code.fromAsset("handlers/", AssetOptions.builder() .bundling(builderOptions .command(packagingInstruction) @@ -253,7 +264,7 @@ private Stack createStackWithLambda() { .build(); LogGroup.Builder - .create(stack, functionName + "-logs") + .create(e2eStack, functionName + "-logs") .logGroupName("/aws/lambda/" + functionName) .retention(RetentionDays.ONE_DAY) .removalPolicy(RemovalPolicy.DESTROY) @@ -261,7 +272,7 @@ private Stack createStackWithLambda() { if (!StringUtils.isEmpty(idempotencyTable)) { Table table = Table.Builder - .create(stack, "IdempotencyTable") + .create(e2eStack, "IdempotencyTable") .billingMode(BillingMode.PAY_PER_REQUEST) .removalPolicy(RemovalPolicy.DESTROY) .partitionKey(Attribute.builder().name("id").type(AttributeType.STRING).build()) @@ -275,7 +286,7 @@ private Stack createStackWithLambda() { if (!StringUtils.isEmpty(queue)) { Queue sqsQueue = Queue.Builder - .create(stack, "SQSQueue") + .create(e2eStack, "SQSQueue") .queueName(queue) .visibilityTimeout(Duration.seconds(timeout * 6)) .retentionPeriod(Duration.seconds(timeout * 6)) @@ -293,14 +304,14 @@ private Stack createStackWithLambda() { .build(); function.addEventSource(sqsEventSource); CfnOutput.Builder - .create(stack, "QueueURL") + .create(e2eStack, "QueueURL") .value(sqsQueue.getQueueUrl()) .build(); createTableForAsyncTests = true; } if (!StringUtils.isEmpty(kinesisStream)) { Stream stream = Stream.Builder - .create(stack, "KinesisStream") + .create(e2eStack, "KinesisStream") .streamMode(StreamMode.ON_DEMAND) .streamName(kinesisStream) .build(); @@ -316,13 +327,13 @@ private Stack createStackWithLambda() { .build(); function.addEventSource(kinesisEventSource); CfnOutput.Builder - .create(stack, "KinesisStreamName") + .create(e2eStack, "KinesisStreamName") .value(stream.getStreamName()) .build(); } if (!StringUtils.isEmpty(ddbStreamsTableName)) { - Table ddbStreamsTable = Table.Builder.create(stack, "DDBStreamsTable") + Table ddbStreamsTable = Table.Builder.create(e2eStack, "DDBStreamsTable") .tableName(ddbStreamsTableName) .stream(StreamViewType.KEYS_ONLY) .removalPolicy(RemovalPolicy.DESTROY) @@ -336,12 +347,12 @@ private Stack createStackWithLambda() { .reportBatchItemFailures(true) .build(); function.addEventSource(ddbEventSource); - CfnOutput.Builder.create(stack, "DdbStreamsTestTable").value(ddbStreamsTable.getTableName()).build(); + CfnOutput.Builder.create(e2eStack, "DdbStreamsTestTable").value(ddbStreamsTable.getTableName()).build(); } if (!StringUtils.isEmpty(largeMessagesBucket)) { Bucket offloadBucket = Bucket.Builder - .create(stack, "LargeMessagesOffloadBucket") + .create(e2eStack, "LargeMessagesOffloadBucket") .removalPolicy(RemovalPolicy.RETAIN) // autodelete does not work without cdk deploy .bucketName(largeMessagesBucket) .build(); @@ -352,19 +363,19 @@ private Stack createStackWithLambda() { if (appConfig != null) { CfnApplication app = CfnApplication.Builder - .create(stack, "AppConfigApp") + .create(e2eStack, "AppConfigApp") .name(appConfig.getApplication()) .build(); CfnEnvironment environment = CfnEnvironment.Builder - .create(stack, "AppConfigEnvironment") + .create(e2eStack, "AppConfigEnvironment") .applicationId(app.getRef()) .name(appConfig.getEnvironment()) .build(); // Create a fast deployment strategy, so we don't have to wait ages CfnDeploymentStrategy fastDeployment = CfnDeploymentStrategy.Builder - .create(stack, "AppConfigDeployment") + .create(e2eStack, "AppConfigDeployment") .name("FastDeploymentStrategy") .deploymentDurationInMinutes(0) .finalBakeTimeInMinutes(0) @@ -377,20 +388,19 @@ private Stack createStackWithLambda() { .create() .actions(singletonList("appconfig:*")) .resources(singletonList("*")) - .build() - ); + .build()); CfnDeployment previousDeployment = null; for (Map.Entry entry : appConfig.getConfigurationValues().entrySet()) { CfnConfigurationProfile configProfile = CfnConfigurationProfile.Builder - .create(stack, "AppConfigProfileFor" + entry.getKey()) + .create(e2eStack, "AppConfigProfileFor" + entry.getKey()) .applicationId(app.getRef()) .locationUri("hosted") .name(entry.getKey()) .build(); CfnHostedConfigurationVersion configVersion = CfnHostedConfigurationVersion.Builder - .create(stack, "AppConfigHostedVersionFor" + entry.getKey()) + .create(e2eStack, "AppConfigHostedVersionFor" + entry.getKey()) .applicationId(app.getRef()) .contentType("text/plain") .configurationProfileId(configProfile.getRef()) @@ -398,7 +408,7 @@ private Stack createStackWithLambda() { .build(); CfnDeployment deployment = CfnDeployment.Builder - .create(stack, "AppConfigDepoymentFor" + entry.getKey()) + .create(e2eStack, "AppConfigDepoymentFor" + entry.getKey()) .applicationId(app.getRef()) .environmentId(environment.getRef()) .deploymentStrategyId(fastDeployment.getRef()) @@ -415,7 +425,7 @@ private Stack createStackWithLambda() { } if (createTableForAsyncTests) { Table table = Table.Builder - .create(stack, "TableForAsyncTests") + .create(e2eStack, "TableForAsyncTests") .billingMode(BillingMode.PAY_PER_REQUEST) .removalPolicy(RemovalPolicy.DESTROY) .partitionKey(Attribute.builder().name("functionName").type(AttributeType.STRING).build()) @@ -424,10 +434,10 @@ private Stack createStackWithLambda() { table.grantReadWriteData(function); function.addEnvironment("TABLE_FOR_ASYNC_TESTS", table.getTableName()); - CfnOutput.Builder.create(stack, "TableNameForAsyncTests").value(table.getTableName()).build(); + CfnOutput.Builder.create(e2eStack, "TableNameForAsyncTests").value(table.getTableName()).build(); } - return stack; + return e2eStack; } /** @@ -444,13 +454,13 @@ private void synthesize() { */ private void uploadAssets() { Map assets = findAssets(); - assets.forEach((objectKey, asset) -> - { + assets.forEach((objectKey, asset) -> { if (!asset.assetPath.endsWith(".jar")) { return; } - ListObjectsV2Response objects = - s3.listObjectsV2(ListObjectsV2Request.builder().bucket(asset.bucketName).build()); + + ListObjectsV2Response objects = s3 + .listObjectsV2(ListObjectsV2Request.builder().bucket(asset.bucketName).build()); if (objects.contents().stream().anyMatch(o -> o.key().equals(objectKey))) { LOG.debug("Asset already exists, skipping"); return; @@ -472,14 +482,13 @@ private Map findAssets() { JsonNode jsonNode = JsonConfig.get().getObjectMapper() .readTree(new File(cfnAssetDirectory, stackName + ".assets.json")); JsonNode files = jsonNode.get("files"); - files.iterator().forEachRemaining(file -> - { + files.iterator().forEachRemaining(file -> { String assetPath = file.get("source").get("path").asText(); String assetPackaging = file.get("source").get("packaging").asText(); - String bucketName = - file.get("destinations").get("current_account-current_region").get("bucketName").asText(); - String objectKey = - file.get("destinations").get("current_account-current_region").get("objectKey").asText(); + String bucketName = file.get("destinations").get("current_account-current_region").get("bucketName") + .asText(); + String objectKey = file.get("destinations").get("current_account-current_region").get("objectKey") + .asText(); Asset asset = new Asset(assetPath, assetPackaging, bucketName.replace("${AWS::AccountId}", account) .replace("${AWS::Region}", region.toString())); assets.put(objectKey, asset); @@ -509,8 +518,6 @@ private Builder() { runtime = mapRuntimeVersion("JAVA_VERSION"); } - - private JavaRuntime mapRuntimeVersion(String environmentVariableName) { String javaVersion = System.getenv(environmentVariableName); // must be set in GitHub actions JavaRuntime ret = null; diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java index 00728f451..186e72d13 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java @@ -54,7 +54,8 @@ public class MetricsFetcher { .build(); /** - * Retrieve the metric values from start to end. Different parameters are required (see {@link CloudWatchClient#getMetricData} for more info). + * Retrieve the metric values from start to end. Different parameters are required (see + * {@link CloudWatchClient#getMetricData} for more info). * Use a retry mechanism as metrics may not be available instantaneously after a function runs. * * @param start @@ -66,14 +67,13 @@ public class MetricsFetcher { * @return */ public List fetchMetrics(Instant start, Instant end, int period, String namespace, String metricName, - Map dimensions) { + Map dimensions) { List dimensionsList = new ArrayList<>(); if (dimensions != null) { dimensions.forEach((key, value) -> dimensionsList.add(Dimension.builder().name(key).value(value).build())); } - Callable> callable = () -> - { + Callable> callable = () -> { LOG.debug("Get Metrics for namespace {}, start {}, end {}, metric {}, dimensions {}", namespace, start, end, metricName, dimensionsList); GetMetricDataResponse metricData = cloudwatch.getMetricData(GetMetricDataRequest.builder() @@ -109,9 +109,8 @@ public List fetchMetrics(Instant start, Instant end, int period, String .build(); CallExecutor> callExecutor = new CallExecutorBuilder>() .config(retryConfig) - .afterFailedTryListener(s -> - { - LOG.warn(s.getLastExceptionThatCausedRetry().getMessage() + ", attempts: " + s.getTotalTries()); + .afterFailedTryListener(s -> { + LOG.warn("{}, attempts: {}", s.getLastExceptionThatCausedRetry().getMessage(), s.getTotalTries()); }) .build(); Status> status = callExecutor.execute(callable); From 98b36b5da4250ed6f88a770a2c753ebe59bda48f Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Tue, 15 Apr 2025 11:10:24 +0200 Subject: [PATCH 215/577] docs: v2 documentation maintenance fixing formatting and dependency issues as well as adding roadmap and llms.txt (#1819) * Update docs requirements using pip-compile. Add privacy plugin. Add llms.txt plugin. Make Idempotency documentation environment variable naming consistent. Fix documentation formatting issue in FAQ.md. * Add roadmap. * Fix outdated AspectJ configuration in documentation pages. * Synchronize Changelog with recent releases. * Add llms.txt to links to navbar. --- .gitignore | 4 +- CHANGELOG.md | 76 ++++++++ README.md | 28 +-- docs/Dockerfile | 6 +- docs/FAQs.md | 66 +++---- docs/core/logging.md | 20 ++- docs/core/metrics.md | 10 +- docs/core/tracing.md | 10 +- docs/index.md | 24 ++- docs/requirements.in | 3 + docs/requirements.txt | 296 +++++++++++++++++++++++++++++++ docs/roadmap.md | 141 +++++++++++++++ docs/utilities/idempotency.md | 24 ++- docs/utilities/large_messages.md | 12 +- docs/utilities/parameters.md | 12 +- docs/utilities/validation.md | 10 +- mkdocs.yml | 32 +++- 17 files changed, 704 insertions(+), 70 deletions(-) create mode 100644 docs/requirements.in create mode 100644 docs/requirements.txt create mode 100644 docs/roadmap.md diff --git a/.gitignore b/.gitignore index 6615ac729..0972d7449 100644 --- a/.gitignore +++ b/.gitignore @@ -28,7 +28,6 @@ native-libs/ classes/ out/ - ###################### # Eclipse ###################### @@ -99,6 +98,7 @@ Desktop.ini docs/node_modules docs/.cache +.cache docs/public /example/.aws-sam/ /example/HelloWorldFunction/.aws-sam/ @@ -110,4 +110,4 @@ example/HelloWorldFunction/build .gradle build/ .terraform* -terraform.tfstate* \ No newline at end of file +terraform.tfstate* diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b9f664fe..20a04c488 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,82 @@ This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) fo ## [Unreleased] +## [1.20.1] - 2025-04-08 + +* docs: fix 2 typos (#1739) by @ntestor +* docs: Correct XML formatting for Maven configuration in Large Messages utility docs (#1796) by @jreijn +* fix: Load version.properties file as resource stream to fix loading when packaged as jar (#1813) by @phipag + +## [1.20.0] - 2025-03-25 + +* feat(cfn-custom-resource): Add optional 'reason' field for detailed failure reporting (#1758) by @moizsh + +## [1.19.0] - 2025-03-07 + +* chore(deps): Update deps for jackson ([#1793](https://github.com/aws-powertools/powertools-lambda-java/pull/1793)) by [@sthulb](https://github.com/sthulb) +* build(deps): bump log4j.version from 2.22.1 to 2.24.3 ([#1777](https://github.com/aws-powertools/powertools-lambda-java/pull/1777)) by [@dependabot](https://github.com/dependabot) +* chore(deps): update JSII to 1.108 ([#1791](https://github.com/aws-powertools/powertools-lambda-java/pull/1791)) by [@sthulb](https://github.com/sthulb) +* build(deps): bump jinja2 from 3.1.5 to 3.1.6 in /docs ([#1789](https://github.com/aws-powertools/powertools-lambda-java/pull/1789)) by [@dependabot](https://github.com/dependabot) +* chore: Update netty version ([#1768](https://github.com/aws-powertools/powertools-lambda-java/pull/1768)) by [@sthulb](https://github.com/sthulb) +* chore: Set versions of transitive dependencies ([#1767](https://github.com/aws-powertools/powertools-lambda-java/pull/1767)) by [@sthulb](https://github.com/sthulb) +* chore: update Jackson in examples ([#1766](https://github.com/aws-powertools/powertools-lambda-java/pull/1766)) by [@sthulb](https://github.com/sthulb) +* build(deps): bump org.apache.maven.plugins:maven-jar-plugin from 3.4.1 to 3.4.2 ([#1731](https://github.com/aws-powertools/powertools-lambda-java/pull/1731)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.xray.recorder.version from 2.15.3 to 2.18.1 ([#1726](https://github.com/aws-powertools/powertools-lambda-java/pull/1726)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.26.29 to 2.27.12 ([#1724](https://github.com/aws-powertools/powertools-lambda-java/pull/1724)) by [@dependabot](https://github.com/dependabot) +* fix: Allow empty responses as well as null response in AppConfig ([#1673](https://github.com/aws-powertools/powertools-lambda-java/pull/1673)) by [@chrisclayson](https://github.com/chrisclayson) +* build(deps): bump aws.sdk.version from 2.27.2 to 2.27.7 ([#1715](https://github.com/aws-powertools/powertools-lambda-java/pull/1715)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.26.29 to 2.27.2 ([#1714](https://github.com/aws-powertools/powertools-lambda-java/pull/1714)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.25.26 to 2.26.29 ([#1713](https://github.com/aws-powertools/powertools-lambda-java/pull/1713)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.26.25 to 2.26.29 ([#1712](https://github.com/aws-powertools/powertools-lambda-java/pull/1712)) by [@dependabot](https://github.com/dependabot) +* chore: deprecate java1.8 al1 ([#1706](https://github.com/aws-powertools/powertools-lambda-java/pull/1706)) by [@jeromevdl](https://github.com/jeromevdl) +* chore: java 1.8 AL1 is deprecated, fix E2E tests ([#1692](https://github.com/aws-powertools/powertools-lambda-java/pull/1692)) by [@jeromevdl](https://github.com/jeromevdl) +* build(deps): bump aws.sdk.version from 2.26.21 to 2.26.25 ([#1703](https://github.com/aws-powertools/powertools-lambda-java/pull/1703)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.26.3 to 2.26.21 ([#1697](https://github.com/aws-powertools/powertools-lambda-java/pull/1697)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump jackson.version from 2.17.0 to 2.17.2 ([#1696](https://github.com/aws-powertools/powertools-lambda-java/pull/1696)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.apache.commons:commons-lang3 from 3.13.0 to 3.14.0 ([#1694](https://github.com/aws-powertools/powertools-lambda-java/pull/1694)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump commons-io:commons-io from 2.15.1 to 2.16.1 ([#1691](https://github.com/aws-powertools/powertools-lambda-java/pull/1691)) by [@dependabot](https://github.com/dependabot) +* docs: improve tracing doc for sdk instrumentation ([#1687](https://github.com/aws-powertools/powertools-lambda-java/pull/1687)) by [@jeromevdl](https://github.com/jeromevdl) +* docs: fix tracing links for xray ([#1686](https://github.com/aws-powertools/powertools-lambda-java/pull/1686)) by [@jeromevdl](https://github.com/jeromevdl) +* build(deps): bump org.apache.maven.plugins:maven-failsafe-plugin from 3.2.5 to 3.3.0 ([#1679](https://github.com/aws-powertools/powertools-lambda-java/pull/1679)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.25.69 to 2.26.3 ([#1658](https://github.com/aws-powertools/powertools-lambda-java/pull/1658)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump com.github.spotbugs:spotbugs-maven-plugin from 4.7.3.6 to 4.8.5.0 ([#1657](https://github.com/aws-powertools/powertools-lambda-java/pull/1657)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.apache.maven.plugins:maven-checkstyle-plugin from 3.3.0 to 3.4.0 ([#1653](https://github.com/aws-powertools/powertools-lambda-java/pull/1653)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.25.50 to 2.25.69 ([#1652](https://github.com/aws-powertools/powertools-lambda-java/pull/1652)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1 ([#1646](https://github.com/aws-powertools/powertools-lambda-java/pull/1646)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.assertj:assertj-core from 3.25.3 to 3.26.0 ([#1644](https://github.com/aws-powertools/powertools-lambda-java/pull/1644)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.xray.recorder.version from 2.15.1 to 2.15.3 ([#1643](https://github.com/aws-powertools/powertools-lambda-java/pull/1643)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.25.35 to 2.25.50 ([#1642](https://github.com/aws-powertools/powertools-lambda-java/pull/1642)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump com.amazonaws:aws-lambda-java-events from 3.11.2 to 3.11.4 ([#1597](https://github.com/aws-powertools/powertools-lambda-java/pull/1597)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.24.10 to 2.25.6 ([#1603](https://github.com/aws-powertools/powertools-lambda-java/pull/1603)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.apache.maven.plugins:maven-surefire-plugin from 3.1.2 to 3.2.5 ([#1596](https://github.com/aws-powertools/powertools-lambda-java/pull/1596)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.codehaus.mojo:exec-maven-plugin from 3.1.0 to 3.2.0 ([#1585](https://github.com/aws-powertools/powertools-lambda-java/pull/1585)) by [@dependabot](https://github.com/dependabot) +* build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib from 2.100.0 to 2.130.0 ([#1586](https://github.com/aws-powertools/powertools-lambda-java/pull/1586)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump io.burt:jmespath-jackson from 0.5.1 to 0.6.0 ([#1587](https://github.com/aws-powertools/powertools-lambda-java/pull/1587)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.21.0 to 2.24.10 ([#1581](https://github.com/aws-powertools/powertools-lambda-java/pull/1581)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump commons-io:commons-io from 2.13.0 to 2.15.1 ([#1584](https://github.com/aws-powertools/powertools-lambda-java/pull/1584)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.xray.recorder.version from 2.14.0 to 2.15.1 ([#1583](https://github.com/aws-powertools/powertools-lambda-java/pull/1583)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.apache.maven.plugins:maven-shade-plugin from 3.5.0 to 3.5.2 ([#1582](https://github.com/aws-powertools/powertools-lambda-java/pull/1582)) by [@dependabot](https://github.com/dependabot) +* build(deps-dev): bump org.yaml:snakeyaml from 2.1 to 2.2 ([#1400](https://github.com/aws-powertools/powertools-lambda-java/pull/1400)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump log4j.version from 2.20.0 to 2.22.1 ([#1547](https://github.com/aws-powertools/powertools-lambda-java/pull/1547)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.apache.maven.plugins:maven-artifact-plugin from 3.4.1 to 3.5.0 ([#1485](https://github.com/aws-powertools/powertools-lambda-java/pull/1485)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump com.amazonaws:aws-lambda-java-serialization from 1.1.2 to 1.1.5 ([#1573](https://github.com/aws-powertools/powertools-lambda-java/pull/1573)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.jacoco:jacoco-maven-plugin from 0.8.10 to 0.8.11 ([#1509](https://github.com/aws-powertools/powertools-lambda-java/pull/1509)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aspectj to 1.9.21 for jdk21 ([#1536](https://github.com/aws-powertools/powertools-lambda-java/pull/1536)) by [@jeromevdl](https://github.com/jeromevdl) +* docs: HelloWorldStreamFunction in examples fails with sam ([#1532](https://github.com/aws-powertools/powertools-lambda-java/pull/1532)) by [@jasoniharris](https://github.com/jasoniharris) +* chore: Testing java21 aspectj pre-release ([#1519](https://github.com/aws-powertools/powertools-lambda-java/pull/1519)) by [@scottgerring](https://github.com/scottgerring) +* fix: LargeMessageIdempotentE2ET Flaky ([#1518](https://github.com/aws-powertools/powertools-lambda-java/pull/1518)) by [@scottgerring](https://github.com/scottgerring) +* build(deps): bump software.amazon.payloadoffloading:payloadoffloading-common from 2.1.3 to 2.2.0 ([#1639](https://github.com/aws-powertools/powertools-lambda-java/pull/1639)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.apache.maven.plugins:maven-jar-plugin from 3.3.0 to 3.4.1 ([#1638](https://github.com/aws-powertools/powertools-lambda-java/pull/1638)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump jackson.version from 2.15.3 to 2.17.0 ([#1637](https://github.com/aws-powertools/powertools-lambda-java/pull/1637)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.25.31 to 2.25.35 ([#1629](https://github.com/aws-powertools/powertools-lambda-java/pull/1629)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.25.16 to 2.25.31 ([#1625](https://github.com/aws-powertools/powertools-lambda-java/pull/1625)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.21.1 to 2.25.26 ([#1622](https://github.com/aws-powertools/powertools-lambda-java/pull/1622)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.apache.maven.plugins:maven-failsafe-plugin from 3.1.2 to 3.2.5 ([#1619](https://github.com/aws-powertools/powertools-lambda-java/pull/1619)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump com.fasterxml.jackson.datatype:jackson-datatype-joda from 2.15.2 to 2.17.0 ([#1616](https://github.com/aws-powertools/powertools-lambda-java/pull/1616)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump aws.sdk.version from 2.25.6 to 2.25.16 ([#1613](https://github.com/aws-powertools/powertools-lambda-java/pull/1613)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.apache.maven.plugins:maven-gpg-plugin from 3.1.0 to 3.2.1 ([#1610](https://github.com/aws-powertools/powertools-lambda-java/pull/1610)) by [@dependabot](https://github.com/dependabot) +* build(deps): bump org.assertj:assertj-core from 3.24.2 to 3.25.3 ([#1609](https://github.com/aws-powertools/powertools-lambda-java/pull/1609)) by [@dependabot](https://github.com/dependabot) + ## [1.18.0] - 2023-11-16 ### Added diff --git a/README.md b/README.md index bf04b54b1..fd72ee148 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Powertools for AWS Lambda (Java) is a developer toolkit to implement Serverless > Also available in [Python](https://github.com/aws-powertools/powertools-lambda-python), [TypeScript](https://github.com/aws-powertools/powertools-lambda-typescript), and [.NET](https://github.com/aws-powertools/powertools-lambda-dotnet). -**[📜Documentation](https://docs.powertools.aws.dev/lambda-java/)** | **[Feature request](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=)** | **[🐛Bug Report](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=bug%2C+triage&template=bug_report.md&title=)** | **[Detailed blog post](https://aws.amazon.com/blogs/opensource/simplifying-serverless-best-practices-with-aws-lambda-powertools-java/)** +**[📜Documentation](https://docs.powertools.aws.dev/lambda-java/preview)** | **[Feature request](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=)** | **[🐛Bug Report](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=bug%2C+triage&template=bug_report.md&title=)** | **[Detailed blog post](https://aws.amazon.com/blogs/opensource/simplifying-serverless-best-practices-with-aws-lambda-powertools-java/)** ## Installation @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your software.amazon.lambda powertools-tracing - 1.18.0 + 2.0.0-SNAPSHOT software.amazon.lambda powertools-logging - 1.18.0 + 2.0.0-SNAPSHOT software.amazon.lambda powertools-metrics - 1.18.0 + 2.0.0-SNAPSHOT ...
    @@ -50,7 +50,7 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 11 11 @@ -70,6 +70,14 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam + + + org.aspectj + aspectjtools + + 1.9.22 + + @@ -108,7 +116,7 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' aspect 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' - implementation "org.aspectj:aspectjrt:1.9.8.RC3" + implementation "org.aspectj:aspectjrt:1.9.22" } sourceCompatibility = 11 @@ -134,10 +142,10 @@ You may need to add the good version of `aspectjrt` to your dependencies based o
    JDK - aspectj dependency matrix -| JDK version | aspectj version | -|-------------|-----------------| -| `11-17` | `1.9.20.1` | -| `21` | `1.9.21` | +| JDK version | aspectj version | +|-------------|------------------------| +| `11-17` | `1.9.20.1` (or higher) | +| `21` | `1.9.21` (or higher) | More info [here](https://github.com/aws-powertools/powertools-lambda-java/pull/1519/files#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R191). diff --git a/docs/Dockerfile b/docs/Dockerfile index 1524933ab..8b5e5e275 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,2 +1,4 @@ -FROM squidfunk/mkdocs-material -RUN pip install mkdocs-git-revision-date-plugin mkdocs-macros-plugin \ No newline at end of file +FROM squidfunk/mkdocs-material@sha256:23b69789b1dd836c53ea25b32f62ef8e1a23366037acd07c90959a219fd1f285 + +COPY requirements.txt /tmp/ +RUN pip install --require-hashes -r /tmp/requirements.txt diff --git a/docs/FAQs.md b/docs/FAQs.md index b42302239..f3fd2514d 100644 --- a/docs/FAQs.md +++ b/docs/FAQs.md @@ -79,7 +79,6 @@ Instead, set a specific classifier of the `aws-crt` to use the one for your targ By specifying the specific target runtime, we prevent other target runtimes from being included in the jar file, resulting in a smaller Lambda package and improved cold start times. ```xml - software.amazon.awssdk @@ -108,39 +107,40 @@ Depending on the Powertools module, there is a different way to configure the SD The following example shows how to use the Lambda Powertools Parameters module while leveraging the AWS CRT Client. - ```java hl_lines="11-16 19-20 22" - import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; - - import com.amazonaws.services.lambda.runtime.Context; - import com.amazonaws.services.lambda.runtime.RequestHandler; - import software.amazon.awssdk.services.ssm.SsmClient; - import software.amazon.awssdk.http.crt.AwsCrtHttpClient; - import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; - - public class RequestHandlerWithParams implements RequestHandler { - - // Get an instance of the SSMProvider with a custom HTTP client (aws crt). - SSMProvider ssmProvider = SSMProvider - .builder() - .withClient( - SsmClient.builder() - .httpClient(AwsCrtHttpClient.builder().build()) - .build() - ) - .build(); - - public String handleRequest(String input, Context context) { - // Retrieve a single param - String value = ssmProvider - .get("/my/secret"); - // We might instead want to retrieve multiple parameters at once, returning a Map of key/value pairs - // .getMultiple("/my/secret/path"); - - // Return the result - return value; - } +```java hl_lines="16 23-24" +import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import software.amazon.awssdk.services.ssm.SsmClient; +import software.amazon.awssdk.http.crt.AwsCrtHttpClient; +import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; + +public class RequestHandlerWithParams implements RequestHandler { + + // Get an instance of the SSMProvider with a custom HTTP client (aws crt). + SSMProvider ssmProvider = SSMProvider + .builder() + .withClient( + SsmClient.builder() + .httpClient(AwsCrtHttpClient.builder().build()) + .build() + ) + .build(); + + public String handleRequest(String input, Context context) { + // Retrieve a single param + String value = ssmProvider + .get("/my/secret"); + // We might instead want to retrieve multiple parameters at once, returning a Map of key/value pairs + // .getMultiple("/my/secret/path"); + + // Return the result + return value; } - ``` +} +``` + The `aws-crt-client` was considered for adoption as the default HTTP client in Lambda Powertools for Java as mentioned in [Move SDK http client to CRT](https://github.com/aws-powertools/powertools-lambda-java/issues/1092), but due to the impact on the developer experience it was decided to stick with the `url-connection-client`. diff --git a/docs/core/logging.md b/docs/core/logging.md index b5dd38ccf..e3b0ebdb3 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -45,7 +45,7 @@ to weave the code and make sure the annotation is processed. dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 11 11 @@ -57,6 +57,14 @@ to weave the code and make sure the annotation is processed. + + + org.aspectj + aspectjtools + + 1.9.22 + + @@ -90,7 +98,7 @@ to weave the code and make sure the annotation is processed. dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 11 11 @@ -102,6 +110,14 @@ to weave the code and make sure the annotation is processed. + + + org.aspectj + aspectjtools + + 1.9.22 + + diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 165c26e1c..6083d935a 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -48,7 +48,7 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 11 11 @@ -60,6 +60,14 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar + + + org.aspectj + aspectjtools + + 1.9.22 + + diff --git a/docs/core/tracing.md b/docs/core/tracing.md index 7ad896462..ea3174fba 100644 --- a/docs/core/tracing.md +++ b/docs/core/tracing.md @@ -37,7 +37,7 @@ a provides functionality to reduce the overhead of performing common tracing tas dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 11 11 @@ -49,6 +49,14 @@ a provides functionality to reduce the overhead of performing common tracing tas + + + org.aspectj + aspectjtools + + 1.9.22 + + diff --git a/docs/index.md b/docs/index.md index 9092adc09..ef30b4197 100644 --- a/docs/index.md +++ b/docs/index.md @@ -106,6 +106,12 @@ Powertools for AWS Lambda (Java) dependencies are available in Maven Central. Yo powertools-metrics {{ powertools.version }} + + + org.aspectj + aspectjrt + 1.9.22 + ... ... @@ -116,7 +122,7 @@ Powertools for AWS Lambda (Java) dependencies are available in Maven Central. Yo dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 11 11 @@ -136,6 +142,14 @@ Powertools for AWS Lambda (Java) dependencies are available in Maven Central. Yo + + + org.aspectj + aspectjtools + + 1.9.22 + + @@ -211,10 +225,10 @@ You may need to add the good version of `aspectjrt` to your dependencies based o Use the following [dependency matrix](https://github.com/eclipse-aspectj/aspectj/blob/master/docs/dist/doc/JavaVersionCompatibility.md) between this library and the JDK: -| JDK version | aspectj version | -|-------------|-----------------| -| `11-17` | `1.9.20.1` | -| `21` | `1.9.21` | +| JDK version | aspectj version | +|-------------|------------------------| +| `11-17` | `1.9.20.1` (or higher) | +| `21` | `1.9.21` (or higher) | ## Environment variables diff --git a/docs/requirements.in b/docs/requirements.in new file mode 100644 index 000000000..e8acc7112 --- /dev/null +++ b/docs/requirements.in @@ -0,0 +1,3 @@ +mkdocs-git-revision-date-plugin==0.3.2 +mkdocs-macros-plugin==1.3.7 +mkdocs-llmstxt==0.2.0 diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 000000000..16529cf3b --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,296 @@ +# +# This file is autogenerated by pip-compile with Python 3.12 +# by the following command: +# +# pip-compile --generate-hashes --output-file=requirements.txt requirements.in +# +beautifulsoup4==4.13.3 \ + --hash=sha256:1bd32405dacc920b42b83ba01644747ed77456a65760e285fbc47633ceddaf8b \ + --hash=sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16 + # via + # markdownify + # mkdocs-llmstxt +click==8.1.8 \ + --hash=sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2 \ + --hash=sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a + # via mkdocs +ghp-import==2.1.0 \ + --hash=sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 \ + --hash=sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343 + # via mkdocs +gitdb==4.0.12 \ + --hash=sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571 \ + --hash=sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf + # via gitpython +gitpython==3.1.44 \ + --hash=sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110 \ + --hash=sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269 + # via mkdocs-git-revision-date-plugin +hjson==3.1.0 \ + --hash=sha256:55af475a27cf83a7969c808399d7bccdec8fb836a07ddbd574587593b9cdcf75 \ + --hash=sha256:65713cdcf13214fb554eb8b4ef803419733f4f5e551047c9b711098ab7186b89 + # via + # mkdocs-macros-plugin + # super-collections +jinja2==3.1.6 \ + --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ + --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 + # via + # mkdocs + # mkdocs-git-revision-date-plugin + # mkdocs-macros-plugin +markdown==3.7 \ + --hash=sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2 \ + --hash=sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803 + # via mkdocs +markdown-it-py==3.0.0 \ + --hash=sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1 \ + --hash=sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb + # via mdformat +markdownify==1.1.0 \ + --hash=sha256:32a5a08e9af02c8a6528942224c91b933b4bd2c7d078f9012943776fc313eeef \ + --hash=sha256:449c0bbbf1401c5112379619524f33b63490a8fa479456d41de9dc9e37560ebd + # via mkdocs-llmstxt +markupsafe==3.0.2 \ + --hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \ + --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \ + --hash=sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0 \ + --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \ + --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \ + --hash=sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13 \ + --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \ + --hash=sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca \ + --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \ + --hash=sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832 \ + --hash=sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0 \ + --hash=sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b \ + --hash=sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579 \ + --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \ + --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \ + --hash=sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff \ + --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \ + --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \ + --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \ + --hash=sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb \ + --hash=sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e \ + --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \ + --hash=sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a \ + --hash=sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d \ + --hash=sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a \ + --hash=sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b \ + --hash=sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8 \ + --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \ + --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \ + --hash=sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144 \ + --hash=sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f \ + --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \ + --hash=sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d \ + --hash=sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93 \ + --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \ + --hash=sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158 \ + --hash=sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84 \ + --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \ + --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \ + --hash=sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171 \ + --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \ + --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \ + --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \ + --hash=sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d \ + --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \ + --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \ + --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \ + --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \ + --hash=sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29 \ + --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \ + --hash=sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798 \ + --hash=sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c \ + --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \ + --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \ + --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \ + --hash=sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a \ + --hash=sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178 \ + --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \ + --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \ + --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \ + --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50 + # via + # jinja2 + # mkdocs +mdformat==0.7.22 \ + --hash=sha256:61122637c9e1d9be1329054f3fa216559f0d1f722b7919b060a8c2a4ae1850e5 \ + --hash=sha256:eef84fa8f233d3162734683c2a8a6222227a229b9206872e6139658d99acb1ea + # via mkdocs-llmstxt +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py +mergedeep==1.3.4 \ + --hash=sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8 \ + --hash=sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 + # via + # mkdocs + # mkdocs-get-deps +mkdocs==1.6.1 \ + --hash=sha256:7b432f01d928c084353ab39c57282f29f92136665bdd6abf7c1ec8d822ef86f2 \ + --hash=sha256:db91759624d1647f3f34aa0c3f327dd2601beae39a366d6e064c03468d35c20e + # via + # mkdocs-git-revision-date-plugin + # mkdocs-macros-plugin +mkdocs-get-deps==0.2.0 \ + --hash=sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c \ + --hash=sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134 + # via mkdocs +mkdocs-git-revision-date-plugin==0.3.2 \ + --hash=sha256:2e67956cb01823dd2418e2833f3623dee8604cdf223bddd005fe36226a56f6ef + # via -r requirements.in +mkdocs-llmstxt==0.2.0 \ + --hash=sha256:104f10b8101167d6baf7761942b4743869be3d8f8a8d909f4e9e0b63307f709e \ + --hash=sha256:907de892e0c8be74002e8b4d553820c2b5bbcf03cc303b95c8bca48fb49c1a29 + # via -r requirements.in +mkdocs-macros-plugin==1.3.7 \ + --hash=sha256:02432033a5b77fb247d6ec7924e72fc4ceec264165b1644ab8d0dc159c22ce59 \ + --hash=sha256:17c7fd1a49b94defcdb502fd453d17a1e730f8836523379d21292eb2be4cb523 + # via -r requirements.in +packaging==24.2 \ + --hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \ + --hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f + # via + # mkdocs + # mkdocs-macros-plugin +pathspec==0.12.1 \ + --hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \ + --hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712 + # via + # mkdocs + # mkdocs-macros-plugin +platformdirs==4.3.7 \ + --hash=sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94 \ + --hash=sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351 + # via mkdocs-get-deps +python-dateutil==2.9.0.post0 \ + --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ + --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 + # via + # ghp-import + # mkdocs-macros-plugin +pyyaml==6.0.2 \ + --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ + --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ + --hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \ + --hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \ + --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \ + --hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \ + --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \ + --hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \ + --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \ + --hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \ + --hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \ + --hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \ + --hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \ + --hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \ + --hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \ + --hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \ + --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \ + --hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \ + --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \ + --hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \ + --hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \ + --hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \ + --hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \ + --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \ + --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \ + --hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \ + --hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \ + --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \ + --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \ + --hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \ + --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \ + --hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \ + --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \ + --hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \ + --hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \ + --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \ + --hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \ + --hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \ + --hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \ + --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \ + --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \ + --hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \ + --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \ + --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \ + --hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \ + --hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \ + --hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \ + --hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \ + --hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \ + --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \ + --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \ + --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \ + --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4 + # via + # mkdocs + # mkdocs-get-deps + # mkdocs-macros-plugin + # pyyaml-env-tag +pyyaml-env-tag==0.1 \ + --hash=sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb \ + --hash=sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069 + # via mkdocs +six==1.17.0 \ + --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ + --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 + # via + # markdownify + # python-dateutil +smmap==5.0.2 \ + --hash=sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5 \ + --hash=sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e + # via gitdb +soupsieve==2.6 \ + --hash=sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb \ + --hash=sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9 + # via beautifulsoup4 +super-collections==0.5.3 \ + --hash=sha256:907d35b25dc4070910e8254bf2f5c928348af1cf8a1f1e8259e06c666e902cff \ + --hash=sha256:94c1ec96c0a0d5e8e7d389ed8cde6882ac246940507c5e6b86e91945c2968d46 + # via mkdocs-macros-plugin +termcolor==3.0.1 \ + --hash=sha256:a6abd5c6e1284cea2934443ba806e70e5ec8fd2449021be55c280f8a3731b611 \ + --hash=sha256:da1ed4ec8a5dc5b2e17476d859febdb3cccb612be1c36e64511a6f2485c10c69 + # via mkdocs-macros-plugin +typing-extensions==4.13.2 \ + --hash=sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c \ + --hash=sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef + # via beautifulsoup4 +watchdog==6.0.0 \ + --hash=sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a \ + --hash=sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2 \ + --hash=sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f \ + --hash=sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c \ + --hash=sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c \ + --hash=sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c \ + --hash=sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0 \ + --hash=sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13 \ + --hash=sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134 \ + --hash=sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa \ + --hash=sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e \ + --hash=sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379 \ + --hash=sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a \ + --hash=sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11 \ + --hash=sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282 \ + --hash=sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b \ + --hash=sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f \ + --hash=sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c \ + --hash=sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112 \ + --hash=sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948 \ + --hash=sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881 \ + --hash=sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860 \ + --hash=sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3 \ + --hash=sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680 \ + --hash=sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26 \ + --hash=sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26 \ + --hash=sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e \ + --hash=sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8 \ + --hash=sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c \ + --hash=sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2 + # via mkdocs diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 000000000..4a86f1437 --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,141 @@ +--- +title: Roadmap +description: Public roadmap for Powertools for AWS Lambda (Java) +--- + +## Overview + +Our public roadmap outlines the high level direction we are working towards. We update this document when our priorities change: security and stability are our top priority. + +### Key areas + +Security and operational excellence take precedence above all else. This means bug fixing, stability, customer's support, and internal compliance may delay one or more key areas below. + +!!! info "We may choose to re-prioritize or defer items based on customer feedback, security, and operational impacts, and business value." + +#### Release Security (p0) + +Our top priority is to establish the processes and infrastructure needed for a fully automated and secure end-to-end release process of new versions to Maven Central. + +- [ ] Implement GitHub workflows and create infrastructure to release to Maven Central +- [x] [Implement end-to-end tests](https://github.com/aws-powertools/powertools-lambda-java/issues/1815){target="\_blank"} +- [x] Implement [OpenSSF Scorecard](https://openssf.org/projects/scorecard/){target="\_blank"} + +#### `v2` Release: Consistency and Ecosystem (p1) + +As part of a new major version `v2` release, we prioritize the Java project's consistency of core utilities (Logging, Metrics, Tracing) with the other runtimes (Python, TypeScript, .NET). Additionally, we will focus on integrating the library with popular technologies and frameworks from the Java and AWS ecosystem. Particularly, we aim at leveraging new techniques to allow customers to reduce Lambda cold-start time. The `v2` release will also drop support for Java 8 moving to Java 11 as the baseline. + +##### Core Utilities + +- [ ] [Review public interfaces and reduce public API surface area](https://github.com/aws-powertools/powertools-lambda-java/issues/1283){target="\_blank"} +- [x] [Release Logging `v2` module](https://github.com/aws-powertools/powertools-lambda-java/issues/965){target="\_blank"} allowing customers to choose the logging framework and adding support for logging deeply nested objects as JSON +- [x] [Support high resolution metrics](https://github.com/aws-powertools/powertools-lambda-java/issues/1041){target="\_blank"} + +##### Ecosystem + +- [x] [Add GraalVM support for core utilities](https://github.com/aws-powertools/powertools-lambda-java/issues/764){target="\_blank"} +- [ ] [Implement priming using CRaC to improve AWS Snapstart support](https://github.com/aws-powertools/powertools-lambda-java/issues/1588){target="\_blank"} +- [ ] [Evaluate integration with popular Java frameworks such as Micronaut, Spring Cloud Function, or Quarkus](https://github.com/aws-powertools/powertools-lambda-java/issues/1701){target="\_blank"} + +##### Other + +- [x] [Validation module integration with HTTP requests](https://github.com/aws-powertools/powertools-lambda-java/issues/1298){target="\_blank"} +- [x] [Support validation module from within the batch module](https://github.com/aws-powertools/powertools-lambda-java/issues/1496){target="\_blank"} +- [x] [Add support for parallel processing in Batch Processing utility](https://github.com/aws-powertools/powertools-lambda-java/issues/1540){target="\_blank"} +- [ ] [Documentation: Review and improve documentation to be consistent with other runtimes](https://github.com/aws-powertools/powertools-lambda-java/issues/1352){target="\_blank"} + +#### Feature Parity (p2) + +If priorities `p0` and `p1` are addressed, we will also focus on feature parity of non-core utilities. This allows customers to achieve better standardization of their development processes across different Powertools runtimes. + +- [ ] [Re-evaluate if there is a need for adding a lightweight customer Powertools event handler](https://github.com/aws-powertools/powertools-lambda-java/issues/1103){target="\_blank"} +- [ ] [Add comprehensive GraalVM support for all utilities](){target="\_blank"} +- [ ] [Add Feature Flags module](https://github.com/aws-powertools/powertools-lambda-java/issues/1086){target="\_blank"} +- [ ] [Add S3 Streaming module](https://github.com/aws-powertools/powertools-lambda-java/issues/1085){target="\_blank"} +- [ ] Add support for Data Masking during JSON serialization + +### Missing something? + +You can help us prioritize by [upvoting existing feature requests](https://github.com/aws-powertools/powertools-lambda-java/issues?q=is%3Aissue%20state%3Aopen%20label%3Aenhancement){target="\_blank"}, +leaving a comment on what use cases it could unblock for you, and by joining our discussions on Discord. + +[![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET){target="\_blank"} + +### Roadmap status definition + +
    +```mermaid +graph LR + Ideas --> Backlog --> Work["Working on it"] --> Merged["Coming soon"] --> Shipped +``` +Visual representation +
    + +Within our [public board](https://github.com/orgs/aws-powertools/projects/4/){target="\_blank"}, you'll see the following values in the `Status` column: + +- **Ideas**. Incoming and existing feature requests that are not being actively considered yet. These will be reviewed + when bandwidth permits. +- **Backlog**. Accepted feature requests or enhancements that we want to work on. +- **Working on it**. Features or enhancements we're currently either researching or implementing it. +- **Coming soon**. Any feature, enhancement, or bug fixes that have been merged and are coming in the next release. +- **Shipped**. Features or enhancements that are now available in the most recent release. + +> Tasks or issues with empty `Status` will be categorized in upcoming review cycles. + +### Process + +
    +```mermaid +graph LR + PFR[Feature request] --> Triage{Need RFC?} + Triage --> |Complex/major change or new utility?| RFC[Ask or write RFC] --> Approval{Approved?} + Triage --> |Minor feature or enhancement?| NoRFC[No RFC required] --> Approval + Approval --> |Yes| Backlog + Approval --> |No | Reject["Inform next steps"] + Backlog --> |Prioritized| Implementation + Backlog --> |Defer| WelcomeContributions["help-wanted label"] +``` +Visual representation +
    + +Our end-to-end mechanism follows four major steps: + +- **Feature Request**. Ideas start with a [feature request](https://github.com/aws-powertools/powertools-lambda-java/issues/new?template=feature_request.md){target="\_blank"} to outline their use case at a high level. For complex use cases, maintainers might ask for/write a + RFC. + - Maintainers review requests based on [project tenets](index.md#tenets){target="\_blank"}, customers reaction (👍), + and use cases. +- **Request-for-comments (RFC)**. Design proposals use + our [RFC template](https://github.com/aws-powertools/powertools-lambda-java/issues/new?q=is%3Aissue+state%3Aopen+label%3Aenhancement&template=rfc.md){target="\_blank"} to describe its implementation, challenges, developer experience, dependencies, and alternative solutions. + - This helps refine the initial idea with community feedback before a decision is made. +- **Decision**. After carefully reviewing and discussing them, maintainers make a final decision on whether to start + implementation, defer or reject it, and update everyone with the next steps. +- **Implementation**. For approved features, maintainers give priority to the original authors for implementation unless + it is a sensitive task that is best handled by maintainers. + +!!! info "See [Maintainers](./processes/maintainers.md){target="\_blank"} document to understand how we triage issues and pull requests, labels and governance." + +### Disclaimer + +The Powertools for AWS Lambda (Java) team values feedback and guidance from its community of users, although final +decisions on inclusion into the project will be made by AWS. + +We determine the high-level direction for our open roadmap based on customer feedback and popularity (👍🏽 and comments), +security and operational impacts, and business value. Where features don’t meet our goals and longer-term strategy, we +will communicate that clearly and openly as quickly as possible with an explanation of why the decision was made. + +### FAQs + +**Q: Why did you build this?** + +A: We know that our customers are making decisions and plans based on what we are developing, and we want to provide our +customers the insights they need to plan. + +**Q: Why are there no dates on your roadmap?** + +A: Because job zero is security and operational stability, we can't provide specific target dates for features. The +roadmap is subject to change at any time, and roadmap issues in this repository do not guarantee a feature will be +launched as proposed. + +**Q: How can I provide feedback or ask for more information?** + +A: For existing features, you can directly comment on issues. For anything else, please open an issue. diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index a6da0e37e..3953949d1 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -47,7 +47,7 @@ times with the same parameters**. This makes idempotent operations safe to retry dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 11 11 @@ -59,6 +59,14 @@ times with the same parameters**. This makes idempotent operations safe to retry + + + org.aspectj + aspectjtools + + 1.9.22 + + @@ -136,7 +144,7 @@ Resources: TableName: !Ref IdempotencyTable Environment: Variables: - IDEMPOTENCY_TABLE: !Ref IdempotencyTable + TABLE_NAME: !Ref IdempotencyTable ``` !!! warning "Warning: Large responses with DynamoDB persistence layer" @@ -429,7 +437,7 @@ To prevent against extended failed retries when a [Lambda function times out](ht Idempotency.config() .withPersistenceStore( DynamoDBPersistenceStore.builder() - .withTableName(System.getenv("IDEMPOTENCY_TABLE")) + .withTableName(System.getenv("TABLE_NAME")) .build()) .configure(); } @@ -889,7 +897,7 @@ The example below shows how to append an HTTP header to an `APIGatewayProxyRespo .build()) .withPersistenceStore( DynamoDBPersistenceStore.builder() - .withTableName(System.getenv("IDEMPOTENCY_TABLE")) + .withTableName(System.getenv("TABLE_NAME")) .build()) .configure(); ``` @@ -1008,7 +1016,7 @@ To unit test your function with DynamoDB Local, you can refer to this guide to [ - idempotency + idempotency eu-central-1 @@ -1112,7 +1120,7 @@ To unit test your function with DynamoDB Local, you can refer to this guide to [ public App(DynamoDbClient ddbClient) { Idempotency.config().withPersistenceStore( DynamoDBPersistenceStore.builder() - .withTableName(System.getenv("IDEMPOTENCY_TABLE_NAME")) + .withTableName(System.getenv("TABLE_NAME")) .withDynamoDbClient(ddbClient) .build() ).configure(); @@ -1149,7 +1157,7 @@ To unit test your function with DynamoDB Local, you can refer to this guide to [ Idempotency.config().withPersistenceStore( DynamoDBPersistenceStore.builder() - .withTableName(System.getenv("IDEMPOTENCY_TABLE_NAME")) + .withTableName(System.getenv("TABLE_NAME")) .withDynamoDbClient(ddbBuilder.build()) .build() ).configure(); @@ -1194,7 +1202,7 @@ To unit test your function with DynamoDB Local, you can refer to this guide to [ ```json hl_lines="3" { "IdempotentFunction": { - "IDEMPOTENCY_TABLE_NAME": "idempotency" + "TABLE_NAME": "idempotency" } } ``` diff --git a/docs/utilities/large_messages.md b/docs/utilities/large_messages.md index 29244de98..38228afe9 100644 --- a/docs/utilities/large_messages.md +++ b/docs/utilities/large_messages.md @@ -114,7 +114,7 @@ of amazon-sns-java-extended-client-lib. dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 11 11 @@ -126,6 +126,14 @@ of amazon-sns-java-extended-client-lib. + + + org.aspectj + aspectjtools + + 1.9.22 + + @@ -344,4 +352,4 @@ If you need to customize this `S3Client`, you can leverage the `LargeMessageConf It gives more control, especially when dealing with partial failures with SQS (see the batch module). - The new module only provides an annotation, an equivalent to the `SqsUtils` class is not available anymore in this new version. -Finally, if you are still using the `powertools-sqs` library for batch processing, consider moving to `powertools-batch` at the same time to remove the dependency on this library completely; it has been deprecated and will be removed in v2. \ No newline at end of file +Finally, if you are still using the `powertools-sqs` library for batch processing, consider moving to `powertools-batch` at the same time to remove the dependency on this library completely; it has been deprecated and will be removed in v2. diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index ab9c04c64..e5fb11800 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -54,7 +54,7 @@ Note that you must provide the concrete parameters module you want to use below dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 11 11 @@ -67,6 +67,14 @@ Note that you must provide the concrete parameters module you want to use below + + + org.aspectj + aspectjtools + + 1.9.22 + + @@ -604,4 +612,4 @@ You can create your own custom parameter store provider by implementing a handfu } } - ``` \ No newline at end of file + ``` diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index 226e10bb6..f73f7e787 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -32,7 +32,7 @@ This utility provides JSON Schema validation for payloads held within events and dev.aspectj aspectj-maven-plugin - 1.13.1 + 1.14 11 11 @@ -44,6 +44,14 @@ This utility provides JSON Schema validation for payloads held within events and + + + org.aspectj + aspectjtools + + 1.9.22 + + diff --git a/mkdocs.yml b/mkdocs.yml index aa7b0e314..cf73d41fc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -6,6 +6,7 @@ nav: - Homepage: index.md - Changelog: changelog.md - FAQs: FAQs.md + - Roadmap: roadmap.md - Core utilities: - core/logging.md - core/tracing.md @@ -20,6 +21,9 @@ nav: - utilities/serialization.md - Processes: - processes/maintainers.md + - Resources: + - "llms.txt": ./llms.txt + - "llms.txt (full version)": ./llms-full.txt theme: name: material @@ -57,8 +61,10 @@ markdown_extensions: alternate_style: true - pymdownx.details - pymdownx.snippets: - base_path: '.' + base_path: "." check_paths: true + - pymdownx.tasklist: + custom_checkbox: true - pymdownx.superfences: custom_fences: - name: mermaid @@ -76,6 +82,30 @@ plugins: - git-revision-date - search - macros + - privacy + - llmstxt: + markdown_description: Powertools for AWS Lambda (Java) is a developer toolkit to implement Serverless best practices and increase developer velocity. It provides a suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. + full_output: llms-full.txt + sections: + Project Overview: + - index.md + - changelog.md + - FAQs.md + - roadmap.md + Core Utilities: + - core/logging.md + - core/metrics.md + - core/tracing.md + Utilities: + - utilities/idempotency.md + - utilities/parameters.md + - utilities/large_messages.md + - utilities/batch.md + - utilities/validation.md + - utilities/custom_resources.md + - utilities/serialization.md + Processes: + - processes/maintainers.md extra_css: - stylesheets/extra.css From 7b18029dff8f86cb9be6be8cbc4567aaacbec418 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Tue, 22 Apr 2025 21:43:29 +0200 Subject: [PATCH 216/577] feat(idempotency): Add support for ReturnValuesOnConditionCheckFailure in Idempotency. (#1821) --- ...IdempotencyItemAlreadyExistsException.java | 15 ++++++ .../internal/IdempotencyHandler.java | 8 +-- .../idempotency/persistence/DataRecord.java | 19 +++++-- .../internal/IdempotencyAspectTest.java | 51 ++++++++++++++++--- .../dynamodb/DynamoDBPersistenceStore.java | 11 +++- .../persistence/dynamodb}/DynamoDBConfig.java | 16 +++--- .../DynamoDBPersistenceStoreTest.java | 26 ++++++---- .../dynamodb}/IdempotencyTest.java | 21 ++++---- .../handlers/IdempotencyFunction.java | 24 +++++---- 9 files changed, 136 insertions(+), 55 deletions(-) rename powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/{software.amazon.lambda.powertools.idempotency.dynamodb => software/amazon/lambda/powertools/idempotency/persistence/dynamodb}/DynamoDBConfig.java (93%) rename powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/{software.amazon.lambda.powertools.idempotency.dynamodb => software/amazon/lambda/powertools/idempotency/persistence/dynamodb}/IdempotencyTest.java (78%) rename powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/{software.amazon.lambda.powertools.idempotency.dynamodb => software/amazon/lambda/powertools/idempotency/persistence/dynamodb}/handlers/IdempotencyFunction.java (85%) diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java index ba7da69bf..aed2e5ae0 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/exceptions/IdempotencyItemAlreadyExistsException.java @@ -14,11 +14,17 @@ package software.amazon.lambda.powertools.idempotency.exceptions; +import java.util.Optional; + +import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; + /** * Exception thrown when trying to store an item which already exists. */ public class IdempotencyItemAlreadyExistsException extends RuntimeException { private static final long serialVersionUID = 9027152772149436500L; + // transient because we don't want to accidentally dump any payloads in logs / stack traces + private transient Optional dr = Optional.empty(); public IdempotencyItemAlreadyExistsException() { super(); @@ -27,4 +33,13 @@ public IdempotencyItemAlreadyExistsException() { public IdempotencyItemAlreadyExistsException(String msg, Throwable e) { super(msg, e); } + + public IdempotencyItemAlreadyExistsException(String msg, Throwable e, DataRecord dr) { + super(msg, e); + this.dr = Optional.ofNullable(dr); + } + + public Optional getDataRecord() { + return dr; + } } diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java index 38196b5d2..0466f244f 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java @@ -94,9 +94,11 @@ private Object processIdempotency() throws Throwable { // already exists. If it succeeds, there's no need to call getRecord. persistenceStore.saveInProgress(data, Instant.now(), getRemainingTimeInMillis()); } catch (IdempotencyItemAlreadyExistsException iaee) { - DataRecord record = getIdempotencyRecord(); - if (record != null) { - return handleForStatus(record); + // If a DataRecord is already present on the Exception we can immediately take that one instead of trying + // to fetch it first. + DataRecord dr = iaee.getDataRecord().orElseGet(this::getIdempotencyRecord); + if (dr != null) { + return handleForStatus(dr); } } catch (IdempotencyKeyException ike) { throw ike; diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DataRecord.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DataRecord.java index 2d56fe349..0621c372b 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DataRecord.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/DataRecord.java @@ -53,7 +53,7 @@ public class DataRecord { private final OptionalLong inProgressExpiryTimestamp; public DataRecord(String idempotencyKey, Status status, long expiryTimestamp, String responseData, - String payloadHash) { + String payloadHash) { this.idempotencyKey = idempotencyKey; this.status = status.toString(); this.expiryTimestamp = expiryTimestamp; @@ -63,7 +63,7 @@ public DataRecord(String idempotencyKey, Status status, long expiryTimestamp, St } public DataRecord(String idempotencyKey, Status status, long expiryTimestamp, String responseData, - String payloadHash, OptionalLong inProgressExpiryTimestamp) { + String payloadHash, OptionalLong inProgressExpiryTimestamp) { this.idempotencyKey = idempotencyKey; this.status = status.toString(); this.expiryTimestamp = expiryTimestamp; @@ -131,13 +131,22 @@ public int hashCode() { return Objects.hash(idempotencyKey, status, expiryTimestamp, responseData, payloadHash); } + @Override + public String toString() { + return "DataRecord{" + + "idempotencyKey='" + idempotencyKey + '\'' + + ", status='" + status + '\'' + + ", expiryTimestamp=" + expiryTimestamp + + ", payloadHash='" + payloadHash + '\'' + + '}'; + } /** * Status of the record: *
      - *
    • INPROGRESS: record initialized when function starts
    • - *
    • COMPLETED: record updated with the result of the function when it ends
    • - *
    • EXPIRED: record expired, idempotency will not happen
    • + *
    • INPROGRESS: record initialized when function starts
    • + *
    • COMPLETED: record updated with the result of the function when it ends
    • + *
    • EXPIRED: record expired, idempotency will not happen
    • *
    */ public enum Status { diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java index a434bcdc0..12113fc9e 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java @@ -20,6 +20,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; @@ -154,7 +155,7 @@ public void secondCall_notExpired_shouldGetFromStore() throws JsonProcessingExce .build()) .configure(); - doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); + doThrow(new IdempotencyItemAlreadyExistsException()).when(store).saveInProgress(any(), any(), any()); Product p = new Product(42, "fake product", 12); Basket b = new Basket(p); @@ -175,6 +176,44 @@ public void secondCall_notExpired_shouldGetFromStore() throws JsonProcessingExce assertThat(function.handlerCalled()).isFalse(); } + @Test + public void secondCall_notExpired_shouldNotGetFromStoreIfPresentOnIdempotencyException() + throws JsonProcessingException { + // GIVEN + Idempotency.config() + .withPersistenceStore(store) + .withConfig(IdempotencyConfig.builder() + .withEventKeyJMESPath("id") + .build()) + .configure(); + + Product p = new Product(42, "fake product", 12); + Basket b = new Basket(p); + DataRecord dr = new DataRecord( + "42", + DataRecord.Status.COMPLETED, + Instant.now().plus(356, SECONDS).getEpochSecond(), + JsonConfig.get().getObjectMapper().writer().writeValueAsString(b), + null); + + // A data record on this exception should take precedence over fetching a record from the store / cache + doThrow(new IdempotencyItemAlreadyExistsException( + "Test message", + new RuntimeException("Test Cause"), + dr)) + .when(store).saveInProgress(any(), any(), any()); + + // WHEN + IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); + Basket basket = function.handleRequest(p, context); + + // THEN + assertThat(basket).isEqualTo(b); + assertThat(function.handlerCalled()).isFalse(); + // Should never call the store because item is already present on IdempotencyItemAlreadyExistsException + verify(store, never()).getRecord(any(), any()); + } + @Test public void secondCall_notExpired_shouldGetStringFromStore() { // GIVEN @@ -185,7 +224,7 @@ public void secondCall_notExpired_shouldGetStringFromStore() { .build()) .configure(); - doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); + doThrow(new IdempotencyItemAlreadyExistsException()).when(store).saveInProgress(any(), any(), any()); Product p = new Product(42, "fake product", 12); DataRecord dr = new DataRecord( @@ -220,7 +259,7 @@ public void secondCall_notExpired_shouldGetStringFromStoreWithResponseHook() { .build()) .configure(); - doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); + doThrow(new IdempotencyItemAlreadyExistsException()).when(store).saveInProgress(any(), any(), any()); Product p = new Product(42, "fake product", 12); DataRecord dr = new DataRecord( @@ -251,7 +290,7 @@ public void secondCall_inProgress_shouldThrowIdempotencyAlreadyInProgressExcepti .build()) .configure(); - doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); + doThrow(new IdempotencyItemAlreadyExistsException()).when(store).saveInProgress(any(), any(), any()); Product p = new Product(42, "fake product", 12); Basket b = new Basket(p); @@ -283,7 +322,7 @@ public void secondCall_inProgress_lambdaTimeout_timeoutExpired_shouldThrowIncons .build()) .configure(); - doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); + doThrow(new IdempotencyItemAlreadyExistsException()).when(store).saveInProgress(any(), any(), any()); Product p = new Product(42, "fake product", 12); Basket b = new Basket(p); @@ -412,7 +451,7 @@ public void idempotencyOnSubMethodAnnotated_secondCall_notExpired_shouldGetFromS .withPersistenceStore(store) .configure(); - doThrow(IdempotencyItemAlreadyExistsException.class).when(store).saveInProgress(any(), any(), any()); + doThrow(new IdempotencyItemAlreadyExistsException()).when(store).saveInProgress(any(), any(), any()); Product p = new Product(42, "fake product", 12); Basket b = new Basket(p); diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java index 0e20e396f..9c96541f6 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java @@ -189,10 +189,17 @@ public void putRecord(DataRecord record, Instant now) throws IdempotencyItemAlre "attribute_not_exists(#id) OR #expiry < :now OR (attribute_exists(#in_progress_expiry) AND #in_progress_expiry < :now_milliseconds AND #status = :inprogress)") .expressionAttributeNames(expressionAttributeNames) .expressionAttributeValues(expressionAttributeValues) - .build() - ); + .returnValuesOnConditionCheckFailure("ALL_OLD") + .build()); } catch (ConditionalCheckFailedException e) { LOG.debug("Failed to put record for already existing idempotency key: {}", record.getIdempotencyKey()); + if (e.hasItem()) { + DataRecord existingRecord = itemToRecord(e.item()); + throw new IdempotencyItemAlreadyExistsException( + "Failed to put record for already existing idempotency key: " + record.getIdempotencyKey() + + ". Existing record: " + existingRecord, + e, existingRecord); + } throw new IdempotencyItemAlreadyExistsException( "Failed to put record for already existing idempotency key: " + record.getIdempotencyKey(), e); } diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/DynamoDBConfig.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java similarity index 93% rename from powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/DynamoDBConfig.java rename to powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java index 30b4976d7..289b0f1cd 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/DynamoDBConfig.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java @@ -12,15 +12,18 @@ * */ -package software.amazon.lambda.powertools.idempotency.dynamodb; +package software.amazon.lambda.powertools.idempotency.persistence.dynamodb; -import com.amazonaws.services.dynamodbv2.local.main.ServerRunner; -import com.amazonaws.services.dynamodbv2.local.server.DynamoDBProxyServer; import java.io.IOException; import java.net.ServerSocket; import java.net.URI; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; + +import com.amazonaws.services.dynamodbv2.local.main.ServerRunner; +import com.amazonaws.services.dynamodbv2.local.server.DynamoDBProxyServer; + import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; @@ -66,13 +69,12 @@ public static void setupDynamo() { .tableName(TABLE_NAME) .keySchema(KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("id").build()) .attributeDefinitions( - AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S).build() - ) + AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S).build()) .billingMode(BillingMode.PAY_PER_REQUEST) .build()); - DescribeTableResponse response = - client.describeTable(DescribeTableRequest.builder().tableName(TABLE_NAME).build()); + DescribeTableResponse response = client + .describeTable(DescribeTableRequest.builder().tableName(TABLE_NAME).build()); if (response == null) { throw new RuntimeException("Table was not created within expected time"); } diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java index cc682a81f..56b32c4f9 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java @@ -32,7 +32,7 @@ import software.amazon.awssdk.services.dynamodb.model.ScanRequest; import software.amazon.lambda.powertools.idempotency.Constants; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; -import software.amazon.lambda.powertools.idempotency.dynamodb.DynamoDBConfig; + import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; @@ -155,13 +155,14 @@ public void putRecord_shouldThrowIdempotencyItemAlreadyExistsException_IfRecordA DataRecord.Status.INPROGRESS, expiry2, null, - null - ), now) - ).isInstanceOf(IdempotencyItemAlreadyExistsException.class); + null), + now)).isInstanceOf(IdempotencyItemAlreadyExistsException.class) + // DataRecord should be present due to returnValuesOnConditionCheckFailure("ALL_OLD") + .matches(e -> ((IdempotencyItemAlreadyExistsException) e).getDataRecord().isPresent()); // THEN: item was not updated, retrieve the initial one - Map itemInDb = - client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); + Map itemInDb = client + .getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); assertThat(itemInDb).isNotNull(); assertThat(itemInDb.get("status").s()).isEqualTo("COMPLETED"); assertThat(itemInDb.get("expiration").n()).isEqualTo(String.valueOf(expiry)); @@ -190,13 +191,16 @@ public void putRecord_shouldBlockUpdate_IfRecordAlreadyExistAndProgressNotExpire DataRecord.Status.INPROGRESS, expiry2, "Fake Data 2", - null - ), now)) - .isInstanceOf(IdempotencyItemAlreadyExistsException.class); + null), + now)) + .isInstanceOf(IdempotencyItemAlreadyExistsException.class) + // DataRecord should be present due to returnValuesOnConditionCheckFailure("ALL_OLD") + .matches(e -> ((IdempotencyItemAlreadyExistsException) e).getDataRecord().isPresent()); + ; // THEN: item was not updated, retrieve the initial one - Map itemInDb = - client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); + Map itemInDb = client + .getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); assertThat(itemInDb).isNotNull(); assertThat(itemInDb.get("status").s()).isEqualTo("INPROGRESS"); assertThat(itemInDb.get("expiration").n()).isEqualTo(String.valueOf(expiry)); diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/IdempotencyTest.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java similarity index 78% rename from powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/IdempotencyTest.java rename to powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java index be915b610..7b43542c8 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/IdempotencyTest.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java @@ -12,20 +12,21 @@ * */ -package software.amazon.lambda.powertools.idempotency.dynamodb; - +package software.amazon.lambda.powertools.idempotency.persistence.dynamodb; import static org.assertj.core.api.Assertions.assertThat; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import com.amazonaws.services.lambda.runtime.tests.EventLoader; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import com.amazonaws.services.lambda.runtime.tests.EventLoader; + import software.amazon.awssdk.services.dynamodb.model.ScanRequest; -import software.amazon.lambda.powertools.idempotency.dynamodb.handlers.IdempotencyFunction; +import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.handlers.IdempotencyFunction; public class IdempotencyTest extends DynamoDBConfig { @@ -41,14 +42,14 @@ void setUp() { public void endToEndTest() { IdempotencyFunction function = new IdempotencyFunction(client); - APIGatewayProxyResponseEvent response = - function.handleRequest(EventLoader.loadApiGatewayRestEvent("apigw_event2.json"), context); + APIGatewayProxyResponseEvent response = function + .handleRequest(EventLoader.loadApiGatewayRestEvent("apigw_event2.json"), context); assertThat(function.handlerExecuted).isTrue(); function.handlerExecuted = false; - APIGatewayProxyResponseEvent response2 = - function.handleRequest(EventLoader.loadApiGatewayRestEvent("apigw_event2.json"), context); + APIGatewayProxyResponseEvent response2 = function + .handleRequest(EventLoader.loadApiGatewayRestEvent("apigw_event2.json"), context); assertThat(function.handlerExecuted).isFalse(); assertThat(response).isEqualTo(response2); diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/handlers/IdempotencyFunction.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/handlers/IdempotencyFunction.java similarity index 85% rename from powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/handlers/IdempotencyFunction.java rename to powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/handlers/IdempotencyFunction.java index 227eea39e..d816af801 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software.amazon.lambda.powertools.idempotency.dynamodb/handlers/IdempotencyFunction.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/handlers/IdempotencyFunction.java @@ -12,14 +12,16 @@ * */ -package software.amazon.lambda.powertools.idempotency.dynamodb.handlers; +package software.amazon.lambda.powertools.idempotency.persistence.dynamodb.handlers; + +import java.util.HashMap; +import java.util.Map; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; -import java.util.HashMap; -import java.util.Map; + import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.lambda.powertools.idempotency.Idempotency; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; @@ -32,15 +34,15 @@ public class IdempotencyFunction implements RequestHandler Date: Thu, 24 Apr 2025 17:46:16 +0200 Subject: [PATCH 217/577] fix(logging): Prevent accidental overwriting of reserved keys via structured arguments * Ignore logging of reserved keys when passed as StructuredArgument. * Add error to reserved log keys. * Update docs with a warning about logging of reserved keys when using structured arguments. * Update docs with warning in MDC section as well. * Update product name in documentation. * Make StructuredArgument implementations package private. They should only be instantiated by factory StructuredArguments. * Make StructuredArgument interface public and remove package private dependency in LambdaLoggingAspectTest. * Move reserved key logic from logging implementation to StructuredArguments. * Remove .keys() method again from StructuredArgument interface. It is no longer needed now. * Update documentation warnings regarding logging of reserved keys. --- docs/core/logging.md | 9 +++ .../json/resolver/PowertoolsResolver.java | 29 ++++---- .../PowertoolsResolverArgumentsTest.java | 25 ++++++- .../internal/handler/PowertoolsArguments.java | 34 +++++++-- .../powertools/logging/logback/JsonUtils.java | 3 +- .../internal/LambdaJsonEncoderTest.java | 16 ++++ .../internal/handler/PowertoolsArguments.java | 34 +++++++-- .../logging/argument/ArrayArgument.java | 4 +- .../logging/argument/JsonArgument.java | 4 +- .../logging/argument/KeyValueArgument.java | 3 +- .../logging/argument/MapArgument.java | 12 ++- .../logging/argument/StructuredArgument.java | 8 +- .../logging/argument/StructuredArguments.java | 74 +++++++++++++++++-- .../argument/StructuredArgumentsTest.java | 64 ++++++++++++++-- .../internal/LambdaLoggingAspectTest.java | 36 ++++----- 15 files changed, 286 insertions(+), 69 deletions(-) diff --git a/docs/core/logging.md b/docs/core/logging.md index e3b0ebdb3..1160f62ff 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -354,6 +354,9 @@ Your logs will always include the following keys in your structured logging: | **xray_trace_id** | String | "1-5759e988-bd862e3fe1be46a994272793" | X-Ray Trace ID when [Tracing is enabled](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html){target="_blank"} | | **error** | Map | `{ "name": "InvalidAmountException", "message": "Amount must be superior to 0", "stack": "at..." }` | Eventual exception (e.g. when doing `logger.error("Error", new InvalidAmountException("Amount must be superior to 0"));`) | +???+ note + If you emit a log message with a key that matches one of the [standard structured keys](#standard-structured-keys) or one of the [additional structured keys](#additional-structured-keys), the Logger will log a warning message and ignore the key. + ## Additional structured keys ### Logging Lambda context information @@ -640,6 +643,9 @@ To append additional keys in your logs, you can use the `StructuredArguments` cl } ``` +???+ warning "Do not use reserved keys in `StructuredArguments`" + If the key name of your structured argument matches any of the [standard structured keys](#standard-structured-keys) or any of the [additional structured keys](#additional-structured-keys), the Logger will log a warning message and ignore the key. This is to protect you from accidentally overwriting reserved keys such as the log level or Lambda context information. + **Using MDC** Mapped Diagnostic Context (MDC) is essentially a Key-Value store. It is supported by the [SLF4J API](https://www.slf4j.org/manual.html#mdc){target="_blank"}, @@ -650,6 +656,9 @@ Mapped Diagnostic Context (MDC) is essentially a Key-Value store. It is supporte ???+ warning "Custom keys stored in the MDC are persisted across warm invocations" Always set additional keys as part of your handler method to ensure they have the latest value, or explicitly clear them with [`clearState=true`](#clearing-state). +???+ warning "Do not add reserved keys to MDC" + Avoid adding any of the keys listed in [standard structured keys](#standard-structured-keys) and [additional structured keys](#additional-structured-keys) to your MDC. This may cause unindented behavior and will overwrite the context set by the Logger. Unlike with `StructuredArguments`, the Logger will **not** ignore reserved keys set via MDC. + ### Removing additional keys diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java index c98da7833..8ada50f49 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java +++ b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java @@ -191,8 +191,8 @@ public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { Object[] arguments = logEvent.getMessage().getParameters(); if (arguments != null) { stream(arguments).filter(StructuredArgument.class::isInstance).forEach(argument -> { - serializer.writeRaw(','); try { + serializer.writeRaw(','); ((StructuredArgument) argument).writeTo(serializer); } catch (IOException e) { System.err.printf("Failed to encode log event, error: %s.%n", e.getMessage()); @@ -204,19 +204,20 @@ public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { private final EventResolver internalResolver; - private static final Map eventResolverMap = Collections.unmodifiableMap(Stream.of(new Object[][] { - { SERVICE.getName(), SERVICE_RESOLVER }, - { FUNCTION_NAME.getName(), FUNCTION_NAME_RESOLVER }, - { FUNCTION_VERSION.getName(), FUNCTION_VERSION_RESOLVER }, - { FUNCTION_ARN.getName(), FUNCTION_ARN_RESOLVER }, - { FUNCTION_MEMORY_SIZE.getName(), FUNCTION_MEMORY_RESOLVER }, - { FUNCTION_REQUEST_ID.getName(), FUNCTION_REQ_RESOLVER }, - { FUNCTION_COLD_START.getName(), COLD_START_RESOLVER }, - { FUNCTION_TRACE_ID.getName(), XRAY_TRACE_RESOLVER }, - { SAMPLING_RATE.getName(), SAMPLING_RATE_RESOLVER }, - { "region", REGION_RESOLVER }, - { "account_id", ACCOUNT_ID_RESOLVER } - }).collect(Collectors.toMap(data -> (String) data[0], data -> (EventResolver) data[1]))); + private static final Map eventResolverMap = Collections + .unmodifiableMap(Stream.of(new Object[][] { + { SERVICE.getName(), SERVICE_RESOLVER }, + { FUNCTION_NAME.getName(), FUNCTION_NAME_RESOLVER }, + { FUNCTION_VERSION.getName(), FUNCTION_VERSION_RESOLVER }, + { FUNCTION_ARN.getName(), FUNCTION_ARN_RESOLVER }, + { FUNCTION_MEMORY_SIZE.getName(), FUNCTION_MEMORY_RESOLVER }, + { FUNCTION_REQUEST_ID.getName(), FUNCTION_REQ_RESOLVER }, + { FUNCTION_COLD_START.getName(), COLD_START_RESOLVER }, + { FUNCTION_TRACE_ID.getName(), XRAY_TRACE_RESOLVER }, + { SAMPLING_RATE.getName(), SAMPLING_RATE_RESOLVER }, + { "region", REGION_RESOLVER }, + { "account_id", ACCOUNT_ID_RESOLVER } + }).collect(Collectors.toMap(data -> (String) data[0], data -> (EventResolver) data[1]))); PowertoolsResolver(final TemplateResolverConfig config) { diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java index 24014a759..463ad043d 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java @@ -35,6 +35,8 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.slf4j.MDC; + +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments; @Order(2) @@ -83,9 +85,17 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + .contains( + "\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); + // Reserved keys should be ignored + PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> { + assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\""); + assertThat(contentOf(logFile)).contains( + "\"message\":\"Attempted to use reserved key '" + reservedKey + + "' in structured argument. This key will be ignored.\""); + }); } @Test @@ -107,9 +117,18 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + .contains( + "\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); + + // Reserved keys should be ignored + PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> { + assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\""); + assertThat(contentOf(logFile)).contains( + "\"message\":\"Attempted to use reserved key '" + reservedKey + + "' in structured argument. This key will be ignored.\""); + }); } private void setupContext() { @@ -119,4 +138,4 @@ private void setupContext() { when(context.getMemoryLimitInMB()).thenReturn(10); when(context.getAwsRequestId()).thenReturn("RequestId"); } -} \ No newline at end of file +} diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java index 387074590..1fc235ff7 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java @@ -16,15 +16,21 @@ import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.fasterxml.jackson.core.JsonProcessingException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; + import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.logging.argument.StructuredArguments; +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; import software.amazon.lambda.powertools.utilities.JsonConfig; public class PowertoolsArguments implements RequestHandler { @@ -41,11 +47,27 @@ public String handleRequest(SQSEvent.SQSMessage input, Context context) { try { MDC.put(CORRELATION_ID.getName(), input.getMessageId()); if (argumentFormat == ArgumentFormat.JSON) { - LOG.debug("SQS Event", StructuredArguments.json("input", - JsonConfig.get().getObjectMapper().writeValueAsString(input))); + LOG.debug("SQS Event", + StructuredArguments.json("input", + JsonConfig.get().getObjectMapper().writeValueAsString(input)), + // function_name is a reserved key by PowertoolsLoggedFields and should be omitted + StructuredArguments.entry("function_name", "shouldBeIgnored")); } else { - LOG.debug("SQS Event", StructuredArguments.entry("input", input)); + LOG.debug("SQS Event", + StructuredArguments.entry("input", input), + // function_name is a reserved key by PowertoolsLoggedFields and should be omitted + StructuredArguments.entry("function_name", "shouldBeIgnored")); + } + + // Attempt logging all reserved keys, the values should not be overwritten by "shouldBeIgnored" + final Map reservedKeysMap = new HashMap<>(); + for (String field : PowertoolsLoggedFields.stringValues()) { + reservedKeysMap.put(field, "shouldBeIgnored"); } + reservedKeysMap.put("message", "shouldBeIgnored"); + reservedKeysMap.put("level", "shouldBeIgnored"); + reservedKeysMap.put("timestamp", "shouldBeIgnored"); + LOG.debug("Reserved keys", StructuredArguments.entries(reservedKeysMap)); LOG.debug("{}", input.getMessageId()); LOG.warn("Message body = {} and id = \"{}\"", input.getBody(), input.getMessageId()); } catch (JsonProcessingException e) { diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/JsonUtils.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/JsonUtils.java index b98a8eada..67d6b268d 100644 --- a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/JsonUtils.java +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/JsonUtils.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.TimeZone; import java.util.TreeMap; + import software.amazon.lambda.powertools.logging.argument.StructuredArgument; import software.amazon.lambda.powertools.logging.internal.JsonSerializer; import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; @@ -36,7 +37,7 @@ private JsonUtils() { } static void serializeTimestamp(JsonSerializer generator, long timestamp, String timestampFormat, - String timestampFormatTimezoneId, String timestampAttributeName) { + String timestampFormatTimezoneId, String timestampAttributeName) { String formattedTimestamp; if (timestampFormat == null || timestamp < 0) { formattedTimestamp = String.valueOf(timestamp); diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 638857cb3..9b6fb8d1c 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -29,6 +29,8 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.util.JSONPObject; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -126,6 +128,13 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") .contains("\"message\":\"Message body = plop and id = \"1212abcd\"\""); + // Reserved keys should be ignored + PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> { + assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\""); + assertThat(contentOf(logFile)).contains( + "\"message\":\"Attempted to use reserved key '" + reservedKey + + "' in structured argument. This key will be ignored.\""); + }); } @Test @@ -150,6 +159,13 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") .contains("\"message\":\"Message body = plop and id = \"1212abcd\"\""); + // Reserved keys should be ignored + PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> { + assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\""); + assertThat(contentOf(logFile)).contains( + "\"message\":\"Attempted to use reserved key '" + reservedKey + + "' in structured argument. This key will be ignored.\""); + }); } private final LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "message", null, null); diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java index 387074590..1fc235ff7 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java @@ -16,15 +16,21 @@ import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.fasterxml.jackson.core.JsonProcessingException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.MDC; + import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.logging.argument.StructuredArguments; +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; import software.amazon.lambda.powertools.utilities.JsonConfig; public class PowertoolsArguments implements RequestHandler { @@ -41,11 +47,27 @@ public String handleRequest(SQSEvent.SQSMessage input, Context context) { try { MDC.put(CORRELATION_ID.getName(), input.getMessageId()); if (argumentFormat == ArgumentFormat.JSON) { - LOG.debug("SQS Event", StructuredArguments.json("input", - JsonConfig.get().getObjectMapper().writeValueAsString(input))); + LOG.debug("SQS Event", + StructuredArguments.json("input", + JsonConfig.get().getObjectMapper().writeValueAsString(input)), + // function_name is a reserved key by PowertoolsLoggedFields and should be omitted + StructuredArguments.entry("function_name", "shouldBeIgnored")); } else { - LOG.debug("SQS Event", StructuredArguments.entry("input", input)); + LOG.debug("SQS Event", + StructuredArguments.entry("input", input), + // function_name is a reserved key by PowertoolsLoggedFields and should be omitted + StructuredArguments.entry("function_name", "shouldBeIgnored")); + } + + // Attempt logging all reserved keys, the values should not be overwritten by "shouldBeIgnored" + final Map reservedKeysMap = new HashMap<>(); + for (String field : PowertoolsLoggedFields.stringValues()) { + reservedKeysMap.put(field, "shouldBeIgnored"); } + reservedKeysMap.put("message", "shouldBeIgnored"); + reservedKeysMap.put("level", "shouldBeIgnored"); + reservedKeysMap.put("timestamp", "shouldBeIgnored"); + LOG.debug("Reserved keys", StructuredArguments.entries(reservedKeysMap)); LOG.debug("{}", input.getMessageId()); LOG.warn("Message body = {} and id = \"{}\"", input.getBody(), input.getMessageId()); } catch (JsonProcessingException e) { diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/ArrayArgument.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/ArrayArgument.java index 28b29146e..cbedbdc0f 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/ArrayArgument.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/ArrayArgument.java @@ -15,12 +15,13 @@ package software.amazon.lambda.powertools.logging.argument; import java.util.Objects; + import software.amazon.lambda.powertools.logging.internal.JsonSerializer; /** * See {@link StructuredArguments#array(String, Object...)} */ -public class ArrayArgument implements StructuredArgument { +class ArrayArgument implements StructuredArgument { private final String key; private final Object[] values; @@ -40,4 +41,5 @@ public void writeTo(JsonSerializer serializer) { public String toString() { return key + "=" + StructuredArguments.toString(values); } + } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/JsonArgument.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/JsonArgument.java index e14f23788..debea18c5 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/JsonArgument.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/JsonArgument.java @@ -15,12 +15,13 @@ package software.amazon.lambda.powertools.logging.argument; import java.util.Objects; + import software.amazon.lambda.powertools.logging.internal.JsonSerializer; /** * See {@link StructuredArguments#json(String, String)} */ -public class JsonArgument implements StructuredArgument { +class JsonArgument implements StructuredArgument { private final String key; private final String rawJson; @@ -39,4 +40,5 @@ public void writeTo(JsonSerializer serializer) { public String toString() { return key + "=" + rawJson; } + } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/KeyValueArgument.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/KeyValueArgument.java index 569667419..54648d99e 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/KeyValueArgument.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/KeyValueArgument.java @@ -15,12 +15,13 @@ package software.amazon.lambda.powertools.logging.argument; import java.util.Objects; + import software.amazon.lambda.powertools.logging.internal.JsonSerializer; /** * See {@link StructuredArguments#entry(String, Object)} */ -public class KeyValueArgument implements StructuredArgument { +class KeyValueArgument implements StructuredArgument { private final String key; private final Object value; diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/MapArgument.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/MapArgument.java index 9a06ea095..1155fa93b 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/MapArgument.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/MapArgument.java @@ -15,13 +15,15 @@ package software.amazon.lambda.powertools.logging.argument; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; + import software.amazon.lambda.powertools.logging.internal.JsonSerializer; /** * See {@link StructuredArguments#entries(Map)} */ -public class MapArgument implements StructuredArgument { +class MapArgument implements StructuredArgument { private final Map map; public MapArgument(Map map) { @@ -35,8 +37,13 @@ public MapArgument(Map map) { @Override public void writeTo(JsonSerializer serializer) { if (map != null) { - for (Map.Entry entry : map.entrySet()) { + for (Iterator> entries = map.entrySet().iterator(); entries.hasNext();) { + Map.Entry entry = entries.next(); serializer.writeObjectField(String.valueOf(entry.getKey()), entry.getValue()); + // If the map has more than one entry, we need to print a (comma) separator to avoid breaking the JSON + if (entries.hasNext()) { + serializer.writeSeparator(); + } } } } @@ -45,4 +52,5 @@ public void writeTo(JsonSerializer serializer) { public String toString() { return String.valueOf(map); } + } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArgument.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArgument.java index 21fea068d..00cc651eb 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArgument.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArgument.java @@ -15,7 +15,9 @@ package software.amazon.lambda.powertools.logging.argument; import java.io.IOException; + import org.slf4j.Logger; + import software.amazon.lambda.powertools.logging.internal.JsonSerializer; /** @@ -26,8 +28,10 @@ public interface StructuredArgument { /** * Writes the data associated with this argument to the given {@link JsonSerializer}. * - * @param serializer the {@link JsonSerializer} to produce JSON content - * @throws IOException if an I/O error occurs + * @param serializer + * the {@link JsonSerializer} to produce JSON content + * @throws IOException + * if an I/O error occurs */ void writeTo(JsonSerializer serializer) throws IOException; diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArguments.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArguments.java index 8a75b3118..f56a42ea3 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArguments.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/argument/StructuredArguments.java @@ -15,7 +15,16 @@ package software.amazon.lambda.powertools.logging.argument; import java.util.Arrays; +import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; /** * Factory for creating {@link StructuredArgument}s. @@ -23,54 +32,109 @@ */ public class StructuredArguments { + private static final Logger LOGGER = LoggerFactory.getLogger(StructuredArguments.class); + + /** + * Set of reserved keys that should not be used in structured arguments. + * When a reserved key is used, the method will return null. + */ + private static final Set RESERVED_KEYS = Stream + .concat(PowertoolsLoggedFields.stringValues().stream(), + List.of("message", "level", "timestamp", "error").stream()) + .collect(Collectors.toSet()); + private StructuredArguments() { // nothing to do, use static methods only } + /** + * Checks if the provided key is a reserved key. + * If the key is reserved, logs a warning message. + * + * @param key the key to check + * @return true if the key is reserved, false otherwise + */ + private static boolean isReservedKey(String key) { + if (key != null && RESERVED_KEYS.contains(key)) { + LOGGER.warn( + "Attempted to use reserved key '{}' in structured argument. This key will be ignored.", key); + return true; + } + return false; + } + /** * Adds "key": "value" to the JSON structure and "key=value" to the formatted message. + * Returns null if the key is a reserved key. * * @param key the field name * @param value the value associated with the key (can be any kind of object) - * @return a {@link StructuredArgument} populated with the data + * @return a {@link StructuredArgument} populated with the data, or null if key is reserved */ public static StructuredArgument entry(String key, Object value) { + if (isReservedKey(key)) { + return null; + } return new KeyValueArgument(key, value); } /** * Adds a "key": "value" to the JSON structure for each entry in the map * and {@code map.toString()} to the formatted message. + * If the map contains any reserved keys, those entries will be filtered out. * * @param map {@link Map} holding the key/value pairs - * @return a {@link MapArgument} populated with the data + * @return a {@link MapArgument} populated with the data, with reserved keys filtered out */ public static StructuredArgument entries(Map map) { - return new MapArgument(map); + if (map == null) { + return null; + } + + // Create a new map without reserved keys + Map filteredMap = new java.util.HashMap<>(); + for (Map.Entry entry : map.entrySet()) { + if (entry.getKey() != null) { + String keyStr = String.valueOf(entry.getKey()); + if (!isReservedKey(keyStr)) { + filteredMap.put(entry.getKey(), entry.getValue()); + } + } + } + + return new MapArgument(filteredMap); } /** * Adds a field to the JSON structure with key as the key and where value * is a JSON array of objects AND a string version of the array to the formatted message: * {@code "key": [value, value]} + * Returns null if the key is a reserved key. * * @param key the field name * @param values elements of the array associated with the key - * @return an {@link ArrayArgument} populated with the data + * @return an {@link ArrayArgument} populated with the data, or null if key is reserved */ public static StructuredArgument array(String key, Object... values) { + if (isReservedKey(key)) { + return null; + } return new ArrayArgument(key, values); } /** * Adds the {@code rawJson} to the JSON structure and * the {@code rawJson} to the formatted message. + * Returns null if the key is a reserved key. * * @param key the field name * @param rawJson the raw JSON String - * @return a {@link JsonArgument} populated with the data + * @return a {@link JsonArgument} populated with the data, or null if key is reserved */ public static StructuredArgument json(String key, String rawJson) { + if (isReservedKey(key)) { + return null; + } return new JsonArgument(key, rawJson); } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/argument/StructuredArgumentsTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/argument/StructuredArgumentsTest.java index 64200e640..b478ac0f0 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/argument/StructuredArgumentsTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/argument/StructuredArgumentsTest.java @@ -15,12 +15,15 @@ package software.amazon.lambda.powertools.logging.argument; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNull; import java.io.IOException; import java.util.HashMap; import java.util.Map; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; + import software.amazon.lambda.powertools.logging.internal.JsonSerializer; import software.amazon.lambda.powertools.logging.model.Basket; import software.amazon.lambda.powertools.logging.model.Product; @@ -47,8 +50,10 @@ void keyValueArgument() throws IOException { argument.writeTo(serializer); // THEN - assertThat(sb.toString()).hasToString("\"basket\":{\"products\":[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]}"); - assertThat(argument.toString()).hasToString("basket=Basket{products=[Product{id=42, name='Nintendo DS', price=299.45}, Product{id=98, name='Playstation 5', price=499.99}]}"); + assertThat(sb.toString()).hasToString( + "\"basket\":{\"products\":[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]}"); + assertThat(argument.toString()).hasToString( + "basket=Basket{products=[Product{id=42, name='Nintendo DS', price=299.45}, Product{id=98, name='Playstation 5', price=499.99}]}"); } @Test @@ -64,17 +69,32 @@ void mapArgument() throws IOException { // THEN assertThat(sb.toString()) - .contains("\"nds\":{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45}") + .contains("\"nds\":{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},") .contains("\"ps5\":{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}"); assertThat(argument.toString()) .contains("nds=Product{id=42, name='Nintendo DS', price=299.45}") .contains("ps5=Product{id=98, name='Playstation 5', price=499.99}"); } + @Test + void emptyMapArgument() throws IOException { + // GIVEN + Map catalog = new HashMap<>(); + + // WHEN + assertNull(StructuredArguments.entries(null)); + StructuredArgument argument = StructuredArguments.entries(catalog); + argument.writeTo(serializer); + + // THEN + assertThat(sb.toString()).isEmpty(); + assertThat(argument.toString()).hasToString("{}"); + } + @Test void arrayArgument() throws IOException { // GIVEN - Product[] products = new Product[]{ + Product[] products = new Product[] { new Product(42, "Nintendo DS", 299.45), new Product(98, "Playstation 5", 499.99) }; @@ -84,8 +104,10 @@ void arrayArgument() throws IOException { argument.writeTo(serializer); // THEN - assertThat(sb.toString()).contains("\"products\":[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]"); - assertThat(argument.toString()).contains("products=[Product{id=42, name='Nintendo DS', price=299.45}, Product{id=98, name='Playstation 5', price=499.99}]"); + assertThat(sb.toString()).contains( + "\"products\":[{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45},{\"id\":98,\"name\":\"Playstation 5\",\"price\":499.99}]"); + assertThat(argument.toString()).contains( + "products=[Product{id=42, name='Nintendo DS', price=299.45}, Product{id=98, name='Playstation 5', price=499.99}]"); } @Test @@ -102,4 +124,34 @@ void jsonArgument() throws IOException { assertThat(argument.toString()).contains("product={\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45}"); } + @Test + void reservedKeywordArgumentIgnored() throws IOException { + // GIVEN + Basket basket = new Basket(); + basket.add(new Product(42, "Nintendo DS", 299.45)); + basket.add(new Product(98, "Playstation 5", 499.99)); + Product[] products = new Product[] { + new Product(42, "Nintendo DS", 299.45), + new Product(98, "Playstation 5", 499.99) + }; + String rawJson = "{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45}"; + Map catalog = new HashMap<>(); + catalog.put("nds", new Product(42, "Nintendo DS", 299.45)); + catalog.put("message", new Product(98, "Playstation 5", 499.99)); + + // THEN + assertNull(StructuredArguments.entry("message", basket)); + assertNull(StructuredArguments.array("message", products)); + assertNull(StructuredArguments.json("message", rawJson)); + + StructuredArgument mapArg = StructuredArguments.entries(catalog); + mapArg.writeTo(serializer); + assertThat(sb.toString()) + .contains("\"nds\":{\"id\":42,\"name\":\"Nintendo DS\",\"price\":299.45}"); + assertThat(sb.toString()).doesNotContain("message"); + assertThat(mapArg.toString()) + .contains("nds=Product{id=42, name='Nintendo DS', price=299.45}"); + assertThat(mapArg.toString()).doesNotContain("message"); + } + } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index 557c6c893..aba4664fe 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -72,7 +72,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; -import software.amazon.lambda.powertools.logging.argument.KeyValueArgument; +import software.amazon.lambda.powertools.logging.argument.StructuredArgument; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayRestApiCorrelationId; @@ -466,9 +466,8 @@ void shouldLogEventForHandlerWithLogEventAnnotation() { // THEN TestLogger logger = (TestLogger) PowertoolsLogEvent.getLogger(); assertThat(logger.getArguments()).hasSize(1); - KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; - assertThat(argument.getKey()).isEqualTo("event"); - assertThat(argument.getValue()).isEqualTo(listOfOneElement); + StructuredArgument argument = (StructuredArgument) logger.getArguments()[0]; + assertThat(argument.toString()).hasToString("event=" + listOfOneElement.toString()); } @Test @@ -487,15 +486,14 @@ void shouldLogEventForHandlerWhenEnvVariableSetToTrue() { requestHandler.handleRequest(message, context); // THEN - TestLogger logger = (TestLogger) ((PowertoolsLogEventEnvVar)requestHandler).getLogger(); + TestLogger logger = (TestLogger) ((PowertoolsLogEventEnvVar) requestHandler).getLogger(); try { assertThat(logger.getArguments()).hasSize(1); - KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; - assertThat(argument.getKey()).isEqualTo("event"); - assertThat(argument.getValue()).isEqualTo(message); + StructuredArgument argument = (StructuredArgument) logger.getArguments()[0]; + assertThat(argument.toString()).hasToString("event={messageId: 1234abcd,awsRegion: eu-west-1,body: body,}"); } finally { LoggingConstants.POWERTOOLS_LOG_EVENT = false; - if (logger != null){ + if (logger != null) { logger.clearArguments(); } } @@ -532,9 +530,8 @@ void shouldLogEventForStreamHandler() throws IOException { TestLogger logger = (TestLogger) PowertoolsLogEventForStream.getLogger(); try { assertThat(logger.getArguments()).hasSize(1); - KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; - assertThat(argument.getKey()).isEqualTo("event"); - assertThat(argument.getValue()).isEqualTo("{\"key\":\"value\"}"); + StructuredArgument argument = (StructuredArgument) logger.getArguments()[0]; + assertThat(argument.toString()).hasToString("event={\"key\":\"value\"}"); } finally { logger.clearArguments(); } @@ -552,9 +549,8 @@ void shouldLogResponseForHandlerWithLogResponseAnnotation() { TestLogger logger = (TestLogger) PowertoolsLogResponse.getLogger(); try { assertThat(logger.getArguments()).hasSize(1); - KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; - assertThat(argument.getKey()).isEqualTo("response"); - assertThat(argument.getValue()).isEqualTo("Hola mundo"); + StructuredArgument argument = (StructuredArgument) logger.getArguments()[0]; + assertThat(argument.toString()).hasToString("response=Hola mundo"); } finally { logger.clearArguments(); } @@ -574,9 +570,8 @@ void shouldLogResponseForHandlerWhenEnvVariableSetToTrue() { TestLogger logger = (TestLogger) PowertoolsLogEnabled.getLogger(); try { assertThat(logger.getArguments()).hasSize(1); - KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; - assertThat(argument.getKey()).isEqualTo("response"); - assertThat(argument.getValue()).isEqualTo("Bonjour le monde"); + StructuredArgument argument = (StructuredArgument) logger.getArguments()[0]; + assertThat(argument.toString()).hasToString("response=Bonjour le monde"); } finally { LoggingConstants.POWERTOOLS_LOG_RESPONSE = false; logger.clearArguments(); @@ -600,9 +595,8 @@ void shouldLogResponseForStreamHandler() throws IOException { TestLogger logger = (TestLogger) PowertoolsLogResponseForStream.getLogger(); try { assertThat(logger.getArguments()).hasSize(1); - KeyValueArgument argument = (KeyValueArgument) logger.getArguments()[0]; - assertThat(argument.getKey()).isEqualTo("response"); - assertThat(argument.getValue()).isEqualTo(input); + StructuredArgument argument = (StructuredArgument) logger.getArguments()[0]; + assertThat(argument.toString()).hasToString("response=" + input); } finally { logger.clearArguments(); } From 33a81374e2ccb2cb4762630c02897a5735f6e8a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 11:39:36 +0200 Subject: [PATCH 218/577] build(deps-dev): bump org.yaml:snakeyaml from 2.2 to 2.4 (#1798) Bumps [org.yaml:snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) from 2.2 to 2.4. - [Commits](https://bitbucket.org/snakeyaml/snakeyaml/branches/compare/snakeyaml-2.4..snakeyaml-2.2) --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Simon Thulbourn --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 03b6fe413..8120e44d8 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -159,7 +159,7 @@ org.yaml snakeyaml - 2.2 + 2.4 test From da9f5265a5c7ef67ba2dee3edfd941a7b4d8e3ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 11:40:35 +0200 Subject: [PATCH 219/577] build(deps): bump com.amazonaws:aws-lambda-java-events (#1799) Bumps [com.amazonaws:aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs) from 3.11.2 to 3.15.0. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-events dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Simon Thulbourn --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- examples/powertools-examples-core-utilities/serverless/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 782162029..d2227a95b 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -13,7 +13,7 @@ 11 11 1.2.3 - 3.11.3 + 3.15.0 2.28.1 1.9.20.1 diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 22a1b0d32..82b0209f5 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -41,7 +41,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.15.0 org.apache.logging.log4j diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 86fa52425..2db4628b4 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -38,7 +38,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.15.0 org.aspectj diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 0b5b06152..41b5a20a1 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -38,7 +38,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.15.0 org.aspectj diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 1918b63a9..7480bd013 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -38,7 +38,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.15.0 org.aspectj diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 2a866fa82..fd673b573 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -52,7 +52,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.15.0 org.aspectj diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/pom.xml index cb0fc4474..5737ffdeb 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/pom.xml @@ -38,7 +38,7 @@ com.amazonaws aws-lambda-java-events - 3.11.4 + 3.15.0 org.aspectj diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 2f9bf77ef..00aba4c8d 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -31,7 +31,7 @@ com.amazonaws aws-lambda-java-events - 3.11.4 + 3.15.0 diff --git a/pom.xml b/pom.xml index 01ca81458..5c4ad2ef6 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,7 @@ 2.2.0 UTF-8 1.2.3 - 3.11.2 + 3.15.0 1.1.5 3.13.0 1.9.7 From 7b5983818432ae12264e687420d46e8a99c59044 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Apr 2025 12:05:52 +0200 Subject: [PATCH 220/577] build(deps): bump org.apache.maven.plugins:maven-checkstyle-plugin (#1751) Bumps [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.3.0 to 3.6.0. - [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.3.0...maven-checkstyle-plugin-3.6.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Simon Thulbourn --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5c4ad2ef6..891420766 100644 --- a/pom.xml +++ b/pom.xml @@ -651,7 +651,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.3.0 + 3.6.0 basedir=${project.rootdir} checkstyle.xml From 51d5f5dd64afe9ec9bc4ae7f34b8646935e9e504 Mon Sep 17 00:00:00 2001 From: Simon Thulbourn Date: Wed, 7 May 2025 18:22:41 +0200 Subject: [PATCH 221/577] chore(automation): Update automation workflows (#1779) (#1830) * chore(automation): Update automation workflows (#1779) * Update to 2.18.2 --------- Co-authored-by: Philipp Page --- .github/ISSUE_TEMPLATE/bug_report.md | 121 ++-- .github/ISSUE_TEMPLATE/maintenance.yml | 4 +- .github/ISSUE_TEMPLATE/rfc.md | 159 +++-- .github/ISSUE_TEMPLATE/share_your_work.yml | 2 +- .github/ISSUE_TEMPLATE/support_powertools.yml | 8 +- .github/ISSUE_TEMPLATE/tech_debt.yml | 60 ++ .github/actions/gradle/action.yml | 0 .github/actions/restore/action.yml | 0 .github/actions/seal/action.yml | 78 +++ .github/actions/version/action.yml | 53 ++ .github/branch_protection_settings/main.json | 53 ++ .github/branch_protection_settings/v2.json | 63 ++ .github/dependency-review-config.yml | 30 + .github/pmd-ruleset.xml | 644 ++++++++++++++++++ .github/workflows/build-docs.yml | 79 ++- .github/workflows/check-build.yml | 109 +++ .github/workflows/check-e2e.yml | 71 ++ .github/workflows/check-pmd.yml | 42 ++ .../{spotbugs.yml => check-spotbugs.yml} | 45 +- .github/workflows/dispatch_analytics.yml | 43 -- .github/workflows/docs.yml | 41 -- .github/workflows/post_release.js | 112 --- .github/workflows/pr_artifacts_size.yml | 64 -- .github/workflows/pr_build.yml | 93 --- .github/workflows/pr_iac_lint.yml | 50 -- .github/workflows/publish.yml | 38 -- .github/workflows/release-drafter.yml | 29 +- .github/workflows/release-prep.yml | 80 --- .github/workflows/release.yml | 289 ++++++++ .github/workflows/run-e2e-tests.yml | 58 -- .github/workflows/secure_workflows.yml | 32 - .../workflows/security-branch-protections.yml | 72 ++ .github/workflows/security-dependabot.yml | 42 ++ .../workflows/security-dependencies-check.yml | 39 ++ .github/workflows/security-osv.yml | 37 + .../cdk/app/pom.xml | 2 +- pom.xml | 21 +- 37 files changed, 1997 insertions(+), 766 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/tech_debt.yml create mode 100644 .github/actions/gradle/action.yml create mode 100644 .github/actions/restore/action.yml create mode 100644 .github/actions/seal/action.yml create mode 100644 .github/actions/version/action.yml create mode 100644 .github/branch_protection_settings/main.json create mode 100644 .github/branch_protection_settings/v2.json create mode 100644 .github/dependency-review-config.yml create mode 100644 .github/pmd-ruleset.xml create mode 100644 .github/workflows/check-build.yml create mode 100644 .github/workflows/check-e2e.yml create mode 100644 .github/workflows/check-pmd.yml rename .github/workflows/{spotbugs.yml => check-spotbugs.yml} (55%) delete mode 100644 .github/workflows/dispatch_analytics.yml delete mode 100644 .github/workflows/docs.yml delete mode 100644 .github/workflows/post_release.js delete mode 100644 .github/workflows/pr_artifacts_size.yml delete mode 100644 .github/workflows/pr_build.yml delete mode 100644 .github/workflows/pr_iac_lint.yml delete mode 100644 .github/workflows/publish.yml delete mode 100644 .github/workflows/release-prep.yml create mode 100644 .github/workflows/release.yml delete mode 100644 .github/workflows/run-e2e-tests.yml delete mode 100644 .github/workflows/secure_workflows.yml create mode 100644 .github/workflows/security-branch-protections.yml create mode 100644 .github/workflows/security-dependabot.yml create mode 100644 .github/workflows/security-dependencies-check.yml create mode 100644 .github/workflows/security-osv.yml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index abd8faa56..8810605b9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,46 +1,81 @@ ---- name: Bug report -about: Create a report to help us improve -title: '' -labels: bug, triage -assignees: '' +description: Report a reproducible bug to help us improve +title: "Bug: TITLE" +labels: ["bug", "triage"] +body: + - type: markdown + attributes: + value: | + Thank you for submitting a bug report. Please add as much information as possible to help us reproduce, and remove any potential sensitive data. ---- + Please become familiar with [our definition of bug](https://docs.powertools.aws.dev/lambda/java/processes/maintainers/#is-that-a-bug). + - type: textarea + id: expected_behaviour + attributes: + label: Expected Behaviour + description: Please share details on the behaviour you expected + validations: + required: true + - type: textarea + id: current_behaviour + attributes: + label: Current Behaviour + description: Please share details on the current issue + validations: + required: true + - type: textarea + id: code_snippet + attributes: + label: Code snippet + description: Please share a code snippet to help us reproduce the issue + render: java + validations: + required: true + - type: textarea + id: solution + attributes: + label: Possible Solution + description: If known, please suggest a potential resolution + validations: + required: false + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: Please share how we might be able to reproduce this issue + validations: + required: true + - type: input + id: version + attributes: + label: Powertools for AWS Lambda (Java) version + placeholder: "latest, 1.19.0" + value: latest + validations: + required: true + - type: dropdown + id: runtime + attributes: + label: AWS Lambda function runtime + options: + - "Java 8" + - "Java 11" + - "Java 17" + - "Java 21" + - "provided.al2023" + validations: + required: true + - type: textarea + id: logs + attributes: + label: Debugging logs + description: If available, please share [debugging logs](https://docs.powertools.aws.dev/lambda/lambda/#debug-mode) + render: java + validations: + required: false + - type: markdown + attributes: + value: | + --- - - - -**What were you trying to accomplish?** - -## Expected Behavior - - - -## Current Behavior - - - -## Possible Solution - - - -## Steps to Reproduce (for bugs) - - -1. -2. -3. -4. - -## Environment - -* **Powertools for AWS Lambda (Java) version used**: -* **Packaging format (Layers, Maven/Gradle)**: -* **AWS Lambda function runtime:** -* **Debugging logs** - -> [How to enable debug mode](https://docs.powertools.aws.dev/lambda-java/#debug-mode)** - -```text -# paste logs here -``` + **Disclaimer**: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/maintenance.yml b/.github/ISSUE_TEMPLATE/maintenance.yml index 843f5103c..1a84ed7ef 100644 --- a/.github/ISSUE_TEMPLATE/maintenance.yml +++ b/.github/ISSUE_TEMPLATE/maintenance.yml @@ -57,11 +57,11 @@ body: options: - label: This request meets [Powertools for AWS Lambda (Java) Tenets](https://docs.powertools.aws.dev/lambda-java/#tenets) required: true - - label: Should this be considered in other Powertools for AWS Lambda (Java) languages? i.e. [Python](https://github.com/aws-powertools/powertools-lambda-python/), [TypeScript](https://github.com/aws-powertools/powertools-lambda-typescript/) + - label: Should this be considered in other Powertools for AWS Lambda languages? i.e. [Python](https://github.com/aws-powertools/powertools-lambda-python/), [TypeScript](https://github.com/aws-powertools/powertools-lambda-typescript/) required: false - type: markdown attributes: value: | --- - **Disclaimer**: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful. + **Disclaimer**: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/rfc.md b/.github/ISSUE_TEMPLATE/rfc.md index 84fce71df..ae2337402 100644 --- a/.github/ISSUE_TEMPLATE/rfc.md +++ b/.github/ISSUE_TEMPLATE/rfc.md @@ -1,52 +1,107 @@ ---- -name: RFC -about: Feature design and proposals -title: 'RFC: ' -labels: RFC, triage -assignees: '' - ---- - -## Key information - -* RFC PR: (leave this empty) -* Related issue(s), if known: -* Area: (i.e. Tracer, Metrics, Logger, etc.) -* Meet [tenets](https://docs.powertools.aws.dev/lambda-java/#tenets): (Yes/no) - -## Summary -[summary]: #summary - -> One paragraph explanation of the feature. - -## Motivation -[motivation]: #motivation - -> Why are we doing this? What use cases does it support? What is the expected outcome? - -## Proposal -[proposal]: #proposal - -> This is the bulk of the RFC. - -> Explain the design in enough detail for somebody familiar with Powertools for AWS Lambda (Java) to understand it, and for somebody familiar with the implementation to implement it. - -> This should get into specifics and corner-cases, and include examples of how the feature is used. Any new terminology should be defined here. - -## Drawbacks -[drawbacks]: #drawbacks - -> Why should we *not* do this? - -> Do we need additional dependencies? Impact performance/package size? - -## Rationale and alternatives -[rationale-and-alternatives]: #rationale-and-alternatives - -* **What other designs have been considered? Why not them?** -* **What is the impact of not doing this?** - -## Unresolved questions -[unresolved-questions]: #unresolved-questions - -> Optional, stash area for topics that need further development e.g. TBD +name: Request for Comments (RFC) +description: Feature design and detailed proposals +title: "RFC: TITLE" +labels: ["RFC", "triage"] +body: + - type: markdown + attributes: + value: | + Thank you for submitting a RFC. Please add as many details as possible to help further enrich this design. + - type: input + id: relation + attributes: + label: Is this related to an existing feature request or issue? + description: Please share a link, if applicable + - type: dropdown + id: area + attributes: + label: Which Powertools for AWS Lambda (Java) utility does this relate to? + options: + - Tracer + - Logger + - Metrics + - Middleware factory + - Parameters + - Batch processing + - Typing + - Validation + - Event Source Data Classes + - Parser + - Idempotency + - Feature flags + - JMESPath functions + - Other + validations: + required: true + - type: textarea + id: summary + attributes: + label: Summary + description: Please provide an overview in one or two paragraphs + validations: + required: true + - type: textarea + id: problem + attributes: + label: Use case + description: Please share the use case and motivation behind this proposal + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposal + description: Please explain the design in detail, so anyone familiar with the project could implement it + placeholder: What the user experience looks like before and after this design? + validations: + required: true + - type: textarea + id: scope + attributes: + label: Out of scope + description: Please explain what should be considered out of scope in your proposal + validations: + required: true + - type: textarea + id: challenges + attributes: + label: Potential challenges + description: Nothing is perfect. Please share what common challenges, edge cases, unresolved areas, and suggestions on how to mitigate them + validations: + required: true + - type: textarea + id: integrations + attributes: + label: Dependencies and Integrations + description: If applicable, please share whether this feature has additional dependencies, and how it might integrate with other utilities available + validations: + required: false + - type: textarea + id: alternatives + attributes: + label: Alternative solutions + description: Please describe what alternative solutions to this use case, if any + render: markdown + validations: + required: false + - type: checkboxes + id: acknowledgment + attributes: + label: Acknowledgment + options: + - label: This feature request meets [Powertools for AWS Lambda (Java) Tenets](https://docs.powertools.aws.dev/lambda/Java/#tenets) + required: true + - label: Should this be considered in other Powertools for AWS Lambda languages? i.e. [Python](https://github.com/aws-powertools/powertools-lambda-python/), [TypeScript](https://github.com/aws-powertools/powertools-lambda-typescript/), and [.NET](https://github.com/aws-powertools/powertools-lambda-dotnet/) + required: false + - type: markdown + attributes: + value: | + --- + + **Disclaimer**: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful. + + Metadata information for admin purposes, please leave them empty. + + * RFC PR: + * Approved by: '' + * Reviewed by: '' \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/share_your_work.yml b/.github/ISSUE_TEMPLATE/share_your_work.yml index 228ee8281..01dae4fdf 100644 --- a/.github/ISSUE_TEMPLATE/share_your_work.yml +++ b/.github/ISSUE_TEMPLATE/share_your_work.yml @@ -53,4 +53,4 @@ body: label: Acknowledgment options: - label: I understand this content may be removed from Powertools for AWS Lambda (Java) documentation if it doesn't conform with the [Code of Conduct](https://aws.github.io/code-of-conduct) - required: true + required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/support_powertools.yml b/.github/ISSUE_TEMPLATE/support_powertools.yml index 2b66d830d..8623c2b73 100644 --- a/.github/ISSUE_TEMPLATE/support_powertools.yml +++ b/.github/ISSUE_TEMPLATE/support_powertools.yml @@ -1,7 +1,7 @@ name: Support Powertools for AWS Lambda (Java) (become a reference) description: Add your organization's name or logo to the Powertools for AWS Lambda (Java) documentation title: "[Support Powertools for AWS Lambda (Java)]: " -labels: ["customer_reference"] +labels: ["customer-reference"] body: - type: markdown attributes: @@ -48,9 +48,9 @@ body: - type: checkboxes id: other_languages attributes: - label: Also using other Powertools for AWS Lambda (Java) languages? + label: Also using other Powertools for AWS Lambda languages? options: - - label: Python + - label: Java required: false - label: TypeScript required: false @@ -59,6 +59,6 @@ body: - type: markdown attributes: value: | - *By raising a Support Powertools for AWS Lambda (Java) issue, you are granting AWS permission to use your company's name (and/or logo) for the limited purpose described here. You are also confirming that you have authority to grant such permission.* + *By raising a Support Powertools for AWS Lambda (Python) issue, you are granting AWS permission to use your company's name (and/or logo) for the limited purpose described here. You are also confirming that you have authority to grant such permission.* *You can opt-out at any time by commenting or reopening this issue.* \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/tech_debt.yml b/.github/ISSUE_TEMPLATE/tech_debt.yml new file mode 100644 index 000000000..56cd4b8c7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/tech_debt.yml @@ -0,0 +1,60 @@ +name: Technical debt +description: Suggest an activity to help address technical debt. +title: "Tech debt: TITLE" +labels: ["tech-debt", "triage"] +body: + - type: markdown + attributes: + value: Thank you for taking the time to help us proactively improve delivery velocity, safely. + - type: textarea + id: importance + attributes: + label: Why is this needed? + description: Please help us understand the value so we can prioritize it accordingly + validations: + required: true + - type: dropdown + id: area + attributes: + label: Which area does this relate to? + multiple: true + options: + - Tests + - Static typing + - Tracer + - Logger + - Metrics + - Middleware factory + - Parameters + - Batch processing + - Validation + - Event Source Data Classes + - Parser + - Idempotency + - Feature flags + - JMESPath functions + - Streaming + - Automation + - Other + - type: textarea + id: suggestion + attributes: + label: Suggestion + description: If available, please share what a good solution would look like + validations: + required: false + - type: checkboxes + id: acknowledgment + attributes: + label: Acknowledgment + options: + - label: This request meets [Powertools for AWS Lambda (Python) Tenets](https://docs.powertools.aws.dev/lambda/python/latest/#tenets) + required: true + - label: Should this be considered in other Powertools for AWS Lambda languages? i.e. [Python](https://github.com/aws-powertools/powertools-lambda-python/), [TypeScript](https://github.com/aws-powertools/powertools-lambda-typescript/), and [.NET](https://github.com/aws-powertools/powertools-lambda-dotnet/) + required: false + - type: markdown + attributes: + value: | + --- + + **Disclaimer**: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful. \ No newline at end of file diff --git a/.github/actions/gradle/action.yml b/.github/actions/gradle/action.yml new file mode 100644 index 000000000..e69de29bb diff --git a/.github/actions/restore/action.yml b/.github/actions/restore/action.yml new file mode 100644 index 000000000..e69de29bb diff --git a/.github/actions/seal/action.yml b/.github/actions/seal/action.yml new file mode 100644 index 000000000..079496c8c --- /dev/null +++ b/.github/actions/seal/action.yml @@ -0,0 +1,78 @@ +name: Seal and hash source code +description: | + Seals and creates a SHA256SUM of an artifact for storage + + Process: + 1. Create a unique name based on environment details + 2. Compress work directory or specified path + 3. Hash compressed file + 4. Upload archive using `actions/upload-artifact` + + Usage: + ```yml + - id: seal + name: Seal + uses: .github/actions/seal + with: + prefix: foo + ``` + +inputs: + prefix: + description: Prefix to use when exporting artifact + required: true +outputs: + hash: + description: SHA256SUM hash of compressed files + value: ${{ steps.hash.outputs.hash }} + artifact_name: + description: Artifact name + value: ${{ steps.artifact_name.outputs.artifact_name }} + +runs: + using: composite + steps: + - id: adjust_path + name: Adjust path + shell: bash + run: echo "${{ github.action_path }}" >> $GITHUB_PATH + + - id: artifact_name + name: Export final artifact name + env: + GITHUB_RUN_ID: ${{ github.run_id }} + ARTIFACT_PREFIX: ${{ inputs.prefix }} + shell: bash + run: | + echo "artifact_name=${ARTIFACT_PREFIX}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" + + - id: compress + name: Create tarball for entire source + env: + ARTIFACT_NAME: ${{ steps.artifact_name.outputs.artifact_name }} + shell: bash + run: | + tar --exclude-vcs -cvf "${ARTIFACT_NAME}".tar * + + - id: hash + name: Hash + env: + ARTIFACT_NAME: ${{ steps.artifact_name.outputs.artifact_name }} + shell: bash + run: | + echo "hash=$(openssl dgst -sha256 -binary "${{ ARTIFACT_NAME }}".tar | openssl enc -base64)" >> "$GITHUB_OUTPUT" + + - name: Upload artifacts + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + with: + if-no-files-found: error + name: ${{ steps.artifact_name.outputs.artifact_name }} + path: ${{ steps.artifact_name.outputs.artifact_name }}.tar + retention-days: 1 + + - name: Remove archive + env: + ARTIFACT_NAME: ${{ steps.artifact_name.outputs.artifact_name }} + shell: bash + run: | + rm -f "${ARTIFACT_NAME}.tar" \ No newline at end of file diff --git a/.github/actions/version/action.yml b/.github/actions/version/action.yml new file mode 100644 index 000000000..f0f0516ee --- /dev/null +++ b/.github/actions/version/action.yml @@ -0,0 +1,53 @@ +name: Version Java Project +description: | + Versions the maven project using an input + + Process: + 1. Grab current version from project.version variable from maven + 2. Set new version using maven-versions-plugin + + Usage: + ```yml + - id: version + name: version + uses: .github/actions/version + with: + new_version: 1.20.0 + snapshot: 'false' + ``` + +inputs: + new_version: + description: New package version, expressed as SemVer (1.x.y) + required: true + snapshot: + description: New version is a SNAPSHOT release + required: true + default: 'false' + +outputs: + old_version: + description: Current version of project + value: ${{ steps.current_version.outputs.current_version}} + +runs: + using: composite + steps: + - id: current_version + name: Get current version + shell: bash + run: | + echo "current_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_OUTPUT + + - id: replace_version + name: Replace current version + shell: bash + run: | + mvn versions:set -DnewVersion=${{ inputs.new_version }} -DprocessAllModules=true -DallowSnapshots=true + + - id: asset_version + name: Replace version for assets + if: ${{ inputs.snapshot == 'false' }} + shell: bash + run: | + grep "${{ steps.current_version.outputs.current_version }}" -r . --include build.gradle --include build.gradle.kts --include mkdocs.yml --include README.md -l | xargs sed -i 's#${{ steps.current_version.outputs.current_version }}#${{ inputs.new_version }}#' \ No newline at end of file diff --git a/.github/branch_protection_settings/main.json b/.github/branch_protection_settings/main.json new file mode 100644 index 000000000..d283b3d5f --- /dev/null +++ b/.github/branch_protection_settings/main.json @@ -0,0 +1,53 @@ +{ + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection", + "required_status_checks": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_status_checks", + "strict": true, + "contexts": [ + "SonarCloud" + ], + "contexts_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_status_checks/contexts", + "checks": [ + { + "context": "SonarCloud", + "app_id": 57789 + } + ] + }, + "required_pull_request_reviews": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_pull_request_reviews", + "dismiss_stale_reviews": false, + "require_code_owner_reviews": false, + "require_last_push_approval": false, + "required_approving_review_count": 0 + }, + "required_signatures": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_signatures", + "enabled": false + }, + "enforce_admins": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/enforce_admins", + "enabled": true + }, + "required_linear_history": { + "enabled": false + }, + "allow_force_pushes": { + "enabled": false + }, + "allow_deletions": { + "enabled": false + }, + "block_creations": { + "enabled": false + }, + "required_conversation_resolution": { + "enabled": false + }, + "lock_branch": { + "enabled": false + }, + "allow_fork_syncing": { + "enabled": false + } +} diff --git a/.github/branch_protection_settings/v2.json b/.github/branch_protection_settings/v2.json new file mode 100644 index 000000000..fb9fdebcd --- /dev/null +++ b/.github/branch_protection_settings/v2.json @@ -0,0 +1,63 @@ +{ + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection", + "required_status_checks": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/required_status_checks", + "strict": true, + "contexts": [], + "contexts_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/required_status_checks/contexts", + "checks": [] + }, + "restrictions": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/restrictions", + "users_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/restrictions/users", + "teams_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/restrictions/teams", + "apps_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/restrictions/apps", + "users": [], + "teams": [], + "apps": [] + }, + "required_pull_request_reviews": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/required_pull_request_reviews", + "dismiss_stale_reviews": true, + "require_code_owner_reviews": false, + "require_last_push_approval": true, + "required_approving_review_count": 1, + "dismissal_restrictions": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/dismissal_restrictions", + "users_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/dismissal_restrictions/users", + "teams_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/dismissal_restrictions/teams", + "users": [], + "teams": [], + "apps": [] + } + }, + "required_signatures": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/required_signatures", + "enabled": false + }, + "enforce_admins": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/enforce_admins", + "enabled": false + }, + "required_linear_history": { + "enabled": true + }, + "allow_force_pushes": { + "enabled": false + }, + "allow_deletions": { + "enabled": false + }, + "block_creations": { + "enabled": true + }, + "required_conversation_resolution": { + "enabled": true + }, + "lock_branch": { + "enabled": false + }, + "allow_fork_syncing": { + "enabled": false + } +} diff --git a/.github/dependency-review-config.yml b/.github/dependency-review-config.yml new file mode 100644 index 000000000..6d737ee55 --- /dev/null +++ b/.github/dependency-review-config.yml @@ -0,0 +1,30 @@ +allow-licenses: + - 'Apache-1.1' + - 'Apache-2.0' + - 'ISC' + - 'MIT' + - 'MIT-0' + - 'MIT-CMU' + - 'MIT-enna' + - 'MIT-feh' + - 'MIT-Festival' + - 'MIT-Modern-Variant' + - 'MIT-open-group' + - 'MIT-testregex' + - 'MIT-Wu' + - 'BSD-1-Clause' + - 'BSD-2-Clause' + - 'BSD-2-Clause-Views' + - 'BSD-3-Clause' + - 'BSD-3-Clause-Attribution' + - 'BSD-3-Clause-Clear' + - 'BSD-3-Clause-flex' + - 'BSD-3-Clause-HP' + - 'BSD-3-Clause-LBNL' + - 'BSD-3-Clause-Modification' + - 'BSD-3-Clause-No-Military-License' + - 'BSD-3-Clause-No-Nuclear-License' + - 'BSD-3-Clause-No-Nuclear-License-2014' + - 'BSD-3-Clause-No-Nuclear-Warranty' + - 'BSD-3-Clause-Open-MPI' +comment-summary-in-pr: on-failure \ No newline at end of file diff --git a/.github/pmd-ruleset.xml b/.github/pmd-ruleset.xml new file mode 100644 index 000000000..b93fa19b8 --- /dev/null +++ b/.github/pmd-ruleset.xml @@ -0,0 +1,644 @@ + + + Rules to check Powertools for Lambda + + + + + + + + + + + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + + + + + + + + 1 + + + + 1 + + + 1 + + + 1 + + + + 1 + + + + + + + 1 + + + + 1 + + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + + + + 1 + + + + + + + 1 + + + + + 1 + + + 1 + + + + + 3 + + + + + + + + + + + + + + + + + + + + + + 1 + + + 1 + + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + + + + + + 1 + + + + + + + + + + + + + + 1 + + + + + + 1 + + + + + + + + + + + + 1 + + + + 1 + + + 1 + + + 1 + + + + + + + 1 + + + + 1 + + + + + + + 1 + + + 1 + + + + 1 + + + + + + 1 + + + + + 1 + + + + + 1 + + + 1 + + + + + + + 1 + + + + + 1 + + + 1 + + + + 1 + + + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + 1 + + + + + + 1 + + + + + 1 + + + + + + + 1 + + + 1 + + + 1 + + + + + + + + + + + + + 1 + + + + + + + 1 + + + 1 + + + + 1 + + + + 1 + + + + + + + 1 + + + + 1 + + + + 1 + + + 1 + + + + 1 + + + 1 + + + + 1 + + + + 1 + + + + 1 + + + 1 + + + + + + + 1 + + + + 1 + + + + + 1 + + + 1 + + + + + 1 + + + 1 + + + + + + 1 + + + 1 + + + + 1 + + + 1 + + + 1 + + + 1 + + + + 1 + + + + + + + 1 + + + + 1 + + + + + + + + 1 + + + + + + + 1 + + + + + + + + + + + + + + + + + replace o.getClass().equals(MyClass.class) with o instanceof MyClass. Make sure MyClass doesn't have descendants + 1 + + + + + + + + + + + replace MyClass.class.equals(o.getClass()) with o instanceof MyClass. Make sure MyClass doesn't have descendants + 3 + + + + + + + + + + + Calling super.visit breaks the rulechain, by starting a full visitor run from the passed node downwards. Add all needed nodes to the rulechain instead. + 1 + + + + + + + + + + + Just returning without calling super stops visiting of nested nodes like inner classes. + 3 + + + + + + + + + + + + Share the invocation matcher and not create a new one every time + 1 + + + + + + + + + + + Use slf4j: LoggerFactory.getLogger(MyClass.class) + 1 + + + + + + + + + \ No newline at end of file diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index a75c13b52..d4bf75a9d 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -1,37 +1,62 @@ -name: Build Docs +# Build Docs +# +# Description: +# Builds the docs and stores them in S3 to be served by our docs platform +# +# The workflow allows us to build to the main location (/lambda/java/) and to an alias +# (i.e. /lambda/java/preview/) if needed +# +# Triggers: +# - workflow_dispatch +# +# Inputs: +# alias – subdirectory to store the docs in for previews or in progress work on: - pull_request: - branches: - - v2 - paths: - - 'docs/**' - - 'mkdocs.yml' - - 'Makefile' + workflow_dispatch: + inputs: + alias: + type: string + required: false + description: | + Alias to deploy the documentation into, this is mostly for testing pre-release + versions of the documentation, such as beta versions or snapshots. + + https://docs.powertools.aws.dev/lambda/java/ - push: - branches: - - main - paths: - - 'docs/**' - - 'mkdocs.yml' - - 'Makefile' +name: Build Docs +run-name: Build Docs - ${{ contains(github.head_ref, 'main') && 'main' || inputs.alias }} jobs: docs: runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + environment: Docs steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Set up Python - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 - with: - python-version: "3.8" - - name: Capture branch and tag - id: branch_name + - name: Sanity Check + if: ${{ github.head_ref != 'main' || inputs.alias == '' }} + run: + echo "::error::No buildable docs" + + - name: Checkout Repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + fetch-depth: 0 + - name: Build run: | - echo "SOURCE_BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV - echo "SOURCE_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - name: Build docs website + mkdir -p dist + docker build -t squidfunk/mkdocs-material ./docs/ + docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build + cp -R site/* dist/ + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 + with: + aws-region: us-east-1 + role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} + - name: Deploy run: | - echo "GIT_PYTHON_REFRESH=quiet" - make build-docs-website \ No newline at end of file + aws s3 sync \ + dist \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ github.head_ref == 'main' && '' || format('{0}/', inputs.alias )}} \ No newline at end of file diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml new file mode 100644 index 000000000..cc5931d05 --- /dev/null +++ b/.github/workflows/check-build.yml @@ -0,0 +1,109 @@ +# Check Build +# +# Description: +# Runs the build for every java version we support +# +# Triggers: +# - pull_request: when a PR is sent to us +# - push: when code is pushed to a specified branch +# +# Notes: +# The matrix build for this workflow is unusual, we need to make it dyanmic since +# we need to change java versions we build for depending on the branch. + + +on: + workflow_dispatch: + pull_request: + paths: + - 'powertools-batch/**' + - 'powertools-core/**' + - 'powertools-cloudformation/**' + - 'powertools-common/**' + - 'powertools-e2e-tests/**' + - 'powertools-idempotency/**' + - 'powertools-large-messages/**' + - 'powertools-logging/**' + - 'powertools-metrics/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' + - 'powertools-sqs/**' + - 'powertools-tracing/**' + - 'powertools-tracing/**' + - 'powertools-validation/**' + - 'examples/**' + - 'pom.xml' + - 'examples/pom.xml' + - '.github/workflows/**' + push: + branches: + - main + - v2 + paths: # add other modules when there are under e2e tests + - 'powertools-batch/**' + - 'powertools-core/**' + - 'powertools-cloudformation/**' + - 'powertools-common/**' + - 'powertools-e2e-tests/**' + - 'powertools-idempotency/**' + - 'powertools-large-messages/**' + - 'powertools-logging/**' + - 'powertools-metrics/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' + - 'powertools-sqs/**' + - 'powertools-tracing/**' + - 'powertools-tracing/**' + - 'powertools-validation/**' + - 'pom.xml' + - 'examples/**' + - 'examples/pom.xml' + - '.github/workflows/**' + +name: Build +run-name: Build - ${{ github.event_name }} + +jobs: + setup: + runs-on: ubuntu-latest + outputs: + build_matrix: ${{ format('{0}{1}', steps.build_matrix_v1.outputs.build_matrix, steps.build_matrix_v1.outputs.build_matrix) }} + steps: + - id: base + name: Base + run: | + echo build_version=$(test ${{ github.ref }} == "v2" && echo "v2" || echo "v1") >> $GITHUB_OUTPUT + - id: build_matrix_v1 + name: Build matrix (v1) + if: ${{ steps.base.outputs.build_version == 'v1' }} + run: | + echo build_matrix='["8", "11", "17", "21"]' >> "$GITHUB_OUTPUT" + - id: build_matrix_v2 + name: Build matrix (v2) + if: ${{ steps.base.outputs.build_version == 'v2' }} + run: | + echo build_matrix='["11", "17", "21"]'>> "$GITHUB_OUTPUT" + build: + runs-on: ubuntu-latest + strategy: + matrix: + java: + - 8 + - 11 + - 17 + - 21 + steps: + - id: checkout + name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Setup Java + uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 + with: + distribution: corretto + java-version: ${{ matrix.java }} + cache: maven + - id: build-maven + name: Build (Maven) + if: ${{ matrix.java != '8' }} + run: | + mvn -B install --file pom.xml \ No newline at end of file diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml new file mode 100644 index 000000000..6420cd6f7 --- /dev/null +++ b/.github/workflows/check-e2e.yml @@ -0,0 +1,71 @@ +# Run E2E tests for a branch +# +# Description: +# Runs E2E tests for a specified branch +# +# Triggers: +# - push +# +# Secrets: +# - E2E.AWS_IAM_ROLE + +on: + workflow_dispatch: + + push: + branches: + - main + - v2 + paths: # add other modules when there are under e2e tests + - 'powertools-batch/**' + - 'powertools-core/**' + - 'powertools-cloudformation/**' + - 'powertools-common/**' + - 'powertools-e2e-tests/**' + - 'powertools-idempotency/**' + - 'powertools-large-messages/**' + - 'powertools-logging/**' + - 'powertools-metrics/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' + - 'powertools-sqs/**' + - 'powertools-tracing/**' + - 'powertools-tracing/**' + - 'powertools-validation/**' + - 'pom.xml' + +name: E2E Tests +run-name: E2E Tests - ${{ github.event_name }} + +permissions: + contents: read + +jobs: + e2e: + name: End-to-end Tests (Java ${{ matrix.java }}) + runs-on: ubuntu-latest + permissions: + id-token: write + environment: E2E + strategy: + max-parallel: 3 + matrix: + java: + - 11 + - 17 + - 21 + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Setup java + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + with: + distribution: 'corretto' + java-version: ${{ matrix.java }} + cache: maven + - name: Setup AWS credentials + uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 + with: + role-to-assume: ${{ secrets.AWS_IAM_ROLE }} + aws-region: us-east-1 + - name: Run e2e test with Maven + run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml \ No newline at end of file diff --git a/.github/workflows/check-pmd.yml b/.github/workflows/check-pmd.yml new file mode 100644 index 000000000..d97698af8 --- /dev/null +++ b/.github/workflows/check-pmd.yml @@ -0,0 +1,42 @@ +# Runs PMD for a Pull Request +# +# Description: +# Runs PMD (pmd.github.io) for a pull request and daily. +# This does not error on failure yet, our rules are too strong and would fail on every run +# +# Triggers: +# - pull_request +# - workflow_dispatch +# - cron: every day at 12:00PM + +on: + pull_request: + workflow_dispatch: + schedule: + - cron: '0 12 * * *' # Run daily at 12:00 UTC + +name: PMD +run-name: PMD - ${{ github.event_name }} + +permissions: + contents: read + +jobs: + pmd_analyse: + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write + steps: + - name: Checkout Repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Setup Java + uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 + with: + java-version: 21 + distribution: corretto + cache: maven + - uses: pmd/pmd-github-action@d9c1f3c5940cbf5923f1354e83fa858b4496ebaa # v2.0.0 + with: + rulesets: '.github/pmd-ruleset.xml' + token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/spotbugs.yml b/.github/workflows/check-spotbugs.yml similarity index 55% rename from .github/workflows/spotbugs.yml rename to .github/workflows/check-spotbugs.yml index 106905a70..0749dfaa0 100644 --- a/.github/workflows/spotbugs.yml +++ b/.github/workflows/check-spotbugs.yml @@ -1,41 +1,50 @@ -name: SpotBugs - +# Check for Spotbug errors +# +# Description: +# Runs Spotbugs for a pull request. +# This does not error on failure yet, our rules are too strong and would fail on every run +# +# Triggers: +# - pull_request on: pull_request: branches: - v2 paths: - - 'powertools-cloudformation/**' + - 'powertools-batch/**' - 'powertools-core/**' - - 'powertools-serialization/**' + - 'powertools-cloudformation/**' + - 'powertools-common/**' + - 'powertools-e2e-tests/**' + - 'powertools-idempotency/**' + - 'powertools-large-messages/**' - 'powertools-logging/**' + - 'powertools-metrics/**' + - 'powertools-parameters/**' + - 'powertools-serialization/**' - 'powertools-sqs/**' - 'powertools-tracing/**' + - 'powertools-tracing/**' - 'powertools-validation/**' - - 'powertools-parameters/**' - - 'powertools-idempotency/**' - - 'powertools-metrics/**' - 'powertools-test-suite/**' - 'pom.xml' - '.github/workflows/**' + +name: SpotBugs +run-name: SpotBugs + +permissions: + contents: read + jobs: codecheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Setup java JDK 11 + - name: Setup Java uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'corretto' - java-version: 11 - # https://github.com/jwgmeligmeyling/spotbugs-github-action/issues/6 - # https://github.blog/2020-08-03-github-actions-improvements-for-fork-and-pull-request-workflows/ - # Avoid complexity of git action with publishing report. Just build with spotbugs profile. -# - name: Build with Maven for spotbugs check to gather reports -# run: mvn -Pbuild-with-spotbugs -B install --file pom.xml -DskipTests -Dmaven.javadoc.skip=true -Dspotbugs.failOnError=false -# - uses: jwgmeligmeyling/spotbugs-github-action@master -# with: -# path: '**/spotbugsXml.xml' -# # Can be simplified post this issue is fixed https://github.com/jwgmeligmeyling/spotbugs-github-action/issues/9 + java-version: 21 - name: Build with Maven for spotbugs check to mark build as fail if voilations found run: mvn -Pbuild-with-spotbugs -B install --file pom.xml -DskipTests -Dmaven.javadoc.skip=true -Dspotbugs.failOnError=true \ No newline at end of file diff --git a/.github/workflows/dispatch_analytics.yml b/.github/workflows/dispatch_analytics.yml deleted file mode 100644 index c93cb5b36..000000000 --- a/.github/workflows/dispatch_analytics.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Dispatch analytics - -on: - workflow_dispatch: - - schedule: - - cron: '0 * * * *' - -permissions: - id-token: write - actions: read - checks: read - contents: read - deployments: read - issues: read - discussions: read - packages: read - pages: read - pull-requests: read - repository-projects: read - security-events: read - statuses: read - -jobs: - dispatch_token: - concurrency: - group: analytics - runs-on: ubuntu-latest - environment: analytics - steps: - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 - with: - aws-region: eu-central-1 - role-to-assume: ${{ secrets.AWS_ANALYTICS_ROLE_ARN }} - - - name: Invoke Lambda function - run: | - payload=$(echo -n '{"githubToken": "${{ secrets.GITHUB_TOKEN }}"}' | base64) - aws lambda invoke \ - --function-name ${{ secrets.AWS_ANALYTICS_DISPATCHER_ARN }} \ - --payload "$payload" response.json - cat response.json diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 5e37c5f45..000000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Docs - -on: - release: - types: - - published - workflow_dispatch: {} - -permissions: - id-token: write - contents: write - pages: write - -jobs: - docs: - runs-on: ubuntu-latest - environment: Docs - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Set up Python - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 - with: - python-version: "3.8" - - name: Capture branch and tag - id: branch_name - run: | - echo "SOURCE_BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV - echo "SOURCE_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - name: Build docs website - run: | - make build-docs-website - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef - with: - aws-region: us-east-1 - role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} - - name: Deploy Docs - run: | - aws s3 sync \ - dist \ - s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/ diff --git a/.github/workflows/post_release.js b/.github/workflows/post_release.js deleted file mode 100644 index 648236421..000000000 --- a/.github/workflows/post_release.js +++ /dev/null @@ -1,112 +0,0 @@ -const STAGED_LABEL = "status/staged-next-release"; - -/** - * Fetch issues using GitHub REST API - * - * @param {object} gh_client - Pre-authenticated REST client (Octokit) - * @param {string} org - GitHub Organization - * @param {string} repository - GitHub repository - * @param {string} state - GitHub issue state (open, closed) - * @param {string} label - Comma-separated issue labels to fetch - * @return {Object[]} issues - Array of issues matching params - * @see {@link https://octokit.github.io/rest.js/v18#usage|Octokit client} - */ -const fetchIssues = async ({ - gh_client, - org, - repository, - state = "open", - label = STAGED_LABEL, - }) => { - - try { - const { data: issues } = await gh_client.rest.issues.listForRepo({ - owner: org, - repo: repository, - state: state, - labels: label, - }); - - return issues; - - } catch (error) { - console.error(error); - throw new Error("Failed to fetch issues") - } - -}; - -/** - * Notify new release and close staged GitHub issue - * - * @param {object} gh_client - Pre-authenticated REST client (Octokit) - * @param {string} owner - GitHub Organization - * @param {string} repository - GitHub repository - * @param {string} release_version - GitHub Release version - * @see {@link https://octokit.github.io/rest.js/v18#usage|Octokit client} - */ -const notifyRelease = async ({ - gh_client, - owner, - repository, - release_version, - }) => { - const release_url = `https://github.com/${owner}/${repository}/releases/tag/v${release_version}`; - - const issues = await fetchIssues({ - gh_client: gh_client, - org: owner, - repository: repository, - }); - - issues.forEach(async (issue) => { - console.info(`Updating issue number ${issue.number}`); - - const comment = `This is now released under [${release_version}](${release_url}) version!`; - try { - await gh_client.rest.issues.createComment({ - owner: owner, - repo: repository, - body: comment, - issue_number: issue.number, - }); - } catch (error) { - console.error(error); - throw new Error(`Failed to update issue ${issue.number} about ${release_version} release`) - } - - - // Close issue and remove staged label; keep existing ones - const labels = issue.labels - .filter((label) => label.name != STAGED_LABEL) - .map((label) => label.name); - - try { - await gh_client.rest.issues.update({ - repo: repository, - owner: owner, - issue_number: issue.number, - state: "closed", - labels: labels, - }); - } catch (error) { - console.error(error); - throw new Error("Failed to close issue") - } - - console.info(`Issue number ${issue.number} closed and updated`); - }); -}; - -// context: https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts -module.exports = async ({ github, context }) => { - const { RELEASE_TAG_VERSION } = process.env; - console.log(`Running post-release script for ${RELEASE_TAG_VERSION} version`); - - await notifyRelease({ - gh_client: github, - owner: context.repo.owner, - repository: context.repo.repo, - release_version: RELEASE_TAG_VERSION, - }); -}; \ No newline at end of file diff --git a/.github/workflows/pr_artifacts_size.yml b/.github/workflows/pr_artifacts_size.yml deleted file mode 100644 index c4d29205b..000000000 --- a/.github/workflows/pr_artifacts_size.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: Artifacts Size - -on: - pull_request: - branches: - - v2 - paths: - - 'powertools-batch/**' - - 'powertools-cloudformation/**' - - 'powertools-common/**' - - 'powertools-e2e-tests/**' - - 'powertools-idempotency-core/**' - - 'powertools-idempotency-dynamodb/**' - - 'powertools-large-messages/**' - - 'powertools-logging/**' - - 'powertools-metrics/**' - - 'powertools-parameters/**' - - 'powertools-serialization/**' - - 'powertools-tracing/**' - - 'powertools-validation/**' - - 'pom.xml' - - '.github/workflows/pr_artifacts_size.yml' -jobs: - codecheck: - runs-on: ubuntu-latest - permissions: - pull-requests: write - issues: read - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Setup java JDK 11 - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 - with: - distribution: 'corretto' - java-version: 11 - - name: Build with Maven - run: mvn clean package --file pom.xml -DskipTests artifact:buildinfo -pl '!software.amazon.lambda.examples:powertools-examples-idempotency,!software.amazon.lambda.examples:powertools-examples-batch,!software.amazon.lambda.examples:powertools-examples-cloudformation,!software.amazon.lambda.examples:powertools-examples-core-utilities-cdk,!software.amazon.lambda.examples:powertools-examples-core-utilities-sam,!software.amazon.lambda.examples:powertools-examples-core-utilities-serverless,!software.amazon.lambda.examples:powertools-examples-core-utilities-terraform,!software.amazon.lambda.examples:powertools-examples-parameters,!software.amazon.lambda.examples:powertools-examples-serialization,!software.amazon.lambda.examples:powertools-examples-validation,!software.amazon.lambda.examples:cdk,!software.amazon.lambda:powertools-examples' - - name: Get artifacts size & build report - id: artifacts-size-report - run: | - echo '## :floppy_disk: Artifacts Size Report' > report.md - echo '| Module | Version | Size (KB) |' >> report.md - echo '| --- | --- | --- |' >> report.md - artifact_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) - for artifact in $(cat target/powertools-parent-*.buildinfo | grep 'outputs.*.jar' | grep -v 'sources.jar'); do - artifact_name=$(echo "$artifact" | cut -d '=' -f2) - artifact_name=${artifact_name%-$artifact_version.jar} - artifact_size=$(grep "${artifact%%.filename*}.length" target/powertools-parent-*.buildinfo | cut -d '=' -f2) - printf "| %s | %s | %.2f |\n" "$artifact_name" "$artifact_version" "$(bc <<< "scale=2; $artifact_size/1000")" >> report.md - done - - name: Find potential existing report - uses: peter-evans/find-comment@a54c31d7fa095754bfef525c0c8e5e5674c4b4b1 # 2.4.0 - id: find-comment - with: - issue-number: ${{ github.event.pull_request.number }} - comment-author: 'github-actions[bot]' - body-includes: Artifacts Size Report - - name: Write artifacts size report in comment - uses: peter-evans/create-or-update-comment@c6c9a1a66007646a28c153e2a8580a5bad27bcfa # 3.0.2 - with: - comment-id: ${{ steps.find-comment.outputs.comment-id }} - issue-number: ${{ github.event.pull_request.number }} - body-path: 'report.md' - edit-mode: replace diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml deleted file mode 100644 index 2079bcb6b..000000000 --- a/.github/workflows/pr_build.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: Build - -on: - pull_request: - branches: - - v2 - paths: - - 'powertools-batch/**' - - 'powertools-cloudformation/**' - - 'powertools-common/**' - - 'powertools-e2e-tests/**' - - 'powertools-idempotency/**' - - 'powertools-large-messages/**' - - 'powertools-logging/**' - - 'powertools-metrics/**' - - 'powertools-parameters/**' - - 'powertools-serialization/**' - - 'powertools-tracing/**' - - 'powertools-validation/**' - - 'examples/**' - - 'pom.xml' - - 'examples/pom.xml' - - '.github/workflows/**' - push: - branches: - - v2 - paths: - - 'powertools-batch/**' - - 'powertools-cloudformation/**' - - 'powertools-common/**' - - 'powertools-e2e-tests/**' - - 'powertools-idempotency/**' - - 'powertools-large-messages/**' - - 'powertools-logging/**' - - 'powertools-metrics/**' - - 'powertools-parameters/**' - - 'powertools-serialization/**' - - 'powertools-tracing/**' - - 'powertools-validation/**' - - 'examples/**' - - 'pom.xml' - - 'examples/pom.xml' - - '.github/workflows/**' -jobs: - build-corretto: - runs-on: ubuntu-latest - strategy: - max-parallel: 5 - matrix: - java: [11, 17, 21] - name: Java ${{ matrix.java }} - env: - JAVA: ${{ matrix.java }} - AWS_REGION: eu-west-1 - permissions: - id-token: write # needed to interact with GitHub's OIDC Token endpoint. - contents: read - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Setup java - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 - with: - distribution: 'corretto' - java-version: ${{ matrix.java }} - cache: 'maven' - - name: Build with Maven - run: mvn -B install --file pom.xml - - name: Build Gradle Example - Java - working-directory: examples/powertools-examples-core-utilities/gradle - run: ./gradlew build - - name: Build Gradle Example - Kotlin - working-directory: examples/powertools-examples-core-utilities/kotlin - run: ./gradlew build - - name: Upload coverage to Codecov - uses: codecov/codecov-action@d9f34f8cd5cb3b3eb79b3e4b5dae3a16df499a70 # v3.1.1 - if: ${{ matrix.java == '11' }} # publish results once - with: - files: ./powertools-cloudformation/target/site/jacoco/jacoco.xml,./powertools-core/target/site/jacoco/jacoco.xml,./powertools-idempotency/target/site/jacoco/jacoco.xml,./powertools-logging/target/site/jacoco/jacoco.xml,./powertools-metrics/target/site/jacoco/jacoco.xml,./powertools-parameters/target/site/jacoco/jacoco.xml,./powertools-serialization/target/site/jacoco/jacoco.xml,./powertools-sqs/target/site/jacoco/jacoco.xml,./powertools-tracing/target/site/jacoco/jacoco.xml,./powertools-validation/target/site/jacoco/jacoco.xml,./powertools-large-messages/target/site/jacoco/jacoco.xml,./powertools-batch/target/site/jacoco/jacoco.xml - savepr: - runs-on: ubuntu-latest - name: Save PR number if running on PR by dependabot - if: github.actor == 'dependabot[bot]' - steps: - - name: Create Directory and save issue - run: | - mkdir -p ./pr - echo ${{ github.event.number }} - echo ${{ github.event.number }} > ./pr/NR - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - name: Upload artifact - with: - name: pr - path: pr/ diff --git a/.github/workflows/pr_iac_lint.yml b/.github/workflows/pr_iac_lint.yml deleted file mode 100644 index 531ccbbcb..000000000 --- a/.github/workflows/pr_iac_lint.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Validate IaC - -on: - push: - branches: - - v2 - pull_request: - branches: - - v2 - paths: - - 'examples/**' -jobs: - linter: - runs-on: ubuntu-latest - strategy: - matrix: - project: ["sam", "gradle", "kotlin"] - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Setup java JDK - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 - with: - distribution: 'corretto' - java-version: 11 - - name: Build Project - working-directory: . - run: | - mvn install -DskipTests - - name: Run SAM validator to check syntax of IaC templates - Java - working-directory: examples/powertools-examples-core-utilities//${{ matrix.project }} - run: | - sam build - sam validate --lint - - name: Setup Terraform - uses: hashicorp/setup-terraform@633666f66e0061ca3b725c73b2ec20cd13a8fdd1 #v2.0.3 - - name: Run Terraform validator to check syntax of IaC templates and produce a plan of changes - working-directory: examples/powertools-examples-core-utilities/terraform - run: | - mvn install - terraform -version - terraform init -backend=false - terraform validate - - name: Setup Terraform lint - uses: terraform-linters/setup-tflint@a5a1af8c6551fb10c53f1cd4ba62359f1973746f # v3.1.1 - - name: Run Terraform lint to check for best practices, errors, deprecated syntax etc. - working-directory: examples/powertools-examples-core-utilities/terraform - run: | - tflint --version - tflint --init - tflint -f compact \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 68c4d2e52..000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Publish package to the Maven Central Repository -on: - release: - types: - - published - workflow_dispatch: {} -jobs: - publish: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Set up Maven Central Repository - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 - with: - distribution: 'corretto' - java-version: 11 - server-id: ossrh - server-username: MAVEN_USERNAME - server-password: MAVEN_PASSWORD - # TODO: use environments https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment - gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }} # Value of the GPG private key to import - gpg-passphrase: GPG_PASSPHRASE # env variable for GPG private key passphrase - - name: Set release notes tag - run: | - RELEASE_TAG_VERSION=${{ github.event.release.tag_name }} - echo "RELEASE_TAG_VERSION=${RELEASE_TAG_VERSION:1}" >> $GITHUB_ENV - - name: Publish package - run: mvn -Prelease clean deploy -DskipTests - env: - MAVEN_USERNAME: ${{ secrets.SNAPSHOT_PUBLISH_USERNAME }} - MAVEN_PASSWORD: ${{ secrets.SNAPSHOT_PUBLISH_PASSWORD }} - GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - - name: Close issues related to this release - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 - with: - script: | - const post_release = require('.github/workflows/post_release.js') - await post_release({github, context, core}) diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index 72bd5c24f..f727ee25d 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -1,15 +1,32 @@ -name: Release Drafter +# Generates release notes +# +# Description: +# Generates release notes based on pull request history. This is based on the config +# stored in .github/release-drafter.yml +# +# Triggers: +# - push: main on: push: - # branches to consider in the event; optional, defaults to all - branches: - - main + branches: [ main ] + +name: Release Drafter +run-name: Release Drafter jobs: +<<<<<<< HEAD update_release_draft: runs-on: ubuntu-latest +======= + update_release: + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write +>>>>>>> 4a17172a (chore(automation): Update automation workflows (#1779)) steps: - - uses: release-drafter/release-drafter@569eb7ee3a85817ab916c8f8ff03a5bd96c9c83e # v5.23.0 + - name: Relase Drafter + uses: release-drafter/release-drafter@b1476f6e6eb133afa41ed8589daba6dc69b4d3f5 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release-prep.yml b/.github/workflows/release-prep.yml deleted file mode 100644 index f7a3c74c0..000000000 --- a/.github/workflows/release-prep.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: Prepare for maven central release -on: - workflow_dispatch: - inputs: - targetRelease: - description: 'Release number to upgrade to. For example X.X.X. Follow Semantic Versioning when deciding on next version.' - required: true - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Get current date - id: date - run: echo "::set-output name=date::$(date +'%Y-%m-%d')" - - name: Set current release version env variable - run: | - echo "CURRENT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV - - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in mkdocs.yml - uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 - with: - find: 'version: ${{ env.CURRENT_VERSION }}' - replace: 'version: ${{ github.event.inputs.targetRelease }}' - regex: false - include: "mkdocs.yml" - - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in main pom.xml - uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 - with: - find: ${{ env.CURRENT_VERSION }} - replace: ${{ github.event.inputs.targetRelease }} - regex: false - include: "pom.xml" - - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in modules pom.xml - uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 - with: - find: ${{ env.CURRENT_VERSION }} - replace: ${{ github.event.inputs.targetRelease }} - regex: false - include: "**/*pom.xml" - - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in build.gradle - uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 - with: - find: ${{ env.CURRENT_VERSION }} - replace: ${{ github.event.inputs.targetRelease }} - regex: false - include: "**/*build.gradle" - - name: Find and Replace ${{ env.CURRENT_VERSION }} with ${{ github.event.inputs.targetRelease }} in README.md - uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 - with: - find: ${{ env.CURRENT_VERSION }} - replace: ${{ github.event.inputs.targetRelease }} - regex: false - include: "README.md" - - name: Create changelog placeholder for ${{ github.event.inputs.targetRelease }} - uses: jacobtomlinson/gha-find-replace@f485fdc3f67a6d87ae6e3d11e41f648c26d7aee3 # v2.0.0 - with: - find: '## [Unreleased]' - replace: | - ## [Unreleased] - - ## [${{ github.event.inputs.targetRelease }}] - ${{ steps.date.outputs.date }} - - - - regex: false - include: CHANGELOG.md - - name: Create Release Pull Request - uses: peter-evans/create-pull-request@18f7dc018cc2cd597073088f7c7591b9d1c02672 # v3.14.0 - with: - commit-message: chore:prep release ${{ github.event.inputs.targetRelease }} - token: ${{ secrets.RELEASE }} - signoff: false - branch: prep-release-${{ github.event.inputs.targetRelease }} - delete-branch: true - title: chore:Prep release ${{ github.event.inputs.targetRelease }} - body: | - This is automated release prep. Remember to update [CHANGELOG.md](https://github.com/aws-powertools/powertools-lambda-java/blob/prep-release-${{ github.event.inputs.targetRelease }}/CHANGELOG.md) to capture changes in this release. Please review changes carefully before merging. - - * [ ] Updated CHANGELOG.md \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..3b650f105 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,289 @@ +# Release +# +# Description: +# Creates a release for the project +# +# 1. Runs a setup job to set needed variables (build_matrix & version) +# 2. Versions to the project and stores as an artifact +# 3. Run quality checks +# 4. Build +# 5. Publish to Maven Central +# 6. Create PR +# 7. Publish docs +# +# Inputs: +# - version (string): SemVer of the new release (X.Y.Z) +# - snapshot (bool): If it's a snapshot release, this skips versioning assets like docs +# - skip_checks (bool): Don't run quality checks if it's an emergency release +# - skip_publish (bool): Don't publish to maven central +# - continue_on_error (bool): Don't fail the workflow if a quality check fails +# +# Triggers: +# - workflow_dispatch +# +# Secrets: +# - RELEASE.GPG_SIGNING_KEY +# - RELEASE.OSSRH_JIRA_USERNAME +# - RELEASE.OSSRH_JIRA_PASSWORD +# - RELEASE.GPG_PASSPHRASE +# - DOCS.AWS_DOCS_ROLE_ARN +# - DOCS.AWS_DOCS_BUCKET + +on: + workflow_dispatch: + inputs: + version: + type: string + description: Semver version to release + snapshot: + type: boolean + description: Create snapshot release + default: false + skip_checks: + type: boolean + description: Skip quality checks + default: false + skip_publish: + type: boolean + description: Skip publish to Maven Central + default: false + continue_on_error: + type: boolean + description: Continue to build if there's an error in quality checks + default: false + +name: Release +run-name: Release – ${{ inputs.version }} + +permissions: + contents: read + +env: + RELEASE_COMMIT: ${{ github.sha }} + RELEASE_TAG_VERSION: ${{ inputs.version }} + +jobs: + setup: + runs-on: ubuntu-latest + outputs: + version: ${{ format('{0}{1}', steps.version_release.outputs.version, steps.version_snapshot.outputs.version) }} + build_matrix: ${{ format('{0}{1}', steps.build_matrix_v1.outputs.build_matrix, steps.build_matrix_v1.outputs.build_matrix) }} + steps: + - id: version_snapshot + if: ${{ inputs.snapshot }} + name: Version + run: | + echo version="$(grep -q "SNAPSHOT" <<< "${{ inputs.version }}" && echo "${{ inputs.version }}" || echo "${{ inputs.version }}-SNAPSHOT")" >> "$GITHUB_OUTPUT" + - id: version_release + if: ${{ !inputs.snapshot }} + name: Version + run: | + echo version="${{ inputs.version }}" >> "$GITHUB_OUTPUT" + - id: base + name: Base + run: | + echo build_version=$(test ${{ github.ref_name }} == "v2" && echo "v2" || echo "v1") >> $GITHUB_OUTPUT + - id: build_matrix_v1 + name: Build matrix (v1) + if: ${{ steps.base.outputs.build_version == 'v1' }} + run: | + echo build_matrix='["8", "11", "17", "21"]' >> "$GITHUB_OUTPUT" + - id: build_matrix_v2 + name: Build matrix (v2) + if: ${{ steps.base.outputs.build_version == 'v2' }} + run: | + echo build_matrix='["11", "17", "21"]'>> "$GITHUB_OUTPUT" + + version_seal: + runs-on: ubuntu-latest + needs: + - setup + outputs: + source_hash: ${{ steps.upload_source.outputs.artifact-digest }} + steps: + - id: checkout + name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - id: version + name: version + uses: ./.github/actions/version + with: + new_version: ${{ needs.setup.outputs.version }} + snapshot: ${{ inputs.snapshot}} + - id: upload_source + name: Upload artifacts + uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + with: + if-no-files-found: error + name: source + path: | + * + !.git/* + include-hidden-files: true + retention-days: 1 + + quality: + runs-on: ubuntu-latest + needs: + - version_seal + if: ${{ inputs.skip_checks == false }} + permissions: + contents: write + id-token: write + steps: + - id: download_source + name: Download artifacts + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.6.1 + with: + name: source + - name: Setup Java + uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 + with: + distribution: corretto + java-version: 21 + cache: maven + # non-exhuastive, but gives a fair indication if the final build will succeed, tests will run when we build later + - name: Run unit tests + run: mvn -B test --file pom.xml + continue-on-error: ${{ inputs.continue_on_error }} + - name: Run Spotbugs + run: mvn -Pbuild-with-spotbugs -B install --file pom.xml -DskipTests -Dmaven.javadoc.skip=true -Dspotbugs.failOnError=true + continue-on-error: ${{ inputs.continue_on_error }} + - uses: pmd/pmd-github-action@d9c1f3c5940cbf5923f1354e83fa858b4496ebaa # v2.0.0 + with: + rulesets: '.github/pmd-ruleset.xml' + token: ${{ secrets.GITHUB_TOKEN }} + uploadSarifReport: false + + build: + runs-on: ubuntu-latest + needs: + - setup + - quality + - version_seal + strategy: + matrix: + java: ${{ fromJson(needs.setup.outputs.build_matrix) }} + steps: + - id: download_source + name: Download artifacts + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.6.1 + with: + name: source + - name: Setup Java + uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 + with: + distribution: corretto + java-version: ${{ matrix.java }} + cache: maven + - id: build-maven + name: Build (Maven) + run: | + mvn -B install --file pom.xml + + publish: + runs-on: ubuntu-latest + if: ${{ github.repository == 'aws-powertools/powertools-lambda-java' }} + needs: + - build + environment: Release + steps: + - id: download_source + name: Download artifacts + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.6.1 + with: + name: source + - name: Setup Java + uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 + with: + distribution: corretto + java-version: 21 + cache: maven + gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }} + gpg-passphrase: GPG_PASSPHRASE + - name: Publish package + run: mvn -Prelease clean deploy -DskipTests + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_JIRA_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.OSSRH_JIRA_PASSWORD }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + + create_pr: + runs-on: ubuntu-latest + if: ${{ inputs.snapshot == false }} + needs: + - build + - publish + permissions: + pull-requests: write + contents: write + steps: + - id: checkout + name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + ref: ${{ env.RELEASE_COMMIT }} + - id: download_source + name: Download artifacts + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.6.1 + with: + name: source + - id: setup-git + name: Git client setup and refresh tip + run: | + git config user.name "Powertools for AWS Lambda (Java) Bot" + git config user.email "151832416+aws-powertools-bot@users.noreply.github.com" + git config pull.rebase true + git config remote.origin.url >&- + - id: branch + name: Create branch + run: | + git checkout -b ci-${{ github.run_id }} + git commit -am "chore(ci): bump version to ${{ inputs.version }}" + git push origin ci-${{ github.run_id }} + - id: create_pr + name: Create PR + run: | + gh pr create \ + --title "chore(ci): bump version to ${{ inputs.version }}" \ + --body "This is an automated PR created from the following workflow: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - id: tag + name: Create release + run: | + gh release create v${{ inputs.version }} --target $(git rev-parse HEAD) + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + docs: + runs-on: ubuntu-latest + if: ${{ inputs.snapshot == false }} + needs: + - create_pr + permissions: + contents: read + id-token: write + environment: Docs + steps: + - id: download_source + name: Download artifacts + uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.6.1 + with: + name: source + - name: Build + run: | + mkdir -p dist + docker build -t squidfunk/mkdocs-material ./docs/ + docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build + cp -R site/* dist/ + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 + with: + aws-region: us-east-1 + role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} + - name: Deploy + run: | + aws s3 sync \ + dist \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/ \ No newline at end of file diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml deleted file mode 100644 index 255c89cfe..000000000 --- a/.github/workflows/run-e2e-tests.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Run end-to-end tests - -on: - workflow_dispatch: - - push: - branches: - - v2 - paths: # add other modules when there are under e2e tests - - 'powertools-e2e-tests/**' - - 'powertools-batch/**' - - 'powertools-core/**' - - 'powertools-common/**' - - 'powertools-idempotency/**' - - 'powertools-large-message/**' - - 'powertools-logging/**' - - 'powertools-metrics/**' - - 'powertools-parameters/**' - - 'powertools-serialization/**' - - 'powertools-tracing/**' - - 'pom.xml' - - '.github/workflows/**' - - pull_request: - branches: - - v2 - paths: - - 'powertools-e2e-tests/**' - -jobs: - e2e: - runs-on: ubuntu-latest - strategy: - max-parallel: 4 - matrix: - java: [ 11, 17, 21 ] - name: End-to-end tests java${{ matrix.java }} - env: - AWS_DEFAULT_REGION: eu-west-1 - JAVA_VERSION: ${{ matrix.java }} - permissions: - id-token: write # needed to interact with GitHub's OIDC Token endpoint. - contents: read - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Setup java - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 - with: - distribution: 'corretto' - java-version: ${{ matrix.java }} - cache: maven - - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 - with: - role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} - aws-region: ${{ env.AWS_DEFAULT_REGION }} - - name: Run e2e test with Maven - run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml \ No newline at end of file diff --git a/.github/workflows/secure_workflows.yml b/.github/workflows/secure_workflows.yml deleted file mode 100644 index 1430e91d6..000000000 --- a/.github/workflows/secure_workflows.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Lockdown untrusted workflows - -# PROCESS -# -# 1. Scans for any external GitHub Action being used without version pinning (@ vs @v3) -# 2. Scans for insecure practices for inline bash scripts (shellcheck) -# 3. Fail CI and prevent PRs to be merged if any malpractice is found - -# USAGE -# -# Always triggered on new PR, PR changes and PR merge. - - -on: - push: - paths: - - ".github/workflows/**" - pull_request: - paths: - - ".github/workflows/**" - -jobs: - enforce_pinned_workflows: - name: Harden Security - runs-on: ubuntu-latest - permissions: - contents: read # checkout code and subsequently GitHub action workflows - steps: - - name: Checkout code - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Ensure 3rd party workflows have SHA pinned - uses: zgosalvez/github-actions-ensure-sha-pinned-actions@555a30da2656b4a7cf47b107800bef097723363e # v2.1.3 diff --git a/.github/workflows/security-branch-protections.yml b/.github/workflows/security-branch-protections.yml new file mode 100644 index 000000000..dc7c06316 --- /dev/null +++ b/.github/workflows/security-branch-protections.yml @@ -0,0 +1,72 @@ +# Branch Protections +# +# Description: +# This workflow compares current security branch protections against those stored, +# if there's any changes, it'll fail the job and alert using a Slack webhook +# +# Triggers: +# - pull_request +# - branch_protection_rule +# - cron: daily at 16:40 +# +# Secrets: +# - SECURITY.BRANCH_PROTECTION_TOKEN +# - SECURITY.SLACK_WEBHOOK_URL +# +# Notes: +# Modified copy of: https://github.com/github/docs/blob/main/.github/workflows/alert-changed-branch-protections.yml + +on: + branch_protection_rule: + schedule: + - cron: '20 16 * * *' # Run daily at 16:20 UTC + pull_request: + paths: + - .github/workflows/security-branch-protections.yml + - .github/branch_protection_settings/*.json + +name: Alert Changed Branch Protections +run-name: Alert Changed Branch Protections + +permissions: + contents: read + +jobs: + check-branch-protections: + runs-on: ubuntu-latest + permissions: + contents: write + environment: Security + if: ${{ github.repository == 'aws-powertools/powertools-lambda-java' }} + strategy: + matrix: + # List of branches we want to monitor for protection changes + branch: + - main + - v2 + steps: + - name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Fetch branch protections + id: fetch + env: + GH_TOKEN: ${{ secrets.BRANCH_PROTECTION_TOKEN }} + run: | + # Fetch branch protections and store them in a file + gh api /repos/${{ github.repository }}/branches/${{ matrix.branch }}/protection | jq \ + > .github/branch_protection_settings/${{ matrix.branch }}.json + - name: Compare branch protections + id: compare + run: | + git diff --quiet .github/branch_protection_settings/${{ matrix.branch }}.json \ + || echo "diff_failed=true" >> $GITHUB_ENV + - name: Send webhook + if: ${{ env.diff_failed == 'true' }} + run: | + curl -X POST -d '{"message": "Branch protections have changed for ${{ github.repository }} on ${{ matrix.branch }}. Please review the changes or revert the changes in GitHub. https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"}' \ + ${{ secrets.SLACK_WEBHOOK_URL }} + - name: Fail workflow + if: ${{ env.diff_failed == 'true' }} + run: | + git diff .github/branch_protection_settings/${{ matrix.branch }}.json + echo "::error::Branch protections have been changed" \ No newline at end of file diff --git a/.github/workflows/security-dependabot.yml b/.github/workflows/security-dependabot.yml new file mode 100644 index 000000000..095219045 --- /dev/null +++ b/.github/workflows/security-dependabot.yml @@ -0,0 +1,42 @@ +# Auto merges dependabot PRs +# +# Description: +# Auto-merges dependabot PRs if all checks pass +# We verify all commits in the PR to ensure no one else has committed to the PR +# +# Triggers: +# - pull_request + +on: + pull_request: + branches: [ dependabot/* ] + +name: Dependabot updates +run-name: Dependabot + +permissions: + contents: read + +jobs: + dependabot: + runs-on: ubuntu-latest + if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'aws-powertools/powertools-lambda-java' }} + permissions: + pull-requests: read + steps: + - id: dependabot-metadata + name: Fetch Dependabot metadata + uses: dependabot/fetch-metadata@d7267f607e9d3fb96fc2fbe83e0af444713e90b7 # v2.3.0 + - name: Fail workflow + if: ${{ steps.dependabot-metadata.outputs.update-type == 'version-update:semver-major' }} + run: | + echo "::error::Major version upgrades are not wanted" + - name: Approve PR + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh pr review "${{ github.event.pull_request.html_url }}" --approve --body '🤖 Approved by another robot.' + - name: Enable auto-merge on PR + run: gh pr merge --auto --squash "${{ github.event.pull_request.html_url }}" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml new file mode 100644 index 000000000..9c588d9be --- /dev/null +++ b/.github/workflows/security-dependencies-check.yml @@ -0,0 +1,39 @@ +# Dependency checks +# +# Description: +# Verifies that dependencies are compatible with our project +# by checking licenses and their security posture +# +# Triggers: +# - pull_request +# - push +# - workflow_dispatch +# - cron: daily at 12:00PM + +on: + pull_request: + workflow_dispatch: + push: + branches: [ main ] + schedule: + - cron: '0 12 * * *' # Run daily at 12:00 UTC + +name: Verify Dependencies +run-name: Verify Dependencies – ${{ github.event_name }} + +permissions: + contents: read + +jobs: + verify: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + steps: + - name: Checkout Repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Verify Contents + uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 + with: + config-file: './.github/dependency-review-config.yml' \ No newline at end of file diff --git a/.github/workflows/security-osv.yml b/.github/workflows/security-osv.yml new file mode 100644 index 000000000..b332faae3 --- /dev/null +++ b/.github/workflows/security-osv.yml @@ -0,0 +1,37 @@ +# Runs OSV scan +# +# Description: +# Checks dependencies already in the project for known issues +# +# Triggers: +# - pull_request +# - workflow_dispatch +# - cron +# - push + +on: + pull_request: + branches: + - main + - v2 + workflow_dispatch: {} + schedule: + - cron: "30 12 * * 1" + push: + branches: + - main + - v2 + +name: OpenSource Vulnerability Scanner +run-name: OpenSource Vulnerability Scanner + +permissions: + contents: read + +jobs: + scan-pr: + permissions: + actions: read + contents: read + security-events: write + uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@764c91816374ff2d8fc2095dab36eecd42d61638 # v1.9.2 \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 82b0209f5..a959432c0 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda.examples - 1.17.0 + 2.0.0-SNAPSHOT powertools-examples-core-utilities-cdk jar diff --git a/pom.xml b/pom.xml index 891420766..353eb7bee 100644 --- a/pom.xml +++ b/pom.xml @@ -71,7 +71,7 @@ 2.0.7 2.17.2 2.28.1 - 2.18.1 + 2.18.2 2.2.0 UTF-8 1.2.3 @@ -79,6 +79,15 @@ 1.1.5 3.13.0 1.9.7 + 1.13.1 + 3.2.5 + 0.8.11 + 1.6.13 + 3.11.2 + 3.3.1 + 3.2.1 + 5.10.0 + 1.0.6 1.14 3.1.2 0.8.12 @@ -89,6 +98,8 @@ 5.10.2 4.1.2 0.6.0 + 1.12.781 + 2.18.0 1.6.0 @@ -317,6 +318,12 @@ + + org.slf4j + slf4j-simple + ${slf4j.version} + test + org.skyscreamer jsonassert @@ -328,6 +335,12 @@ aspectjtools ${aspectj.version} + + org.mockito + mockito-core + ${mockito.version} + test + com.amazonaws aws-lambda-java-tests @@ -603,100 +616,6 @@ - - olderThanJdk11 - - (,11) - - - - 4.11.0 - - - - org.mockito - mockito-core - ${mockito.version} - test - - - org.mockito - mockito-inline - ${mockito.version} - test - - - - - newerThanJdk11 - - [11,) - - - 5.6.0 - - - - - org.mockito - mockito-core - ${mockito.version} - test - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - - true - - - - - - - - newerThanJdk8 - - [9,) - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.6.0 - - basedir=${project.rootdir} - checkstyle.xml - true - true - false - - - - - com.puppycrawl.tools - checkstyle - 10.18.1 - - - - - - check - - - - - - - diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 66a5e3087..819c19927 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -73,6 +73,16 @@ aws-lambda-java-tests test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + \ No newline at end of file diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index e3e4748d6..36392fce2 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -75,6 +75,16 @@ junit-jupiter-params test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + org.assertj assertj-core @@ -86,13 +96,4 @@ test - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - - - \ No newline at end of file + diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index ee6097310..47a505325 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -76,6 +76,16 @@ assertj-core test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + @@ -182,11 +192,5 @@ src/main/resources - - - org.apache.maven.plugins - maven-checkstyle-plugin - - - \ No newline at end of file + diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index c23707600..306e8060b 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -176,10 +176,6 @@ - - org.apache.maven.plugins - maven-checkstyle-plugin - org.apache.maven.plugins diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 302cc24f5..59b69da0f 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -38,5 +38,15 @@ powertools-serialization + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + \ No newline at end of file diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 4206183de..afbd0aa37 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -97,6 +97,16 @@ junit-pioneer test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + org.apache.commons commons-lang3 @@ -130,11 +140,7 @@
    - - org.apache.maven.plugins - maven-checkstyle-plugin - - \ No newline at end of file + diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 9d57c4221..62cb9c352 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -67,6 +67,16 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + org.junit-pioneer junit-pioneer @@ -201,10 +211,6 @@ - - org.apache.maven.plugins - maven-checkstyle-plugin - org.apache.maven.plugins maven-surefire-plugin @@ -217,4 +223,4 @@ - \ No newline at end of file + diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index ac1969010..96a9a7043 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -51,6 +51,11 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + org.junit-pioneer junit-pioneer @@ -215,10 +220,6 @@
    - - org.apache.maven.plugins - maven-checkstyle-plugin - org.apache.maven.plugins maven-surefire-plugin @@ -234,4 +235,4 @@ - \ No newline at end of file + diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 4af69ab77..a94801345 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -48,6 +48,11 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + org.apache.commons commons-lang3 @@ -208,10 +213,6 @@ - - org.apache.maven.plugins - maven-checkstyle-plugin - org.apache.maven.plugins maven-surefire-plugin @@ -228,4 +229,4 @@ - \ No newline at end of file + diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 22ac3c68e..d51ea5b33 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -77,6 +77,16 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + org.junit-pioneer junit-pioneer @@ -197,11 +207,5 @@ src/main/resources - - - org.apache.maven.plugins - maven-checkstyle-plugin - - diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 0f2b37151..09b8d3b2f 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -87,10 +87,6 @@ - - org.apache.maven.plugins - maven-checkstyle-plugin - diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 34b1238f6..be47fbddb 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -52,6 +52,16 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + org.apache.commons commons-lang3 @@ -80,10 +90,6 @@
    - - org.apache.maven.plugins - maven-checkstyle-plugin - - \ No newline at end of file + diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 2ec6ad27c..1713dbad5 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -53,6 +53,16 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + org.apache.commons commons-lang3 @@ -81,10 +91,6 @@
    - - org.apache.maven.plugins - maven-checkstyle-plugin - - \ No newline at end of file + diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 3275d0ee0..c2ea66f5c 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -53,6 +53,16 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + org.apache.commons commons-lang3 @@ -81,10 +91,6 @@
    - - org.apache.maven.plugins - maven-checkstyle-plugin - - \ No newline at end of file + diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 65332c9ef..475aca8f2 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -53,6 +53,16 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + org.apache.commons commons-lang3 @@ -81,10 +91,6 @@ - - org.apache.maven.plugins - maven-checkstyle-plugin - - \ No newline at end of file + diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index d8e9b2a02..6ab2e4155 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -48,6 +48,16 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + org.apache.commons commons-lang3 diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index e2bbbe82b..6c45b62dd 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -56,6 +56,11 @@ junit-jupiter-api test + + org.slf4j + slf4j-simple + test + org.assertj assertj-core @@ -172,11 +177,7 @@ true - - org.apache.maven.plugins - maven-checkstyle-plugin - - \ No newline at end of file + diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index ad0ed289f..140c212e3 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -78,6 +78,16 @@ junit-jupiter-engine test + + org.mockito + mockito-core + test + + + org.slf4j + slf4j-simple + test + org.junit-pioneer junit-pioneer @@ -196,14 +206,4 @@ - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - - - - \ No newline at end of file + diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index c1521f1c7..7d460eec3 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -83,7 +83,21 @@ junit-jupiter-engine test - + + org.slf4j + slf4j-simple + test + + + org.mockito + mockito-core + test + + + com.amazonaws + aws-lambda-java-tests + test + org.apache.commons commons-lang3 @@ -105,14 +119,4 @@ test - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - - - - - \ No newline at end of file + diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java index bcbba9e03..68900d334 100644 --- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationAspect.java @@ -40,11 +40,15 @@ import com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent; import com.amazonaws.services.lambda.runtime.events.RabbitMQEvent; import com.amazonaws.services.lambda.runtime.events.SNSEvent; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.amazonaws.services.lambda.runtime.events.ScheduledEvent; +import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; import com.networknt.schema.JsonSchema; +import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.ListIterator; import java.util.Map; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -57,7 +61,7 @@ import software.amazon.lambda.powertools.validation.ValidationException; /** - * Aspect for {@link Validation} annotation + * Aspect for {@link Validation} annotation. Internal to Powertools, use the annotation itself. */ @Aspect public class ValidationAspect { @@ -77,11 +81,12 @@ public Object around(ProceedingJoinPoint pjp, if (validation.schemaVersion() != V201909) { ValidationConfig.get().setSchemaVersion(validation.schemaVersion()); } - + // we need this result object to be null at this point as validation of API events, if // it fails, will catch the ValidationException and generate a 400 API response. This response // will be stored in the result object to prevent executing the lambda - Object result = null; + Object validationResult = null; + boolean failFast = false; if (placedOnRequestHandler(pjp)) { validationNeeded = true; @@ -94,16 +99,19 @@ public Object around(ProceedingJoinPoint pjp, validate(obj, inboundJsonSchema, validation.envelope()); } else if (obj instanceof APIGatewayProxyRequestEvent) { APIGatewayProxyRequestEvent event = (APIGatewayProxyRequestEvent) obj; - result = validateAPIGatewayProxyBody(event.getBody(), inboundJsonSchema, null, null); + validationResult = validateAPIGatewayProxyBody(event.getBody(), inboundJsonSchema, null, null); + failFast = true; } else if (obj instanceof APIGatewayV2HTTPEvent) { APIGatewayV2HTTPEvent event = (APIGatewayV2HTTPEvent) obj; - result = validateAPIGatewayV2HTTPBody(event.getBody(), inboundJsonSchema, null, null); + validationResult = validateAPIGatewayV2HTTPBody(event.getBody(), inboundJsonSchema, null, null); + failFast = true; } else if (obj instanceof SNSEvent) { SNSEvent event = (SNSEvent) obj; - event.getRecords().forEach(record -> validate(record.getSNS().getMessage(), inboundJsonSchema)); + event.getRecords() + .forEach(snsRecord -> validate(snsRecord.getSNS().getMessage(), inboundJsonSchema)); } else if (obj instanceof SQSEvent) { SQSEvent event = (SQSEvent) obj; - event.getRecords().forEach(record -> validate(record.getBody(), inboundJsonSchema)); + validationResult = validateSQSEventMessages(event.getRecords(), inboundJsonSchema); } else if (obj instanceof ScheduledEvent) { ScheduledEvent event = (ScheduledEvent) obj; validate(event.getDetail(), inboundJsonSchema); @@ -118,30 +126,32 @@ public Object around(ProceedingJoinPoint pjp, validate(event.getResourceProperties(), inboundJsonSchema); } else if (obj instanceof KinesisEvent) { KinesisEvent event = (KinesisEvent) obj; - event.getRecords() - .forEach(record -> validate(decode(record.getKinesis().getData()), inboundJsonSchema)); + validationResult = validateKinesisEventRecords(event.getRecords(), inboundJsonSchema); } else if (obj instanceof KinesisFirehoseEvent) { KinesisFirehoseEvent event = (KinesisFirehoseEvent) obj; - event.getRecords().forEach(record -> validate(decode(record.getData()), inboundJsonSchema)); + event.getRecords() + .forEach(eventRecord -> validate(decode(eventRecord.getData()), inboundJsonSchema)); } else if (obj instanceof KafkaEvent) { KafkaEvent event = (KafkaEvent) obj; event.getRecords().forEach((s, records) -> records.forEach( - record -> validate(decode(record.getValue()), inboundJsonSchema))); + eventRecord -> validate(decode(eventRecord.getValue()), inboundJsonSchema))); } else if (obj instanceof ActiveMQEvent) { ActiveMQEvent event = (ActiveMQEvent) obj; - event.getMessages().forEach(record -> validate(decode(record.getData()), inboundJsonSchema)); + event.getMessages().forEach(message -> validate(decode(message.getData()), inboundJsonSchema)); } else if (obj instanceof RabbitMQEvent) { RabbitMQEvent event = (RabbitMQEvent) obj; event.getRmqMessagesByQueue().forEach((s, records) -> records.forEach( - record -> validate(decode(record.getData()), inboundJsonSchema))); + message -> validate(decode(message.getData()), inboundJsonSchema))); } else if (obj instanceof KinesisAnalyticsFirehoseInputPreprocessingEvent) { KinesisAnalyticsFirehoseInputPreprocessingEvent event = (KinesisAnalyticsFirehoseInputPreprocessingEvent) obj; - event.getRecords().forEach(record -> validate(decode(record.getData()), inboundJsonSchema)); + event.getRecords() + .forEach(eventRecord -> validate(decode(eventRecord.getData()), inboundJsonSchema)); } else if (obj instanceof KinesisAnalyticsStreamsInputPreprocessingEvent) { KinesisAnalyticsStreamsInputPreprocessingEvent event = (KinesisAnalyticsStreamsInputPreprocessingEvent) obj; - event.getRecords().forEach(record -> validate(decode(record.getData()), inboundJsonSchema)); + event.getRecords() + .forEach(eventRecord -> validate(decode(eventRecord.getData()), inboundJsonSchema)); } else { LOG.warn("Unhandled event type {}, please use the 'envelope' parameter to specify what to validate", obj.getClass().getName()); @@ -149,100 +159,183 @@ record -> validate(decode(record.getData()), inboundJsonSchema))); } } - // don't execute the lambda if result was set by previous validation step + Object result; + + // don't execute the lambda if result was set by previous validation step and should fail fast // in that case result should already hold a response with validation information - if (result != null) { - LOG.error("Incoming API event's body failed inbound schema validation."); + if (failFast && validationResult != null) { + LOG.error("Incoming API event's body failed inbound schema validation."); + return validationResult; + } else { + result = pjp.proceed(proceedArgs); + + if (validationResult != null && result != null) { + // in the case of batches (SQS, Kinesis), we copy the batch item failures to the result + if (result instanceof SQSBatchResponse && validationResult instanceof SQSBatchResponse) { + SQSBatchResponse validationResponse = (SQSBatchResponse) validationResult; + SQSBatchResponse response = (SQSBatchResponse) result; + if (response.getBatchItemFailures() == null) { + response.setBatchItemFailures(validationResponse.getBatchItemFailures()); + } else { + response.getBatchItemFailures().addAll(validationResponse.getBatchItemFailures()); + } + } else if (result instanceof StreamsEventResponse && validationResult instanceof StreamsEventResponse) { + StreamsEventResponse validationResponse = (StreamsEventResponse) validationResult; + StreamsEventResponse response = (StreamsEventResponse) result; + if (response.getBatchItemFailures() == null) { + response.setBatchItemFailures(validationResponse.getBatchItemFailures()); + } else { + response.getBatchItemFailures().addAll(validationResponse.getBatchItemFailures()); + } + } + } + + if (result != null && validationNeeded && !validation.outboundSchema().isEmpty()) { + JsonSchema outboundJsonSchema = getJsonSchema(validation.outboundSchema(), true); + + Object overridenResponse = null; + // The normal behavior of @Validation is to throw an exception if response's validation fails. + // but in the case of APIGatewayProxyResponseEvent and APIGatewayV2HTTPResponse we want to return + // a 400 response with the validation errors instead of throwing an exception. + if (result instanceof APIGatewayProxyResponseEvent) { + APIGatewayProxyResponseEvent response = (APIGatewayProxyResponseEvent) result; + overridenResponse = + validateAPIGatewayProxyBody(response.getBody(), outboundJsonSchema, response.getHeaders(), + response.getMultiValueHeaders()); + } else if (result instanceof APIGatewayV2HTTPResponse) { + APIGatewayV2HTTPResponse response = (APIGatewayV2HTTPResponse) result; + overridenResponse = + validateAPIGatewayV2HTTPBody(response.getBody(), outboundJsonSchema, response.getHeaders(), + response.getMultiValueHeaders()); + // all type of below responses will throw an exception if validation fails + } else if (result instanceof APIGatewayV2WebSocketResponse) { + APIGatewayV2WebSocketResponse response = (APIGatewayV2WebSocketResponse) result; + validate(response.getBody(), outboundJsonSchema); + } else if (result instanceof ApplicationLoadBalancerResponseEvent) { + ApplicationLoadBalancerResponseEvent response = (ApplicationLoadBalancerResponseEvent) result; + validate(response.getBody(), outboundJsonSchema); + } else if (result instanceof KinesisAnalyticsInputPreprocessingResponse) { + KinesisAnalyticsInputPreprocessingResponse response = + (KinesisAnalyticsInputPreprocessingResponse) result; + response.getRecords().forEach(record -> validate(decode(record.getData()), outboundJsonSchema)); + } else { + LOG.warn( + "Unhandled response type {}, please use the 'envelope' parameter to specify what to validate", + result.getClass().getName()); + } + + if (overridenResponse != null) { + result = overridenResponse; + LOG.error("API response failed outbound schema validation."); + } + } } - else { - result = pjp.proceed(proceedArgs); - - if (validationNeeded && !validation.outboundSchema().isEmpty()) { - JsonSchema outboundJsonSchema = getJsonSchema(validation.outboundSchema(), true); - - Object overridenResponse = null; - // The normal behavior of @Validation is to throw an exception if response's validation fails. - // but in the case of APIGatewayProxyResponseEvent and APIGatewayV2HTTPResponse we want to return - // a 400 response with the validation errors instead of throwing an exception. - if (result instanceof APIGatewayProxyResponseEvent) { - APIGatewayProxyResponseEvent response = (APIGatewayProxyResponseEvent) result; - overridenResponse = validateAPIGatewayProxyBody(response.getBody(), outboundJsonSchema, response.getHeaders(), - response.getMultiValueHeaders()); - } else if (result instanceof APIGatewayV2HTTPResponse) { - APIGatewayV2HTTPResponse response = (APIGatewayV2HTTPResponse) result; - overridenResponse = validateAPIGatewayV2HTTPBody(response.getBody(), outboundJsonSchema, response.getHeaders(), - response.getMultiValueHeaders()); - // all type of below responses will throw an exception if validation fails - } else if (result instanceof APIGatewayV2WebSocketResponse) { - APIGatewayV2WebSocketResponse response = (APIGatewayV2WebSocketResponse) result; - validate(response.getBody(), outboundJsonSchema); - } else if (result instanceof ApplicationLoadBalancerResponseEvent) { - ApplicationLoadBalancerResponseEvent response = (ApplicationLoadBalancerResponseEvent) result; - validate(response.getBody(), outboundJsonSchema); - } else if (result instanceof KinesisAnalyticsInputPreprocessingResponse) { - KinesisAnalyticsInputPreprocessingResponse response = - (KinesisAnalyticsInputPreprocessingResponse) result; - response.getRecords().forEach(record -> validate(decode(record.getData()), outboundJsonSchema)); - } else { - LOG.warn("Unhandled response type {}, please use the 'envelope' parameter to specify what to validate", - result.getClass().getName()); - } - - if (overridenResponse != null) { - result = overridenResponse; - LOG.error("API response failed outbound schema validation."); - } - } - } return result; } - + + /** + * Validate each Kinesis record body. If an error occurs, do not fail the whole batch but only add invalid items in BatchItemFailure. + * Note that the valid records will be decoded twice (during validation and within the handler by the user), which will slightly reduce performance. + * @param records Kinesis records + * @param inboundJsonSchema validation schema + * @return the stream response with items in failure + */ + private StreamsEventResponse validateKinesisEventRecords(List records, + JsonSchema inboundJsonSchema) { + StreamsEventResponse response = StreamsEventResponse.builder().withBatchItemFailures(new ArrayList<>()).build(); + + ListIterator listIterator = records.listIterator(); // using iterator to remove while browsing + while (listIterator.hasNext()) { + KinesisEvent.KinesisEventRecord eventRecord = listIterator.next(); + try { + validate(decode(eventRecord.getKinesis().getData()), inboundJsonSchema); + } catch (ValidationException e) { + LOG.error("Validation error on message {}: {}", eventRecord.getKinesis().getSequenceNumber(), + e.getMessage()); + listIterator.remove(); + response.getBatchItemFailures().add(StreamsEventResponse.BatchItemFailure.builder() + .withItemIdentifier(eventRecord.getKinesis().getSequenceNumber()).build()); + } + } + return response; + } + + /** + * Validate each SQS message body. If an error occurs, do not fail the whole batch but only add invalid items in BatchItemFailure. + * + * @param messages SQS messages + * @param inboundJsonSchema validation schema + * @return the SQS batch response + */ + private SQSBatchResponse validateSQSEventMessages(List messages, + JsonSchema inboundJsonSchema) { + SQSBatchResponse response = SQSBatchResponse.builder().withBatchItemFailures(new ArrayList<>()).build(); + ListIterator listIterator = messages.listIterator(); // using iterator to remove while browsing + while (listIterator.hasNext()) { + SQSEvent.SQSMessage message = listIterator.next(); + try { + validate(message.getBody(), inboundJsonSchema); + } catch (ValidationException e) { + LOG.error("Validation error on message {}: {}", message.getMessageId(), e.getMessage()); + listIterator.remove(); + response.getBatchItemFailures() + .add(SQSBatchResponse.BatchItemFailure.builder().withItemIdentifier(message.getMessageId()) + .build()); + } + } + return response; + } + /** * Validates the given body against the provided JsonSchema. If validation fails the ValidationException * will be catched and transformed to a 400, bad request, API response - * @param body body of the event to validate - * @param inboundJsonSchema validation schema + * + * @param body body of the event to validate + * @param jsonSchema validation schema * @return null if validation passed, or a 400 response object otherwise */ private APIGatewayProxyResponseEvent validateAPIGatewayProxyBody(final String body, final JsonSchema jsonSchema, - final Map headers, Map> multivalueHeaders) { - APIGatewayProxyResponseEvent result = null; - try { - validate(body, jsonSchema); - } catch (ValidationException e) { - LOG.error("There were validation errors: {}", e.getMessage()); - result = new APIGatewayProxyResponseEvent(); - result.setBody(e.getMessage()); - result.setHeaders(headers == null ? Collections.emptyMap() : headers); - result.setMultiValueHeaders(multivalueHeaders == null ? Collections.emptyMap() : multivalueHeaders); - result.setStatusCode(400); - result.setIsBase64Encoded(false); - } - return result; + final Map headers, + Map> multivalueHeaders) { + APIGatewayProxyResponseEvent result = null; + try { + validate(body, jsonSchema); + } catch (ValidationException e) { + LOG.error("There were validation errors: {}", e.getMessage()); + result = new APIGatewayProxyResponseEvent(); + result.setBody(e.getMessage()); + result.setHeaders(headers == null ? Collections.emptyMap() : headers); + result.setMultiValueHeaders(multivalueHeaders == null ? Collections.emptyMap() : multivalueHeaders); + result.setStatusCode(400); + result.setIsBase64Encoded(false); + } + return result; } - + /** * Validates the given body against the provided JsonSchema. If validation fails the ValidationException * will be catched and transformed to a 400, bad request, API response - * @param body body of the event to validate - * @param inboundJsonSchema validation schema + * + * @param body body of the event to validate + * @param jsonSchema validation schema * @return null if validation passed, or a 400 response object otherwise */ private APIGatewayV2HTTPResponse validateAPIGatewayV2HTTPBody(final String body, final JsonSchema jsonSchema, - final Map headers, Map> multivalueHeaders) { - APIGatewayV2HTTPResponse result = null; - try { - validate(body, jsonSchema); - } catch (ValidationException e) { - LOG.error("There were validation errors: {}", e.getMessage()); - result = new APIGatewayV2HTTPResponse(); - result.setBody(e.getMessage()); - result.setHeaders(headers == null ? Collections.emptyMap() : headers); - result.setMultiValueHeaders(multivalueHeaders == null ? Collections.emptyMap() : multivalueHeaders); - result.setStatusCode(400); - result.setIsBase64Encoded(false); - } - return result; + final Map headers, + Map> multivalueHeaders) { + APIGatewayV2HTTPResponse result = null; + try { + validate(body, jsonSchema); + } catch (ValidationException e) { + LOG.error("There were validation errors: {}", e.getMessage()); + result = new APIGatewayV2HTTPResponse(); + result.setBody(e.getMessage()); + result.setHeaders(headers == null ? Collections.emptyMap() : headers); + result.setMultiValueHeaders(multivalueHeaders == null ? Collections.emptyMap() : multivalueHeaders); + result.setStatusCode(400); + result.setIsBase64Encoded(false); + } + return result; } } diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/KinesisHandlerWithError.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/KinesisHandlerWithError.java new file mode 100644 index 000000000..e6e702fb6 --- /dev/null +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/KinesisHandlerWithError.java @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.validation.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.KinesisEvent; +import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; +import java.util.ArrayList; +import software.amazon.lambda.powertools.validation.Validation; + +public class KinesisHandlerWithError implements RequestHandler { + + @Override + @Validation(inboundSchema = "classpath:/schema_v7.json") + public StreamsEventResponse handleRequest(KinesisEvent input, Context context) { + StreamsEventResponse response = StreamsEventResponse.builder().withBatchItemFailures(new ArrayList<>()).build(); + assert input.getRecords().size() == 2; // invalid messages have been removed from the input + response.getBatchItemFailures().add(StreamsEventResponse.BatchItemFailure.builder().withItemIdentifier("1234").build()); + return response; + } +} diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSHandlerWithError.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSHandlerWithError.java new file mode 100644 index 000000000..23fceab5b --- /dev/null +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/SQSHandlerWithError.java @@ -0,0 +1,34 @@ +/* + * Copyright 2024 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.validation.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import java.util.ArrayList; +import software.amazon.lambda.powertools.validation.Validation; + +public class SQSHandlerWithError implements RequestHandler { + + @Override + @Validation(inboundSchema = "classpath:/schema_v7.json") + public SQSBatchResponse handleRequest(SQSEvent input, Context context) { + SQSBatchResponse response = SQSBatchResponse.builder().withBatchItemFailures(new ArrayList<>()).build(); + assert input.getRecords().size() == 2; // invalid messages have been removed from the input + response.getBatchItemFailures().add(SQSBatchResponse.BatchItemFailure.builder().withItemIdentifier("1234").build()); + return response; + } +} diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/StandardKinesisHandler.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/StandardKinesisHandler.java new file mode 100644 index 000000000..1afc5c5ec --- /dev/null +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/StandardKinesisHandler.java @@ -0,0 +1,32 @@ +/* + * Copyright 2024 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.validation.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.KinesisEvent; +import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; +import software.amazon.lambda.powertools.validation.Validation; + +public class StandardKinesisHandler implements RequestHandler { + + @Override + @Validation(inboundSchema = "classpath:/schema_v7.json") + public StreamsEventResponse handleRequest(KinesisEvent input, Context context) { + StreamsEventResponse response = StreamsEventResponse.builder().build(); + assert input.getRecords().size() == 2; // invalid messages have been removed from the input + return response; + } +} diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/StandardSQSHandler.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/StandardSQSHandler.java new file mode 100644 index 000000000..e0f0ece2d --- /dev/null +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/handlers/StandardSQSHandler.java @@ -0,0 +1,32 @@ +/* + * Copyright 2024 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.validation.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import software.amazon.lambda.powertools.validation.Validation; + +public class StandardSQSHandler implements RequestHandler { + + @Override + @Validation(inboundSchema = "classpath:/schema_v7.json") + public SQSBatchResponse handleRequest(SQSEvent input, Context context) { + SQSBatchResponse response = SQSBatchResponse.builder().build(); + assert input.getRecords().size() == 2; // invalid messages have been removed from the input + return response; + } +} diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java index 1708ebeeb..42a18307e 100644 --- a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationAspectTest.java @@ -20,24 +20,6 @@ import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.Mockito.when; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; - -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.Signature; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.ArgumentsSource; -import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; @@ -55,24 +37,45 @@ import com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent; import com.amazonaws.services.lambda.runtime.events.RabbitMQEvent; import com.amazonaws.services.lambda.runtime.events.SNSEvent; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.amazonaws.services.lambda.runtime.events.ScheduledEvent; -import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer; -import com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers; +import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; +import com.amazonaws.services.lambda.runtime.tests.annotations.Event; import com.networknt.schema.SpecVersion; - +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.ArgumentsSource; +import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import software.amazon.lambda.powertools.validation.Validation; import software.amazon.lambda.powertools.validation.ValidationConfig; import software.amazon.lambda.powertools.validation.ValidationException; import software.amazon.lambda.powertools.validation.handlers.GenericSchemaV7APIGatewayProxyRequestEventHandler; import software.amazon.lambda.powertools.validation.handlers.GenericSchemaV7StringHandler; +import software.amazon.lambda.powertools.validation.handlers.KinesisHandlerWithError; +import software.amazon.lambda.powertools.validation.handlers.SQSHandlerWithError; import software.amazon.lambda.powertools.validation.handlers.SQSWithCustomEnvelopeHandler; import software.amazon.lambda.powertools.validation.handlers.SQSWithWrongEnvelopeHandler; +import software.amazon.lambda.powertools.validation.handlers.StandardKinesisHandler; +import software.amazon.lambda.powertools.validation.handlers.StandardSQSHandler; import software.amazon.lambda.powertools.validation.handlers.ValidationInboundAPIGatewayV2HTTPEventHandler; import software.amazon.lambda.powertools.validation.model.MyCustomEvent; -public class ValidationAspectTest { +class ValidationAspectTest { @Mock Validation validation; @@ -167,7 +170,7 @@ void testValidateOutboundJsonSchemaWithHandledExceptions(Object object) throws T } @Test - public void testValidateOutboundJsonSchema_APIGWV2() throws Throwable { + void testValidateOutboundJsonSchema_APIGWV2() throws Throwable { when(validation.schemaVersion()).thenReturn(SpecVersion.VersionFlag.V7); when(pjp.getSignature()).thenReturn(signature); when(pjp.getSignature().getDeclaringType()).thenReturn(RequestHandler.class); @@ -187,7 +190,7 @@ public void testValidateOutboundJsonSchema_APIGWV2() throws Throwable { } @Test - public void validate_inputOK_schemaInClasspath_shouldValidate() { + void validate_inputOK_schemaInClasspath_shouldValidate() { GenericSchemaV7APIGatewayProxyRequestEventHandler handler = new GenericSchemaV7APIGatewayProxyRequestEventHandler(); APIGatewayProxyRequestEvent event = new APIGatewayProxyRequestEvent(); event.setBody("{" + @@ -204,7 +207,7 @@ public void validate_inputOK_schemaInClasspath_shouldValidate() { } @Test - public void validate_inputKO_schemaInClasspath_shouldThrowValidationException() { + void validate_inputKO_schemaInClasspath_shouldThrowValidationException() { GenericSchemaV7APIGatewayProxyRequestEventHandler handler = new GenericSchemaV7APIGatewayProxyRequestEventHandler(); Map headers = new HashMap<>(); @@ -232,7 +235,7 @@ public void validate_inputKO_schemaInClasspath_shouldThrowValidationException() } @Test - public void validate_inputOK_schemaInString_shouldValidate() { + void validate_inputOK_schemaInString_shouldValidate() { ValidationInboundAPIGatewayV2HTTPEventHandler handler = new ValidationInboundAPIGatewayV2HTTPEventHandler(); APIGatewayV2HTTPEvent event = new APIGatewayV2HTTPEvent(); event.setBody("{" + @@ -248,7 +251,7 @@ public void validate_inputOK_schemaInString_shouldValidate() { @Test - public void validate_inputKO_schemaInString_shouldThrowValidationException() { + void validate_inputKO_schemaInString_shouldThrowValidationException() { ValidationInboundAPIGatewayV2HTTPEventHandler handler = new ValidationInboundAPIGatewayV2HTTPEventHandler(); Map headers = new HashMap<>(); @@ -268,49 +271,77 @@ public void validate_inputKO_schemaInString_shouldThrowValidationException() { assertThat(response.getMultiValueHeaders()).isEmpty(); } - @Test - public void validate_SQS() { - PojoSerializer pojoSerializer = - LambdaEventSerializers.serializerFor(SQSEvent.class, ClassLoader.getSystemClassLoader()); - SQSEvent event = pojoSerializer.fromJson(this.getClass().getResourceAsStream("/sqs.json")); - + @ParameterizedTest + @Event(value = "sqs.json", type = SQSEvent.class) + void validate_SQS(SQSEvent event) { GenericSchemaV7StringHandler handler = new GenericSchemaV7StringHandler<>(); assertThat(handler.handleRequest(event, context)).isEqualTo("OK"); } - @Test - public void validate_SQS_CustomEnvelopeTakePrecedence() { - PojoSerializer pojoSerializer = - LambdaEventSerializers.serializerFor(SQSEvent.class, ClassLoader.getSystemClassLoader()); - SQSEvent event = pojoSerializer.fromJson(this.getClass().getResourceAsStream("/sqs_message.json")); + @ParameterizedTest + @Event(value = "sqs_invalid_messages.json", type = SQSEvent.class) + void validate_SQS_with_validation_partial_failure(SQSEvent event) { + StandardSQSHandler handler = new StandardSQSHandler(); + SQSBatchResponse response = handler.handleRequest(event, context); + assertThat(response.getBatchItemFailures()).hasSize(2); + assertThat(response.getBatchItemFailures().stream().map(SQSBatchResponse.BatchItemFailure::getItemIdentifier).collect( + Collectors.toList())).contains("d9144555-9a4f-4ec3-99a0-fc4e625a8db3", "d9144555-9a4f-4ec3-99a0-fc4e625a8db5"); + } + + @ParameterizedTest + @Event(value = "sqs_invalid_messages.json", type = SQSEvent.class) + void validate_SQS_with_partial_failure(SQSEvent event) { + SQSHandlerWithError handler = new SQSHandlerWithError(); + SQSBatchResponse response = handler.handleRequest(event, context); + assertThat(response.getBatchItemFailures()).hasSize(3); + assertThat(response.getBatchItemFailures().stream().map(SQSBatchResponse.BatchItemFailure::getItemIdentifier).collect( + Collectors.toList())).contains("d9144555-9a4f-4ec3-99a0-fc4e625a8db3", "d9144555-9a4f-4ec3-99a0-fc4e625a8db5", "1234"); + } + @ParameterizedTest + @Event(value = "sqs_message.json", type = SQSEvent.class) + void validate_SQS_CustomEnvelopeTakePrecedence(SQSEvent event) { SQSWithCustomEnvelopeHandler handler = new SQSWithCustomEnvelopeHandler(); assertThat(handler.handleRequest(event, context)).isEqualTo("OK"); } - @Test - public void validate_SQS_WrongEnvelope_shouldThrowValidationException() { - PojoSerializer pojoSerializer = - LambdaEventSerializers.serializerFor(SQSEvent.class, ClassLoader.getSystemClassLoader()); - SQSEvent event = pojoSerializer.fromJson(this.getClass().getResourceAsStream("/sqs_message.json")); - + @ParameterizedTest + @Event(value = "sqs_message.json", type = SQSEvent.class) + void validate_SQS_WrongEnvelope_shouldThrowValidationException(SQSEvent event) { SQSWithWrongEnvelopeHandler handler = new SQSWithWrongEnvelopeHandler(); assertThatExceptionOfType(ValidationException.class).isThrownBy(() -> handler.handleRequest(event, context)); } - @Test - public void validate_Kinesis() { - PojoSerializer pojoSerializer = - LambdaEventSerializers.serializerFor(KinesisEvent.class, ClassLoader.getSystemClassLoader()); - KinesisEvent event = pojoSerializer.fromJson(this.getClass().getResourceAsStream("/kinesis.json")); - + @ParameterizedTest + @Event(value = "kinesis.json", type = KinesisEvent.class) + void validate_Kinesis(KinesisEvent event) { GenericSchemaV7StringHandler handler = new GenericSchemaV7StringHandler<>(); assertThat(handler.handleRequest(event, context)).isEqualTo("OK"); } + @ParameterizedTest + @Event(value = "kinesis_invalid_messages.json", type = KinesisEvent.class) + void validate_Kinesis_with_validation_partial_failure(KinesisEvent event) { + StandardKinesisHandler handler = new StandardKinesisHandler(); + StreamsEventResponse response = handler.handleRequest(event, context); + assertThat(response.getBatchItemFailures()).hasSize(2); + assertThat(response.getBatchItemFailures().stream().map(StreamsEventResponse.BatchItemFailure::getItemIdentifier).collect( + Collectors.toList())).contains("49545115243490985018280067714973144582180062593244200962", "49545115243490985018280067714973144582180062593244200964"); + } + + @ParameterizedTest + @Event(value = "kinesis_invalid_messages.json", type = KinesisEvent.class) + void validate_Kinesis_with_partial_failure(KinesisEvent event) { + KinesisHandlerWithError handler = new KinesisHandlerWithError(); + StreamsEventResponse response = handler.handleRequest(event, context); + assertThat(response.getBatchItemFailures()).hasSize(3); + assertThat(response.getBatchItemFailures().stream().map(StreamsEventResponse.BatchItemFailure::getItemIdentifier).collect( + Collectors.toList())).contains("49545115243490985018280067714973144582180062593244200962", "49545115243490985018280067714973144582180062593244200964", "1234"); + } + @ParameterizedTest @MethodSource("provideEventAndEventType") - public void validateEEvent(String jsonResource, Class eventClass) throws IOException { + void validateEEvent(String jsonResource, Class eventClass) throws IOException { Object event = ValidationConfig.get().getObjectMapper() .readValue(this.getClass().getResourceAsStream(jsonResource), eventClass); diff --git a/powertools-validation/src/test/resources/kinesis_invalid_messages.json b/powertools-validation/src/test/resources/kinesis_invalid_messages.json new file mode 100644 index 000000000..3d805c4dd --- /dev/null +++ b/powertools-validation/src/test/resources/kinesis_invalid_messages.json @@ -0,0 +1,72 @@ +{ + "Records": [ + { + "kinesis": { + "partitionKey": "partitionKey-03", + "kinesisSchemaVersion": "1.0", + "data": "ewogICJpZCI6IDQzMjQyLAogICJuYW1lIjogIkZvb0JhciBYWSIsCiAgInByaWNlIjogMjU4Cn0=", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200961", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-04", + "kinesisSchemaVersion": "1.0", + "data": "ewogICJpZCI6InN0cmluZ0lkIiwKICAibmFtZSI6ICJGb29CYXIgWFkiLAogICJwcmljZSI6IDI1OAp9", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200962", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-04", + "kinesisSchemaVersion": "1.0", + "data": "ewogICJpZCI6IDQyNSwKICAibmFtZSI6ICJCYXJGb28iLAogICJwcmljZSI6IDQzCn0=", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200963", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + }, + { + "kinesis": { + "partitionKey": "partitionKey-04", + "kinesisSchemaVersion": "1.0", + "data": "ewogICJpZCI6MTIzNCwKICAibmFtZSI6ICJGb28iLAogICJwcmljZSI6IDI1OAp9", + "sequenceNumber": "49545115243490985018280067714973144582180062593244200964", + "approximateArrivalTimestamp": 1428537600, + "encryptionType": "NONE" + }, + "eventSource": "aws:kinesis", + "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961", + "invokeIdentityArn": "arn:aws:iam::EXAMPLE", + "eventVersion": "1.0", + "eventName": "aws:kinesis:record", + "eventSourceARN": "arn:aws:kinesis:EXAMPLE", + "awsRegion": "eu-central-1" + } + ] +} diff --git a/powertools-validation/src/test/resources/sqs_invalid_messages.json b/powertools-validation/src/test/resources/sqs_invalid_messages.json new file mode 100644 index 000000000..aaec54bfd --- /dev/null +++ b/powertools-validation/src/test/resources/sqs_invalid_messages.json @@ -0,0 +1,72 @@ +{ + "Records": [ + { + "messageId": "d9144555-9a4f-4ec3-99a0-fc4e625a8db2", + "receiptHandle": "7kam5bfzbDsjtcjElvhSbxeLJbeey3A==", + "body": "{\n \"id\": 43242,\n \"name\": \"FooBar XY\",\n \"price\": 258\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975709495", + "SenderId": "AROAIFU457DVZ5L2J53F2", + "ApproximateFirstReceiveTimestamp": "1601975709499" + }, + "messageAttributes": { + }, + "md5OfBody": "0f96e88a291edb4429f2f7b9fdc3df96", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "d9144555-9a4f-4ec3-99a0-fc4e625a8db3", + "receiptHandle": "7kam5bfzbDsjtcjElvhSbxeLJbeey3A==", + "body": "{\n \"id\": 43245,\n \"name\": \"Foo\",\n \"price\": 258\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975709495", + "SenderId": "AROAIFU457DVZ5L2J53F2", + "ApproximateFirstReceiveTimestamp": "1601975709499" + }, + "messageAttributes": { + }, + "md5OfBody": "0f96e88a291edb4429f2f7b9fdc3df96", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "d9144555-9a4f-4ec3-99a0-fc4e625a8db4", + "receiptHandle": "7kam5bfzbDsjtcjElvhSbxeLJbeey3A==", + "body": "{\n \"id\": 43246,\n \"name\": \"FooBar XYZ\",\n \"price\": 258\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975709495", + "SenderId": "AROAIFU457DVZ5L2J53F2", + "ApproximateFirstReceiveTimestamp": "1601975709499" + }, + "messageAttributes": { + }, + "md5OfBody": "0f96e88a291edb4429f2f7b9fdc3df96", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "d9144555-9a4f-4ec3-99a0-fc4e625a8db5", + "receiptHandle": "7kam5bfzbDsjtcjElvhSbxeLJbeey3A==", + "body": "{\n \"id\": \"stringId\",\n \"name\": \"FooBar XY\",\n \"price\": 258\n}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975709495", + "SenderId": "AROAIFU457DVZ5L2J53F2", + "ApproximateFirstReceiveTimestamp": "1601975709499" + }, + "messageAttributes": { + }, + "md5OfBody": "0f96e88a291edb4429f2f7b9fdc3df96", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + } + ] +} \ No newline at end of file From 9d111b396719d3076998ce0586bef960c4bf8e90 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 15 May 2025 16:23:29 +0200 Subject: [PATCH 234/577] fix(logging): Escape double-quotes when serializing strings into JSON. (#1845) --- .../internal/LambdaJsonEncoderTest.java | 9 +++-- .../logging/internal/JsonSerializer.java | 36 +++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 9b6fb8d1c..4a7067540 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -127,7 +127,8 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { assertThat(contentOf(logFile)) .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") - .contains("\"message\":\"Message body = plop and id = \"1212abcd\"\""); + // Should auto-escape double quotes around id + .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); // Reserved keys should be ignored PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> { assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\""); @@ -158,7 +159,8 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { assertThat(contentOf(logFile)) .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") - .contains("\"message\":\"Message body = plop and id = \"1212abcd\"\""); + // Should auto-escape double quotes around id + .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); // Reserved keys should be ignored PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> { assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\""); @@ -295,7 +297,8 @@ void shouldLogEventAsStringForStreamHandler() throws IOException { File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) .contains("\"message\":\"Handler Event\"") - .contains("\"event\":\"{\"key\":\"value\"}\""); // logged as String for StreamHandler + // logged as String for StreamHandler (should auto-escape double-quotes to avoid breaking JSON format) + .contains("\"event\":\"{\\\"key\\\":\\\"value\\\"}\""); } @Test diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java index 0b4359825..82bc76a38 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java @@ -53,7 +53,7 @@ public JsonSerializer(StringBuilder builder) { } this.builder = builder; } - + public void writeStartArray() { builder.append('['); } @@ -84,7 +84,8 @@ public void writeString(String text) { if (text == null) { writeNull(); } else { - builder.append("\"").append(text).append("\""); + // Escape double quotes to avoid breaking JSON format + builder.append("\"").append(text.replace("\"", "\\\"")).append("\""); } } @@ -314,7 +315,7 @@ public void writeMap(final Map map) { writeNull(); } else { writeStartObject(); - for (Iterator> entries = map.entrySet().iterator(); entries.hasNext(); ) { + for (Iterator> entries = map.entrySet().iterator(); entries.hasNext();) { Map.Entry entry = entries.next(); writeObjectField(String.valueOf(entry.getKey()), entry.getValue()); if (entries.hasNext()) { @@ -326,16 +327,16 @@ public void writeMap(final Map map) { } public void writeObject(Object value) { - + // null if (value == null) { writeNull(); - } - + } + else if (value instanceof String) { writeString((String) value); - } - + } + // number & boolean else if (value instanceof Number) { Number n = (Number) value; @@ -364,8 +365,8 @@ else if (value instanceof Number) { writeBoolean((Boolean) value); } else if (value instanceof AtomicBoolean) { writeBoolean(((AtomicBoolean) value).get()); - } - + } + // list & collection else if (value instanceof List) { final List list = (List) value; @@ -373,15 +374,14 @@ else if (value instanceof List) { } else if (value instanceof Collection) { final Collection collection = (Collection) value; writeArray(collection); - } - + } + // map else if (value instanceof Map) { final Map map = (Map) value; writeMap(map); } - // arrays else if (value instanceof char[]) { final char[] charValues = (char[]) value; @@ -411,7 +411,7 @@ else if (value instanceof char[]) { final Object[] values = (Object[]) value; writeArray(values); } - + else if (value instanceof JsonNode) { JsonNode node = (JsonNode) value; @@ -462,7 +462,7 @@ else if (value instanceof JsonNode) { case OBJECT: case POJO: writeStartObject(); - for (Iterator> entries = node.fields(); entries.hasNext(); ) { + for (Iterator> entries = node.fields(); entries.hasNext();) { Map.Entry entry = entries.next(); writeObjectField(entry.getKey(), entry.getValue()); if (entries.hasNext()) { @@ -475,7 +475,7 @@ else if (value instanceof JsonNode) { case ARRAY: ArrayNode arrayNode = (ArrayNode) node; writeStartArray(); - for (Iterator elements = arrayNode.elements(); elements.hasNext(); ) { + for (Iterator elements = arrayNode.elements(); elements.hasNext();) { writeObject(elements.next()); if (elements.hasNext()) { builder.append(','); @@ -558,7 +558,7 @@ public void writeTree(TreeNode rootNode) { writeNull(); } else if (rootNode instanceof TextNode) { writeString(((TextNode) rootNode).asText()); - } else if (rootNode instanceof BooleanNode) { + } else if (rootNode instanceof BooleanNode) { writeBoolean(((BooleanNode) rootNode).asBoolean()); } else if (rootNode instanceof NumericNode) { NumericNode numericNode = (NumericNode) rootNode; @@ -595,5 +595,3 @@ public void close() { // nothing to do } } - - From 00198dddb152aceca1bc556d11356a0bcc316233 Mon Sep 17 00:00:00 2001 From: Jeroen Reijn Date: Mon, 26 May 2025 16:42:13 +0200 Subject: [PATCH 235/577] feat(v2): GraalVM support for parameters module (#1824) * Initial commit of all adding graalvm metadata to all parameter modules * Introduce a working example with sam and graalvm for parameters module * Add GraalVM to example name. * Add 'mvn clean package -P native-image' to Makefile again. * Remove test dependency GraalVM metadata. * Set minimum version of core utility parameters example to Java 11 to allow GitHub workflows to check minimum compatible Java version. * remove wrongly introduced class * Set AspectJ versioon to 1.9.20.1 for core utility graalvm example. --------- Co-authored-by: Philipp Page Co-authored-by: Philipp Page --- examples/pom.xml | 4 +- .../sam-graalvm/pom.xml | 10 +- .../sam-graalvm/Dockerfile | 14 + .../sam-graalvm/Makefile | 6 + .../sam-graalvm/README.md | 80 ++++ .../sam-graalvm/pom.xml | 204 ++++++++++ .../sam-graalvm/src/main/config/bootstrap | 4 + .../java/org/demo/parameters/MyObject.java | 0 .../demo/parameters/ParametersFunction.java | 0 .../aws-lambda-java-core/reflect-config.json | 13 + .../reflect-config.json | 35 ++ .../jni-config.json | 11 + .../native-image.properties | 1 + .../reflect-config.json | 34 ++ .../resource-config.json | 19 + .../reflect-config.json | 25 ++ .../helloworld/native-image.properties | 1 + .../helloworld/reflect-config.json | 20 + .../helloworld/resource-config.json | 7 + .../src/main/resources/log4j2.xml | 0 .../sam-graalvm/template.yaml | 100 +++++ .../{ => sam}/README.md | 2 +- .../{ => sam}/pom.xml | 2 +- .../java/org/demo/parameters/MyObject.java | 48 +++ .../demo/parameters/ParametersFunction.java | 109 ++++++ .../sam/src/main/resources/log4j2.xml | 16 + .../{ => sam}/template.yaml | 0 powertools-parameters/pom.xml | 94 +++++ .../powertools-parameters-appconfig/pom.xml | 94 +++++ .../jni-config.json | 26 ++ .../reflect-config.json | 365 ++++++++++++++++++ .../resource-config.json | 59 +++ .../powertools-parameters-dynamodb/pom.xml | 94 +++++ .../jni-config.json | 22 ++ .../reflect-config.json | 326 ++++++++++++++++ .../resource-config.json | 23 ++ .../powertools-parameters-secrets/pom.xml | 94 +++++ .../jni-config.json | 22 ++ .../reflect-config.json | 323 ++++++++++++++++ .../resource-config.json | 23 ++ .../powertools-parameters-ssm/pom.xml | 96 ++++- .../powertools-parameters-ssm/jni-config.json | 26 ++ .../reflect-config.json | 341 ++++++++++++++++ .../resource-config.json | 23 ++ .../powertools-parameters-tests/pom.xml | 94 +++++ .../powertools-parameters/reflect-config.json | 197 ++++++++++ 46 files changed, 3098 insertions(+), 9 deletions(-) create mode 100644 examples/powertools-examples-parameters/sam-graalvm/Dockerfile create mode 100644 examples/powertools-examples-parameters/sam-graalvm/Makefile create mode 100644 examples/powertools-examples-parameters/sam-graalvm/README.md create mode 100644 examples/powertools-examples-parameters/sam-graalvm/pom.xml create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/config/bootstrap rename examples/powertools-examples-parameters/{ => sam-graalvm}/src/main/java/org/demo/parameters/MyObject.java (100%) rename examples/powertools-examples-parameters/{ => sam-graalvm}/src/main/java/org/demo/parameters/ParametersFunction.java (100%) create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json create mode 100644 examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json rename examples/powertools-examples-parameters/{ => sam-graalvm}/src/main/resources/log4j2.xml (100%) create mode 100644 examples/powertools-examples-parameters/sam-graalvm/template.yaml rename examples/powertools-examples-parameters/{ => sam}/README.md (96%) rename examples/powertools-examples-parameters/{ => sam}/pom.xml (98%) create mode 100644 examples/powertools-examples-parameters/sam/src/main/java/org/demo/parameters/MyObject.java create mode 100644 examples/powertools-examples-parameters/sam/src/main/java/org/demo/parameters/ParametersFunction.java create mode 100644 examples/powertools-examples-parameters/sam/src/main/resources/log4j2.xml rename examples/powertools-examples-parameters/{ => sam}/template.yaml (100%) create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/jni-config.json create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/resource-config.json create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/jni-config.json create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/resource-config.json create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/jni-config.json create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/resource-config.json create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/jni-config.json create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/resource-config.json create mode 100644 powertools-parameters/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters/reflect-config.json diff --git a/examples/pom.xml b/examples/pom.xml index 1f985a9cf..63625214c 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -30,12 +30,14 @@ powertools-examples-core-utilities/sam + powertools-examples-core-utilities/sam-graalvm powertools-examples-core-utilities/cdk/app powertools-examples-core-utilities/cdk/infra powertools-examples-core-utilities/serverless powertools-examples-core-utilities/terraform powertools-examples-idempotency - powertools-examples-parameters + powertools-examples-parameters/sam + powertools-examples-parameters/sam-graalvm powertools-examples-serialization powertools-examples-batch powertools-examples-validation diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 4ba4db943..d25e1fcb7 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -2,17 +2,17 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM + Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM software.amazon.lambda.examples 2.0.0-SNAPSHOT - powertools-examples-core-utilitiessam-graalvm + powertools-examples-core-utilities-sam-graalvm jar 2.24.0 - 21 - 21 - 1.9.22.1 + 11 + 11 + 1.9.20.1 diff --git a/examples/powertools-examples-parameters/sam-graalvm/Dockerfile b/examples/powertools-examples-parameters/sam-graalvm/Dockerfile new file mode 100644 index 000000000..a690606ad --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/Dockerfile @@ -0,0 +1,14 @@ +#Use the official AWS SAM base image for Java 21 +FROM public.ecr.aws/sam/build-java21:latest + +#Install GraalVM dependencies +RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz +RUN mv graalvm-jdk-21.* /usr/lib/graalvm + +#Make native image and mvn available on CLI +RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image +RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn + +#Set GraalVM as default +ENV JAVA_HOME=/usr/lib/graalvm +ENV PATH=/usr/lib/graalvm/bin:$PATH diff --git a/examples/powertools-examples-parameters/sam-graalvm/Makefile b/examples/powertools-examples-parameters/sam-graalvm/Makefile new file mode 100644 index 000000000..5a3a00a69 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/Makefile @@ -0,0 +1,6 @@ +build-ParametersFunction: + mvn clean package -P native-image + chmod +x target/hello-world + cp target/hello-world $(ARTIFACTS_DIR) # (ARTIFACTS_DIR --> https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/custom_make/DESIGN.md#implementation) + chmod +x src/main/config/bootstrap + cp src/main/config/bootstrap $(ARTIFACTS_DIR) diff --git a/examples/powertools-examples-parameters/sam-graalvm/README.md b/examples/powertools-examples-parameters/sam-graalvm/README.md new file mode 100644 index 000000000..3797c778b --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/README.md @@ -0,0 +1,80 @@ +# Powertools for AWS Lambda (Java) - Parameters Example with SAM on GraalVM + +This project contains an example of Lambda function using the parameters module of Powertools for AWS Lambda (Java). For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda-java/utilities/parameters/). + +The example uses the [SSM Parameter Store](https://docs.powertools.aws.dev/lambda/java/utilities/parameters/#ssm-parameter-store) +and the [Secrets Manager](https://docs.powertools.aws.dev/lambda/java/utilities/parameters/#secrets-manager) to inject +runtime parameters into the application. +Have a look at [ParametersFunction.java](src/main/java/org/demo/parameters/ParametersFunction.java) for the full details. + +## Configuration + +- SAM uses [template.yaml](template.yaml) to define the application's AWS resources. + This file defines the Lambda function to be deployed as well as API Gateway for it. + +- Set the environment to use GraalVM + +```shell +export JAVA_HOME= +``` + +## Build the sample application + +- Build the Docker image that will be used as the environment for SAM build: + +```shell +docker build --platform linux/amd64 . -t powertools-examples-parameters-sam-graalvm +``` + +- Build the SAM project using the docker image + +```shell +sam build --use-container --build-image powertools-examples-parameters-sam-graalvm +``` + +#### [Optional] Building with -SNAPSHOT versions of PowerTools + +- If you are testing the example with a -SNAPSHOT version of PowerTools, the maven build inside the docker image will fail. This is because the -SNAPSHOT version of the PowerTools library that you are working on is still not available in maven central/snapshot repository. + To get around this, follow these steps: + - Create the native image using the `docker` command below on your development machine. The native image is created in the `target` directory. + - `` docker run --platform linux/amd64 -it -v `pwd`:`pwd` -w `pwd` -v ~/.m2:/root/.m2 powertools-examples-parameters-sam-graalvm mvn clean -Pnative-image package -DskipTests `` + - Edit the [`Makefile`](Makefile) remove this line + - `mvn clean package -P native-image` + - Build the SAM project using the docker image + - `sam build --use-container --build-image powertools-examples-parameters-sam-graalvm` + +## Deploy the sample application + +- SAM deploy + +```shell +sam deploy +``` + +This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting +started with SAM in [the examples directory](../../README.md) + +## Test the application + +First, hit the URL of the application. You can do this with curl or your browser: + +```bash + curl https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/params/ +``` +You will get your IP address back. The contents of the logs will be more interesting, and show you the values +of the parameters injected into the handler: + +```bash +sam logs --stack-name $MY_STACK_NAME --tail +``` + +```json +{ + ... + "thread": "main", + "level": "INFO", + "loggerName": "org.demo.parameters.ParametersFunction", + "message": "secretjsonobj=MyObject{id=23443, code='hk38543oj24kn796kp67bkb234gkj679l68'}\n", + ... +} +``` diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml new file mode 100644 index 000000000..34f469c6c --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -0,0 +1,204 @@ + + 4.0.0 + software.amazon.lambda.examples + 2.0.0-SNAPSHOT + powertools-examples-parameters-sam-graalvm + jar + Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM + + + 2.24.0 + 11 + 11 + 1.9.20.1 + + + + + software.amazon.lambda + powertools-logging-log4j + ${project.version} + + + software.amazon.lambda + powertools-parameters-ssm + ${project.version} + + + software.amazon.lambda + powertools-parameters-secrets + ${project.version} + + + + com.amazonaws + aws-lambda-java-core + 1.2.3 + + + com.amazonaws + aws-lambda-java-events + 3.15.0 + + + org.aspectj + aspectjrt + ${aspectj.version} + + + com.amazonaws + aws-lambda-java-runtime-interface-client + 2.1.1 + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + org.apache.logging.log4j + log4j-slf4j2-impl + ${log4j.version} + + + org.apache.logging.log4j + log4j-layout-template-json + ${log4j.version} + + + + + org.mockito + mockito-core + 5.1.1 + test + + + org.junit.jupiter + junit-jupiter-api + 5.11.1 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.9.3 + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 3.2.5 + + + dev.aspectj + aspectj-maven-plugin + 1.14 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-parameters + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + false + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.1.0 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.2 + + true + + + + + + + native-image + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.1 + true + + + build-native + + build + + package + + + + hello-world + com.amazonaws.services.lambda.runtime.api.client.AWSLambda + + + --enable-url-protocols=http + --add-opens java.base/java.util=ALL-UNNAMED + + + + + + + + diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/config/bootstrap b/examples/powertools-examples-parameters/sam-graalvm/src/main/config/bootstrap new file mode 100644 index 000000000..8e7928cd3 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/config/bootstrap @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +./hello-world $_HANDLER \ No newline at end of file diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/MyObject.java b/examples/powertools-examples-parameters/sam-graalvm/src/main/java/org/demo/parameters/MyObject.java similarity index 100% rename from examples/powertools-examples-parameters/src/main/java/org/demo/parameters/MyObject.java rename to examples/powertools-examples-parameters/sam-graalvm/src/main/java/org/demo/parameters/MyObject.java diff --git a/examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/sam-graalvm/src/main/java/org/demo/parameters/ParametersFunction.java similarity index 100% rename from examples/powertools-examples-parameters/src/main/java/org/demo/parameters/ParametersFunction.java rename to examples/powertools-examples-parameters/sam-graalvm/src/main/java/org/demo/parameters/ParametersFunction.java diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..d30696750 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..106edef38 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,34 @@ +[ + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields":[{"name":"logger"}] + }, + { + "name":"java.lang.Void", + "methods":[{"name":"","parameterTypes":[] }] + }, + { + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] + }, + { + "name":"jdk.internal.module.IllegalAccessLogger", + "fields":[{"name":"logger"}] + }, + { + "name":"sun.misc.Unsafe", + "fields":[{"name":"theUnsafe"}] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..7cc78a494 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qaarch64/aws-lambda-runtime-interface-client.glibc.so\\E" + }, + { + "pattern": "\\Qaarch64/aws-lambda-runtime-interface-client.musl.so\\E" + }, + { + "pattern": "\\Qx86_64/aws-lambda-runtime-interface-client.glibc.so\\E" + }, + { + "pattern": "\\Qx86_64/aws-lambda-runtime-interface-client.musl.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties new file mode 100644 index 000000000..db5ebaa55 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties @@ -0,0 +1 @@ +Args = --enable-url-protocols=http,https \ No newline at end of file diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json new file mode 100644 index 000000000..16a37f483 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "org.demo.parameters.ParametersFunction", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "org.demo.parameters.MyObject", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/examples/powertools-examples-parameters/src/main/resources/log4j2.xml b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/log4j2.xml similarity index 100% rename from examples/powertools-examples-parameters/src/main/resources/log4j2.xml rename to examples/powertools-examples-parameters/sam-graalvm/src/main/resources/log4j2.xml diff --git a/examples/powertools-examples-parameters/sam-graalvm/template.yaml b/examples/powertools-examples-parameters/sam-graalvm/template.yaml new file mode 100644 index 000000000..b4a4d6907 --- /dev/null +++ b/examples/powertools-examples-parameters/sam-graalvm/template.yaml @@ -0,0 +1,100 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + validation demo + +Globals: + Function: + Timeout: 20 + MemorySize: 512 + Tracing: Active + + +Resources: + ParametersFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: org.demo.parameters.ParametersFunction::handleRequest + Runtime: provided.al2023 + MemorySize: 512 + Tracing: Active + Environment: + Variables: + LOG_LEVEL: INFO + Policies: + - AWSSecretsManagerGetSecretValuePolicy: + SecretArn: !Ref UserPwd + - AWSSecretsManagerGetSecretValuePolicy: + SecretArn: !Ref SecretConfig + - Statement: + - Sid: SSMGetParameterPolicy + Effect: Allow + Action: + - ssm:GetParameter + - ssm:GetParameters + - ssm:GetParametersByPath + Resource: '*' + Events: + HelloWorld: + Type: Api + Properties: + Path: /params + Method: get + + UserPwd: + Type: AWS::SecretsManager::Secret + Properties: + Name: /powertools-java/userpwd + Description: Generated secret for lambda-powertools-java powertools-parameters + module + GenerateSecretString: + SecretStringTemplate: '{"username": "test-user"}' + GenerateStringKey: password + PasswordLength: 15 + ExcludeCharacters: '"@/\' + SecretConfig: + Type: AWS::SecretsManager::Secret + Properties: + Name: /powertools-java/secretcode + Description: Json secret for lambda-powertools-java powertools-parameters module + SecretString: '{"id":23443,"code":"hk38543oj24kn796kp67bkb234gkj679l68"}' + BasicParameter: + Type: AWS::SSM::Parameter + Properties: + Name: /powertools-java/sample/simplekey + Type: String + Value: simplevalue + Description: Simple SSM Parameter for lambda-powertools-java powertools-parameters + module + ParameterList: + Type: AWS::SSM::Parameter + Properties: + Name: /powertools-java/sample/keylist + Type: StringList + Value: value1,value2,value3 + Description: SSM Parameter List for lambda-powertools-java powertools-parameters + module + JsonParameter: + Type: AWS::SSM::Parameter + Properties: + Name: /powertools-java/sample/keyjson + Type: String + Value: '{"id":23443,"code":"hk38543oj24kn796kp67bkb234gkj679l68"}' + Description: Json SSM Parameter for lambda-powertools-java powertools-parameters + module + Base64Parameter: + Type: AWS::SSM::Parameter + Properties: + Name: /powertools-java/sample/keybase64 + Type: String + Value: aGVsbG8gd29ybGQ= + Description: Base64 SSM Parameter for lambda-powertools-java powertools-parameters module + +Outputs: + ParametersApi: + Description: "API Gateway endpoint URL for Prod stage for Parameters function" + Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/params/" + ParametersFunction: + Description: "Parameters Lambda Function ARN" + Value: !GetAtt ParametersFunction.Arn \ No newline at end of file diff --git a/examples/powertools-examples-parameters/README.md b/examples/powertools-examples-parameters/sam/README.md similarity index 96% rename from examples/powertools-examples-parameters/README.md rename to examples/powertools-examples-parameters/sam/README.md index a65307f69..661752957 100644 --- a/examples/powertools-examples-parameters/README.md +++ b/examples/powertools-examples-parameters/sam/README.md @@ -10,7 +10,7 @@ Have a look at [ParametersFunction.java](src/main/java/org/demo/parameters/Param ## Deploy the sample application This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting -started with SAM in [the examples directory](../README.md) +started with SAM in [the examples directory](../../README.md) ## Test the application diff --git a/examples/powertools-examples-parameters/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml similarity index 98% rename from examples/powertools-examples-parameters/pom.xml rename to examples/powertools-examples-parameters/sam/pom.xml index 5737ffdeb..d0d8028d6 100644 --- a/examples/powertools-examples-parameters/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples 2.0.0-SNAPSHOT - powertools-examples-parameters + powertools-examples-parameters-sam jar Powertools for AWS Lambda (Java) - Examples - Parameters diff --git a/examples/powertools-examples-parameters/sam/src/main/java/org/demo/parameters/MyObject.java b/examples/powertools-examples-parameters/sam/src/main/java/org/demo/parameters/MyObject.java new file mode 100644 index 000000000..d406ae3df --- /dev/null +++ b/examples/powertools-examples-parameters/sam/src/main/java/org/demo/parameters/MyObject.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.demo.parameters; + +public class MyObject { + + private long id; + private String code; + + public MyObject() { + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + @Override + public String toString() { + return "MyObject{" + + "id=" + id + + ", code='" + code + '\'' + + '}'; + } +} diff --git a/examples/powertools-examples-parameters/sam/src/main/java/org/demo/parameters/ParametersFunction.java b/examples/powertools-examples-parameters/sam/src/main/java/org/demo/parameters/ParametersFunction.java new file mode 100644 index 000000000..9c3c422cf --- /dev/null +++ b/examples/powertools-examples-parameters/sam/src/main/java/org/demo/parameters/ParametersFunction.java @@ -0,0 +1,109 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.demo.parameters; + +import static java.time.temporal.ChronoUnit.SECONDS; +import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; +import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.parameters.secrets.SecretsParam; +import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider; +import software.amazon.lambda.powertools.parameters.ssm.SSMParam; +import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; + +public class ParametersFunction implements RequestHandler { + private static final Logger log = LoggerFactory.getLogger(ParametersFunction.class); + + // Annotation-style injection from secrets manager + @SecretsParam(key = "/powertools-java/userpwd") + String secretParamInjected; + + // Annotation-style injection from Systems Manager + @SSMParam(key = "/powertools-java/sample/simplekey") + String ssmParamInjected; + + SSMProvider ssmProvider = SSMProvider + .builder() + .build(); + SecretsProvider secretsProvider = SecretsProvider + .builder() + .build(); + + String simpleValue = ssmProvider.withMaxAge(30, SECONDS).get("/powertools-java/sample/simplekey"); + String listValue = ssmProvider.withMaxAge(60, SECONDS).get("/powertools-java/sample/keylist"); + MyObject jsonObj = ssmProvider.withTransformation(json).get("/powertools-java/sample/keyjson", MyObject.class); + Map allValues = ssmProvider.getMultiple("/powertools-java/sample"); + String b64value = ssmProvider.withTransformation(base64).get("/powertools-java/sample/keybase64"); + + Map secretJson = + secretsProvider.withTransformation(json).get("/powertools-java/userpwd", Map.class); + MyObject secretJsonObj = secretsProvider.withMaxAge(42, SECONDS).withTransformation(json) + .get("/powertools-java/secretcode", MyObject.class); + + @Override + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + + log.info("\n=============== SSM Parameter Store ==============="); + log.info("simplevalue={}, listvalue={}, b64value={}\n", simpleValue, listValue, b64value); + log.info("jsonobj={}\n", jsonObj); + + log.info("allvalues (multiple):"); + allValues.forEach((key, value) -> log.info("- {}={}\n", key, value)); + + log.info("\n=============== Secrets Manager ==============="); + log.info("secretjson:"); + secretJson.forEach((key, value) -> log.info("- {}={}\n", key, value)); + log.info("secretjsonobj={}\n", secretJsonObj); + + Map headers = new HashMap<>(); + headers.put("Content-Type", "application/json"); + headers.put("X-Custom-Header", "application/json"); + + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() + .withHeaders(headers); + try { + final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); + String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); + + return response + .withStatusCode(200) + .withBody(output); + } catch (IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-parameters/sam/src/main/resources/log4j2.xml b/examples/powertools-examples-parameters/sam/src/main/resources/log4j2.xml new file mode 100644 index 000000000..fe943d707 --- /dev/null +++ b/examples/powertools-examples-parameters/sam/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/powertools-examples-parameters/template.yaml b/examples/powertools-examples-parameters/sam/template.yaml similarity index 100% rename from examples/powertools-examples-parameters/template.yaml rename to examples/powertools-examples-parameters/sam/template.yaml diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 09b8d3b2f..44292c755 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -89,4 +89,98 @@ + + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-parameters + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + + + + + + + diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index be47fbddb..f4af26062 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -79,6 +79,100 @@ + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-parameters-appconfig + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + + + + + + + + diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/jni-config.json b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/jni-config.json new file mode 100644 index 000000000..2c4de0562 --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/jni-config.json @@ -0,0 +1,26 @@ +[ +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"org.apache.maven.surefire.booter.ForkedBooter", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"sun.instrument.InstrumentationImpl", + "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json new file mode 100644 index 000000000..7e7b40197 --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json @@ -0,0 +1,365 @@ +[ +{ + "name":"com.sun.crypto.provider.AESCipher$General", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ARCFOURCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESedeCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.AutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedParameterizedType", + "methods":[{"name":"getAnnotatedActualTypeArguments","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedTypeVariable", + "methods":[{"name":"getAnnotatedBounds","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedWildcardType", + "methods":[{"name":"getAnnotatedUpperBounds","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.TypeVariable", + "methods":[{"name":"getAnnotatedBounds","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.security.AlgorithmParametersSpi" +}, +{ + "name":"java.security.KeyStoreSpi" +}, +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"javax.security.auth.x500.X500Principal", + "fields":[{"name":"thisX500Name"}], + "methods":[{"name":"","parameterTypes":["sun.security.x509.X500Name"] }] +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.Unit" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apache.maven.surefire.junitplatform.JUnitPlatformProvider", + "methods":[{"name":"","parameterTypes":["org.apache.maven.surefire.api.provider.ProviderParameters"] }] +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"org.junit.internal.AssumptionViolatedException" +}, +{ + "name":"org.junit.jupiter.api.Test", + "queryAllPublicMethods":true +}, +{ + "name":"org.junit.platform.commons.annotation.Testable", + "queryAllPublicMethods":true +}, +{ + "name":"org.junit.platform.launcher.LauncherSession", + "methods":[{"name":"getLauncher","parameterTypes":[] }] +}, +{ + "name":"org.junit.platform.launcher.core.LauncherFactory", + "methods":[{"name":"openSession","parameterTypes":[] }] +}, +{ + "name":"scala.util.Properties" +}, +{ + "name":"software.amazon.awssdk.awscore.AwsClient", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"software.amazon.awssdk.core.SdkClient", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"serviceName","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.services.appconfigdata.AppConfigDataClient", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getLatestConfiguration","parameterTypes":["java.util.function.Consumer"] }, {"name":"getLatestConfiguration","parameterTypes":["software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationRequest"] }, {"name":"serviceClientConfiguration","parameterTypes":[] }, {"name":"startConfigurationSession","parameterTypes":["java.util.function.Consumer"] }, {"name":"startConfigurationSession","parameterTypes":["software.amazon.awssdk.services.appconfigdata.model.StartConfigurationSessionRequest"] }] +}, +{ + "name":"software.amazon.awssdk.utils.SdkAutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"close","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.BaseProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"get","parameterTypes":["java.lang.String"] }, {"name":"get","parameterTypes":["java.lang.String","java.lang.Class"] }, {"name":"getMultiple","parameterTypes":["java.lang.String"] }, {"name":"now","parameterTypes":[] }, {"name":"resetToDefaults","parameterTypes":[] }, {"name":"withMaxAge","parameterTypes":["int","java.time.temporal.ChronoUnit"] }, {"name":"withTransformation","parameterTypes":["java.lang.Class"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.ParamProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"software.amazon.lambda.powertools.parameters.appconfig.AppConfigParamAspectTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"parameterInjectedByProvider","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.appconfig.AppConfigParamAspectTest$MyInjectedClass", + "fields":[{"name":"myParameter"}] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.appconfig.AppConfigParametersAspect", + "fields":[{"name":"providerBuilder"}] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getMultipleValues","parameterTypes":["java.lang.String"] }, {"name":"getValue","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.appconfig.AppConfigProviderTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"getMultipleValuesThrowsException","parameterTypes":[] }, {"name":"getValueNoValueExists","parameterTypes":[] }, {"name":"getValueRetrievesValue","parameterTypes":[] }, {"name":"init","parameterTypes":[] }, {"name":"multipleKeysRetrievalWorks","parameterTypes":[] }, {"name":"testAppConfigProviderBuilderMissingApplication_throwsException","parameterTypes":[] }, {"name":"testAppConfigProviderBuilderMissingEnvironment_throwsException","parameterTypes":[] }, {"name":"testAppConfigProvider_withoutParameter_shouldHaveDefaultTransformationManager","parameterTypes":[] }] +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.X509Factory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAKeyFactory$Legacy", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.SSLContextImpl$TLSContext", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.x509.AuthorityInfoAccessExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.AuthorityKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.BasicConstraintsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CRLDistributionPointsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CertificatePoliciesExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.ExtendedKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.IssuerAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.KeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.NetscapeCertTypeExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.PrivateKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +} +] diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/resource-config.json b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/resource-config.json new file mode 100644 index 000000000..63bcd679e --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/resource-config.json @@ -0,0 +1,59 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" + }, { + "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.engine.TestEngine\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherDiscoveryListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherSessionListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.PostDiscoveryFilter\\E" + }, { + "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.TestExecutionListener\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qjunit-platform.properties\\E" + }, { + "pattern":"\\Qmockito-extensions/org.mockito.plugins.AnnotationEngine\\E" + }, { + "pattern":"\\Qmockito-extensions/org.mockito.plugins.DoNotMockEnforcer\\E" + }, { + "pattern":"\\Qmockito-extensions/org.mockito.plugins.InstantiatorProvider2\\E" + }, { + "pattern":"\\Qmockito-extensions/org.mockito.plugins.MemberAccessor\\E" + }, { + "pattern":"\\Qmockito-extensions/org.mockito.plugins.MockMaker\\E" + }, { + "pattern":"\\Qmockito-extensions/org.mockito.plugins.MockResolver\\E" + }, { + "pattern":"\\Qmockito-extensions/org.mockito.plugins.MockitoLogger\\E" + }, { + "pattern":"\\Qmockito-extensions/org.mockito.plugins.PluginSwitch\\E" + }, { + "pattern":"\\Qmockito-extensions/org.mockito.plugins.StackTraceCleanerProvider\\E" + }, { + "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/services/appconfigdata/execution.interceptors\\E" + }, { + "pattern":"\\Qversion.properties\\E" + }, { + "pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt72b/nfc.nrm\\E" + }]}, + "bundles":[] +} diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 1713dbad5..fde6c190b 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -80,6 +80,100 @@ + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-parameters-dynamodb + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + + + + + + + + diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/jni-config.json b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/jni-config.json new file mode 100644 index 000000000..2689203aa --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/jni-config.json @@ -0,0 +1,22 @@ +[ +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"sun.instrument.InstrumentationImpl", + "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json new file mode 100644 index 000000000..77e953aac --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json @@ -0,0 +1,326 @@ +[ +{ + "name":"com.sun.crypto.provider.AESCipher$General", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ARCFOURCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESedeCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.AutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedParameterizedType", + "methods":[{"name":"getAnnotatedActualTypeArguments","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedTypeVariable", + "methods":[{"name":"getAnnotatedBounds","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedWildcardType", + "methods":[{"name":"getAnnotatedUpperBounds","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.TypeVariable", + "methods":[{"name":"getAnnotatedBounds","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.security.AlgorithmParametersSpi" +}, +{ + "name":"java.security.KeyStoreSpi" +}, +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"javax.security.auth.x500.X500Principal", + "fields":[{"name":"thisX500Name"}], + "methods":[{"name":"","parameterTypes":["sun.security.x509.X500Name"] }] +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.Unit" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"scala.util.Properties" +}, +{ + "name":"software.amazon.awssdk.awscore.AwsClient", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"software.amazon.awssdk.core.SdkClient", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"serviceName","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.services.dynamodb.DynamoDbClient", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"batchExecuteStatement","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchExecuteStatement","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.BatchExecuteStatementRequest"] }, {"name":"batchGetItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchGetItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.BatchGetItemRequest"] }, {"name":"batchGetItemPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchGetItemPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.BatchGetItemRequest"] }, {"name":"batchWriteItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchWriteItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.BatchWriteItemRequest"] }, {"name":"createBackup","parameterTypes":["java.util.function.Consumer"] }, {"name":"createBackup","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.CreateBackupRequest"] }, {"name":"createGlobalTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"createGlobalTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.CreateGlobalTableRequest"] }, {"name":"createTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"createTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.CreateTableRequest"] }, {"name":"deleteBackup","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteBackup","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DeleteBackupRequest"] }, {"name":"deleteItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest"] }, {"name":"deleteResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteResourcePolicy","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DeleteResourcePolicyRequest"] }, {"name":"deleteTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest"] }, {"name":"describeBackup","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeBackup","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeBackupRequest"] }, {"name":"describeContinuousBackups","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeContinuousBackups","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeContinuousBackupsRequest"] }, {"name":"describeContributorInsights","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeContributorInsights","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeContributorInsightsRequest"] }, {"name":"describeEndpoints","parameterTypes":[] }, {"name":"describeEndpoints","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeEndpoints","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeEndpointsRequest"] }, {"name":"describeExport","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeExport","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeExportRequest"] }, {"name":"describeGlobalTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeGlobalTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeGlobalTableRequest"] }, {"name":"describeGlobalTableSettings","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeGlobalTableSettings","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeGlobalTableSettingsRequest"] }, {"name":"describeImport","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeImport","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeImportRequest"] }, {"name":"describeKinesisStreamingDestination","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeKinesisStreamingDestination","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeKinesisStreamingDestinationRequest"] }, {"name":"describeLimits","parameterTypes":[] }, {"name":"describeLimits","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeLimits","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeLimitsRequest"] }, {"name":"describeTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest"] }, {"name":"describeTableReplicaAutoScaling","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeTableReplicaAutoScaling","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeTableReplicaAutoScalingRequest"] }, {"name":"describeTimeToLive","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeTimeToLive","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeTimeToLiveRequest"] }, {"name":"disableKinesisStreamingDestination","parameterTypes":["java.util.function.Consumer"] }, {"name":"disableKinesisStreamingDestination","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DisableKinesisStreamingDestinationRequest"] }, {"name":"enableKinesisStreamingDestination","parameterTypes":["java.util.function.Consumer"] }, {"name":"enableKinesisStreamingDestination","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.EnableKinesisStreamingDestinationRequest"] }, {"name":"executeStatement","parameterTypes":["java.util.function.Consumer"] }, {"name":"executeStatement","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ExecuteStatementRequest"] }, {"name":"executeTransaction","parameterTypes":["java.util.function.Consumer"] }, {"name":"executeTransaction","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ExecuteTransactionRequest"] }, {"name":"exportTableToPointInTime","parameterTypes":["java.util.function.Consumer"] }, {"name":"exportTableToPointInTime","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ExportTableToPointInTimeRequest"] }, {"name":"getItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"getItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.GetItemRequest"] }, {"name":"getResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"getResourcePolicy","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.GetResourcePolicyRequest"] }, {"name":"importTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"importTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ImportTableRequest"] }, {"name":"listBackups","parameterTypes":[] }, {"name":"listBackups","parameterTypes":["java.util.function.Consumer"] }, {"name":"listBackups","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListBackupsRequest"] }, {"name":"listContributorInsights","parameterTypes":["java.util.function.Consumer"] }, {"name":"listContributorInsights","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListContributorInsightsRequest"] }, {"name":"listContributorInsightsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listContributorInsightsPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListContributorInsightsRequest"] }, {"name":"listExports","parameterTypes":["java.util.function.Consumer"] }, {"name":"listExports","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListExportsRequest"] }, {"name":"listExportsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listExportsPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListExportsRequest"] }, {"name":"listGlobalTables","parameterTypes":[] }, {"name":"listGlobalTables","parameterTypes":["java.util.function.Consumer"] }, {"name":"listGlobalTables","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListGlobalTablesRequest"] }, {"name":"listImports","parameterTypes":["java.util.function.Consumer"] }, {"name":"listImports","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListImportsRequest"] }, {"name":"listImportsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listImportsPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListImportsRequest"] }, {"name":"listTables","parameterTypes":[] }, {"name":"listTables","parameterTypes":["java.util.function.Consumer"] }, {"name":"listTables","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListTablesRequest"] }, {"name":"listTablesPaginator","parameterTypes":[] }, {"name":"listTablesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listTablesPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListTablesRequest"] }, {"name":"listTagsOfResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"listTagsOfResource","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListTagsOfResourceRequest"] }, {"name":"putItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"putItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.PutItemRequest"] }, {"name":"putResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"putResourcePolicy","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.PutResourcePolicyRequest"] }, {"name":"query","parameterTypes":["java.util.function.Consumer"] }, {"name":"query","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.QueryRequest"] }, {"name":"queryPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"queryPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.QueryRequest"] }, {"name":"restoreTableFromBackup","parameterTypes":["java.util.function.Consumer"] }, {"name":"restoreTableFromBackup","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.RestoreTableFromBackupRequest"] }, {"name":"restoreTableToPointInTime","parameterTypes":["java.util.function.Consumer"] }, {"name":"restoreTableToPointInTime","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.RestoreTableToPointInTimeRequest"] }, {"name":"scan","parameterTypes":["java.util.function.Consumer"] }, {"name":"scan","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ScanRequest"] }, {"name":"scanPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"scanPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ScanRequest"] }, {"name":"serviceClientConfiguration","parameterTypes":[] }, {"name":"tagResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"tagResource","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.TagResourceRequest"] }, {"name":"transactGetItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"transactGetItems","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.TransactGetItemsRequest"] }, {"name":"transactWriteItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"transactWriteItems","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.TransactWriteItemsRequest"] }, {"name":"untagResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"untagResource","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UntagResourceRequest"] }, {"name":"updateContinuousBackups","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateContinuousBackups","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateContinuousBackupsRequest"] }, {"name":"updateContributorInsights","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateContributorInsights","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateContributorInsightsRequest"] }, {"name":"updateGlobalTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateGlobalTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateGlobalTableRequest"] }, {"name":"updateGlobalTableSettings","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateGlobalTableSettings","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateGlobalTableSettingsRequest"] }, {"name":"updateItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest"] }, {"name":"updateKinesisStreamingDestination","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateKinesisStreamingDestination","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateKinesisStreamingDestinationRequest"] }, {"name":"updateTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateTableRequest"] }, {"name":"updateTableReplicaAutoScaling","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateTableReplicaAutoScaling","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateTableReplicaAutoScalingRequest"] }, {"name":"updateTimeToLive","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateTimeToLive","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateTimeToLiveRequest"] }, {"name":"waiter","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.utils.SdkAutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"close","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.BaseProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"get","parameterTypes":["java.lang.String"] }, {"name":"get","parameterTypes":["java.lang.String","java.lang.Class"] }, {"name":"getMultiple","parameterTypes":["java.lang.String"] }, {"name":"now","parameterTypes":[] }, {"name":"resetToDefaults","parameterTypes":[] }, {"name":"withMaxAge","parameterTypes":["int","java.time.temporal.ChronoUnit"] }, {"name":"withTransformation","parameterTypes":["java.lang.Class"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.ParamProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbParamAspect", + "fields":[{"name":"providerBuilder"}] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getMultipleValues","parameterTypes":["java.lang.String"] }, {"name":"getValue","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.transform.TransformationManager", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"performBasicTransformation","parameterTypes":["java.lang.String"] }, {"name":"performComplexTransformation","parameterTypes":["java.lang.String","java.lang.Class"] }, {"name":"setTransformer","parameterTypes":["java.lang.Class"] }, {"name":"shouldTransform","parameterTypes":[] }] +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.X509Factory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAKeyFactory$Legacy", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.SSLContextImpl$TLSContext", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.x509.AuthorityInfoAccessExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.AuthorityKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.BasicConstraintsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CRLDistributionPointsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CertificatePoliciesExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.ExtendedKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.IssuerAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.KeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.NetscapeCertTypeExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.PrivateKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +} +] diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/resource-config.json b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/resource-config.json new file mode 100644 index 000000000..abbae66cf --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/resource-config.json @@ -0,0 +1,23 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/services/dynamodb/execution.interceptors\\E" + }, { + "pattern":"\\Qversion.properties\\E" + }, { + "pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt72b/nfc.nrm\\E" + }]}, + "bundles":[] +} diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index c2ea66f5c..a652f14e0 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -80,6 +80,100 @@ + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-parameters-secrets + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + + + + + + + + diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/jni-config.json b/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/jni-config.json new file mode 100644 index 000000000..2689203aa --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/jni-config.json @@ -0,0 +1,22 @@ +[ +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"sun.instrument.InstrumentationImpl", + "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json b/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json new file mode 100644 index 000000000..7dfaf1b03 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json @@ -0,0 +1,323 @@ +[ +{ + "name":"com.sun.crypto.provider.AESCipher$General", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ARCFOURCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESedeCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.AutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedParameterizedType", + "methods":[{"name":"getAnnotatedActualTypeArguments","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedTypeVariable", + "methods":[{"name":"getAnnotatedBounds","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedWildcardType", + "methods":[{"name":"getAnnotatedUpperBounds","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.TypeVariable", + "methods":[{"name":"getAnnotatedBounds","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.security.AlgorithmParametersSpi" +}, +{ + "name":"java.security.KeyStoreSpi" +}, +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"javax.security.auth.x500.X500Principal", + "fields":[{"name":"thisX500Name"}], + "methods":[{"name":"","parameterTypes":["sun.security.x509.X500Name"] }] +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"scala.util.Properties" +}, +{ + "name":"software.amazon.awssdk.awscore.AwsClient", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"software.amazon.awssdk.core.SdkClient", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"serviceName","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.services.secretsmanager.SecretsManagerClient", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"batchGetSecretValue","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchGetSecretValue","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.BatchGetSecretValueRequest"] }, {"name":"batchGetSecretValuePaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchGetSecretValuePaginator","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.BatchGetSecretValueRequest"] }, {"name":"cancelRotateSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"cancelRotateSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.CancelRotateSecretRequest"] }, {"name":"createSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"createSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.CreateSecretRequest"] }, {"name":"deleteResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteResourcePolicy","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.DeleteResourcePolicyRequest"] }, {"name":"deleteSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.DeleteSecretRequest"] }, {"name":"describeSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.DescribeSecretRequest"] }, {"name":"getRandomPassword","parameterTypes":[] }, {"name":"getRandomPassword","parameterTypes":["java.util.function.Consumer"] }, {"name":"getRandomPassword","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.GetRandomPasswordRequest"] }, {"name":"getResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"getResourcePolicy","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.GetResourcePolicyRequest"] }, {"name":"getSecretValue","parameterTypes":["java.util.function.Consumer"] }, {"name":"getSecretValue","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest"] }, {"name":"listSecretVersionIds","parameterTypes":["java.util.function.Consumer"] }, {"name":"listSecretVersionIds","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ListSecretVersionIdsRequest"] }, {"name":"listSecretVersionIdsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listSecretVersionIdsPaginator","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ListSecretVersionIdsRequest"] }, {"name":"listSecrets","parameterTypes":[] }, {"name":"listSecrets","parameterTypes":["java.util.function.Consumer"] }, {"name":"listSecrets","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ListSecretsRequest"] }, {"name":"listSecretsPaginator","parameterTypes":[] }, {"name":"listSecretsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listSecretsPaginator","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ListSecretsRequest"] }, {"name":"putResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"putResourcePolicy","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.PutResourcePolicyRequest"] }, {"name":"putSecretValue","parameterTypes":["java.util.function.Consumer"] }, {"name":"putSecretValue","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.PutSecretValueRequest"] }, {"name":"removeRegionsFromReplication","parameterTypes":["java.util.function.Consumer"] }, {"name":"removeRegionsFromReplication","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.RemoveRegionsFromReplicationRequest"] }, {"name":"replicateSecretToRegions","parameterTypes":["java.util.function.Consumer"] }, {"name":"replicateSecretToRegions","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ReplicateSecretToRegionsRequest"] }, {"name":"restoreSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"restoreSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.RestoreSecretRequest"] }, {"name":"rotateSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"rotateSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.RotateSecretRequest"] }, {"name":"serviceClientConfiguration","parameterTypes":[] }, {"name":"stopReplicationToReplica","parameterTypes":["java.util.function.Consumer"] }, {"name":"stopReplicationToReplica","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.StopReplicationToReplicaRequest"] }, {"name":"tagResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"tagResource","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.TagResourceRequest"] }, {"name":"untagResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"untagResource","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.UntagResourceRequest"] }, {"name":"updateSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.UpdateSecretRequest"] }, {"name":"updateSecretVersionStage","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateSecretVersionStage","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.UpdateSecretVersionStageRequest"] }, {"name":"validateResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"validateResourcePolicy","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ValidateResourcePolicyRequest"] }] +}, +{ + "name":"software.amazon.awssdk.utils.SdkAutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"close","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.BaseProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"get","parameterTypes":["java.lang.String"] }, {"name":"get","parameterTypes":["java.lang.String","java.lang.Class"] }, {"name":"getMultiple","parameterTypes":["java.lang.String"] }, {"name":"now","parameterTypes":[] }, {"name":"resetToDefaults","parameterTypes":[] }, {"name":"withMaxAge","parameterTypes":["int","java.time.temporal.ChronoUnit"] }, {"name":"withTransformation","parameterTypes":["java.lang.Class"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.ParamProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"software.amazon.lambda.powertools.parameters.secrets.SecretsParamAspect", + "fields":[{"name":"providerBuilder"}] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.secrets.SecretsProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getMultipleValues","parameterTypes":["java.lang.String"] }, {"name":"getValue","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.transform.TransformationManager", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"performBasicTransformation","parameterTypes":["java.lang.String"] }, {"name":"performComplexTransformation","parameterTypes":["java.lang.String","java.lang.Class"] }, {"name":"setTransformer","parameterTypes":["java.lang.Class"] }, {"name":"shouldTransform","parameterTypes":[] }] +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.X509Factory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAKeyFactory$Legacy", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.SSLContextImpl$TLSContext", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.x509.AuthorityInfoAccessExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.AuthorityKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.BasicConstraintsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CRLDistributionPointsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CertificatePoliciesExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.ExtendedKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.IssuerAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.KeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.NetscapeCertTypeExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.PrivateKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +} +] diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/resource-config.json b/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/resource-config.json new file mode 100644 index 000000000..f914dbf44 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/resource-config.json @@ -0,0 +1,23 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/services/secretsmanager/execution.interceptors\\E" + }, { + "pattern":"\\Qversion.properties\\E" + }, { + "pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt72b/nfc.nrm\\E" + }]}, + "bundles":[] +} diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 475aca8f2..ec13c10cc 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -93,4 +93,98 @@ - + + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-parameters-ssm + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + + + + + + + + \ No newline at end of file diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/jni-config.json b/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/jni-config.json new file mode 100644 index 000000000..2c4de0562 --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/jni-config.json @@ -0,0 +1,26 @@ +[ +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"org.apache.maven.surefire.booter.ForkedBooter", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"sun.instrument.InstrumentationImpl", + "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json b/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json new file mode 100644 index 000000000..5bc2deb4a --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json @@ -0,0 +1,341 @@ +[ +{ + "name":"com.sun.crypto.provider.AESCipher$General", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ARCFOURCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESedeCipher", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.AutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedParameterizedType", + "methods":[{"name":"getAnnotatedActualTypeArguments","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedTypeVariable", + "methods":[{"name":"getAnnotatedBounds","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedWildcardType", + "methods":[{"name":"getAnnotatedUpperBounds","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.TypeVariable", + "methods":[{"name":"getAnnotatedBounds","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.security.AlgorithmParametersSpi" +}, +{ + "name":"java.security.KeyStoreSpi" +}, +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"javax.security.auth.x500.X500Principal", + "fields":[{"name":"thisX500Name"}], + "methods":[{"name":"","parameterTypes":["sun.security.x509.X500Name"] }] +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"scala.util.Properties" +}, +{ + "name":"software.amazon.awssdk.awscore.AwsClient", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"software.amazon.awssdk.core.SdkClient", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"serviceName","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.services.ssm.SsmClient", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"addTagsToResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"addTagsToResource","parameterTypes":["software.amazon.awssdk.services.ssm.model.AddTagsToResourceRequest"] }, {"name":"associateOpsItemRelatedItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"associateOpsItemRelatedItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.AssociateOpsItemRelatedItemRequest"] }, {"name":"cancelCommand","parameterTypes":["java.util.function.Consumer"] }, {"name":"cancelCommand","parameterTypes":["software.amazon.awssdk.services.ssm.model.CancelCommandRequest"] }, {"name":"cancelMaintenanceWindowExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"cancelMaintenanceWindowExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.CancelMaintenanceWindowExecutionRequest"] }, {"name":"createActivation","parameterTypes":["java.util.function.Consumer"] }, {"name":"createActivation","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateActivationRequest"] }, {"name":"createAssociation","parameterTypes":["java.util.function.Consumer"] }, {"name":"createAssociation","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateAssociationRequest"] }, {"name":"createAssociationBatch","parameterTypes":["java.util.function.Consumer"] }, {"name":"createAssociationBatch","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateAssociationBatchRequest"] }, {"name":"createDocument","parameterTypes":["java.util.function.Consumer"] }, {"name":"createDocument","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateDocumentRequest"] }, {"name":"createMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"createMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateMaintenanceWindowRequest"] }, {"name":"createOpsItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"createOpsItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateOpsItemRequest"] }, {"name":"createOpsMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"createOpsMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateOpsMetadataRequest"] }, {"name":"createPatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"createPatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreatePatchBaselineRequest"] }, {"name":"createResourceDataSync","parameterTypes":["java.util.function.Consumer"] }, {"name":"createResourceDataSync","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateResourceDataSyncRequest"] }, {"name":"deleteActivation","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteActivation","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteActivationRequest"] }, {"name":"deleteAssociation","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteAssociation","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteAssociationRequest"] }, {"name":"deleteDocument","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteDocument","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteDocumentRequest"] }, {"name":"deleteInventory","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteInventory","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteInventoryRequest"] }, {"name":"deleteMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteMaintenanceWindowRequest"] }, {"name":"deleteOpsItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteOpsItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteOpsItemRequest"] }, {"name":"deleteOpsMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteOpsMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteOpsMetadataRequest"] }, {"name":"deleteParameter","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteParameter","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteParameterRequest"] }, {"name":"deleteParameters","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteParameters","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteParametersRequest"] }, {"name":"deletePatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"deletePatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeletePatchBaselineRequest"] }, {"name":"deleteResourceDataSync","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteResourceDataSync","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteResourceDataSyncRequest"] }, {"name":"deleteResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteResourcePolicy","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteResourcePolicyRequest"] }, {"name":"deregisterManagedInstance","parameterTypes":["java.util.function.Consumer"] }, {"name":"deregisterManagedInstance","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeregisterManagedInstanceRequest"] }, {"name":"deregisterPatchBaselineForPatchGroup","parameterTypes":["java.util.function.Consumer"] }, {"name":"deregisterPatchBaselineForPatchGroup","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeregisterPatchBaselineForPatchGroupRequest"] }, {"name":"deregisterTargetFromMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"deregisterTargetFromMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeregisterTargetFromMaintenanceWindowRequest"] }, {"name":"deregisterTaskFromMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"deregisterTaskFromMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeregisterTaskFromMaintenanceWindowRequest"] }, {"name":"describeActivations","parameterTypes":[] }, {"name":"describeActivations","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeActivations","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeActivationsRequest"] }, {"name":"describeActivationsPaginator","parameterTypes":[] }, {"name":"describeActivationsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeActivationsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeActivationsRequest"] }, {"name":"describeAssociation","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAssociation","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAssociationRequest"] }, {"name":"describeAssociationExecutionTargets","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAssociationExecutionTargets","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAssociationExecutionTargetsRequest"] }, {"name":"describeAssociationExecutionTargetsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAssociationExecutionTargetsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAssociationExecutionTargetsRequest"] }, {"name":"describeAssociationExecutions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAssociationExecutions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAssociationExecutionsRequest"] }, {"name":"describeAssociationExecutionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAssociationExecutionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAssociationExecutionsRequest"] }, {"name":"describeAutomationExecutions","parameterTypes":[] }, {"name":"describeAutomationExecutions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAutomationExecutions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAutomationExecutionsRequest"] }, {"name":"describeAutomationExecutionsPaginator","parameterTypes":[] }, {"name":"describeAutomationExecutionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAutomationExecutionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAutomationExecutionsRequest"] }, {"name":"describeAutomationStepExecutions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAutomationStepExecutions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAutomationStepExecutionsRequest"] }, {"name":"describeAutomationStepExecutionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAutomationStepExecutionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAutomationStepExecutionsRequest"] }, {"name":"describeAvailablePatches","parameterTypes":[] }, {"name":"describeAvailablePatches","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAvailablePatches","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAvailablePatchesRequest"] }, {"name":"describeAvailablePatchesPaginator","parameterTypes":[] }, {"name":"describeAvailablePatchesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAvailablePatchesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAvailablePatchesRequest"] }, {"name":"describeDocument","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeDocument","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeDocumentRequest"] }, {"name":"describeDocumentPermission","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeDocumentPermission","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeDocumentPermissionRequest"] }, {"name":"describeEffectiveInstanceAssociations","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeEffectiveInstanceAssociations","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeEffectiveInstanceAssociationsRequest"] }, {"name":"describeEffectiveInstanceAssociationsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeEffectiveInstanceAssociationsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeEffectiveInstanceAssociationsRequest"] }, {"name":"describeEffectivePatchesForPatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeEffectivePatchesForPatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeEffectivePatchesForPatchBaselineRequest"] }, {"name":"describeEffectivePatchesForPatchBaselinePaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeEffectivePatchesForPatchBaselinePaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeEffectivePatchesForPatchBaselineRequest"] }, {"name":"describeInstanceAssociationsStatus","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstanceAssociationsStatus","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstanceAssociationsStatusRequest"] }, {"name":"describeInstanceAssociationsStatusPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstanceAssociationsStatusPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstanceAssociationsStatusRequest"] }, {"name":"describeInstanceInformation","parameterTypes":[] }, {"name":"describeInstanceInformation","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstanceInformation","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstanceInformationRequest"] }, {"name":"describeInstanceInformationPaginator","parameterTypes":[] }, {"name":"describeInstanceInformationPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstanceInformationPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstanceInformationRequest"] }, {"name":"describeInstancePatchStates","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatchStates","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchStatesRequest"] }, {"name":"describeInstancePatchStatesForPatchGroup","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatchStatesForPatchGroup","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchStatesForPatchGroupRequest"] }, {"name":"describeInstancePatchStatesForPatchGroupPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatchStatesForPatchGroupPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchStatesForPatchGroupRequest"] }, {"name":"describeInstancePatchStatesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatchStatesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchStatesRequest"] }, {"name":"describeInstancePatches","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatches","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchesRequest"] }, {"name":"describeInstancePatchesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatchesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchesRequest"] }, {"name":"describeInstanceProperties","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstanceProperties","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePropertiesRequest"] }, {"name":"describeInstancePropertiesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePropertiesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePropertiesRequest"] }, {"name":"describeInventoryDeletions","parameterTypes":[] }, {"name":"describeInventoryDeletions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInventoryDeletions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInventoryDeletionsRequest"] }, {"name":"describeInventoryDeletionsPaginator","parameterTypes":[] }, {"name":"describeInventoryDeletionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInventoryDeletionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInventoryDeletionsRequest"] }, {"name":"describeMaintenanceWindowExecutionTaskInvocations","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutionTaskInvocations","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionTaskInvocationsRequest"] }, {"name":"describeMaintenanceWindowExecutionTaskInvocationsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutionTaskInvocationsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionTaskInvocationsRequest"] }, {"name":"describeMaintenanceWindowExecutionTasks","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutionTasks","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionTasksRequest"] }, {"name":"describeMaintenanceWindowExecutionTasksPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutionTasksPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionTasksRequest"] }, {"name":"describeMaintenanceWindowExecutions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionsRequest"] }, {"name":"describeMaintenanceWindowExecutionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionsRequest"] }, {"name":"describeMaintenanceWindowSchedule","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowSchedule","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowScheduleRequest"] }, {"name":"describeMaintenanceWindowSchedulePaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowSchedulePaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowScheduleRequest"] }, {"name":"describeMaintenanceWindowTargets","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowTargets","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowTargetsRequest"] }, {"name":"describeMaintenanceWindowTargetsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowTargetsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowTargetsRequest"] }, {"name":"describeMaintenanceWindowTasks","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowTasks","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowTasksRequest"] }, {"name":"describeMaintenanceWindowTasksPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowTasksPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowTasksRequest"] }, {"name":"describeMaintenanceWindows","parameterTypes":[] }, {"name":"describeMaintenanceWindows","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindows","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowsRequest"] }, {"name":"describeMaintenanceWindowsForTarget","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowsForTarget","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowsForTargetRequest"] }, {"name":"describeMaintenanceWindowsForTargetPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowsForTargetPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowsForTargetRequest"] }, {"name":"describeMaintenanceWindowsPaginator","parameterTypes":[] }, {"name":"describeMaintenanceWindowsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowsRequest"] }, {"name":"describeOpsItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeOpsItems","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeOpsItemsRequest"] }, {"name":"describeOpsItemsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeOpsItemsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeOpsItemsRequest"] }, {"name":"describeParameters","parameterTypes":[] }, {"name":"describeParameters","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeParameters","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeParametersRequest"] }, {"name":"describeParametersPaginator","parameterTypes":[] }, {"name":"describeParametersPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeParametersPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeParametersRequest"] }, {"name":"describePatchBaselines","parameterTypes":[] }, {"name":"describePatchBaselines","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchBaselines","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchBaselinesRequest"] }, {"name":"describePatchBaselinesPaginator","parameterTypes":[] }, {"name":"describePatchBaselinesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchBaselinesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchBaselinesRequest"] }, {"name":"describePatchGroupState","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchGroupState","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchGroupStateRequest"] }, {"name":"describePatchGroups","parameterTypes":[] }, {"name":"describePatchGroups","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchGroups","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchGroupsRequest"] }, {"name":"describePatchGroupsPaginator","parameterTypes":[] }, {"name":"describePatchGroupsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchGroupsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchGroupsRequest"] }, {"name":"describePatchProperties","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchProperties","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchPropertiesRequest"] }, {"name":"describePatchPropertiesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchPropertiesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchPropertiesRequest"] }, {"name":"describeSessions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeSessions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeSessionsRequest"] }, {"name":"describeSessionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeSessionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeSessionsRequest"] }, {"name":"disassociateOpsItemRelatedItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"disassociateOpsItemRelatedItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.DisassociateOpsItemRelatedItemRequest"] }, {"name":"getAutomationExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"getAutomationExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetAutomationExecutionRequest"] }, {"name":"getCalendarState","parameterTypes":["java.util.function.Consumer"] }, {"name":"getCalendarState","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetCalendarStateRequest"] }, {"name":"getCommandInvocation","parameterTypes":["java.util.function.Consumer"] }, {"name":"getCommandInvocation","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetCommandInvocationRequest"] }, {"name":"getConnectionStatus","parameterTypes":["java.util.function.Consumer"] }, {"name":"getConnectionStatus","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetConnectionStatusRequest"] }, {"name":"getDefaultPatchBaseline","parameterTypes":[] }, {"name":"getDefaultPatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"getDefaultPatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetDefaultPatchBaselineRequest"] }, {"name":"getDeployablePatchSnapshotForInstance","parameterTypes":["java.util.function.Consumer"] }, {"name":"getDeployablePatchSnapshotForInstance","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetDeployablePatchSnapshotForInstanceRequest"] }, {"name":"getDocument","parameterTypes":["java.util.function.Consumer"] }, {"name":"getDocument","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetDocumentRequest"] }, {"name":"getInventory","parameterTypes":[] }, {"name":"getInventory","parameterTypes":["java.util.function.Consumer"] }, {"name":"getInventory","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetInventoryRequest"] }, {"name":"getInventoryPaginator","parameterTypes":[] }, {"name":"getInventoryPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getInventoryPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetInventoryRequest"] }, {"name":"getInventorySchema","parameterTypes":[] }, {"name":"getInventorySchema","parameterTypes":["java.util.function.Consumer"] }, {"name":"getInventorySchema","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetInventorySchemaRequest"] }, {"name":"getInventorySchemaPaginator","parameterTypes":[] }, {"name":"getInventorySchemaPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getInventorySchemaPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetInventorySchemaRequest"] }, {"name":"getMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"getMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetMaintenanceWindowRequest"] }, {"name":"getMaintenanceWindowExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"getMaintenanceWindowExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetMaintenanceWindowExecutionRequest"] }, {"name":"getMaintenanceWindowExecutionTask","parameterTypes":["java.util.function.Consumer"] }, {"name":"getMaintenanceWindowExecutionTask","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetMaintenanceWindowExecutionTaskRequest"] }, {"name":"getMaintenanceWindowExecutionTaskInvocation","parameterTypes":["java.util.function.Consumer"] }, {"name":"getMaintenanceWindowExecutionTaskInvocation","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetMaintenanceWindowExecutionTaskInvocationRequest"] }, {"name":"getMaintenanceWindowTask","parameterTypes":["java.util.function.Consumer"] }, {"name":"getMaintenanceWindowTask","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetMaintenanceWindowTaskRequest"] }, {"name":"getOpsItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"getOpsItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetOpsItemRequest"] }, {"name":"getOpsMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"getOpsMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetOpsMetadataRequest"] }, {"name":"getOpsSummary","parameterTypes":["java.util.function.Consumer"] }, {"name":"getOpsSummary","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetOpsSummaryRequest"] }, {"name":"getOpsSummaryPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getOpsSummaryPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetOpsSummaryRequest"] }, {"name":"getParameter","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParameter","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParameterRequest"] }, {"name":"getParameterHistory","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParameterHistory","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParameterHistoryRequest"] }, {"name":"getParameterHistoryPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParameterHistoryPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParameterHistoryRequest"] }, {"name":"getParameters","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParameters","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParametersRequest"] }, {"name":"getParametersByPath","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParametersByPath","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest"] }, {"name":"getParametersByPathPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParametersByPathPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest"] }, {"name":"getPatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"getPatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetPatchBaselineRequest"] }, {"name":"getPatchBaselineForPatchGroup","parameterTypes":["java.util.function.Consumer"] }, {"name":"getPatchBaselineForPatchGroup","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetPatchBaselineForPatchGroupRequest"] }, {"name":"getResourcePolicies","parameterTypes":["java.util.function.Consumer"] }, {"name":"getResourcePolicies","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetResourcePoliciesRequest"] }, {"name":"getResourcePoliciesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getResourcePoliciesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetResourcePoliciesRequest"] }, {"name":"getServiceSetting","parameterTypes":["java.util.function.Consumer"] }, {"name":"getServiceSetting","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetServiceSettingRequest"] }, {"name":"labelParameterVersion","parameterTypes":["java.util.function.Consumer"] }, {"name":"labelParameterVersion","parameterTypes":["software.amazon.awssdk.services.ssm.model.LabelParameterVersionRequest"] }, {"name":"listAssociationVersions","parameterTypes":["java.util.function.Consumer"] }, {"name":"listAssociationVersions","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListAssociationVersionsRequest"] }, {"name":"listAssociationVersionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listAssociationVersionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListAssociationVersionsRequest"] }, {"name":"listAssociations","parameterTypes":[] }, {"name":"listAssociations","parameterTypes":["java.util.function.Consumer"] }, {"name":"listAssociations","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListAssociationsRequest"] }, {"name":"listAssociationsPaginator","parameterTypes":[] }, {"name":"listAssociationsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listAssociationsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListAssociationsRequest"] }, {"name":"listCommandInvocations","parameterTypes":[] }, {"name":"listCommandInvocations","parameterTypes":["java.util.function.Consumer"] }, {"name":"listCommandInvocations","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListCommandInvocationsRequest"] }, {"name":"listCommandInvocationsPaginator","parameterTypes":[] }, {"name":"listCommandInvocationsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listCommandInvocationsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListCommandInvocationsRequest"] }, {"name":"listCommands","parameterTypes":[] }, {"name":"listCommands","parameterTypes":["java.util.function.Consumer"] }, {"name":"listCommands","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListCommandsRequest"] }, {"name":"listCommandsPaginator","parameterTypes":[] }, {"name":"listCommandsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listCommandsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListCommandsRequest"] }, {"name":"listComplianceItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"listComplianceItems","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListComplianceItemsRequest"] }, {"name":"listComplianceItemsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listComplianceItemsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListComplianceItemsRequest"] }, {"name":"listComplianceSummaries","parameterTypes":[] }, {"name":"listComplianceSummaries","parameterTypes":["java.util.function.Consumer"] }, {"name":"listComplianceSummaries","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListComplianceSummariesRequest"] }, {"name":"listComplianceSummariesPaginator","parameterTypes":[] }, {"name":"listComplianceSummariesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listComplianceSummariesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListComplianceSummariesRequest"] }, {"name":"listDocumentMetadataHistory","parameterTypes":["java.util.function.Consumer"] }, {"name":"listDocumentMetadataHistory","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListDocumentMetadataHistoryRequest"] }, {"name":"listDocumentVersions","parameterTypes":["java.util.function.Consumer"] }, {"name":"listDocumentVersions","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListDocumentVersionsRequest"] }, {"name":"listDocumentVersionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listDocumentVersionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListDocumentVersionsRequest"] }, {"name":"listDocuments","parameterTypes":[] }, {"name":"listDocuments","parameterTypes":["java.util.function.Consumer"] }, {"name":"listDocuments","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListDocumentsRequest"] }, {"name":"listDocumentsPaginator","parameterTypes":[] }, {"name":"listDocumentsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listDocumentsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListDocumentsRequest"] }, {"name":"listInventoryEntries","parameterTypes":["java.util.function.Consumer"] }, {"name":"listInventoryEntries","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListInventoryEntriesRequest"] }, {"name":"listOpsItemEvents","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsItemEvents","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsItemEventsRequest"] }, {"name":"listOpsItemEventsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsItemEventsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsItemEventsRequest"] }, {"name":"listOpsItemRelatedItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsItemRelatedItems","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsItemRelatedItemsRequest"] }, {"name":"listOpsItemRelatedItemsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsItemRelatedItemsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsItemRelatedItemsRequest"] }, {"name":"listOpsMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsMetadataRequest"] }, {"name":"listOpsMetadataPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsMetadataPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsMetadataRequest"] }, {"name":"listResourceComplianceSummaries","parameterTypes":[] }, {"name":"listResourceComplianceSummaries","parameterTypes":["java.util.function.Consumer"] }, {"name":"listResourceComplianceSummaries","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListResourceComplianceSummariesRequest"] }, {"name":"listResourceComplianceSummariesPaginator","parameterTypes":[] }, {"name":"listResourceComplianceSummariesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listResourceComplianceSummariesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListResourceComplianceSummariesRequest"] }, {"name":"listResourceDataSync","parameterTypes":[] }, {"name":"listResourceDataSync","parameterTypes":["java.util.function.Consumer"] }, {"name":"listResourceDataSync","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListResourceDataSyncRequest"] }, {"name":"listResourceDataSyncPaginator","parameterTypes":[] }, {"name":"listResourceDataSyncPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listResourceDataSyncPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListResourceDataSyncRequest"] }, {"name":"listTagsForResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"listTagsForResource","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListTagsForResourceRequest"] }, {"name":"modifyDocumentPermission","parameterTypes":["java.util.function.Consumer"] }, {"name":"modifyDocumentPermission","parameterTypes":["software.amazon.awssdk.services.ssm.model.ModifyDocumentPermissionRequest"] }, {"name":"putComplianceItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"putComplianceItems","parameterTypes":["software.amazon.awssdk.services.ssm.model.PutComplianceItemsRequest"] }, {"name":"putInventory","parameterTypes":["java.util.function.Consumer"] }, {"name":"putInventory","parameterTypes":["software.amazon.awssdk.services.ssm.model.PutInventoryRequest"] }, {"name":"putParameter","parameterTypes":["java.util.function.Consumer"] }, {"name":"putParameter","parameterTypes":["software.amazon.awssdk.services.ssm.model.PutParameterRequest"] }, {"name":"putResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"putResourcePolicy","parameterTypes":["software.amazon.awssdk.services.ssm.model.PutResourcePolicyRequest"] }, {"name":"registerDefaultPatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"registerDefaultPatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.RegisterDefaultPatchBaselineRequest"] }, {"name":"registerPatchBaselineForPatchGroup","parameterTypes":["java.util.function.Consumer"] }, {"name":"registerPatchBaselineForPatchGroup","parameterTypes":["software.amazon.awssdk.services.ssm.model.RegisterPatchBaselineForPatchGroupRequest"] }, {"name":"registerTargetWithMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"registerTargetWithMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.RegisterTargetWithMaintenanceWindowRequest"] }, {"name":"registerTaskWithMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"registerTaskWithMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.RegisterTaskWithMaintenanceWindowRequest"] }, {"name":"removeTagsFromResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"removeTagsFromResource","parameterTypes":["software.amazon.awssdk.services.ssm.model.RemoveTagsFromResourceRequest"] }, {"name":"resetServiceSetting","parameterTypes":["java.util.function.Consumer"] }, {"name":"resetServiceSetting","parameterTypes":["software.amazon.awssdk.services.ssm.model.ResetServiceSettingRequest"] }, {"name":"resumeSession","parameterTypes":["java.util.function.Consumer"] }, {"name":"resumeSession","parameterTypes":["software.amazon.awssdk.services.ssm.model.ResumeSessionRequest"] }, {"name":"sendAutomationSignal","parameterTypes":["java.util.function.Consumer"] }, {"name":"sendAutomationSignal","parameterTypes":["software.amazon.awssdk.services.ssm.model.SendAutomationSignalRequest"] }, {"name":"sendCommand","parameterTypes":["java.util.function.Consumer"] }, {"name":"sendCommand","parameterTypes":["software.amazon.awssdk.services.ssm.model.SendCommandRequest"] }, {"name":"serviceClientConfiguration","parameterTypes":[] }, {"name":"startAssociationsOnce","parameterTypes":["java.util.function.Consumer"] }, {"name":"startAssociationsOnce","parameterTypes":["software.amazon.awssdk.services.ssm.model.StartAssociationsOnceRequest"] }, {"name":"startAutomationExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"startAutomationExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.StartAutomationExecutionRequest"] }, {"name":"startChangeRequestExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"startChangeRequestExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.StartChangeRequestExecutionRequest"] }, {"name":"startSession","parameterTypes":["java.util.function.Consumer"] }, {"name":"startSession","parameterTypes":["software.amazon.awssdk.services.ssm.model.StartSessionRequest"] }, {"name":"stopAutomationExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"stopAutomationExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.StopAutomationExecutionRequest"] }, {"name":"terminateSession","parameterTypes":["java.util.function.Consumer"] }, {"name":"terminateSession","parameterTypes":["software.amazon.awssdk.services.ssm.model.TerminateSessionRequest"] }, {"name":"unlabelParameterVersion","parameterTypes":["java.util.function.Consumer"] }, {"name":"unlabelParameterVersion","parameterTypes":["software.amazon.awssdk.services.ssm.model.UnlabelParameterVersionRequest"] }, {"name":"updateAssociation","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateAssociation","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateAssociationRequest"] }, {"name":"updateAssociationStatus","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateAssociationStatus","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateAssociationStatusRequest"] }, {"name":"updateDocument","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateDocument","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateDocumentRequest"] }, {"name":"updateDocumentDefaultVersion","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateDocumentDefaultVersion","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateDocumentDefaultVersionRequest"] }, {"name":"updateDocumentMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateDocumentMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateDocumentMetadataRequest"] }, {"name":"updateMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateMaintenanceWindowRequest"] }, {"name":"updateMaintenanceWindowTarget","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateMaintenanceWindowTarget","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateMaintenanceWindowTargetRequest"] }, {"name":"updateMaintenanceWindowTask","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateMaintenanceWindowTask","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateMaintenanceWindowTaskRequest"] }, {"name":"updateManagedInstanceRole","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateManagedInstanceRole","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateManagedInstanceRoleRequest"] }, {"name":"updateOpsItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateOpsItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateOpsItemRequest"] }, {"name":"updateOpsMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateOpsMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateOpsMetadataRequest"] }, {"name":"updatePatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"updatePatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdatePatchBaselineRequest"] }, {"name":"updateResourceDataSync","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateResourceDataSync","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateResourceDataSyncRequest"] }, {"name":"updateServiceSetting","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateServiceSetting","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateServiceSettingRequest"] }, {"name":"waiter","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.utils.SdkAutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"close","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.BaseProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"get","parameterTypes":["java.lang.String"] }, {"name":"get","parameterTypes":["java.lang.String","java.lang.Class"] }, {"name":"getMultiple","parameterTypes":["java.lang.String"] }, {"name":"now","parameterTypes":[] }, {"name":"withMaxAge","parameterTypes":["int","java.time.temporal.ChronoUnit"] }, {"name":"withTransformation","parameterTypes":["java.lang.Class"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.ParamProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"software.amazon.lambda.powertools.parameters.ssm.SSMParamAspect", + "fields":[{"name":"providerBuilder"}] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.ssm.SSMProvider", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getMultipleValues","parameterTypes":["java.lang.String"] }, {"name":"getValue","parameterTypes":["java.lang.String"] }, {"name":"recursive","parameterTypes":[] }, {"name":"resetToDefaults","parameterTypes":[] }, {"name":"withDecryption","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.transform.TransformationManager", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"performBasicTransformation","parameterTypes":["java.lang.String"] }, {"name":"performComplexTransformation","parameterTypes":["java.lang.String","java.lang.Class"] }, {"name":"setTransformer","parameterTypes":["java.lang.Class"] }, {"name":"shouldTransform","parameterTypes":[] }] +}, +{ + "name": "software.amazon.lambda.powertools.parameters.transform.JsonTransformer", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods": [{"name": "applyTransformation","parameterTypes":["java.lang.String","java.lang.Class"]}] +}, +{ + "name": "software.amazon.lambda.powertools.parameters.transform.Base64Transformer", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods": [{"name": "applyTransformation","parameterTypes":["java.lang.String"]}] +}, +{ + "name": "software.amazon.lambda.powertools.parameters.transform.BasicTransformer", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods": [{"name": "applyTransformation","parameterTypes":["java.lang.String","java.lang.Class"]}] +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"","parameterTypes":[] }, {"name":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.X509Factory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAKeyFactory$Legacy", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.SSLContextImpl$TLSContext", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.x509.AuthorityInfoAccessExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.AuthorityKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.BasicConstraintsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CRLDistributionPointsExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CertificatePoliciesExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.ExtendedKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.IssuerAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.KeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.NetscapeCertTypeExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.PrivateKeyUsageExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectAlternativeNameExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectKeyIdentifierExtension", + "methods":[{"name":"","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +} +] diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/resource-config.json b/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/resource-config.json new file mode 100644 index 000000000..6d8f3660f --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/resource-config.json @@ -0,0 +1,23 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/services/ssm/execution.interceptors\\E" + }, { + "pattern":"\\Qversion.properties\\E" + }, { + "pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt72b/nfc.nrm\\E" + }]}, + "bundles":[] +} diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 6ab2e4155..e62323bd6 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -74,4 +74,98 @@ test + + + + generate-graalvm-files + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.3 + + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + graalvm-native + + + org.mockito + mockito-subclass + 5.6.0 + test + + + + + + org.graalvm.buildtools + native-maven-plugin + 0.10.2 + true + + + test-native + + test + + test + + + + powertools-parameters + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --no-fallback + -Dorg.graalvm.nativeimage.imagecode=agent + -H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun + -H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun + -H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun + --initialize-at-build-time=org.slf4j.simple.SimpleLogger + --initialize-at-build-time=org.slf4j.LoggerFactory + --initialize-at-build-time=org.junit.Ignore + --initialize-at-build-time=java.lang.annotation.Annotation + --initialize-at-build-time=org.junit.runners.model.FrameworkField + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --verbose + --native-image-info + -H:+UnlockExperimentalVMOptions + -H:Log=registerResource:5 + + + + + + + \ No newline at end of file diff --git a/powertools-parameters/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters/reflect-config.json b/powertools-parameters/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters/reflect-config.json new file mode 100644 index 000000000..380489707 --- /dev/null +++ b/powertools-parameters/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters/reflect-config.json @@ -0,0 +1,197 @@ +[ +{ + "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.AutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedParameterizedType", + "methods":[{"name":"getAnnotatedActualTypeArguments","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"software.amazon.awssdk.awscore.AwsClient", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"software.amazon.awssdk.core.SdkClient", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"serviceName","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.services.dynamodb.DynamoDbClient", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"batchExecuteStatement","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchExecuteStatement","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.BatchExecuteStatementRequest"] }, {"name":"batchGetItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchGetItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.BatchGetItemRequest"] }, {"name":"batchGetItemPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchGetItemPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.BatchGetItemRequest"] }, {"name":"batchWriteItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchWriteItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.BatchWriteItemRequest"] }, {"name":"createBackup","parameterTypes":["java.util.function.Consumer"] }, {"name":"createBackup","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.CreateBackupRequest"] }, {"name":"createGlobalTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"createGlobalTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.CreateGlobalTableRequest"] }, {"name":"createTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"createTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.CreateTableRequest"] }, {"name":"deleteBackup","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteBackup","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DeleteBackupRequest"] }, {"name":"deleteItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest"] }, {"name":"deleteResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteResourcePolicy","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DeleteResourcePolicyRequest"] }, {"name":"deleteTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest"] }, {"name":"describeBackup","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeBackup","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeBackupRequest"] }, {"name":"describeContinuousBackups","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeContinuousBackups","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeContinuousBackupsRequest"] }, {"name":"describeContributorInsights","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeContributorInsights","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeContributorInsightsRequest"] }, {"name":"describeEndpoints","parameterTypes":[] }, {"name":"describeEndpoints","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeEndpoints","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeEndpointsRequest"] }, {"name":"describeExport","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeExport","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeExportRequest"] }, {"name":"describeGlobalTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeGlobalTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeGlobalTableRequest"] }, {"name":"describeGlobalTableSettings","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeGlobalTableSettings","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeGlobalTableSettingsRequest"] }, {"name":"describeImport","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeImport","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeImportRequest"] }, {"name":"describeKinesisStreamingDestination","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeKinesisStreamingDestination","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeKinesisStreamingDestinationRequest"] }, {"name":"describeLimits","parameterTypes":[] }, {"name":"describeLimits","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeLimits","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeLimitsRequest"] }, {"name":"describeTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest"] }, {"name":"describeTableReplicaAutoScaling","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeTableReplicaAutoScaling","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeTableReplicaAutoScalingRequest"] }, {"name":"describeTimeToLive","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeTimeToLive","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DescribeTimeToLiveRequest"] }, {"name":"disableKinesisStreamingDestination","parameterTypes":["java.util.function.Consumer"] }, {"name":"disableKinesisStreamingDestination","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.DisableKinesisStreamingDestinationRequest"] }, {"name":"enableKinesisStreamingDestination","parameterTypes":["java.util.function.Consumer"] }, {"name":"enableKinesisStreamingDestination","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.EnableKinesisStreamingDestinationRequest"] }, {"name":"executeStatement","parameterTypes":["java.util.function.Consumer"] }, {"name":"executeStatement","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ExecuteStatementRequest"] }, {"name":"executeTransaction","parameterTypes":["java.util.function.Consumer"] }, {"name":"executeTransaction","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ExecuteTransactionRequest"] }, {"name":"exportTableToPointInTime","parameterTypes":["java.util.function.Consumer"] }, {"name":"exportTableToPointInTime","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ExportTableToPointInTimeRequest"] }, {"name":"getItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"getItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.GetItemRequest"] }, {"name":"getResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"getResourcePolicy","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.GetResourcePolicyRequest"] }, {"name":"importTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"importTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ImportTableRequest"] }, {"name":"listBackups","parameterTypes":[] }, {"name":"listBackups","parameterTypes":["java.util.function.Consumer"] }, {"name":"listBackups","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListBackupsRequest"] }, {"name":"listContributorInsights","parameterTypes":["java.util.function.Consumer"] }, {"name":"listContributorInsights","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListContributorInsightsRequest"] }, {"name":"listContributorInsightsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listContributorInsightsPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListContributorInsightsRequest"] }, {"name":"listExports","parameterTypes":["java.util.function.Consumer"] }, {"name":"listExports","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListExportsRequest"] }, {"name":"listExportsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listExportsPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListExportsRequest"] }, {"name":"listGlobalTables","parameterTypes":[] }, {"name":"listGlobalTables","parameterTypes":["java.util.function.Consumer"] }, {"name":"listGlobalTables","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListGlobalTablesRequest"] }, {"name":"listImports","parameterTypes":["java.util.function.Consumer"] }, {"name":"listImports","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListImportsRequest"] }, {"name":"listImportsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listImportsPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListImportsRequest"] }, {"name":"listTables","parameterTypes":[] }, {"name":"listTables","parameterTypes":["java.util.function.Consumer"] }, {"name":"listTables","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListTablesRequest"] }, {"name":"listTablesPaginator","parameterTypes":[] }, {"name":"listTablesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listTablesPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListTablesRequest"] }, {"name":"listTagsOfResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"listTagsOfResource","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ListTagsOfResourceRequest"] }, {"name":"putItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"putItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.PutItemRequest"] }, {"name":"putResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"putResourcePolicy","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.PutResourcePolicyRequest"] }, {"name":"query","parameterTypes":["java.util.function.Consumer"] }, {"name":"query","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.QueryRequest"] }, {"name":"queryPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"queryPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.QueryRequest"] }, {"name":"restoreTableFromBackup","parameterTypes":["java.util.function.Consumer"] }, {"name":"restoreTableFromBackup","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.RestoreTableFromBackupRequest"] }, {"name":"restoreTableToPointInTime","parameterTypes":["java.util.function.Consumer"] }, {"name":"restoreTableToPointInTime","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.RestoreTableToPointInTimeRequest"] }, {"name":"scan","parameterTypes":["java.util.function.Consumer"] }, {"name":"scan","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ScanRequest"] }, {"name":"scanPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"scanPaginator","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.ScanRequest"] }, {"name":"serviceClientConfiguration","parameterTypes":[] }, {"name":"tagResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"tagResource","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.TagResourceRequest"] }, {"name":"transactGetItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"transactGetItems","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.TransactGetItemsRequest"] }, {"name":"transactWriteItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"transactWriteItems","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.TransactWriteItemsRequest"] }, {"name":"untagResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"untagResource","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UntagResourceRequest"] }, {"name":"updateContinuousBackups","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateContinuousBackups","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateContinuousBackupsRequest"] }, {"name":"updateContributorInsights","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateContributorInsights","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateContributorInsightsRequest"] }, {"name":"updateGlobalTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateGlobalTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateGlobalTableRequest"] }, {"name":"updateGlobalTableSettings","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateGlobalTableSettings","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateGlobalTableSettingsRequest"] }, {"name":"updateItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateItem","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest"] }, {"name":"updateKinesisStreamingDestination","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateKinesisStreamingDestination","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateKinesisStreamingDestinationRequest"] }, {"name":"updateTable","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateTable","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateTableRequest"] }, {"name":"updateTableReplicaAutoScaling","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateTableReplicaAutoScaling","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateTableReplicaAutoScalingRequest"] }, {"name":"updateTimeToLive","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateTimeToLive","parameterTypes":["software.amazon.awssdk.services.dynamodb.model.UpdateTimeToLiveRequest"] }, {"name":"waiter","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.services.secretsmanager.SecretsManagerClient", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"batchGetSecretValue","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchGetSecretValue","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.BatchGetSecretValueRequest"] }, {"name":"batchGetSecretValuePaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"batchGetSecretValuePaginator","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.BatchGetSecretValueRequest"] }, {"name":"cancelRotateSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"cancelRotateSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.CancelRotateSecretRequest"] }, {"name":"createSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"createSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.CreateSecretRequest"] }, {"name":"deleteResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteResourcePolicy","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.DeleteResourcePolicyRequest"] }, {"name":"deleteSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.DeleteSecretRequest"] }, {"name":"describeSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.DescribeSecretRequest"] }, {"name":"getRandomPassword","parameterTypes":[] }, {"name":"getRandomPassword","parameterTypes":["java.util.function.Consumer"] }, {"name":"getRandomPassword","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.GetRandomPasswordRequest"] }, {"name":"getResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"getResourcePolicy","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.GetResourcePolicyRequest"] }, {"name":"getSecretValue","parameterTypes":["java.util.function.Consumer"] }, {"name":"getSecretValue","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest"] }, {"name":"listSecretVersionIds","parameterTypes":["java.util.function.Consumer"] }, {"name":"listSecretVersionIds","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ListSecretVersionIdsRequest"] }, {"name":"listSecretVersionIdsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listSecretVersionIdsPaginator","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ListSecretVersionIdsRequest"] }, {"name":"listSecrets","parameterTypes":[] }, {"name":"listSecrets","parameterTypes":["java.util.function.Consumer"] }, {"name":"listSecrets","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ListSecretsRequest"] }, {"name":"listSecretsPaginator","parameterTypes":[] }, {"name":"listSecretsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listSecretsPaginator","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ListSecretsRequest"] }, {"name":"putResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"putResourcePolicy","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.PutResourcePolicyRequest"] }, {"name":"putSecretValue","parameterTypes":["java.util.function.Consumer"] }, {"name":"putSecretValue","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.PutSecretValueRequest"] }, {"name":"removeRegionsFromReplication","parameterTypes":["java.util.function.Consumer"] }, {"name":"removeRegionsFromReplication","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.RemoveRegionsFromReplicationRequest"] }, {"name":"replicateSecretToRegions","parameterTypes":["java.util.function.Consumer"] }, {"name":"replicateSecretToRegions","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ReplicateSecretToRegionsRequest"] }, {"name":"restoreSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"restoreSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.RestoreSecretRequest"] }, {"name":"rotateSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"rotateSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.RotateSecretRequest"] }, {"name":"serviceClientConfiguration","parameterTypes":[] }, {"name":"stopReplicationToReplica","parameterTypes":["java.util.function.Consumer"] }, {"name":"stopReplicationToReplica","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.StopReplicationToReplicaRequest"] }, {"name":"tagResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"tagResource","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.TagResourceRequest"] }, {"name":"untagResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"untagResource","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.UntagResourceRequest"] }, {"name":"updateSecret","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateSecret","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.UpdateSecretRequest"] }, {"name":"updateSecretVersionStage","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateSecretVersionStage","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.UpdateSecretVersionStageRequest"] }, {"name":"validateResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"validateResourcePolicy","parameterTypes":["software.amazon.awssdk.services.secretsmanager.model.ValidateResourcePolicyRequest"] }] +}, +{ + "name":"software.amazon.awssdk.services.ssm.SsmClient", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"addTagsToResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"addTagsToResource","parameterTypes":["software.amazon.awssdk.services.ssm.model.AddTagsToResourceRequest"] }, {"name":"associateOpsItemRelatedItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"associateOpsItemRelatedItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.AssociateOpsItemRelatedItemRequest"] }, {"name":"cancelCommand","parameterTypes":["java.util.function.Consumer"] }, {"name":"cancelCommand","parameterTypes":["software.amazon.awssdk.services.ssm.model.CancelCommandRequest"] }, {"name":"cancelMaintenanceWindowExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"cancelMaintenanceWindowExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.CancelMaintenanceWindowExecutionRequest"] }, {"name":"createActivation","parameterTypes":["java.util.function.Consumer"] }, {"name":"createActivation","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateActivationRequest"] }, {"name":"createAssociation","parameterTypes":["java.util.function.Consumer"] }, {"name":"createAssociation","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateAssociationRequest"] }, {"name":"createAssociationBatch","parameterTypes":["java.util.function.Consumer"] }, {"name":"createAssociationBatch","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateAssociationBatchRequest"] }, {"name":"createDocument","parameterTypes":["java.util.function.Consumer"] }, {"name":"createDocument","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateDocumentRequest"] }, {"name":"createMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"createMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateMaintenanceWindowRequest"] }, {"name":"createOpsItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"createOpsItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateOpsItemRequest"] }, {"name":"createOpsMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"createOpsMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateOpsMetadataRequest"] }, {"name":"createPatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"createPatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreatePatchBaselineRequest"] }, {"name":"createResourceDataSync","parameterTypes":["java.util.function.Consumer"] }, {"name":"createResourceDataSync","parameterTypes":["software.amazon.awssdk.services.ssm.model.CreateResourceDataSyncRequest"] }, {"name":"deleteActivation","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteActivation","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteActivationRequest"] }, {"name":"deleteAssociation","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteAssociation","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteAssociationRequest"] }, {"name":"deleteDocument","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteDocument","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteDocumentRequest"] }, {"name":"deleteInventory","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteInventory","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteInventoryRequest"] }, {"name":"deleteMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteMaintenanceWindowRequest"] }, {"name":"deleteOpsItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteOpsItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteOpsItemRequest"] }, {"name":"deleteOpsMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteOpsMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteOpsMetadataRequest"] }, {"name":"deleteParameter","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteParameter","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteParameterRequest"] }, {"name":"deleteParameters","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteParameters","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteParametersRequest"] }, {"name":"deletePatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"deletePatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeletePatchBaselineRequest"] }, {"name":"deleteResourceDataSync","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteResourceDataSync","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteResourceDataSyncRequest"] }, {"name":"deleteResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"deleteResourcePolicy","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeleteResourcePolicyRequest"] }, {"name":"deregisterManagedInstance","parameterTypes":["java.util.function.Consumer"] }, {"name":"deregisterManagedInstance","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeregisterManagedInstanceRequest"] }, {"name":"deregisterPatchBaselineForPatchGroup","parameterTypes":["java.util.function.Consumer"] }, {"name":"deregisterPatchBaselineForPatchGroup","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeregisterPatchBaselineForPatchGroupRequest"] }, {"name":"deregisterTargetFromMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"deregisterTargetFromMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeregisterTargetFromMaintenanceWindowRequest"] }, {"name":"deregisterTaskFromMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"deregisterTaskFromMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.DeregisterTaskFromMaintenanceWindowRequest"] }, {"name":"describeActivations","parameterTypes":[] }, {"name":"describeActivations","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeActivations","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeActivationsRequest"] }, {"name":"describeActivationsPaginator","parameterTypes":[] }, {"name":"describeActivationsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeActivationsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeActivationsRequest"] }, {"name":"describeAssociation","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAssociation","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAssociationRequest"] }, {"name":"describeAssociationExecutionTargets","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAssociationExecutionTargets","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAssociationExecutionTargetsRequest"] }, {"name":"describeAssociationExecutionTargetsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAssociationExecutionTargetsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAssociationExecutionTargetsRequest"] }, {"name":"describeAssociationExecutions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAssociationExecutions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAssociationExecutionsRequest"] }, {"name":"describeAssociationExecutionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAssociationExecutionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAssociationExecutionsRequest"] }, {"name":"describeAutomationExecutions","parameterTypes":[] }, {"name":"describeAutomationExecutions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAutomationExecutions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAutomationExecutionsRequest"] }, {"name":"describeAutomationExecutionsPaginator","parameterTypes":[] }, {"name":"describeAutomationExecutionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAutomationExecutionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAutomationExecutionsRequest"] }, {"name":"describeAutomationStepExecutions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAutomationStepExecutions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAutomationStepExecutionsRequest"] }, {"name":"describeAutomationStepExecutionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAutomationStepExecutionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAutomationStepExecutionsRequest"] }, {"name":"describeAvailablePatches","parameterTypes":[] }, {"name":"describeAvailablePatches","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAvailablePatches","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAvailablePatchesRequest"] }, {"name":"describeAvailablePatchesPaginator","parameterTypes":[] }, {"name":"describeAvailablePatchesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeAvailablePatchesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeAvailablePatchesRequest"] }, {"name":"describeDocument","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeDocument","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeDocumentRequest"] }, {"name":"describeDocumentPermission","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeDocumentPermission","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeDocumentPermissionRequest"] }, {"name":"describeEffectiveInstanceAssociations","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeEffectiveInstanceAssociations","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeEffectiveInstanceAssociationsRequest"] }, {"name":"describeEffectiveInstanceAssociationsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeEffectiveInstanceAssociationsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeEffectiveInstanceAssociationsRequest"] }, {"name":"describeEffectivePatchesForPatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeEffectivePatchesForPatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeEffectivePatchesForPatchBaselineRequest"] }, {"name":"describeEffectivePatchesForPatchBaselinePaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeEffectivePatchesForPatchBaselinePaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeEffectivePatchesForPatchBaselineRequest"] }, {"name":"describeInstanceAssociationsStatus","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstanceAssociationsStatus","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstanceAssociationsStatusRequest"] }, {"name":"describeInstanceAssociationsStatusPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstanceAssociationsStatusPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstanceAssociationsStatusRequest"] }, {"name":"describeInstanceInformation","parameterTypes":[] }, {"name":"describeInstanceInformation","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstanceInformation","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstanceInformationRequest"] }, {"name":"describeInstanceInformationPaginator","parameterTypes":[] }, {"name":"describeInstanceInformationPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstanceInformationPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstanceInformationRequest"] }, {"name":"describeInstancePatchStates","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatchStates","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchStatesRequest"] }, {"name":"describeInstancePatchStatesForPatchGroup","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatchStatesForPatchGroup","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchStatesForPatchGroupRequest"] }, {"name":"describeInstancePatchStatesForPatchGroupPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatchStatesForPatchGroupPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchStatesForPatchGroupRequest"] }, {"name":"describeInstancePatchStatesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatchStatesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchStatesRequest"] }, {"name":"describeInstancePatches","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatches","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchesRequest"] }, {"name":"describeInstancePatchesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePatchesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePatchesRequest"] }, {"name":"describeInstanceProperties","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstanceProperties","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePropertiesRequest"] }, {"name":"describeInstancePropertiesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInstancePropertiesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInstancePropertiesRequest"] }, {"name":"describeInventoryDeletions","parameterTypes":[] }, {"name":"describeInventoryDeletions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInventoryDeletions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInventoryDeletionsRequest"] }, {"name":"describeInventoryDeletionsPaginator","parameterTypes":[] }, {"name":"describeInventoryDeletionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeInventoryDeletionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeInventoryDeletionsRequest"] }, {"name":"describeMaintenanceWindowExecutionTaskInvocations","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutionTaskInvocations","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionTaskInvocationsRequest"] }, {"name":"describeMaintenanceWindowExecutionTaskInvocationsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutionTaskInvocationsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionTaskInvocationsRequest"] }, {"name":"describeMaintenanceWindowExecutionTasks","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutionTasks","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionTasksRequest"] }, {"name":"describeMaintenanceWindowExecutionTasksPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutionTasksPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionTasksRequest"] }, {"name":"describeMaintenanceWindowExecutions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionsRequest"] }, {"name":"describeMaintenanceWindowExecutionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowExecutionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowExecutionsRequest"] }, {"name":"describeMaintenanceWindowSchedule","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowSchedule","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowScheduleRequest"] }, {"name":"describeMaintenanceWindowSchedulePaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowSchedulePaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowScheduleRequest"] }, {"name":"describeMaintenanceWindowTargets","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowTargets","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowTargetsRequest"] }, {"name":"describeMaintenanceWindowTargetsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowTargetsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowTargetsRequest"] }, {"name":"describeMaintenanceWindowTasks","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowTasks","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowTasksRequest"] }, {"name":"describeMaintenanceWindowTasksPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowTasksPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowTasksRequest"] }, {"name":"describeMaintenanceWindows","parameterTypes":[] }, {"name":"describeMaintenanceWindows","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindows","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowsRequest"] }, {"name":"describeMaintenanceWindowsForTarget","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowsForTarget","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowsForTargetRequest"] }, {"name":"describeMaintenanceWindowsForTargetPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowsForTargetPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowsForTargetRequest"] }, {"name":"describeMaintenanceWindowsPaginator","parameterTypes":[] }, {"name":"describeMaintenanceWindowsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeMaintenanceWindowsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeMaintenanceWindowsRequest"] }, {"name":"describeOpsItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeOpsItems","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeOpsItemsRequest"] }, {"name":"describeOpsItemsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeOpsItemsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeOpsItemsRequest"] }, {"name":"describeParameters","parameterTypes":[] }, {"name":"describeParameters","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeParameters","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeParametersRequest"] }, {"name":"describeParametersPaginator","parameterTypes":[] }, {"name":"describeParametersPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeParametersPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeParametersRequest"] }, {"name":"describePatchBaselines","parameterTypes":[] }, {"name":"describePatchBaselines","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchBaselines","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchBaselinesRequest"] }, {"name":"describePatchBaselinesPaginator","parameterTypes":[] }, {"name":"describePatchBaselinesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchBaselinesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchBaselinesRequest"] }, {"name":"describePatchGroupState","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchGroupState","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchGroupStateRequest"] }, {"name":"describePatchGroups","parameterTypes":[] }, {"name":"describePatchGroups","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchGroups","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchGroupsRequest"] }, {"name":"describePatchGroupsPaginator","parameterTypes":[] }, {"name":"describePatchGroupsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchGroupsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchGroupsRequest"] }, {"name":"describePatchProperties","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchProperties","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchPropertiesRequest"] }, {"name":"describePatchPropertiesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describePatchPropertiesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribePatchPropertiesRequest"] }, {"name":"describeSessions","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeSessions","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeSessionsRequest"] }, {"name":"describeSessionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"describeSessionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.DescribeSessionsRequest"] }, {"name":"disassociateOpsItemRelatedItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"disassociateOpsItemRelatedItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.DisassociateOpsItemRelatedItemRequest"] }, {"name":"getAutomationExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"getAutomationExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetAutomationExecutionRequest"] }, {"name":"getCalendarState","parameterTypes":["java.util.function.Consumer"] }, {"name":"getCalendarState","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetCalendarStateRequest"] }, {"name":"getCommandInvocation","parameterTypes":["java.util.function.Consumer"] }, {"name":"getCommandInvocation","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetCommandInvocationRequest"] }, {"name":"getConnectionStatus","parameterTypes":["java.util.function.Consumer"] }, {"name":"getConnectionStatus","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetConnectionStatusRequest"] }, {"name":"getDefaultPatchBaseline","parameterTypes":[] }, {"name":"getDefaultPatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"getDefaultPatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetDefaultPatchBaselineRequest"] }, {"name":"getDeployablePatchSnapshotForInstance","parameterTypes":["java.util.function.Consumer"] }, {"name":"getDeployablePatchSnapshotForInstance","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetDeployablePatchSnapshotForInstanceRequest"] }, {"name":"getDocument","parameterTypes":["java.util.function.Consumer"] }, {"name":"getDocument","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetDocumentRequest"] }, {"name":"getInventory","parameterTypes":[] }, {"name":"getInventory","parameterTypes":["java.util.function.Consumer"] }, {"name":"getInventory","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetInventoryRequest"] }, {"name":"getInventoryPaginator","parameterTypes":[] }, {"name":"getInventoryPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getInventoryPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetInventoryRequest"] }, {"name":"getInventorySchema","parameterTypes":[] }, {"name":"getInventorySchema","parameterTypes":["java.util.function.Consumer"] }, {"name":"getInventorySchema","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetInventorySchemaRequest"] }, {"name":"getInventorySchemaPaginator","parameterTypes":[] }, {"name":"getInventorySchemaPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getInventorySchemaPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetInventorySchemaRequest"] }, {"name":"getMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"getMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetMaintenanceWindowRequest"] }, {"name":"getMaintenanceWindowExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"getMaintenanceWindowExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetMaintenanceWindowExecutionRequest"] }, {"name":"getMaintenanceWindowExecutionTask","parameterTypes":["java.util.function.Consumer"] }, {"name":"getMaintenanceWindowExecutionTask","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetMaintenanceWindowExecutionTaskRequest"] }, {"name":"getMaintenanceWindowExecutionTaskInvocation","parameterTypes":["java.util.function.Consumer"] }, {"name":"getMaintenanceWindowExecutionTaskInvocation","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetMaintenanceWindowExecutionTaskInvocationRequest"] }, {"name":"getMaintenanceWindowTask","parameterTypes":["java.util.function.Consumer"] }, {"name":"getMaintenanceWindowTask","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetMaintenanceWindowTaskRequest"] }, {"name":"getOpsItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"getOpsItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetOpsItemRequest"] }, {"name":"getOpsMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"getOpsMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetOpsMetadataRequest"] }, {"name":"getOpsSummary","parameterTypes":["java.util.function.Consumer"] }, {"name":"getOpsSummary","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetOpsSummaryRequest"] }, {"name":"getOpsSummaryPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getOpsSummaryPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetOpsSummaryRequest"] }, {"name":"getParameter","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParameter","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParameterRequest"] }, {"name":"getParameterHistory","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParameterHistory","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParameterHistoryRequest"] }, {"name":"getParameterHistoryPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParameterHistoryPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParameterHistoryRequest"] }, {"name":"getParameters","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParameters","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParametersRequest"] }, {"name":"getParametersByPath","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParametersByPath","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest"] }, {"name":"getParametersByPathPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getParametersByPathPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetParametersByPathRequest"] }, {"name":"getPatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"getPatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetPatchBaselineRequest"] }, {"name":"getPatchBaselineForPatchGroup","parameterTypes":["java.util.function.Consumer"] }, {"name":"getPatchBaselineForPatchGroup","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetPatchBaselineForPatchGroupRequest"] }, {"name":"getResourcePolicies","parameterTypes":["java.util.function.Consumer"] }, {"name":"getResourcePolicies","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetResourcePoliciesRequest"] }, {"name":"getResourcePoliciesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"getResourcePoliciesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetResourcePoliciesRequest"] }, {"name":"getServiceSetting","parameterTypes":["java.util.function.Consumer"] }, {"name":"getServiceSetting","parameterTypes":["software.amazon.awssdk.services.ssm.model.GetServiceSettingRequest"] }, {"name":"labelParameterVersion","parameterTypes":["java.util.function.Consumer"] }, {"name":"labelParameterVersion","parameterTypes":["software.amazon.awssdk.services.ssm.model.LabelParameterVersionRequest"] }, {"name":"listAssociationVersions","parameterTypes":["java.util.function.Consumer"] }, {"name":"listAssociationVersions","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListAssociationVersionsRequest"] }, {"name":"listAssociationVersionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listAssociationVersionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListAssociationVersionsRequest"] }, {"name":"listAssociations","parameterTypes":[] }, {"name":"listAssociations","parameterTypes":["java.util.function.Consumer"] }, {"name":"listAssociations","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListAssociationsRequest"] }, {"name":"listAssociationsPaginator","parameterTypes":[] }, {"name":"listAssociationsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listAssociationsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListAssociationsRequest"] }, {"name":"listCommandInvocations","parameterTypes":[] }, {"name":"listCommandInvocations","parameterTypes":["java.util.function.Consumer"] }, {"name":"listCommandInvocations","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListCommandInvocationsRequest"] }, {"name":"listCommandInvocationsPaginator","parameterTypes":[] }, {"name":"listCommandInvocationsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listCommandInvocationsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListCommandInvocationsRequest"] }, {"name":"listCommands","parameterTypes":[] }, {"name":"listCommands","parameterTypes":["java.util.function.Consumer"] }, {"name":"listCommands","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListCommandsRequest"] }, {"name":"listCommandsPaginator","parameterTypes":[] }, {"name":"listCommandsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listCommandsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListCommandsRequest"] }, {"name":"listComplianceItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"listComplianceItems","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListComplianceItemsRequest"] }, {"name":"listComplianceItemsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listComplianceItemsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListComplianceItemsRequest"] }, {"name":"listComplianceSummaries","parameterTypes":[] }, {"name":"listComplianceSummaries","parameterTypes":["java.util.function.Consumer"] }, {"name":"listComplianceSummaries","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListComplianceSummariesRequest"] }, {"name":"listComplianceSummariesPaginator","parameterTypes":[] }, {"name":"listComplianceSummariesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listComplianceSummariesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListComplianceSummariesRequest"] }, {"name":"listDocumentMetadataHistory","parameterTypes":["java.util.function.Consumer"] }, {"name":"listDocumentMetadataHistory","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListDocumentMetadataHistoryRequest"] }, {"name":"listDocumentVersions","parameterTypes":["java.util.function.Consumer"] }, {"name":"listDocumentVersions","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListDocumentVersionsRequest"] }, {"name":"listDocumentVersionsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listDocumentVersionsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListDocumentVersionsRequest"] }, {"name":"listDocuments","parameterTypes":[] }, {"name":"listDocuments","parameterTypes":["java.util.function.Consumer"] }, {"name":"listDocuments","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListDocumentsRequest"] }, {"name":"listDocumentsPaginator","parameterTypes":[] }, {"name":"listDocumentsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listDocumentsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListDocumentsRequest"] }, {"name":"listInventoryEntries","parameterTypes":["java.util.function.Consumer"] }, {"name":"listInventoryEntries","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListInventoryEntriesRequest"] }, {"name":"listOpsItemEvents","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsItemEvents","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsItemEventsRequest"] }, {"name":"listOpsItemEventsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsItemEventsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsItemEventsRequest"] }, {"name":"listOpsItemRelatedItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsItemRelatedItems","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsItemRelatedItemsRequest"] }, {"name":"listOpsItemRelatedItemsPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsItemRelatedItemsPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsItemRelatedItemsRequest"] }, {"name":"listOpsMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsMetadataRequest"] }, {"name":"listOpsMetadataPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listOpsMetadataPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListOpsMetadataRequest"] }, {"name":"listResourceComplianceSummaries","parameterTypes":[] }, {"name":"listResourceComplianceSummaries","parameterTypes":["java.util.function.Consumer"] }, {"name":"listResourceComplianceSummaries","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListResourceComplianceSummariesRequest"] }, {"name":"listResourceComplianceSummariesPaginator","parameterTypes":[] }, {"name":"listResourceComplianceSummariesPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listResourceComplianceSummariesPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListResourceComplianceSummariesRequest"] }, {"name":"listResourceDataSync","parameterTypes":[] }, {"name":"listResourceDataSync","parameterTypes":["java.util.function.Consumer"] }, {"name":"listResourceDataSync","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListResourceDataSyncRequest"] }, {"name":"listResourceDataSyncPaginator","parameterTypes":[] }, {"name":"listResourceDataSyncPaginator","parameterTypes":["java.util.function.Consumer"] }, {"name":"listResourceDataSyncPaginator","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListResourceDataSyncRequest"] }, {"name":"listTagsForResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"listTagsForResource","parameterTypes":["software.amazon.awssdk.services.ssm.model.ListTagsForResourceRequest"] }, {"name":"modifyDocumentPermission","parameterTypes":["java.util.function.Consumer"] }, {"name":"modifyDocumentPermission","parameterTypes":["software.amazon.awssdk.services.ssm.model.ModifyDocumentPermissionRequest"] }, {"name":"putComplianceItems","parameterTypes":["java.util.function.Consumer"] }, {"name":"putComplianceItems","parameterTypes":["software.amazon.awssdk.services.ssm.model.PutComplianceItemsRequest"] }, {"name":"putInventory","parameterTypes":["java.util.function.Consumer"] }, {"name":"putInventory","parameterTypes":["software.amazon.awssdk.services.ssm.model.PutInventoryRequest"] }, {"name":"putParameter","parameterTypes":["java.util.function.Consumer"] }, {"name":"putParameter","parameterTypes":["software.amazon.awssdk.services.ssm.model.PutParameterRequest"] }, {"name":"putResourcePolicy","parameterTypes":["java.util.function.Consumer"] }, {"name":"putResourcePolicy","parameterTypes":["software.amazon.awssdk.services.ssm.model.PutResourcePolicyRequest"] }, {"name":"registerDefaultPatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"registerDefaultPatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.RegisterDefaultPatchBaselineRequest"] }, {"name":"registerPatchBaselineForPatchGroup","parameterTypes":["java.util.function.Consumer"] }, {"name":"registerPatchBaselineForPatchGroup","parameterTypes":["software.amazon.awssdk.services.ssm.model.RegisterPatchBaselineForPatchGroupRequest"] }, {"name":"registerTargetWithMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"registerTargetWithMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.RegisterTargetWithMaintenanceWindowRequest"] }, {"name":"registerTaskWithMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"registerTaskWithMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.RegisterTaskWithMaintenanceWindowRequest"] }, {"name":"removeTagsFromResource","parameterTypes":["java.util.function.Consumer"] }, {"name":"removeTagsFromResource","parameterTypes":["software.amazon.awssdk.services.ssm.model.RemoveTagsFromResourceRequest"] }, {"name":"resetServiceSetting","parameterTypes":["java.util.function.Consumer"] }, {"name":"resetServiceSetting","parameterTypes":["software.amazon.awssdk.services.ssm.model.ResetServiceSettingRequest"] }, {"name":"resumeSession","parameterTypes":["java.util.function.Consumer"] }, {"name":"resumeSession","parameterTypes":["software.amazon.awssdk.services.ssm.model.ResumeSessionRequest"] }, {"name":"sendAutomationSignal","parameterTypes":["java.util.function.Consumer"] }, {"name":"sendAutomationSignal","parameterTypes":["software.amazon.awssdk.services.ssm.model.SendAutomationSignalRequest"] }, {"name":"sendCommand","parameterTypes":["java.util.function.Consumer"] }, {"name":"sendCommand","parameterTypes":["software.amazon.awssdk.services.ssm.model.SendCommandRequest"] }, {"name":"serviceClientConfiguration","parameterTypes":[] }, {"name":"startAssociationsOnce","parameterTypes":["java.util.function.Consumer"] }, {"name":"startAssociationsOnce","parameterTypes":["software.amazon.awssdk.services.ssm.model.StartAssociationsOnceRequest"] }, {"name":"startAutomationExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"startAutomationExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.StartAutomationExecutionRequest"] }, {"name":"startChangeRequestExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"startChangeRequestExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.StartChangeRequestExecutionRequest"] }, {"name":"startSession","parameterTypes":["java.util.function.Consumer"] }, {"name":"startSession","parameterTypes":["software.amazon.awssdk.services.ssm.model.StartSessionRequest"] }, {"name":"stopAutomationExecution","parameterTypes":["java.util.function.Consumer"] }, {"name":"stopAutomationExecution","parameterTypes":["software.amazon.awssdk.services.ssm.model.StopAutomationExecutionRequest"] }, {"name":"terminateSession","parameterTypes":["java.util.function.Consumer"] }, {"name":"terminateSession","parameterTypes":["software.amazon.awssdk.services.ssm.model.TerminateSessionRequest"] }, {"name":"unlabelParameterVersion","parameterTypes":["java.util.function.Consumer"] }, {"name":"unlabelParameterVersion","parameterTypes":["software.amazon.awssdk.services.ssm.model.UnlabelParameterVersionRequest"] }, {"name":"updateAssociation","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateAssociation","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateAssociationRequest"] }, {"name":"updateAssociationStatus","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateAssociationStatus","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateAssociationStatusRequest"] }, {"name":"updateDocument","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateDocument","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateDocumentRequest"] }, {"name":"updateDocumentDefaultVersion","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateDocumentDefaultVersion","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateDocumentDefaultVersionRequest"] }, {"name":"updateDocumentMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateDocumentMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateDocumentMetadataRequest"] }, {"name":"updateMaintenanceWindow","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateMaintenanceWindow","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateMaintenanceWindowRequest"] }, {"name":"updateMaintenanceWindowTarget","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateMaintenanceWindowTarget","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateMaintenanceWindowTargetRequest"] }, {"name":"updateMaintenanceWindowTask","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateMaintenanceWindowTask","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateMaintenanceWindowTaskRequest"] }, {"name":"updateManagedInstanceRole","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateManagedInstanceRole","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateManagedInstanceRoleRequest"] }, {"name":"updateOpsItem","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateOpsItem","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateOpsItemRequest"] }, {"name":"updateOpsMetadata","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateOpsMetadata","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateOpsMetadataRequest"] }, {"name":"updatePatchBaseline","parameterTypes":["java.util.function.Consumer"] }, {"name":"updatePatchBaseline","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdatePatchBaselineRequest"] }, {"name":"updateResourceDataSync","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateResourceDataSync","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateResourceDataSyncRequest"] }, {"name":"updateServiceSetting","parameterTypes":["java.util.function.Consumer"] }, {"name":"updateServiceSetting","parameterTypes":["software.amazon.awssdk.services.ssm.model.UpdateServiceSettingRequest"] }, {"name":"waiter","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.utils.SdkAutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"close","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.transform.Base64Transformer", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.transform.BasicTransformer", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.transform.JsonTransformer", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.transform.ObjectToDeserialize", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setBar","parameterTypes":["int"] }, {"name":"setBaz","parameterTypes":["long"] }, {"name":"setFoo","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +} +] From 8066e0385a439c49bbc57b88eb38b3ce5747860f Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Tue, 27 May 2025 10:11:59 +0200 Subject: [PATCH 236/577] docs(v2): Create upgrade guide and versioning policy (#1856) * Update docs requirements using pip-compile. Add privacy plugin. Add llms.txt plugin. Make Idempotency documentation environment variable naming consistent. Fix documentation formatting issue in FAQ.md. * Add roadmap. * Fix outdated AspectJ configuration in documentation pages. * Synchronize Changelog with recent releases. * Add llms.txt to links to navbar. * Add Versioning policy page. * Update site url in mkdocs.yml. * Add versioning.md to llms.txt. * Update maintainers.md. * Fix formatting. * Fix formatting. * Add upgrade guide. * Update docs/upgrade.md Co-authored-by: Stefano Vozza * Update docs/upgrade.md Co-authored-by: Stefano Vozza * Update docs/upgrade.md Co-authored-by: Stefano Vozza * Update docs/upgrade.md Co-authored-by: Stefano Vozza * Update docs/upgrade.md Co-authored-by: Stefano Vozza * Update docs/upgrade.md Co-authored-by: Stefano Vozza * Update docs/upgrade.md Co-authored-by: Stefano Vozza * Update docs/upgrade.md Co-authored-by: Leandro Damascena * Update docs/processes/maintainers.md * Update docs/upgrade.md * Update docs/processes/maintainers.md * Update docs/upgrade.md * Update docs/upgrade.md * Fix formatting. Make Maintainer playbook naming consistent. --------- Co-authored-by: Andrea Amorosi Co-authored-by: Stefano Vozza Co-authored-by: Leandro Damascena --- docs/processes/maintainers.md | 22 +- docs/processes/versioning.md | 60 +++++ docs/upgrade.md | 410 +++++++++++++++++++++++++++++ docs/utilities/custom_resources.md | 9 +- docs/utilities/validation.md | 6 +- mkdocs.yml | 5 +- 6 files changed, 494 insertions(+), 18 deletions(-) create mode 100644 docs/processes/versioning.md create mode 100644 docs/upgrade.md diff --git a/docs/processes/maintainers.md b/docs/processes/maintainers.md index 6b3d9e126..8f7f6a8fd 100644 --- a/docs/processes/maintainers.md +++ b/docs/processes/maintainers.md @@ -14,21 +14,23 @@ This is document explains who the maintainers are, their responsibilities, and h ## Current Maintainers -| Maintainer | GitHub ID | Affiliation | -|-----------------------|---------------------------------------------------------------------------------| ----------- | -| Jerome Van Der Linden | [jeromevdl](https://github.com/jeromevdl){target="_blank"} | Amazon | -| Michele Ricciardi | [mriccia](https://github.com/mriccia){target="_blank"} | Amazon | -| Scott Gerring | [scottgerring](https://github.com/scottgerring){target="_blank"} | Amazon | +| Maintainer | GitHub ID | Affiliation | +| --------------- | -------------------------------------------------------------------- | ----------- | +| Philipp Page | [phipag](https://github.com/phipag){target="\_blank" rel="nofollow"} | Amazon | +| Simon Thulbourn | [sthulb](https://github.com/sthulb){target="\_blank" rel="nofollow"} | Amazon | ## Emeritus Previous active maintainers who contributed to this project. -| Maintainer | GitHub ID | Affiliation | -|----------------|-----------------------------------------------------------------------------------------|---------------| -| Mark Sailes | [msailes](https://github.com/msailes){target="_blank"} | Amazon | -| Pankaj Agrawal | [pankajagrawal16](https://github.com/pankajagrawal16){target="_blank"} | Former Amazon | -| Steve Houel | [stevehouel](https://github.com/stevehouel) | Amazon | +| Maintainer | GitHub ID | Affiliation | +| --------------------- | -------------------------------------------------------------------------------------- | ------------- | +| Jerome Van Der Linden | [jeromevdl](https://github.com/jeromevdl){target="\_blank" rel="nofollow"} | Amazon | +| Michele Ricciardi | [mriccia](https://github.com/mriccia){target="\_blank" rel="nofollow"} | Amazon | +| Scott Gerring | [scottgerring](https://github.com/scottgerring){target="\_blank" rel="nofollow"} | DataDog | +| Mark Sailes | [msailes](https://github.com/msailes){target="\_blank" rel="nofollow"} | Former Amazon | +| Pankaj Agrawal | [pankajagrawal16](https://github.com/pankajagrawal16){target="\_blank" rel="nofollow"} | Former Amazon | +| Steve Houel | [stevehouel](https://github.com/stevehouel){target="\_blank" rel="nofollow"} | Amazon | ## Labels diff --git a/docs/processes/versioning.md b/docs/processes/versioning.md new file mode 100644 index 000000000..8b12e0fa9 --- /dev/null +++ b/docs/processes/versioning.md @@ -0,0 +1,60 @@ +--- +title: Versioning and maintenance policy +description: Versioning and maintenance policy for Powertools for AWS Lambda (Python) +--- + +### Overview + +This document outlines the maintenance policy for Powertools for AWS Lambda and their underlying dependencies. AWS regularly provides Powertools for AWS Lambda with updates that may contain new features, enhancements, bug fixes, security patches, or documentation updates. Updates may also address changes with dependencies, language runtimes, and operating systems. Powertools for AWS Lambda is published to package managers (e.g. PyPi, NPM, Maven, NuGet), and are available as source code on GitHub. + +We recommend users to stay up-to-date with Powertools for AWS Lambda releases to keep up with the latest features, security updates, and underlying dependencies. Continued use of an unsupported Powertools for AWS Lambda version is not recommended and is done at the user’s discretion. + +!!! info "For brevity, we will interchangeably refer to Powertools for AWS Lambda as "SDK" _(Software Development Toolkit)_." + +### Versioning + +Powertools for AWS Lambda release versions are in the form of X.Y.Z where X represents the major version. Increasing the major version of an SDK indicates that this SDK underwent significant and substantial changes to support new idioms and patterns in the language. Major versions are introduced when public interfaces _(e.g. classes, methods, types, etc.)_, behaviors, or semantics have changed. Applications need to be updated in order for them to work with the newest SDK version. It is important to update major versions carefully and in accordance with the upgrade guidelines provided by AWS. + +### SDK major version lifecycle + +The lifecycle for major Powertools for AWS Lambda versions consists of 5 phases, which are outlined below. + +- **Developer Preview** (Phase 0) - During this phase, SDKs are not supported, should not be used in production environments, and are meant for early access and feedback purposes only. It is possible for future releases to introduce breaking changes. Once AWS identifies a release to be a stable product, it may mark it as a Release Candidate. Release Candidates are ready for GA release unless significant bugs emerge, and will receive full AWS support. +- **General Availability (GA)** (Phase 1) - During this phase, SDKs are fully supported. AWS will provide regular SDK releases that include support for new features, enhancements, as well as bug and security fixes. AWS will support the GA version of an SDK for _at least 24 months_, unless otherwise specified. +- **Maintenance Announcement** (Phase 2) - AWS will make a public announcement at least 6 months before an SDK enters maintenance mode. During this period, the SDK will continue to be fully supported. Typically, maintenance mode is announced at the same time as the next major version is transitioned to GA. +- **Maintenance** (Phase 3) - During the maintenance mode, AWS limits SDK releases to address critical bug fixes and security issues only. An SDK will not receive API updates for new or existing services, or be updated to support new regions. Maintenance mode has a _default duration of 6 months_, unless otherwise specified. +- **End-of-Support** (Phase 4) - When an SDK reaches end-of support, it will no longer receive updates or releases. Previously published releases will continue to be available via public package managers and the code will remain on GitHub. The GitHub repository may be archived. Use of an SDK which has reached end-of-support is done at the user’s discretion. We recommend users upgrade to the new major version. + +!!! note "Please note that the timelines shown below are illustrative and not binding" + +![Maintenance policy timelines](https://docs.aws.amazon.com/images/sdkref/latest/guide/images/maint-policy.png) + +### Dependency lifecycle + +Most AWS SDKs have underlying dependencies, such as language runtimes, AWS Lambda runtime, or third party libraries and frameworks. These dependencies are typically tied to the language community or the vendor who owns that particular component. Each community or vendor publishes their own end-of-support schedule for their product. + +The following terms are used to classify underlying third party dependencies: + +- [**AWS Lambda Runtime**](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html): Examples include `java17`, `nodejs20.x`, `python3.13`, etc. +- **Language Runtime**: Examples include Java 17, Python 3.13, NodeJS 20, .NET Core, etc. +- **Third party Library**: Examples include Jackson Project, AWS X-Ray SDK, AWS Encryption SDK, etc. + +Powertools for AWS Lambda follows the [AWS Lambda Runtime deprecation policy cycle](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#runtime-support-policy), when it comes to Language Runtime. This means we will stop supporting their respective deprecated Language Runtime _(e.g., `java8`)_ without increasing the major SDK version. + +!!! note "AWS reserves the right to stop support for an underlying dependency without increasing the major SDK version" + +### Communication methods + +Maintenance announcements are communicated in several ways: + +- A pinned GitHub Request For Comments (RFC) issue indicating the campaign for the next major version. The RFC will outline the path to end-of-support, specify campaign timelines, and upgrade guidance. +- AWS SDK documentation, such as API reference documentation, user guides, SDK product marketing pages, and GitHub readme(s) are updated to indicate the campaign timeline and provide guidance on upgrading affected applications. +- Deprecation warnings are added to the SDKs, outlining the path to end-of-support and linking to the upgrade guide. + +To see the list of available major versions of Powertools for AWS Lambda and where they are in their maintenance lifecycle, see the [version support matrix](#version-support-matrix). + +### Version support matrix + +| SDK | Major version | Current Phase | General Availability Date | Notes | +| -------------------------------- | ------------- | -------------------- | ------------------------- | ------------------------------------------------------------------------------------------------- | +| Powertools for AWS Lambda (Java) | 1.x | General Availability | 11/04/2020 | See [Release notes](https://github.com/aws-powertools/powertools-lambda-java/releases/tag/v1.0.0) | diff --git a/docs/upgrade.md b/docs/upgrade.md new file mode 100644 index 000000000..11be3dc5f --- /dev/null +++ b/docs/upgrade.md @@ -0,0 +1,410 @@ +--- +title: Upgrade guide +description: Guide to update between major Powertools for AWS Lambda (Java) versions +--- + +## End of support v1 + + + +Given our commitment to all of our customers using Powertools for AWS Lambda (Java), we will keep [Maven Central](https://central.sonatype.com/search?q=powertools){target="\_blank"} `v1` releases and a `v1` documentation archive to prevent any disruption. + +## Migrate to v2 from v1 + +!!! info "We strongly encourage you to migrate to `v2`. Refer to our [versioning policy](./processes/versioning.md) to learn more about our version support process." + +We've made minimal breaking changes to make your transition to `v2` as smooth as possible. + +### Quick summary + +The following table shows a summary of the changes made in `v2` and whether code changes are necessary. Each change that requires a code change links to a section below explaining more details. + +| Area | Change | Code change required | +| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | +| **Logging** | The [logging module was re-designed](#redesigned-logging-utility) from scratch to support popular Java logging paradigms and libraries like `log4j2`, `logback`, and `slf4j`. | Yes | +| **Metrics** | [Changed public interface](#updated-metrics-utility-interface) to remove direct coupling with `aws-embedded-metrics-java`. | Yes | +| **Tracing** | [Removed deprecated `captureResponse` and `captureError` options](#deprecated-capture-mode-related-tracing-annotation-parameters) on `@Tracing` annotation. | Yes | +| **Idempotency** | The [`powertools-idempotency` module was split by provider](#idempotency-utility-split-into-sub-modules-by-provider) to improve modularity and reduce the deployment package size. | Yes | +| **Idempotency** | Updated `IdempotencyConfig` interface to support addition of response hooks. | No | +| **Parameters** | The [`powertools-parameters` module was split by provider](#parameters-utility-split-into-sub-modules-by-provider) to improve modularity and reduce the deployment package size. | Yes | +| **Batch Processing** | [Removed deprecated `powertools-sqs` module](#removed-powertools-sqs-module-in-favor-of-powertools-batch) in favor of the more generic [Batch Processing](./utilities/batch.md) utility. | Yes | +| **Batch Processing** | Updated Batch Processing `BatchMessageHandler` interface to add support for parallel processing. | No | +| **Validation** | The `@Validation` utility returns 4xx error codes instead of 5xx error codes when used with API Gateway now. | No | +| **Validation** | Validating batch event sources now adds failed events as partial batch failures and does not fail the whole batch anymore. | No | +| **Custom Resources** | [Removed deprecated `Response.failed()` and `Response.success()` methods](#custom-resources-updates-the-response-class). | Yes | +| **Custom Resources** | Changed interface of `Response` class to add an optional `reason` field. | No | +| **Dependencies** | Renamed `powertools-core` to `powertools-common`. This module should not be used as direct dependency and is listed here for completeness. | No | +| **Dependencies** | [Removed `org.aspectj.aspectjrt` as project dependency](#aspectj-runtime-not-included-by-default-anymore) in favor of consumers including the version they prefer. | Yes | +| **Language support** | Removed support for Java 8. The minimum required Java version is Java 11. | N/A | + +### First Steps + +Before you start, we suggest making a copy of your current working project or create a new branch with `git`. + +1. **Upgrade** Java to at least version 11. While version 11 is supported, we recommend using the [newest available LTS version](https://downloads.corretto.aws/#/downloads){target="\_blank"} of Java. +2. **Review** the following section to confirm if you need to make changes to your code. + +## Redesigned Logging Utility + + + +The logging utility was re-designed from scratch to integrate better with Java idiomatic conventions and to remove the hard dependency on `log4j` as logging implementation. The new logging utility now supports `slfj4` as logging interface and gives you the choice among `log4j2` and `logback` as logging implementations. Consider the following steps to migrate from the v1 logging utility to the v2 logging utility: + +**1. Remove `powertools-logging` dependency and replace it with your logging backend of choice** + +In order to support different logging implementations, dedicated logging modules were created for the different logging implementations. Remove `powertools-logging` as a dependency and replace it with either `powertools-logging-log4j` or `powertools-logging-logback`. + +```diff + +- +- software.amazon.lambda +- powertools-logging +- 1.x.x +- + + ++ ++ software.amazon.lambda ++ powertools-logging-log4j ++ 2.x.x ++ +``` + + +!!! info "The AspectJ configuration still needs to depend on `powertools-logging`" + We have only replaced the logging implementation dependency. The AspectJ configuration still needs to depend on `powertools-logging` which contains the main logic. + + ```xml + + software.amazon.lambda + powertools-logging + + ``` + + +**2. Update `log4j2.xml` including new `JsonTemplateLayout`** + +This step is only required if you are using log4j2 as your logging implementation. The deprecated `#!xml ` element was removed. Replace it with the log4j2 agnostic `#!xml ` element. + +```diff + + + + +- ++ + + + + + + + + + + + +``` + +**3. Migrate all logging specific calls to SLF4J native primitives (recommended)** + +The new logging utility is designed to integrate seamlessly with Java SLF4J to allow customers adopt Powertools Logging without large code refactorings. This improvement requires the migration of non-native SLF4J primitives from the v1 Logging utility. + +!!! info "While we recommend using SLF4J as a logging implementation independent facade, you can still use the log4j2 and logback interfaces directly." + +Consider the following code example which gives you hints on how to achieve the same functionality between v1 and v2 Logging: + +```diff +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.logging.Logging; +// ... other imports + +public class PaymentFunction implements RequestHandler { + // BEFORE v2: Uses org.apache.logging.log4j.LogManager +- private static final Logger LOGGER = LogManager.getLogger(PaymentFunction.class); + // AFTER v2: Use org.slf4j.LoggerFactory ++ private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); + + @Logging + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + // ... + + // BEFORE v2: Uses LoggingUtils.appendKey to append custom global keys + // LoggingUtils was removed! +- LoggingUtils.appendKey("cardNumber", card.getId()); + // AFTER v2: Uses native SLF4J Mapped Diagnostic Context (MDC) ++ MDC.put("cardNumber", card.getId()); + + // Regular logging has not changed + LOGGER.info("My log message with argument."); + + // Adding custom keys on a specific log message + // BEFORE v2: No direct way, only supported via LoggingUtils.appendKey and LoggingUtils.removeKey + // AFTER v2: Extensive support for StructuredArguments ++ LOGGER.info("Collecting payment", StructuredArguments.entry("orderId", order.getId())); + // { "message": "Collecting payment", ..., "orderId": 123} + Map customKeys = new HashMap<>(); + customKeys.put("paymentId", payment.getId()); + customKeys.put("amount", payment.getAmount); ++ LOGGER.info("Payment successful", StructuredArguments.entries(customKeys)); + // { "message": "Payment successful", ..., "paymentId": 123, "amount": 12.99} + } +} +``` + +!!! info "Make sure to learn more about the advanced structured argument serialization features in the [Logging v2 documentation](./core/logging.md/#custom-keys)." + +## Updated Metrics utility interface + + + +The Metrics utility is currently undergoing changes to the public interface as part of GitHub issue [#1848](https://github.com/aws-powertools/powertools-lambda-java/issues/1848). We will keep this upgrade guide updated with the most recent changes as soon as they are released. Stay tuned for updates! + +## Deprecated capture mode related `@Tracing` annotation parameters + + + +The deprecated `captureError` and `captureResponse` arguments to the `@Tracing` annotation were removed in v2 and replaced by a new `captureMode` parameter. The parameter can be passed an Enum value of `CaptureMode`. + +You should update your code using the new `captureMode` argument: + +```diff +- @Tracing(captureError = false, captureResponse = false) ++ @Tracing(captureMode = CaptureMode.DISABLED) +public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + // ... +} +``` + +Learn more about valid `CaptureMode` values in the [Tracing documentation](./core/tracing.md). + +## Idempotency utility split into sub-modules by provider + +The Idempotency utility was split from the common `powertools-idempotency` package into individual packages for different persistence store providers. The main business logic is now in the `powertools-idempotency-core` package. + +You should now include the `powertools-idempotency-core` package as an AspectJ library and the provider package like `powertools-idempotency-dynamodb` as a regular dependency. + +```diff + +- +- software.amazon.lambda +- powertools-idempotency +- 1.x.x +- + + ++ ++ software.amazon.lambda ++ powertools-idempotency-dynamodb ++ 2.x.x ++ + ++ ++ software.amazon.lambda ++ powertools-idempotency-core ++ +``` + +## Parameters utility split into sub-modules by provider + +Parameters utilities were split from the common `powertools-parameters` package into individual packages for different parameter providers. You should now include the specific parameters dependency for your provider. If you use multiple providers, you can include multiple packages. Each parameter provider needs to be included as a dependency and an AspectJ library to use annotations. + +This new structure reduces the bundle size of your deployment package. + +```diff + + +- +- software.amazon.lambda +- powertools-parameters +- 1.x.x +- + +- +- software.amazon.lambda +- powertools-parameters +- + + ++ ++ software.amazon.lambda ++ powertools-parameters-secrets ++ 2.x.x ++ + + ++ ++ software.amazon.lambda ++ powertools-parameters-secrets ++ + +``` + +!!! info "Find the full list of supported providers in the [Parameters utility documentation](./utilities/parameters.md)." + +## Custom Resources updates the `Response` class + + + +The `Response` class supporting CloudFormation Custom Resource implementations was updated to remove deprecated methods. + +The `#!java Response.failed()` and `#!java Response.success()` methods without parameters were removed and require the physical resource ID now. You should update your code to use: + +- `#!java Response.failed(String physicalResourceId)` +- `#!java Response.success(String physicalResourceId)` + +```diff +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; +import software.amazon.lambda.powertools.cloudformation.AbstractCustomResourceHandler; +import software.amazon.lambda.powertools.cloudformation.Response; + +public class MyCustomResourceHandler extends AbstractCustomResourceHandler { + + // ... + + @Override + protected Response update(CloudFormationCustomResourceEvent updateEvent, Context context) { ++ String physicalResourceId = updateEvent.getPhysicalResourceId(); + UpdateResult updateResult = doUpdates(physicalResourceId); + if (updateResult.isSuccessful()) { +- return Response.success(); ++ return Response.success(physicalResourceId); + } else { +- return Response.failed(); ++ return Response.failed(physicalResourceId); + } + } + + // ... +} +``` + +## Improved integration of Validation utility with other utilities + + + +The Validation utility includes two updates that change the behavior of integration with other utilities and AWS services. + +**1. Updated HTTP status code when using `@Validation` with API Gateway** + +This does not require a code change in the Lambda function using the Validation utility but might impact how your calling application treats exceptions. Prior to `v2`, a 500 HTTP status code was returned when the validation did not pass. Consistent with the [HTTP specification](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status){target="\_blank"}, a 400 status code is returned now indicating a user error instead of a server error. + +Consider the following example: + +```java +import software.amazon.lambda.powertools.validation.Validation; + +public class MyFunctionHandler implements RequestHandler { + + @Override + @Validation(inboundSchema = "classpath:/schema_in.json", outboundSchema = "classpath:/schema_out.json") + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + // ... + return something; + } +} +``` + +If the request validation fails, you can expect the following change in the HTTP response status code on the client-side: + +```sh +# BEFORE v2: 500 Internal Server Error +❯ curl -s -o /dev/null -w "%{http_code}" https://{API_ID}.execute-api.{REGION}.amazonaws.com/{STAGE}/{PATH} +500 +# AFTER v2: 400 Bad Request +❯ curl -s -o /dev/null -w "%{http_code}" https://{API_ID}.execute-api.{REGION}.amazonaws.com/{STAGE}/{PATH} +400 +``` + +**2. Integration with partial batch failures when using Batch utility** + +This does not require a code change but might affect the batch processing flow when using the Validation utility in combination with the Batch processing utility. + +Consider the following example: + +```java +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder; +import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; + +public class SqsBatchHandler implements RequestHandler { + + private final BatchMessageHandler handler; + + public SqsBatchHandler() { + handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithMessageHandler(this::processMessage, Product.class); + } + + @Override + @Validation(inboundSchema = "classpath:/schema_in.json", outboundSchema = "classpath:/schema_out.json") + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + return handler.processBatch(sqsEvent, context); + } + + private void processMessage(Product p, Context c) { + // Process the product + } +} +``` + +- **Prior to `v2`** this caused the whole batch to fail. +- **After `v2`** this will add only the failed events to the batch item failure list in the response and process the remaining messages. + +!!! info "Check if your workload can tolerate this behavior and make sure it is designed for idempotency when using partial batch item failures. We offer the [Idempotency](./utilities/idempotency.md) utility to simplify integration of idempotent behavior in your workloads." + +## AspectJ runtime not included by default anymore + +The AspectJ runtime is no longer included as a transitive dependency of Powertools. For all utilities offering annotations using AspectJ compile-time weaving, you need to include the AspectJ runtime yourself now. This is also documented, with a complete example, in our [installation guide](./index.md). For Maven projects, make sure to add the following dependency in your dependencies section: + +```diff ++ ++ org.aspectj ++ aspectjrt ++ 1.9.22 ++ +``` + +## Removed `powertools-sqs` module in favor of `powertools-batch` + +The archived documentation contains a migration guide for both large message handling using `powertools-sqs` and batch processing using `powertools-sqs`. The sections below explain the high-level steps for your convenience. + +### Migrating SQS Batch processing (`@SqsBatch`) + +The [batch processing library](./utilities/batch.md) provides a way to process messages and gracefully handle partial failures for SQS, Kinesis Streams, and DynamoDB Streams batch sources. In comparison to the legacy SQS Batch library, it relies on [Lambda partial batch responses](https://docs.aws.amazon.com/lambda/latest/dg/services-sqs-errorhandling.html#services-sqs-batchfailurereporting){target="\_blank"}, which allows the library to provide a simpler, more reliable interface for processing batches. + +In order to get started, check out the new [processing messages from SQS](./utilities/batch.md/#processing-messages-from-sqs) documentation. In most cases, you will simply be able to retain your existing batch message handler function, and wrap it with the new batch processing interface. Unlike the `powertools-sqs` module, the new `powertools-batch` module uses _partial batch responses_ to communicate to Lambda which messages have been processed and must be removed from the queue. The return value of the handler's process function must be returned to Lambda. + +The new library also no longer requires the `SQS:DeleteMessage` action on the Lambda function's role policy, as Lambda +itself now manages removal of messages from the queue. + + +!!! info "Some tuneables from `powertools-sqs` are no longer provided." + - **Non-retryable Exceptions** - there is no mechanism to indicate in a partial batch response that a particular message + should not be retried and instead moved to DLQ - a message either succeeds, or fails and is retried. A message + will be moved to the DLQ once the normal retry process has expired. + - **Suppress Exception** - The new batch processor does not throw an exception on failure of a handler. Instead, + its result must be returned by your code from your message handler to Lambda, so that Lambda can manage + the completed messages and retry behaviour. + + +### Migrating SQS Large message handling (`@SqsLargeMessage`) + +- Replace the dependency in Maven / Gradle: `powertools-sqs` ==> `powertools-large-messages` +- Replace the annotation: `@SqsLargeMessage` ==> `@LargeMessage` (the new module handles both SQS and SNS) +- Move the annotation away from the Lambda `handleRequest` method and put it on a method with `SQSEvent.SQSMessage` or `SNSEvent.SNSRecord` as first parameter. +- The annotation now handles a single message, contrary to the previous version that was handling the complete batch. This gives more control, especially when dealing with partial failures with SQS (see the batch module). +- The new module only provides an annotation: an equivalent to the `SqsUtils` class is not available anymore in this new version. diff --git a/docs/utilities/custom_resources.md b/docs/utilities/custom_resources.md index d0c1eacf2..053e8a9d7 100644 --- a/docs/utilities/custom_resources.md +++ b/docs/utilities/custom_resources.md @@ -223,7 +223,7 @@ public class CustomSerializationHandler extends AbstractResourceHandler { While the library provides an easy-to-use interface, we recommend that you understand the lifecycle of CloudFormation custom resources before using them in production. #### Creating a custom resource -When CloudFormation issues a CREATE on a custom resource, there are 2 possible states: `CREATE_COMPLETE` and `CREATE_FAILED` +When CloudFormation issues a `CREATE` on a custom resource, there are 2 possible states: `CREATE_COMPLETE` and `CREATE_FAILED` ```mermaid stateDiagram direction LR @@ -237,7 +237,7 @@ If the resource is created successfully, the `physicalResourceId` is stored by C If the resource failed to create, CloudFormation triggers a rollback operation by default (rollback can be disabled, see [stack failure options](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stack-failure-options.html)) #### Updating a custom resource -CloudFormation issues an UPDATE operation on a custom resource only when one or more custom resource properties change. +CloudFormation issues an `UPDATE` operation on a custom resource only when one or more custom resource properties change. During the update, the custom resource may update successfully, or may fail the update. ```mermaid stateDiagram @@ -278,7 +278,8 @@ stateDiagram #### Deleting a custom resource -CloudFormation issues a DELETE on a custom resource when: +CloudFormation issues a `DELETE` on a custom resource when: + - the CloudFormation stack is being deleted - a new `physicalResourceId` was received during an update, and CloudFormation proceeds to rollback(DELETE) the custom resource with the previous `physicalResourceId`. @@ -289,4 +290,4 @@ stateDiagram [*] --> deleteState deleteState --> DELETE_COMPLETE deleteState --> DELETE_FAILED -``` \ No newline at end of file +``` diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index b257c5dde..96bdd142b 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -163,7 +163,7 @@ You can also gracefully handle schema validation errors by catching `ValidationE For the following events and responses, the Validator will automatically perform validation on the content. -** Events ** +**Events** | Type of event | Class | Path to content | |---------------------------------|-------------------------------------------------|----------------------------------------------| @@ -181,7 +181,7 @@ For the following events and responses, the Validator will automatically perform | SNS | SNSEvent | `Records[*].Sns.Message` | | SQS | SQSEvent | `Records[*].body` | -** Responses ** +**Responses** | Type of response | Class | Path to content (envelope) | |-----------------------|---------------------------------------------|---------------------------------------| @@ -189,7 +189,7 @@ For the following events and responses, the Validator will automatically perform | API Gateway HTTP | APIGatewayV2HTTPResponse} | `body` | | API Gateway WebSocket | APIGatewayV2WebSocketResponse} | `body` | | Load Balancer | ApplicationLoadBalancerResponseEvent} | `body` | -| Kinesis Analytics | KinesisAnalyticsInputPreprocessingResponse} | `Records[*].powertools_base64(data)`` | +| Kinesis Analytics | KinesisAnalyticsInputPreprocessingResponse} | `Records[*].powertools_base64(data)` | ## Custom events and responses diff --git a/mkdocs.yml b/mkdocs.yml index cf73d41fc..ee5f77dde 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,10 +1,11 @@ site_name: Powertools for AWS Lambda (Java) Preview site_description: Powertools for AWS Lambda (Java) Preview site_author: Amazon Web Services -site_url: https://docs.powertools.aws.dev/lambda-java/ +site_url: https://docs.powertools.aws.dev/lambda/java/preview/ nav: - Homepage: index.md - Changelog: changelog.md + - Upgrade Guide: upgrade.md - FAQs: FAQs.md - Roadmap: roadmap.md - Core utilities: @@ -21,6 +22,7 @@ nav: - utilities/serialization.md - Processes: - processes/maintainers.md + - "Versioning policy": processes/versioning.md - Resources: - "llms.txt": ./llms.txt - "llms.txt (full version)": ./llms-full.txt @@ -106,6 +108,7 @@ plugins: - utilities/serialization.md Processes: - processes/maintainers.md + - processes/versioning.md extra_css: - stylesheets/extra.css From 875e9936bab8adbb48ca5c0b32354c762a8065f7 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 28 May 2025 10:45:49 +0200 Subject: [PATCH 237/577] chore(ci): Publish to Maven Central instead of OSSRH instance (#1858) * Add Maven Central as release target. * Update secret location for Maven Central credentials. --- .github/workflows/release.yml | 8 ++++---- pom.xml | 13 ++++++------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index da01b89c1..826536136 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -202,14 +202,14 @@ jobs: cache: maven gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }} gpg-passphrase: GPG_PASSPHRASE - server-id: ossrh + server-id: central server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD - name: Publish package run: mvn -Prelease clean deploy -DskipTests env: - MAVEN_USERNAME: ${{ secrets.OSSRH_JIRA_USERNAME }} - MAVEN_PASSWORD: ${{ secrets.OSSRH_JIRA_PASSWORD }} + MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} create_pr: @@ -290,4 +290,4 @@ jobs: run: | aws s3 sync \ dist \ - s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/ \ No newline at end of file + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/ diff --git a/pom.xml b/pom.xml index 0c12aa9c6..d78daeb4e 100644 --- a/pom.xml +++ b/pom.xml @@ -110,8 +110,8 @@ - ossrh - https://aws.oss.sonatype.org/content/repositories/snapshots + central-portal-snapshots + https://central.sonatype.com/repository/maven-snapshots/ @@ -478,13 +478,12 @@ - org.sonatype.plugins - nexus-staging-maven-plugin + org.sonatype.central + central-publishing-maven-plugin + 0.7.0 true - ossrh - https://aws.oss.sonatype.org - true + central From 54ef1e9daa925e707d140221981ec84bf3493260 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 28 May 2025 10:46:44 +0200 Subject: [PATCH 238/577] fix(ci): Fix failing E2E tests and temporarily exclude TracingE2E (#1847) * fix(ci): Remove unused workflows and add JAVA_VERSION env var to e2e tests. * Test e2e test for Java 11 only. * Debug Parameteres E2E test only. * Revert "Debug Parameteres E2E test only." This reverts commit 06648527c86be6e2616173d396db751dbe8e51f9. * Exlucde TracingE2ET for testing. * Enable Java version matrix again. --- .github/workflows/auto-merge.yml | 66 ----------------------- .github/workflows/check-e2e.yml | 5 +- .github/workflows/docs-v2-snapshot.yml | 40 -------------- .github/workflows/publish-v2-snapshot.yml | 29 ---------- powertools-e2e-tests/pom.xml | 10 ++-- 5 files changed, 11 insertions(+), 139 deletions(-) delete mode 100644 .github/workflows/auto-merge.yml delete mode 100644 .github/workflows/docs-v2-snapshot.yml delete mode 100644 .github/workflows/publish-v2-snapshot.yml diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml deleted file mode 100644 index 5401eedc9..000000000 --- a/.github/workflows/auto-merge.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Auto merge if dependabot PR - -on: - workflow_run: - workflows: ["Build"] - types: [completed] - -permissions: - pull-requests: write - issues: write - repository-projects: write - contents: write - -jobs: - merge-me: - name: Merge me! - runs-on: ubuntu-latest - if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' && github.actor == 'dependabot[bot]' - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - uses: ahmadnassri/action-workflow-run-wait@2aa3d9e1a12ecaaa9908e368eaf2123bb084323e # v1.4.4 - with: - timeout: 300000 - - name: 'Download artifact' - uses: actions/github-script@47f7cf65b5ced0830a325f705cad64f2f58dddf7 # v3.1.0 - with: - script: | - var artifacts = await github.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: ${{github.event.workflow_run.id }}, - }); - var matchArtifact = artifacts.data.artifacts.filter((artifact) => { - return artifact.name == "pr" - })[0]; - var download = await github.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: matchArtifact.id, - archive_format: 'zip', - }); - var fs = require('fs'); - fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data)); - - run: unzip pr.zip - - name: Create review - uses: actions/github-script@47f7cf65b5ced0830a325f705cad64f2f58dddf7 # v3.1.0 - with: - script: | - var fs = require('fs'); - var issue_number = Number(fs.readFileSync('./NR')); - - github.pulls.createReview({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - pull_number: issue_number, - event: 'APPROVE' - }) - - github.pulls.merge({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - pull_number: issue_number, - merge_method: 'squash' - }) - - github-token: ${{ secrets.AUTOMERGE }} diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 6420cd6f7..14eab5394 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -54,6 +54,7 @@ jobs: - 11 - 17 - 21 + steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java @@ -68,4 +69,6 @@ jobs: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 - name: Run e2e test with Maven - run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml \ No newline at end of file + env: + JAVA_VERSION: ${{ matrix.java }} + run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml diff --git a/.github/workflows/docs-v2-snapshot.yml b/.github/workflows/docs-v2-snapshot.yml deleted file mode 100644 index 55803c737..000000000 --- a/.github/workflows/docs-v2-snapshot.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Docs -on: - push: - branches: - - v2 - workflow_dispatch: {} - -permissions: - id-token: write - contents: write - pages: write - -jobs: - docs: - runs-on: ubuntu-latest - environment: Docs - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Set up Python - uses: actions/setup-python@bd6b4b6205c4dbad673328db7b31b7fab9e241c0 # v4.6.1 - with: - python-version: "3.8" - - name: Capture branch and tag - id: branch_name - run: | - echo "SOURCE_BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV - echo "SOURCE_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - name: Build docs website - run: | - make build-docs-website - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e1e17a757e536f70e52b5a12b2e8d1d1c60e04ef - with: - aws-region: us-east-1 - role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} - - name: Deploy Docs - run: | - aws s3 sync \ - dist \ - s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/preview/ diff --git a/.github/workflows/publish-v2-snapshot.yml b/.github/workflows/publish-v2-snapshot.yml deleted file mode 100644 index d5a683261..000000000 --- a/.github/workflows/publish-v2-snapshot.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Publish v2 -on: - push: - branches: - - v2 - workflow_dispatch: {} -jobs: - publish: - runs-on: ubuntu-latest - environment: snapshot - steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - - name: Set up Maven Central Repository - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 - with: - distribution: 'corretto' - java-version: 11 - server-id: ossrh - server-username: MAVEN_USERNAME - server-password: MAVEN_PASSWORD - # TODO: use environments https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment - gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }} # Value of the GPG private key to import - gpg-passphrase: GPG_PASSPHRASE # env variable for GPG private key passphrase - - name: Publish package - run: mvn -Prelease clean validate deploy -DskipTests # We use validate here to run maven enforcer, to make sure we are only publishing SNAPSHOT builds - env: - MAVEN_USERNAME: ${{ secrets.SNAPSHOT_PUBLISH_USERNAME }} - MAVEN_PASSWORD: ${{ secrets.SNAPSHOT_PUBLISH_PASSWORD }} - GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 306e8060b..9cb604f56 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -14,8 +14,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 powertools-parent @@ -216,10 +216,14 @@ - 1 + 1 **/*E2ET.java + + **/TracingE2ET.java + From 4444b4bce8eb1cc19880d1c1ef07188d97de9126 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 28 May 2025 12:33:43 +0200 Subject: [PATCH 239/577] chore(ci): Set snapshot repository to "central" server ID --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index d78daeb4e..cb761183e 100644 --- a/pom.xml +++ b/pom.xml @@ -110,7 +110,7 @@ - central-portal-snapshots + central https://central.sonatype.com/repository/maven-snapshots/ From 57ae1534ac4d837b24deac8027e577db7a7ad6af Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 6 Jun 2025 11:56:44 +0200 Subject: [PATCH 240/577] feat(metrics): New metrics module implementation with support for Metrics providers and usage without annotations (#1863) * Rewrite metrics module with interface abstraction and provider pattern to be able to support multiple metrics providers. * Update default dimension and namespace logic to have the precedence: @Metrics annotation. MetricsLoggerBuilder, Environment variables. * Small cosmetic changes. * Add unit tests. * Update metrics documentation with new interface. * Make unit tests compatible with GraalVM. It is not supported to mock interface with Mockito. * Add GraalVM support bullet points to docs pages. * Update GraalVM metadata files after re-implementing metrics module. * Fix spotbugs issue. This is expected for this factory class for MetricsLogger to enable user configuration of the MetricsLogger singleton. * Fix SonarCube findings. * Rename back namespace to ServerlessAirline example. * Fix DimensionSet validation to be inline with most recent specification. * Overload void addDimension(DimensionSet dimensionSet) to be able to add multi-dimensional dimensions also for non default dimensions. * Update setDefaultDimensions to take a DimensionSet instead of a Map. * Add warning if not emitting metrics and raiseOnEmptyMetrics is false. * Remove unused imports. * Add namespace validation. Refacator into own Validator class. Require namespace to be set or raise an exception otherwise. * Update docs with DimensionSet.of instead of Map.of. Fix naming consistency. * Add example for overwriting dimension of cold start metric. * Add note that metadata needs to be added before flushing. * Remove test classes from GRM reflect-config.json. * Rename pushSingleMetric to flushSingleMetric. * Add example for high cardinality dimensions using DimensionSet. * Add support for POWERTOOLS_METRICS_DISABLED environment variable. * Only add service name dimension if the service is actually defined. * Add support for POWERTOOLS_METRICS_FUNCTION_NAME. * Add Testing your code section to docs. * Rename @Metrics to @FlushMetrics. * Rename MetricsLogger to Metrics, rename MetricsLoggerBuilder to MetricsBuilder, rename MetricsLoggerFactory to MetricsFactory. * Add support for setTimestamp. * Update regex for namespace validation. * Fix namespace regex and fix metrics e2e tests. * Add comment in empty callAt method to satisfy pmd_analyse. * Replace usages of standalone Powertools wording with alternative wording. * Reduce cognitive complexity of around() method in LambdaMetricsAspect. * Re-generate GRM files after applying MetricsLogger renaming. --- docs/FAQs.md | 43 +- docs/core/logging.md | 11 +- docs/core/metrics.md | 474 +++++++++++---- docs/core/tracing.md | 3 +- docs/index.md | 5 +- docs/upgrade.md | 2 +- docs/utilities/parameters.md | 1 + .../cdk/app/src/main/java/helloworld/App.java | 26 +- .../src/main/java/helloworld/AppStream.java | 4 +- .../gradle/src/main/java/helloworld/App.java | 23 +- .../src/main/java/helloworld/AppStream.java | 4 +- .../kotlin/src/main/kotlin/helloworld/App.kt | 29 +- .../src/main/kotlin/helloworld/AppStream.kt | 2 +- .../src/main/java/helloworld/App.java | 29 +- .../sam/src/main/java/helloworld/App.java | 40 +- .../src/main/java/helloworld/AppStream.java | 4 +- .../src/main/java/helloworld/App.java | 25 +- .../src/main/java/helloworld/AppStream.java | 4 +- .../src/main/java/helloworld/App.java | 25 +- .../src/main/java/helloworld/AppStream.java | 4 +- pom.xml | 29 +- .../lambda/powertools/e2e/Function.java | 31 +- powertools-metrics/pom.xml | 67 ++- .../emf/model/MetricsLoggerHelper.java | 42 -- .../powertools/metrics/FlushMetrics.java | 71 +++ .../lambda/powertools/metrics/Metrics.java | 209 +++++-- .../powertools/metrics/MetricsBuilder.java | 144 +++++ .../powertools/metrics/MetricsFactory.java | 71 +++ .../powertools/metrics/MetricsUtils.java | 172 ------ .../metrics/internal/EmfMetricsLogger.java | 326 ++++++++++ .../metrics/internal/LambdaMetricsAspect.java | 153 +++-- .../metrics/internal/Validator.java | 135 +++++ .../metrics/model/DimensionSet.java | 193 ++++++ .../MetricResolution.java} | 18 +- .../powertools/metrics/model/MetricUnit.java | 58 ++ .../metrics/provider/EmfMetricsProvider.java | 31 + .../metrics/provider/MetricsProvider.java | 30 + .../powertools-metrics/jni-config.json | 51 +- .../powertools-metrics/reflect-config.json | 433 +++++--------- .../powertools-metrics/resource-config.json | 28 +- .../metrics/ConfigurationPrecedenceTest.java | 206 +++++++ .../metrics/MetricsBuilderTest.java | 186 ++++++ .../metrics/MetricsFactoryTest.java | 166 ++++++ .../powertools/metrics/MetricsLoggerTest.java | 232 -------- ...ertoolsMetricsColdStartEnabledHandler.java | 35 -- ...MetricsEnabledDefaultDimensionHandler.java | 46 -- ...tricsEnabledDefaultNoDimensionHandler.java | 45 -- .../PowertoolsMetricsEnabledHandler.java | 41 -- ...PowertoolsMetricsEnabledStreamHandler.java | 35 -- ...sMetricsExceptionWhenNoMetricsHandler.java | 34 -- .../PowertoolsMetricsNoDimensionsHandler.java | 36 -- ...etricsNoExceptionWhenNoMetricsHandler.java | 34 -- ...rtoolsMetricsTooManyDimensionsHandler.java | 40 -- ...wertoolsMetricsWithExceptionInHandler.java | 33 - .../internal/EmfMetricsLoggerTest.java | 521 ++++++++++++++++ .../internal/LambdaMetricsAspectTest.java | 562 ++++++++---------- .../metrics/internal/ValidatorTest.java | 224 +++++++ .../metrics/model/DimensionSetTest.java | 166 ++++++ .../provider/EmfMetricsProviderTest.java | 39 ++ .../metrics/testutils/TestContext.java | 77 +++ .../metrics/testutils/TestMetrics.java | 85 +++ .../testutils/TestMetricsProvider.java | 11 + .../test/resources/simplelogger.properties | 7 + spotbugs-exclude.xml | 4 +- 64 files changed, 4044 insertions(+), 1871 deletions(-) delete mode 100644 powertools-metrics/src/main/java/software/amazon/cloudwatchlogs/emf/model/MetricsLoggerHelper.java create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/FlushMetrics.java create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsBuilder.java create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java delete mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/Validator.java create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/DimensionSet.java rename powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/{ValidationException.java => model/MetricResolution.java} (66%) create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/MetricUnit.java create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/provider/EmfMetricsProvider.java create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/provider/MetricsProvider.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsBuilderTest.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsColdStartEnabledHandler.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledHandler.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledStreamHandler.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsExceptionWhenNoMetricsHandler.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoDimensionsHandler.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoExceptionWhenNoMetricsHandler.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java delete mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsWithExceptionInHandler.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/ValidatorTest.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/model/DimensionSetTest.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/provider/EmfMetricsProviderTest.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetrics.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetricsProvider.java create mode 100644 powertools-metrics/src/test/resources/simplelogger.properties diff --git a/docs/FAQs.md b/docs/FAQs.md index f3fd2514d..75f699c91 100644 --- a/docs/FAQs.md +++ b/docs/FAQs.md @@ -3,16 +3,15 @@ title: FAQs description: Frequently Asked Questions --- - ## How can I use Powertools for AWS Lambda (Java) with Lombok? -Powertools uses `aspectj-maven-plugin` to compile-time weave (CTW) aspects into the project. In case you want to use `Lombok` or other compile-time preprocessor for your project, it is required to change `aspectj-maven-plugin` configuration to enable in-place weaving feature. Otherwise the plugin will ignore changes introduced by `Lombok` and will use `.java` files as a source. +Many utilities in this library use `aspectj-maven-plugin` to compile-time weave (CTW) aspects into the project. In case you want to use `Lombok` or other compile-time preprocessor for your project, it is required to change `aspectj-maven-plugin` configuration to enable in-place weaving feature. Otherwise the plugin will ignore changes introduced by `Lombok` and will use `.java` files as a source. To enable in-place weaving feature you need to use following `aspectj-maven-plugin` configuration: ```xml hl_lines="2-6" - true + true ${project.build.directory}/classes @@ -29,14 +28,14 @@ To enable in-place weaving feature you need to use following `aspectj-maven-plug ## How can I use Powertools for AWS Lambda (Java) with Kotlin projects? -Powertools uses `aspectj-maven-plugin` to compile-time weave (CTW) aspects into the project. When using it with Kotlin projects, it is required to `forceAjcCompile`. -No explicit configuration should be required for gradle projects. +Many utilities use `aspectj-maven-plugin` to compile-time weave (CTW) aspects into the project. When using it with Kotlin projects, it is required to `forceAjcCompile`. +No explicit configuration should be required for gradle projects. To enable `forceAjcCompile` you need to use following `aspectj-maven-plugin` configuration: ```xml hl_lines="2" - true + true ... @@ -49,17 +48,17 @@ To enable `forceAjcCompile` you need to use following `aspectj-maven-plugin` con ## How can I use Powertools for AWS Lambda (Java) with the AWS CRT HTTP Client? -Powertools uses the `url-connection-client` as the default HTTP client. The `url-connection-client` is a lightweight HTTP client, which keeps the impact on Lambda cold starts to a minimum. -With the [announcement](https://aws.amazon.com/blogs/developer/announcing-availability-of-the-aws-crt-http-client-in-the-aws-sdk-for-java-2-x/) of the `aws-crt-client` a new HTTP client has been released, which offers faster SDK startup time and smaller memory footprint. +Utilities relying on AWS SDK clients use the `url-connection-client` as the default HTTP client. The `url-connection-client` is a lightweight HTTP client, which keeps the impact on Lambda cold starts to a minimum. +With the [announcement](https://aws.amazon.com/blogs/developer/announcing-availability-of-the-aws-crt-http-client-in-the-aws-sdk-for-java-2-x/) of the `aws-crt-client` a new HTTP client has been released, which offers faster SDK startup time and smaller memory footprint. -Unfortunately, replacing the `url-connection-client` dependency with the `aws-crt-client` will not immediately improve the lambda cold start performance and memory footprint, -as the default version of the dependency contains native system libraries for all supported runtimes and architectures (Linux, MacOS, Windows, AMD64, ARM64, etc). This makes the CRT client portable, without the user having to consider _where_ their code will run, but comes at the cost of JAR size. +Unfortunately, replacing the `url-connection-client` dependency with the `aws-crt-client` will not immediately improve the lambda cold start performance and memory footprint, +as the default version of the dependency contains native system libraries for all supported runtimes and architectures (Linux, MacOS, Windows, AMD64, ARM64, etc). This makes the CRT client portable, without the user having to consider _where_ their code will run, but comes at the cost of JAR size. ### Configuring dependencies -Using the `aws-crt-client` in your project requires the exclusion of the `url-connection-client` transitive dependency from the powertools dependency. +Using the `aws-crt-client` in your project requires the exclusion of the `url-connection-client` transitive dependency from the `powertools-*` dependency. -```xml +```xml software.amazon.lambda powertools-parameters @@ -72,8 +71,9 @@ Using the `aws-crt-client` in your project requires the exclusion of the `url-co ``` -Next, add the `aws-crt-client` and exclude the "generic" `aws-crt` dependency (contains all runtime libraries). -Instead, set a specific classifier of the `aws-crt` to use the one for your target runtime: either `linux-x86_64` for a Lambda configured for x86 or `linux-aarch_64` for Lambda using arm64. + +Next, add the `aws-crt-client` and exclude the "generic" `aws-crt` dependency (contains all runtime libraries). +Instead, set a specific classifier of the `aws-crt` to use the one for your target runtime: either `linux-x86_64` for a Lambda configured for x86 or `linux-aarch_64` for Lambda using arm64. !!! note "You will need to add a separate maven profile to build and debug locally when your development environment does not share the target architecture you are using in Lambda." By specifying the specific target runtime, we prevent other target runtimes from being included in the jar file, resulting in a smaller Lambda package and improved cold start times. @@ -102,10 +102,11 @@ By specifying the specific target runtime, we prevent other target runtimes from ``` ### Explicitly set the AWS CRT HTTP Client -After configuring the dependencies, it's required to explicitly specify the AWS SDK HTTP client. -Depending on the Powertools module, there is a different way to configure the SDK client. -The following example shows how to use the Lambda Powertools Parameters module while leveraging the AWS CRT Client. +After configuring the dependencies, it's required to explicitly specify the AWS SDK HTTP client. +Depending on the utility you are using, there is a different way to configure the SDK client. + +The following example shows how to use the Parameters module while leveraging the AWS CRT Client. ```java hl_lines="16 23-24" import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; @@ -141,12 +142,12 @@ public class RequestHandlerWithParams implements RequestHandler } ``` -The `aws-crt-client` was considered for adoption as the default HTTP client in Lambda Powertools for Java as mentioned in [Move SDK http client to CRT](https://github.com/aws-powertools/powertools-lambda-java/issues/1092), +The `aws-crt-client` was considered for adoption as the default HTTP client in Powertools for AWS Lambda (Java) as mentioned in [Move SDK http client to CRT](https://github.com/aws-powertools/powertools-lambda-java/issues/1092), but due to the impact on the developer experience it was decided to stick with the `url-connection-client`. ## How can I use Powertools for AWS Lambda (Java) with GraalVM? -Powertools core utilities, i.e. [logging](./core/logging.md), [metrics](./core/metrics.md) and [tracing](./core/tracing.md), include the [GraalVM Reachability Metadata (GRM)](https://www.graalvm.org/latest/reference-manual/native-image/metadata/) in the `META-INF` directories of the respective JARs. You can find a working example of Serverless Application Model (SAM) based application in the [examples](../examples/powertools-examples-core-utilities/sam-graalvm/README.md) directory. +Core utilities, i.e. [logging](./core/logging.md), [metrics](./core/metrics.md) and [tracing](./core/tracing.md), include the [GraalVM Reachability Metadata (GRM)](https://www.graalvm.org/latest/reference-manual/native-image/metadata/) in the `META-INF` directories of the respective JARs. You can find a working example of Serverless Application Model (SAM) based application in the [examples](../examples/powertools-examples-core-utilities/sam-graalvm/README.md) directory. Below, you find typical steps you need to follow in a Maven based Java project: @@ -157,6 +158,7 @@ export JAVA_HOME= ``` ### Use log4j `>2.24.0` + Log4j version `2.24.0` adds [support for GraalVM](https://github.com/apache/logging-log4j2/issues/1539#issuecomment-2106766878). Depending on your project's dependency hierarchy, older version of log4j might be included in the final dependency graph. Make sure version `>2.24.0` of these dependencies are used by your Maven project: ```xml @@ -245,10 +247,11 @@ Create a Docker image using a `Dockerfile` like [this](../examples/powertools-ex docker build --platform linux/amd64 . -t your-org/your-app-graalvm-builder ``` -Create the native image of you Lambda function using the Docker command below. +Create the native image of you Lambda function using the Docker command below. ```shell docker run --platform linux/amd64 -it -v `pwd`:`pwd` -w `pwd` -v ~/.m2:/root/.m2 your-org/your-app-graalvm-builder mvn clean -Pnative-image package ``` + The native image is created in the `target/` directory. diff --git a/docs/core/logging.md b/docs/core/logging.md index 1160f62ff..2d9e57dda 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -13,6 +13,7 @@ Logging provides an opinionated logger with output structured as JSON. * Optionally logs Lambda response * Optionally supports log sampling by including a configurable percentage of DEBUG logs in logging output * Allows additional keys to be appended to the structured log at any point in time +* GraalVM support ## Getting started @@ -219,7 +220,7 @@ You can leverage the standard configuration files (_log4j2.xml_ or _logback.xml_ === "log4j2.xml" With log4j2, we leverage the [`JsonTemplateLayout`](https://logging.apache.org/log4j/2.x/manual/json-template-layout.html){target="_blank"} - to provide structured logging. A default template is provided in powertools ([_LambdaJsonLayout.json_](https://github.com/aws-powertools/powertools-lambda-java/tree/v2/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json){target="_blank"}): + to provide structured logging. A default template is provided in powertools ([_LambdaJsonLayout.json_](https://github.com/aws-powertools/powertools-lambda-java/blob/4444b4bce8eb1cc19880d1c1ef07188d97de9126/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json){target="_blank"}): ```xml hl_lines="5" @@ -277,7 +278,7 @@ If the level is set to any other value, we set it to the default value (`INFO`). With [AWS Lambda Advanced Logging Controls (ALC)](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced){target="_blank"}, you can enforce a minimum log level that Lambda will accept from your application code. -When enabled, you should keep Powertools and ALC log level in sync to avoid data loss. +When enabled, you should keep your own log level and ALC log level in sync to avoid data loss. Here's a sequence diagram to demonstrate how ALC will drop both `INFO` and `DEBUG` logs emitted from `Logger`, when ALC log level is stricter than `Logger`. @@ -308,7 +309,7 @@ We prioritise log level settings in this order: 2. `POWERTOOLS_LOG_LEVEL` environment variable 3. level defined in the `log4j2.xml` or `logback.xml` files -If you set Powertools level lower than ALC, we will emit a warning informing you that your messages will be discarded by Lambda. +If you set `POWERTOOLS_LOG_LEVEL` lower than ALC, we will emit a warning informing you that your messages will be discarded by Lambda. > **NOTE** > @@ -738,7 +739,7 @@ When debugging in non-production environments, you can instruct the `@Logging` a ``` ???+ note - If you use this on a RequestStreamHandler, Powertools must duplicate input streams in order to log them. + If you use this on a RequestStreamHandler, the SDK must duplicate input streams in order to log them. ## Logging handler response @@ -973,7 +974,7 @@ You can also customize how [exceptions are logged](https://logging.apache.org/lo See the [JSON Layout template documentation](https://logging.apache.org/log4j/2.x/manual/json-template-layout.html){target="_blank"} for more details. ### Logback configuration -Logback configuration is done in _logback.xml_ and the Powertools [`LambdaJsonEncoder`](): +Logback configuration is done in _logback.xml_ and the `LambdaJsonEncoder`: ```xml diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 6083d935a..35d08b140 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -3,23 +3,29 @@ title: Metrics description: Core utility --- -Metrics creates custom metrics asynchronously by logging metrics to standard output following Amazon CloudWatch Embedded Metric Format (EMF). +Metrics creates custom metrics asynchronously by logging metrics to standard output following [Amazon CloudWatch Embedded Metric Format (EMF)](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html). -These metrics can be visualized through [Amazon CloudWatch Console](https://console.aws.amazon.com/cloudwatch/). +These metrics can be visualized through [Amazon CloudWatch Console](https://aws.amazon.com/cloudwatch/). -**Key features** +## Key features -* Aggregate up to 100 metrics using a single CloudWatch EMF object (large JSON blob). -* Validate against common metric definitions mistakes (metric unit, values, max dimensions, max metrics, etc). -* Metrics are created asynchronously by the CloudWatch service, no custom stacks needed. -* Context manager to create a one off metric with a different dimension. +- Aggregate up to 100 metrics using a single [CloudWatch EMF](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html){target="\_blank"} object (large JSON blob) +- Validating your metrics against common metric definitions mistakes (for example, metric unit, values, max dimensions, max metrics) +- Metrics are created asynchronously by the CloudWatch service. You do not need any custom stacks, and there is no impact to Lambda function latency +- Support for creating one off metrics with different dimensions +- GraalVM support ## Terminologies -If you're new to Amazon CloudWatch, there are two terminologies you must be aware of before using this utility: +If you're new to Amazon CloudWatch, there are some terminologies you must be aware of before using this utility: -* **Namespace**. It's the highest level container that will group multiple metrics from multiple services for a given application, for example `ServerlessEcommerce`. -* **Dimensions**. Metrics metadata in key-value format. They help you slice and dice metrics visualization, for example `ColdStart` metric by Payment `service`. +- **Namespace**. It's the highest level container that will group multiple metrics from multiple services for a given application, for example `ServerlessAirline`. +- **Dimensions**. Metrics metadata in key-value format. They help you slice and dice metrics visualization, for example `ColdStart` metric by `service`. +- **Metric**. It's the name of the metric, for example: `SuccessfulBooking` or `UpdatedBooking`. +- **Unit**. It's a value representing the unit of measure for the corresponding metric, for example: `Count` or `Seconds`. +- **Resolution**. It's a value representing the storage resolution for the corresponding metric. Metrics can be either `Standard` or `High` resolution. Read more about CloudWatch Periods [here](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Resolution_definition). + +Visit the AWS documentation for a complete explanation for [Amazon CloudWatch concepts](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html).
    @@ -88,30 +94,44 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar id 'java' id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' } - + repositories { mavenCentral() } - + dependencies { aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' } - + sourceCompatibility = 11 targetCompatibility = 11 ``` ## Getting started -Metric has two global settings that will be used across all metrics emitted: +Metrics has three global settings that will be used across all metrics emitted. Use your application or main service as the metric namespace to easily group all metrics: -| Setting | Description | Environment variable | Constructor parameter | -|----------------------|---------------------------------------------------------------------------------|--------------------------------|-----------------------| -| **Metric namespace** | Logical container where all metrics will be placed e.g. `ServerlessAirline` | `POWERTOOLS_METRICS_NAMESPACE` | `namespace` | -| **Service** | Optionally, sets **service** metric dimension across all metrics e.g. `payment` | `POWERTOOLS_SERVICE_NAME` | `service` | +| Setting | Description | Environment variable | Decorator parameter | +| -------------------- | ------------------------------------------------------------------------------- | ---------------------------------- | ------------------- | +| **Metric namespace** | Logical container where all metrics will be placed e.g. `ServerlessAirline` | `POWERTOOLS_METRICS_NAMESPACE` | `namespace` | +| **Service** | Optionally, sets **service** metric dimension across all metrics e.g. `payment` | `POWERTOOLS_SERVICE_NAME` | `service` | +| **Function name** | Function name used as dimension for the cold start metric | `POWERTOOLS_METRICS_FUNCTION_NAME` | `functionName` | +| **Disable Metrics** | Optionally, disables all metrics flushing | `POWERTOOLS_METRICS_DISABLED` | N/A | !!! tip "Use your application or main service as the metric namespace to easily group all metrics" +!!! info "`POWERTOOLS_METRICS_DISABLED` will not disable default metrics created by AWS services." + +### Order of Precedence of `Metrics` configuration + +The `Metrics` Singleton can be configured by three different interfaces. The following order of precedence applies: + +1. `@FlushMetrics` annotation +2. `MetricsBuilder` using Builder pattern (see [Advanced section](#usage-without-metrics-annotation)) +3. Environment variables (recommended) + +For most use-cases, we recommend using Environment variables and only overwrite settings in code where needed using either the `@FlushMetrics` annotation or `MetricsBuilder` if the annotation cannot be used. + === "template.yaml" ```yaml hl_lines="9 10" @@ -129,101 +149,159 @@ Metric has two global settings that will be used across all metrics emitted: === "MetricsEnabledHandler.java" - ```java hl_lines="8" - import software.amazon.lambda.powertools.metrics.Metrics; - + ```java hl_lines="9" + import software.amazon.lambda.powertools.metrics.FlushMetrics; + import software.amazon.lambda.powertools.metrics.MetricsFactory; + public class MetricsEnabledHandler implements RequestHandler { - - MetricsLogger metricsLogger = MetricsUtils.metricsLogger(); - + + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + @Override - @Metrics(namespace = "ExampleApplication", service = "booking") + @FlushMetrics(namespace = "ServerlessAirline", service = "payment") public Object handleRequest(Object input, Context context) { // ... } } ``` -You can initialize Metrics anywhere in your code as many times as you need - It'll keep track of your aggregate metrics in memory. +`Metrics` is implemented as a Singleton to keep track of your aggregate metrics in memory and make them accessible anywhere in your code. To guarantee that metrics are flushed properly the `@FlushMetrics` annotation must be added on the lambda handler. + +!!!info "You can use the Metrics utility without the `@FlushMetrics` annotation and flush manually. Read more in the [advanced section below](#usage-without-metrics-annotation)." ## Creating metrics -You can create metrics using `putMetric`, and manually create dimensions for all your aggregate metrics using `putDimensions`. +You can create metrics using `addMetric`, and manually create dimensions for all your aggregate metrics using `addDimension`. Anywhere in your code, you can access the current `Metrics` Singleton using the `MetricsFactory`. === "MetricsEnabledHandler.java" - ```java hl_lines="11 12" + ```java hl_lines="13" + import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; - import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; + import software.amazon.lambda.powertools.metrics.MetricsFactory; + import software.amazon.lambda.powertools.metrics.model.MetricUnit; public class MetricsEnabledHandler implements RequestHandler { - - MetricsLogger metricsLogger = MetricsUtils.metricsLogger(); - + + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + @Override - @Metrics(namespace = "ExampleApplication", service = "booking") + @FlushMetrics(namespace = "ServerlessAirline", service = "payment") public Object handleRequest(Object input, Context context) { - metricsLogger.putDimensions(DimensionSet.of("environment", "prod")); - metricsLogger.putMetric("SuccessfulBooking", 1, Unit.COUNT); + metrics.addDimension("environment", "prod"); + metrics.addMetric("SuccessfulBooking", 1, MetricUnit.COUNT); // ... } } ``` -!!! tip "The `Unit` enum facilitate finding a supported metric unit by CloudWatch." - -!!! note "Metrics overflow" - CloudWatch EMF supports a max of 100 metrics. Metrics utility will flush all metrics when adding the 100th metric while subsequent metrics will be aggregated into a new EMF object, for your convenience. +!!! tip "The `MetricUnit` enum facilitates finding a supported metric unit by CloudWatch." + +!!! note "Metrics dimensions" + CloudWatch EMF supports a max of 9 dimensions per metric. The Metrics utility will validate this limit when adding dimensions. + ### Adding high-resolution metrics You can create [high-resolution metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html#high-resolution-metrics) -passing a `storageResolution` to the `putMetric` method: +passing a `#!java MetricResolution.HIGH` to the `addMetric` method. If nothing is passed `#!java MetricResolution.STANDARD` will be used. === "HigResMetricsHandler.java" ```java hl_lines="3 13" + import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; - import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; - import software.amazon.cloudwatchlogs.emf.model.StorageResolution; + import software.amazon.lambda.powertools.metrics.model.MetricResolution; public class MetricsEnabledHandler implements RequestHandler { - - MetricsLogger metricsLogger = MetricsUtils.metricsLogger(); - + + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + @Override - @Metrics(namespace = "ExampleApplication", service = "booking") + @FlushMetrics(namespace = "ServerlessAirline", service = "payment") public Object handleRequest(Object input, Context context) { // ... - metricsLogger.putMetric("SuccessfulBooking", 1, Unit.COUNT, StorageResolution.HIGH); + metrics.addMetric("SuccessfulBooking", 1, MetricUnit.COUNT, MetricResolution.HIGH); } } ``` + !!! info "When is it useful?" High-resolution metrics are data with a granularity of one second and are very useful in several situations such as telemetry, time series, real-time incident management, and others. + + +### Adding dimensions + +You can add dimensions to your metrics using the `addDimension` method. You can either pass key-value pairs or you can create higher cardinality dimensions using `DimensionSet`. + +=== "KeyValueDimensionHandler.java" + + ```java hl_lines="3 13" + import software.amazon.lambda.powertools.metrics.FlushMetrics; + import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.model.MetricResolution; + + public class MetricsEnabledHandler implements RequestHandler { + + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + + @Override + @FlushMetrics(namespace = "ServerlessAirline", service = "payment") + public Object handleRequest(Object input, Context context) { + metrics.addDimension("Dimension", "Value"); + metrics.addMetric("SuccessfulBooking", 1, MetricUnit.COUNT); + } + } + ``` + +=== "HighCardinalityDimensionHandler.java" + + ```java hl_lines="4 13-14" + import software.amazon.lambda.powertools.metrics.FlushMetrics; + import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.model.MetricResolution; + import software.amazon.lambda.powertools.metrics.model.DimensionSet; + + public class MetricsEnabledHandler implements RequestHandler { + + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + + @Override + @FlushMetrics(namespace = "ServerlessAirline", service = "payment") + public Object handleRequest(Object input, Context context) { + // You can add up to 30 dimensions in a single DimensionSet + metrics.addDimension(DimensionSet.of("Dimension1", "Value1", "Dimension2", "Value2")); + metrics.addMetric("SuccessfulBooking", 1, MetricUnit.COUNT); + } + } + ``` ### Flushing metrics -The `@Metrics` annotation **validates**, **serializes**, and **flushes** all your metrics. During metrics validation, -if no metrics are provided no exception will be raised. If metrics are provided, and any of the following criteria are -not met, `ValidationException` exception will be raised. +The `@FlushMetrics` annotation **validates**, **serializes**, and **flushes** all your metrics. During metrics validation, +if no metrics are provided no exception will be raised. If metrics are provided, and any of the following criteria are +not met, `IllegalStateException` or `IllegalArgumentException` exceptions will be raised. + !!! tip "Metric validation" - * Maximum of 9 dimensions + - Maximum of 30 dimensions (`Service` default dimension counts as a regular dimension) + - Dimension keys and values cannot be null or empty + - Metric values must be valid numbers + -If you want to ensure that at least one metric is emitted, you can pass `raiseOnEmptyMetrics = true` to the **@Metrics** annotation: +If you want to ensure that at least one metric is emitted, you can pass `raiseOnEmptyMetrics = true` to the `@FlushMetrics` annotation: === "MetricsRaiseOnEmpty.java" ```java hl_lines="6" - import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.FlushMetrics; public class MetricsRaiseOnEmpty implements RequestHandler { @Override - @Metrics(raiseOnEmptyMetrics = true) + @FlushMetrics(raiseOnEmptyMetrics = true) public Object handleRequest(Object input, Context context) { ... } @@ -232,17 +310,17 @@ If you want to ensure that at least one metric is emitted, you can pass `raiseOn ## Capturing cold start metric -You can capture cold start metrics automatically with `@Metrics` via the `captureColdStart` variable. +You can capture cold start metrics automatically with `@FlushMetrics` via the `captureColdStart` variable. === "MetricsColdStart.java" ```java hl_lines="6" - import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.FlushMetrics; public class MetricsColdStart implements RequestHandler { @Override - @Metrics(captureColdStart = true) + @FlushMetrics(captureColdStart = true) public Object handleRequest(Object input, Context context) { ... } @@ -251,33 +329,77 @@ You can capture cold start metrics automatically with `@Metrics` via the `captur If it's a cold start invocation, this feature will: -* Create a separate EMF blob solely containing a metric named `ColdStart` -* Add `FunctionName` and `Service` dimensions +- Create a separate EMF blob solely containing a metric named `ColdStart` +- Add `FunctionName` and `Service` dimensions This has the advantage of keeping cold start metric separate from your application metrics. +You can also specify a custom function name to be used in the cold start metric: + +=== "MetricsColdStartCustomFunction.java" + + ```java hl_lines="6" + import software.amazon.lambda.powertools.metrics.FlushMetrics; + + public class MetricsColdStartCustomFunction implements RequestHandler { + + @Override + @FlushMetrics(captureColdStart = true, functionName = "CustomFunction") + public Object handleRequest(Object input, Context context) { + ... + } + } + ``` + + +!!!tip "You can overwrite the default `Service` and `FunctionName` dimensions of the cold start metric" + Set `#!java @FlushMetrics(captureColdStart = false)` and use the `captureColdStartMetric` method manually: + + ```java hl_lines="6 8" + public class MetricsColdStartCustomFunction implements RequestHandler { + + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + + @Override + @FlushMetrics(captureColdStart = false) + public Object handleRequest(Object input, Context context) { + metrics.captureColdStartMetric(context, DimensionSet.of("CustomDimension", "CustomValue")); + ... + } + } + ``` + + ## Advanced -## Adding metadata +### Adding metadata -You can use `putMetadata` for advanced use cases, where you want to metadata as part of the serialized metrics object. +You can use `addMetadata` for advanced use cases, where you want to add metadata as part of the serialized metrics object. + !!! info - **This will not be available during metrics visualization, use `dimensions` for this purpose.** + This will not be available during metrics visualization, use Dimensions for this purpose. + +!!! info + Adding metadata with a key that is the same as an existing metric will be ignored + === "App.java" - ```java hl_lines="8 9" + ```java hl_lines="13" + import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; - import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; + import software.amazon.lambda.powertools.metrics.MetricsFactory; public class App implements RequestHandler { + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + @Override - @Metrics(namespace = "ServerlessAirline", service = "payment") + @FlushMetrics(namespace = "ServerlessAirline", service = "booking-service") public Object handleRequest(Object input, Context context) { - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); - metricsLogger().putMetadata("booking_id", "1234567890"); + metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT); + metrics.addMetadata("booking_id", "1234567890"); // Needs to be added BEFORE flushing ... } } @@ -285,79 +407,225 @@ You can use `putMetadata` for advanced use cases, where you want to metadata as This will be available in CloudWatch Logs to ease operations on high cardinal data. -## Overriding default dimension set +### Setting default dimensions + +By default, all metrics emitted via module captures `Service` as one of the default dimensions. This is either specified via `POWERTOOLS_SERVICE_NAME` environment variable or via `service` attribute on `Metrics` annotation. -By default, all metrics emitted via module captures `Service` as one of the default dimension. This is either specified via -`POWERTOOLS_SERVICE_NAME` environment variable or via `service` attribute on `Metrics` annotation. If you wish to override the default -Dimension, it can be done via `#!java MetricsUtils.defaultDimensions()`. +If you wish to set custom default dimensions, it can be done via `#!java metrics.setDefaultDimensions()`. You can also use the `MetricsBuilder` instead of the `MetricsFactory` to configure **and** retrieve the `Metrics` Singleton at the same time (see `MetricsBuilder.java` tab). === "App.java" - ```java hl_lines="8 9 10" + ```java hl_lines="13" + import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; - import static software.amazon.lambda.powertools.metrics.MetricsUtils; - + import software.amazon.lambda.powertools.metrics.MetricsFactory; + import software.amazon.lambda.powertools.metrics.model.DimensionSet; + public class App implements RequestHandler { - - MetricsLogger metricsLogger = MetricsUtils.metricsLogger(); - - static { - MetricsUtils.defaultDimensions(DimensionSet.of("CustomDimension", "booking")); + + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + + @Override + @FlushMetrics(namespace = "ServerlessAirline", service = "payment") + public Object handleRequest(Object input, Context context) { + metrics.setDefaultDimensions(DimensionSet.of("CustomDimension", "booking", "Environment", "prod")); + ... } - + } + ``` + +=== "MetricsBuilder.java" + + ```java hl_lines="8-10" + import software.amazon.lambda.powertools.metrics.FlushMetrics; + import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.MetricsFactory; + import software.amazon.lambda.powertools.metrics.model.DimensionSet; + + public class App implements RequestHandler { + + private static final Metrics metrics = MetricsBuilder.builder() + .withDefaultDimensions(DimensionSet.of("CustomDimension", "booking", "Environment", "prod")) + .build(); + @Override - @Metrics(namespace = "ExampleApplication", service = "booking") + @FlushMetrics(namespace = "ServerlessAirline", service = "payment") public Object handleRequest(Object input, Context context) { + metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT); ... - MetricsUtils.withSingleMetric("Metric2", 1, Unit.COUNT, log -> {}); } } ``` -## Creating a metric with a different dimension + +!!!note + Overwriting the default dimensions will also overwrite the default `Service` dimension. If you wish to keep `Service` in your default dimensions, you need to add it manually. + -CloudWatch EMF uses the same dimensions across all your metrics. Use `withSingleMetric` if you have a metric that should have different dimensions. +### Creating a single metric with different configuration -!!! info - Generally, this would be an edge case since you [pay for unique metric](https://aws.amazon.com/cloudwatch/pricing/). Keep the following formula in mind: - **unique metric = (metric_name + dimension_name + dimension_value)** +You can create a single metric with its own namespace and dimensions using `flushSingleMetric`: === "App.java" - ```java hl_lines="7 8 9" - import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; + ```java hl_lines="12-18" + import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.MetricsFactory; + import software.amazon.lambda.powertools.metrics.model.DimensionSet; + import software.amazon.lambda.powertools.metrics.model.MetricUnit; public class App implements RequestHandler { + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); @Override + @FlushMetrics(namespace = "ServerlessAirline", service = "payment") public Object handleRequest(Object input, Context context) { - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - }); + metrics.flushSingleMetric( + "CustomMetric", + 1, + MetricUnit.COUNT, + "CustomNamespace", + DimensionSet.of("CustomDimension", "value") // Dimensions are optional + ); } } ``` -## Creating metrics with different configurations + +!!! info + Generally, this would be an edge case since you [pay for unique metric](https://aws.amazon.com/cloudwatch/pricing). Keep the following formula in mind: -Use `withMetricsLogger` if you have one or more metrics that should have different configurations e.g. dimensions or namespace. + **unique metric = (metric_name + dimension_name + dimension_value)** + + +### Usage without `@FlushMetrics` annotation + +The `Metrics` Singleton provides all configuration options via `MetricsBuilder` in addition to the `@FlushMetrics` annotation. This can be useful if work in an environment or framework that does not leverage the vanilla Lambda `handleRequest` method. + +!!!info "The environment variables for Service and Namespace configuration still apply but can be overwritten with `MetricsBuilder` if needed." + +The following example shows how to configure a custom `Metrics` Singleton using the Builder pattern. Note that it is necessary to manually flush metrics now. === "App.java" - ```java hl_lines="7 8 9 10 11 12 13" - import static software.amazon.lambda.powertools.metrics.MetricsUtils.withMetricsLogger; + ```java hl_lines="7-12 19 23" + import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.MetricsBuilder; + import software.amazon.lambda.powertools.metrics.model.DimensionSet; + import software.amazon.lambda.powertools.metrics.model.MetricUnit; public class App implements RequestHandler { + // Create and configure a Metrics singleton without annotation + private static final Metrics customMetrics = MetricsBuilder.builder() + .withNamespace("ServerlessAirline") + .withRaiseOnEmptyMetrics(true) + .withService("payment") + .build(); @Override public Object handleRequest(Object input, Context context) { - withMetricsLogger(logger -> { - // override default dimensions - logger.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - // add metrics - logger.putMetric("CustomMetrics1", 1, Unit.COUNT); - logger.putMetric("CustomMetrics2", 5, Unit.COUNT); - }); + // You can manually capture the cold start metric + // Lambda context is an optional argument if not available in your environment + // Dimensions are also optional. + customMetrics.captureColdStartMetric(context, DimensionSet.of("FunctionName", "MyFunction", "Service", "payment")); + + // Add metrics to the custom metrics singleton + customMetrics.addMetric("CustomMetric", 1, MetricUnit.COUNT); + customMetrics.flush(); } } ``` + +## Testing your code + +### Suppressing metrics output + +If you would like to suppress metrics output during your unit tests, you can use the `POWERTOOLS_DISABLE_METRICS` environment variable. For example, using Maven you can set in your build plugins: + +```xml + + org.apache.maven.plugins + maven-surefire-plugin + + + true + + + +``` + +### Asserting EMF output + +When unit testing your code, you can run assertions against the output generated by the `Metrics` Singleton. For the `EmfMetricsLogger`, you can assert the generated JSON blob following the [CloudWatch EMF specification](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html) against your expected output. + +Consider the following example where we redirect the standard output to a custom `PrintStream`. We use the Jackson library to parse the EMF output into a `JsonNode` and run assertions against that. + +```java hl_lines="23 28 33 50-55" +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.metrics.model.MetricUnit; +import software.amazon.lambda.powertools.metrics.testutils.TestContext; + +class MetricsTestExample { + + private final PrintStream standardOut = System.out; + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + private final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp() { + System.setOut(new PrintStream(outputStreamCaptor)); + } + + @AfterEach + void tearDown() { + System.setOut(standardOut); + } + + @Test + void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { + // Given + RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("test-metric")).isTrue(); + assertThat(rootNode.get("test-metric").asDouble()).isEqualTo(100.0); + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("CustomNamespace"); + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("CustomService"); + } + + static class HandlerWithMetricsAnnotation implements RequestHandler, String> { + @Override + @FlushMetrics(namespace = "CustomNamespace", service = "CustomService") + public String handleRequest(Map input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + return "OK"; + } + } +} +``` diff --git a/docs/core/tracing.md b/docs/core/tracing.md index ea3174fba..883f8db86 100644 --- a/docs/core/tracing.md +++ b/docs/core/tracing.md @@ -3,7 +3,7 @@ title: Tracing description: Core utility --- -Powertools tracing is an opinionated thin wrapper for [AWS X-Ray Java SDK](https://github.com/aws/aws-xray-sdk-java/) +The Tracing utility is an opinionated thin wrapper for [AWS X-Ray Java SDK](https://github.com/aws/aws-xray-sdk-java/) a provides functionality to reduce the overhead of performing common tracing tasks. ![Tracing showcase](../media/tracing_utility_showcase.png) @@ -14,6 +14,7 @@ a provides functionality to reduce the overhead of performing common tracing tas * Helper methods to improve the developer experience of creating new X-Ray subsegments. * Better developer experience when developing with multiple threads. * Auto patch supported modules by AWS X-Ray + * GraalVM support ## Install diff --git a/docs/index.md b/docs/index.md index ef30b4197..43d1ea03b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -236,12 +236,13 @@ Use the following [dependency matrix](https://github.com/eclipse-aspectj/aspectj **Explicit parameters take precedence over environment variables.** | Environment variable | Description | Utility | -|----------------------------------------|----------------------------------------------------------------------------------------|---------------------------| +| -------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------- | | **POWERTOOLS_SERVICE_NAME** | Sets service name used for tracing namespace, metrics dimension and structured logging | All | | **POWERTOOLS_METRICS_NAMESPACE** | Sets namespace used for metrics | [Metrics](./core/metrics) | +| **POWERTOOLS_METRICS_FUNCTION_NAME** | Function name used as dimension for the cold start metric | [Metrics](./core/metrics) | +| **POWERTOOLS_METRICS_DISABLED** | Disables all flushing of metrics | [Metrics](./core/metrics) | | **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logging](./core/logging) | | **POWERTOOLS_LOG_LEVEL** | Sets logging level | [Logging](./core/logging) | | **POWERTOOLS_LOGGER_LOG_EVENT** | Enables/Disables whether to log the incoming event when using the aspect | [Logging](./core/logging) | | **POWERTOOLS_TRACER_CAPTURE_RESPONSE** | Enables/Disables tracing mode to capture method response | [Tracing](./core/tracing) | | **POWERTOOLS_TRACER_CAPTURE_ERROR** | Enables/Disables tracing mode to capture method error | [Tracing](./core/tracing) | - diff --git a/docs/upgrade.md b/docs/upgrade.md index 11be3dc5f..d2b1af096 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -112,7 +112,7 @@ This step is only required if you are using log4j2 as your logging implementatio **3. Migrate all logging specific calls to SLF4J native primitives (recommended)** -The new logging utility is designed to integrate seamlessly with Java SLF4J to allow customers adopt Powertools Logging without large code refactorings. This improvement requires the migration of non-native SLF4J primitives from the v1 Logging utility. +The new logging utility is designed to integrate seamlessly with Java SLF4J to allow customers adopt the Logging utility without large code refactorings. This improvement requires the migration of non-native SLF4J primitives from the v1 Logging utility. !!! info "While we recommend using SLF4J as a logging implementation independent facade, you can still use the log4j2 and logback interfaces directly." diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index e5fb11800..beb460aa6 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -14,6 +14,7 @@ or [AWS AppConfig](https://aws.amazon.com/systems-manager/features/appconfig/). * Retrieve one or multiple parameters from an underlying provider in a standard way * Cache parameter values for a given amount of time (defaults to 5 seconds) * Transform parameter values from JSON or base 64 encoded strings +* GraalVM support ## Install In order to provide lightweight dependencies, each parameters module is available as its own diff --git a/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java index 5aa268ffe..bb21f84d3 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/App.java @@ -14,8 +14,6 @@ package helloworld; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; import com.amazonaws.services.lambda.runtime.Context; @@ -32,10 +30,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; import software.amazon.lambda.powertools.tracing.CaptureMode; import software.amazon.lambda.powertools.tracing.Tracing; import software.amazon.lambda.powertools.tracing.TracingUtils; @@ -45,22 +45,23 @@ */ public class App implements RequestHandler { private static final Logger log = LoggerFactory.getLogger(App.class); + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); headers.put("Content-Type", "application/json"); headers.put("X-Custom-Header", "application/json"); - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT); - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> - { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); - }); + DimensionSet dimensionSet = DimensionSet.of( + "AnotherService", "CustomService", + "AnotherService1", "CustomService1"); + metrics.flushSingleMetric("CustomMetric2", 1, MetricUnit.COUNT, "Another", dimensionSet); MDC.put("test", "willBeLogged"); @@ -72,8 +73,7 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv TracingUtils.putAnnotation("Test", "New"); String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); - TracingUtils.withSubsegment("loggingResponse", subsegment -> - { + TracingUtils.withSubsegment("loggingResponse", subsegment -> { String sampled = "log something out"; log.info(sampled); log.info(output); diff --git a/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/AppStream.java index 94806cc38..8bc57b201 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/AppStream.java +++ b/examples/powertools-examples-core-utilities/cdk/app/src/main/java/helloworld/AppStream.java @@ -26,7 +26,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import java.io.InputStreamReader; import java.io.BufferedReader; @@ -40,7 +40,7 @@ public class AppStream implements RequestStreamHandler { @Override @Logging(logEvent = true) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) // RequestStreamHandler can be used instead of RequestHandler for cases when you'd like to deserialize request body or serialize response body yourself, instead of allowing that to happen automatically // Note that you still need to return a proper JSON for API Gateway to handle // See Lambda Response format for examples: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html diff --git a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java index b1a701b8f..39ed6f8d8 100644 --- a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/App.java @@ -15,8 +15,6 @@ package helloworld; import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; import com.amazonaws.services.lambda.runtime.Context; @@ -33,10 +31,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; import software.amazon.lambda.powertools.tracing.CaptureMode; import software.amazon.lambda.powertools.tracing.Tracing; import software.amazon.lambda.powertools.tracing.TracingUtils; @@ -46,23 +46,24 @@ */ public class App implements RequestHandler { private static final Logger log = LoggerFactory.getLogger(App.class); + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); headers.put("Content-Type", "application/json"); headers.put("X-Custom-Header", "application/json"); - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT); - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> - { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); - }); + DimensionSet dimensionSet = DimensionSet.of( + "AnotherService", "CustomService", + "AnotherService1", "CustomService1" + ); + metrics.flushSingleMetric("CustomMetric2", 1, MetricUnit.COUNT, "Another", dimensionSet); MDC.put("test", "willBeLogged"); diff --git a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java index 94806cc38..8bc57b201 100644 --- a/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java +++ b/examples/powertools-examples-core-utilities/gradle/src/main/java/helloworld/AppStream.java @@ -26,7 +26,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import java.io.InputStreamReader; import java.io.BufferedReader; @@ -40,7 +40,7 @@ public class AppStream implements RequestStreamHandler { @Override @Logging(logEvent = true) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) // RequestStreamHandler can be used instead of RequestHandler for cases when you'd like to deserialize request body or serialize response body yourself, instead of allowing that to happen automatically // Note that you still need to return a proper JSON for API Gateway to handle // See Lambda Response format for examples: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html diff --git a/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt b/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt index 8e8857079..b05e0d055 100644 --- a/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt +++ b/examples/powertools-examples-core-utilities/kotlin/src/main/kotlin/helloworld/App.kt @@ -20,13 +20,13 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent import com.amazonaws.xray.entities.Subsegment import org.slf4j.LoggerFactory import org.slf4j.MDC -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger -import software.amazon.cloudwatchlogs.emf.model.DimensionSet -import software.amazon.cloudwatchlogs.emf.model.Unit import software.amazon.lambda.powertools.logging.Logging import software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry import software.amazon.lambda.powertools.metrics.Metrics -import software.amazon.lambda.powertools.metrics.MetricsUtils +import software.amazon.lambda.powertools.metrics.Metrics +import software.amazon.lambda.powertools.metrics.MetricsFactory +import software.amazon.lambda.powertools.metrics.model.DimensionSet +import software.amazon.lambda.powertools.metrics.model.MetricUnit import software.amazon.lambda.powertools.tracing.CaptureMode import software.amazon.lambda.powertools.tracing.Tracing import software.amazon.lambda.powertools.tracing.TracingUtils @@ -39,16 +39,23 @@ import java.net.URL */ class App : RequestHandler { + private val log = LoggerFactory.getLogger(this::class.java) + private val metrics: Metrics = MetricsFactory.getMetricsInstance() + @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) override fun handleRequest(input: APIGatewayProxyRequestEvent?, context: Context?): APIGatewayProxyResponseEvent { val headers = mapOf("Content-Type" to "application/json", "X-Custom-Header" to "application/json") - MetricsUtils.metricsLogger().putMetric("CustomMetric1", 1.0, Unit.COUNT) - MetricsUtils.withSingleMetric("CustomMetrics2", 1.0, Unit.COUNT, "Another") { metric: MetricsLogger -> - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")) - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")) - } + + metrics.addMetric("CustomMetric1", 1.0, MetricUnit.COUNT) + + val dimensionSet = DimensionSet.of( + "AnotherService", "CustomService", + "AnotherService1", "CustomService1" + ) + metrics.flushSingleMetric("CustomMetric2", 1.0, MetricUnit.COUNT, "Another", dimensionSet) + MDC.put("test", "willBeLogged") val response = APIGatewayProxyResponseEvent().withHeaders(headers) return try { @@ -89,6 +96,4 @@ class App : RequestHandler = mapper.readValue(input, MutableMap::class.java) diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/java/helloworld/App.java index e7c410042..68664feec 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/java/helloworld/App.java @@ -15,8 +15,6 @@ package helloworld; import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; import com.amazonaws.services.lambda.runtime.Context; @@ -33,11 +31,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.StorageResolution; -import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricResolution; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; import software.amazon.lambda.powertools.tracing.CaptureMode; import software.amazon.lambda.powertools.tracing.Tracing; import software.amazon.lambda.powertools.tracing.TracingUtils; @@ -47,25 +47,25 @@ */ public class App implements RequestHandler { private static final Logger log = LoggerFactory.getLogger(App.class); + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); headers.put("Content-Type", "application/json"); headers.put("X-Custom-Header", "application/json"); - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT); - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> - { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); - }); + DimensionSet dimensionSet = DimensionSet.of( + "AnotherService", "CustomService", + "AnotherService1", "CustomService1"); + metrics.flushSingleMetric("CustomMetric2", 1, MetricUnit.COUNT, "Another", dimensionSet); - metricsLogger().putMetric("CustomMetric3", 1, Unit.COUNT, StorageResolution.HIGH); + metrics.addMetric("CustomMetric3", 1, MetricUnit.COUNT, MetricResolution.HIGH); MDC.put("test", "willBeLogged"); @@ -77,8 +77,7 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv TracingUtils.putAnnotation("Test", "New"); String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); - TracingUtils.withSubsegment("loggingResponse", subsegment -> - { + TracingUtils.withSubsegment("loggingResponse", subsegment -> { String sampled = "log something out"; log.info(sampled); log.info(output); diff --git a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java index e7c410042..2675c96eb 100644 --- a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java @@ -15,14 +15,8 @@ package helloworld; import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; -import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -30,14 +24,23 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.StorageResolution; -import software.amazon.cloudwatchlogs.emf.model.Unit; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricResolution; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; import software.amazon.lambda.powertools.tracing.CaptureMode; import software.amazon.lambda.powertools.tracing.Tracing; import software.amazon.lambda.powertools.tracing.TracingUtils; @@ -47,25 +50,25 @@ */ public class App implements RequestHandler { private static final Logger log = LoggerFactory.getLogger(App.class); + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); headers.put("Content-Type", "application/json"); headers.put("X-Custom-Header", "application/json"); - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT); - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> - { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); - }); + DimensionSet dimensionSet = new DimensionSet(); + dimensionSet.addDimension("AnotherService", "CustomService"); + dimensionSet.addDimension("AnotherService1", "CustomService1"); + metrics.flushSingleMetric("CustomMetric2", 1, MetricUnit.COUNT, "Another", dimensionSet); - metricsLogger().putMetric("CustomMetric3", 1, Unit.COUNT, StorageResolution.HIGH); + metrics.addMetric("CustomMetric3", 1, MetricUnit.COUNT, MetricResolution.HIGH); MDC.put("test", "willBeLogged"); @@ -77,8 +80,7 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv TracingUtils.putAnnotation("Test", "New"); String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); - TracingUtils.withSubsegment("loggingResponse", subsegment -> - { + TracingUtils.withSubsegment("loggingResponse", subsegment -> { String sampled = "log something out"; log.info(sampled); log.info(output); diff --git a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/AppStream.java index 94806cc38..8bc57b201 100644 --- a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/AppStream.java +++ b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/AppStream.java @@ -26,7 +26,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import java.io.InputStreamReader; import java.io.BufferedReader; @@ -40,7 +40,7 @@ public class AppStream implements RequestStreamHandler { @Override @Logging(logEvent = true) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) // RequestStreamHandler can be used instead of RequestHandler for cases when you'd like to deserialize request body or serialize response body yourself, instead of allowing that to happen automatically // Note that you still need to return a proper JSON for API Gateway to handle // See Lambda Response format for examples: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html diff --git a/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/App.java index e0b1a2979..771f5c1f1 100644 --- a/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/App.java @@ -15,8 +15,6 @@ package helloworld; import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; import com.amazonaws.services.lambda.runtime.Context; @@ -33,10 +31,12 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.slf4j.MDC; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; import software.amazon.lambda.powertools.tracing.CaptureMode; import software.amazon.lambda.powertools.tracing.Tracing; import software.amazon.lambda.powertools.tracing.TracingUtils; @@ -46,23 +46,23 @@ */ public class App implements RequestHandler { private static final Logger log = LogManager.getLogger(App.class); + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); headers.put("Content-Type", "application/json"); headers.put("X-Custom-Header", "application/json"); - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT); - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> - { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); - }); + DimensionSet dimensionSet = DimensionSet.of( + "AnotherService", "CustomService", + "AnotherService1", "CustomService1"); + metrics.flushSingleMetric("CustomMetric2", 1, MetricUnit.COUNT, "Another", dimensionSet); MDC.put("test", "willBeLogged"); @@ -74,8 +74,7 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv TracingUtils.putAnnotation("Test", "New"); String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); - TracingUtils.withSubsegment("loggingResponse", subsegment -> - { + TracingUtils.withSubsegment("loggingResponse", subsegment -> { String sampled = "log something out"; log.info(sampled); log.info(output); diff --git a/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/AppStream.java index 401ef8c48..c13ab9f2e 100644 --- a/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/AppStream.java +++ b/examples/powertools-examples-core-utilities/serverless/src/main/java/helloworld/AppStream.java @@ -22,14 +22,14 @@ import java.io.OutputStream; import java.util.Map; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.FlushMetrics; public class AppStream implements RequestStreamHandler { private static final ObjectMapper mapper = new ObjectMapper(); @Override @Logging(logEvent = true) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { Map map = mapper.readValue(input, Map.class); diff --git a/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/App.java index e0b1a2979..771f5c1f1 100644 --- a/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/App.java @@ -15,8 +15,6 @@ package helloworld; import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; import com.amazonaws.services.lambda.runtime.Context; @@ -33,10 +31,12 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.slf4j.MDC; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; import software.amazon.lambda.powertools.tracing.CaptureMode; import software.amazon.lambda.powertools.tracing.Tracing; import software.amazon.lambda.powertools.tracing.TracingUtils; @@ -46,23 +46,23 @@ */ public class App implements RequestHandler { private static final Logger log = LogManager.getLogger(App.class); + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); @Logging(logEvent = true, samplingRate = 0.7) @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map headers = new HashMap<>(); headers.put("Content-Type", "application/json"); headers.put("X-Custom-Header", "application/json"); - metricsLogger().putMetric("CustomMetric1", 1, Unit.COUNT); + metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT); - withSingleMetric("CustomMetrics2", 1, Unit.COUNT, "Another", (metric) -> - { - metric.setDimensions(DimensionSet.of("AnotherService", "CustomService")); - metric.setDimensions(DimensionSet.of("AnotherService1", "CustomService1")); - }); + DimensionSet dimensionSet = DimensionSet.of( + "AnotherService", "CustomService", + "AnotherService1", "CustomService1"); + metrics.flushSingleMetric("CustomMetric2", 1, MetricUnit.COUNT, "Another", dimensionSet); MDC.put("test", "willBeLogged"); @@ -74,8 +74,7 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv TracingUtils.putAnnotation("Test", "New"); String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); - TracingUtils.withSubsegment("loggingResponse", subsegment -> - { + TracingUtils.withSubsegment("loggingResponse", subsegment -> { String sampled = "log something out"; log.info(sampled); log.info(output); diff --git a/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/AppStream.java index 401ef8c48..c13ab9f2e 100644 --- a/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/AppStream.java +++ b/examples/powertools-examples-core-utilities/terraform/src/main/java/helloworld/AppStream.java @@ -22,14 +22,14 @@ import java.io.OutputStream; import java.util.Map; import software.amazon.lambda.powertools.logging.Logging; -import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.FlushMetrics; public class AppStream implements RequestStreamHandler { private static final ObjectMapper mapper = new ObjectMapper(); @Override @Logging(logEvent = true) - @Metrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException { Map map = mapper.readValue(input, Map.class); diff --git a/pom.xml b/pom.xml index cb761183e..81e513b8c 100644 --- a/pom.xml +++ b/pom.xml @@ -14,8 +14,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 software.amazon.lambda @@ -101,7 +101,7 @@ 1.12.781 2.18.0 1.6.0 - 5.12.0 + 5.17.0 @@ -279,6 +279,11 @@ aws-embedded-metrics ${aws-embedded-metrics.version} + + org.apache.commons + commons-lang3 + 3.15.0 + @@ -294,12 +299,6 @@ 1.9.1 test - - org.apache.commons - commons-lang3 - 3.15.0 - test - org.aspectj aspectjweaver @@ -341,6 +340,18 @@ ${mockito.version} test + + org.mockito + mockito-junit-jupiter + ${mockito.version} + test + + + org.mockito + mockito-subclass + ${mockito.version} + test + com.amazonaws aws-lambda-java-tests diff --git a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index a86e515f7..7244b3212 100644 --- a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -16,37 +16,36 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.StorageResolution; -import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; -import software.amazon.lambda.powertools.metrics.MetricsUtils; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricResolution; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.temporal.ChronoUnit; import java.time.Instant; - public class Function implements RequestHandler { - MetricsLogger metricsLogger = MetricsUtils.metricsLogger(); + Metrics metrics = MetricsFactory.getMetricsInstance(); - @Metrics(captureColdStart = true) + @FlushMetrics(captureColdStart = true) public String handleRequest(Input input, Context context) { - Instant currentTimeTruncatedPlusThirty = - LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES).toInstant(ZoneOffset.UTC).plusSeconds(30); - metricsLogger.setTimestamp(currentTimeTruncatedPlusThirty); + Instant currentTimeTruncatedPlusThirty = LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES) + .toInstant(ZoneOffset.UTC).plusSeconds(30); + metrics.setTimestamp(currentTimeTruncatedPlusThirty); DimensionSet dimensionSet = new DimensionSet(); input.getDimensions().forEach((key, value) -> dimensionSet.addDimension(key, value)); - metricsLogger.putDimensions(dimensionSet); + metrics.addDimension(dimensionSet); - input.getMetrics().forEach((key, value) -> metricsLogger.putMetric(key, value, Unit.COUNT, - input.getHighResolution().equalsIgnoreCase("true") ? StorageResolution.HIGH : - StorageResolution.STANDARD)); + input.getMetrics().forEach((key, value) -> metrics.addMetric(key, value, MetricUnit.COUNT, + input.getHighResolution().equalsIgnoreCase("true") ? MetricResolution.HIGH + : MetricResolution.STANDARD)); return "OK"; } -} \ No newline at end of file +} diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index d51ea5b33..46f7bcd99 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -14,8 +14,8 @@ --> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 powertools-metrics @@ -65,6 +65,10 @@ com.fasterxml.jackson.core jackson-databind + + org.apache.commons + commons-lang3 + @@ -82,6 +86,11 @@ mockito-core test + + org.mockito + mockito-junit-jupiter + test + org.slf4j slf4j-simple @@ -92,11 +101,6 @@ junit-pioneer test - - org.apache.commons - commons-lang3 - test - org.aspectj aspectjweaver @@ -116,7 +120,6 @@ org.mockito mockito-subclass - 5.17.0 test @@ -125,9 +128,9 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.3 - -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics,experimental-class-define-support + -Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -142,7 +145,6 @@ org.mockito mockito-subclass - 5.17.0 test @@ -151,7 +153,7 @@ org.graalvm.buildtools native-maven-plugin - 0.10.2 + 0.10.6 true @@ -178,16 +180,26 @@ --initialize-at-build-time=org.junit.Ignore --initialize-at-build-time=java.lang.annotation.Annotation --initialize-at-build-time=org.junit.runners.model.FrameworkField - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 + + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic + + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 + + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 + + --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader + + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase + + --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType + + --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod + + --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2 --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable @@ -207,5 +219,16 @@ src/main/resources + + + org.apache.maven.plugins + maven-surefire-plugin + + + Lambda + + + + diff --git a/powertools-metrics/src/main/java/software/amazon/cloudwatchlogs/emf/model/MetricsLoggerHelper.java b/powertools-metrics/src/main/java/software/amazon/cloudwatchlogs/emf/model/MetricsLoggerHelper.java deleted file mode 100644 index e2d886fe5..000000000 --- a/powertools-metrics/src/main/java/software/amazon/cloudwatchlogs/emf/model/MetricsLoggerHelper.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.cloudwatchlogs.emf.model; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; - -import java.lang.reflect.Field; - -public final class MetricsLoggerHelper { - private MetricsLoggerHelper() { - } - - public static boolean hasNoMetrics() { - return metricsContext().getRootNode().getAws().isEmpty(); - } - - public static long dimensionsCount() { - return metricsContext().getDimensions().size(); - } - - public static MetricsContext metricsContext() { - try { - Field f = metricsLogger().getClass().getDeclaredField("context"); - f.setAccessible(true); - return (MetricsContext) f.get(metricsLogger()); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); - } - } -} diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/FlushMetrics.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/FlushMetrics.java new file mode 100644 index 000000000..952625f5b --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/FlushMetrics.java @@ -0,0 +1,71 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * {@code FlushMetrics} is used to signal that the annotated Lambda handler method should be + * extended with Metrics flushing functionality. Will have no effect when used on a method that is not a Lambda handler. + * + *

    {@code FlushMetrics} allows users to asynchronously create Amazon + * CloudWatch metrics by using the CloudWatch Embedded Metrics Format. + * {@code FlushMetrics} manages the life-cycle and configuration of Metrics to simplify the user experience when used with AWS Lambda. + * + *

    {@code FlushMetrics} should be used with the handleRequest method of a class + * which implements either + * {@code com.amazonaws.services.lambda.runtime.RequestHandler} or + * {@code com.amazonaws.services.lambda.runtime.RequestStreamHandler}.

    + * + *

    {@code FlushMetrics} creates Amazon CloudWatch custom metrics. You can find + * pricing information on the CloudWatch pricing documentation page.

    + * + *

    To enable creation of custom metrics for cold starts you can add {@code @FlushMetrics(captureColdStart = true)}. + *
    This will create a metric with the key {@code "ColdStart"} and the unit type {@code COUNT}. + *

    + * + *

    To raise exception if no metrics are emitted, use {@code @FlushMetrics(raiseOnEmptyMetrics = true)}. + *
    This will create an exception if no metrics are emitted. By default its value is set to false. + *

    + * + *

    By default the service name associated with metrics created will be + * "service_undefined". This can be overridden with the environment variable {@code POWERTOOLS_SERVICE_NAME} + * or the annotation variable {@code @FlushMetrics(service = "Service Name")}. + * If both are specified then the value of the annotation variable will be used.

    + * + *

    A namespace must be specified for metrics. This can be set with the environment variable {@code POWERTOOLS_METRICS_NAMESPACE} + * or the annotation variable {@code @FlushMetrics(namespace = "Namespace")}. If not specified, an IllegalStateException will be thrown. + * If both are specified then the value of the annotation variable will be used.

    + * + *

    You can specify a custom function name with {@code @FlushMetrics(functionName = "MyFunction")}. + * If specified, this will be used instead of the function name from the Lambda context. + *

    + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface FlushMetrics { + String namespace() default ""; + + String service() default ""; + + String functionName() default ""; + + boolean captureColdStart() default false; + + boolean raiseOnEmptyMetrics() default false; +} diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java index fb92c900d..d21fe163e 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java @@ -14,54 +14,175 @@ package software.amazon.lambda.powertools.metrics; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import com.amazonaws.services.lambda.runtime.Context; +import java.time.Instant; + +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricResolution; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; /** - * {@code Metrics} is used to signal that the annotated method should be - * extended with Metrics functionality. - * - *

    {@code Metrics} allows users to asynchronously create Amazon - * CloudWatch metrics by using the CloudWatch Embedded Metrics Format. - * {@code Metrics} manages the life-cycle of the MetricsLogger class, - * to simplify the user experience when used with AWS Lambda. - * - *

    {@code Metrics} should be used with the handleRequest method of a class - * which implements either - * {@code com.amazonaws.services.lambda.runtime.RequestHandler} or - * {@code com.amazonaws.services.lambda.runtime.RequestStreamHandler}.

    - * - *

    {@code Metrics} creates Amazon CloudWatch custom metrics. You can find - * pricing information on the CloudWatch pricing documentation page.

    - * - *

    To enable creation of custom metrics for cold starts you can add {@code @Metrics(captureColdStart = true)}. - *
    This will create a metric with the key {@code "ColdStart"} and the unit type {@code COUNT}. - *

    - * - *

    To raise exception if no metrics are emitted, use {@code @Metrics(raiseOnEmptyMetrics = true)}. - *
    This will create a create a exception of type {@link ValidationException}. By default its value is set to false. - *

    - * - *

    By default the service name associated with metrics created will be - * "service_undefined". This can be overridden with the environment variable {@code POWERTOOLS_SERVICE_NAME} - * or the annotation variable {@code @Metrics(service = "Service Name")}. - * If both are specified then the value of the annotation variable will be used.

    - * - *

    By default the namespace associated with metrics created will be "aws-embedded-metrics". - * This can be overridden with the environment variable {@code POWERTOOLS_METRICS_NAMESPACE} - * or the annotation variable {@code @Metrics(namespace = "Namespace")}. - * If both are specified then the value of the annotation variable will be used.

    + * Interface for metrics implementations. + * This interface is used to collect metrics in the Lambda function. + * It provides methods to add metrics, dimensions, and metadata. */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface Metrics { - String namespace() default ""; +public interface Metrics { + + /** + * Add a metric + * + * @param key the name of the metric + * @param value the value of the metric + * @param unit the unit of the metric + * @param resolution the resolution of the metric + */ + void addMetric(String key, double value, MetricUnit unit, MetricResolution resolution); + + /** + * Add a metric with default resolution + * + * @param key the name of the metric + * @param value the value of the metric + * @param unit the unit of the metric + */ + default void addMetric(String key, double value, MetricUnit unit) { + addMetric(key, value, unit, MetricResolution.STANDARD); + } + + /** + * Add a metric with default unit and resolution + * + * @param key the name of the metric + * @param value the value of the metric + */ + default void addMetric(String key, double value) { + addMetric(key, value, MetricUnit.NONE, MetricResolution.STANDARD); + } + + /** + * Add a dimension + * This is equivalent to calling {@code addDimension(DimensionSet.of(key, value))} + * + * @param key the name of the dimension + * @param value the value of the dimension + */ + default void addDimension(String key, String value) { + addDimension(DimensionSet.of(key, value)); + } + + /** + * Add a dimension set + * + * @param dimensionSet the dimension set to add + */ + void addDimension(DimensionSet dimensionSet); + + /** + * Set a custom timestamp for the metrics + * + * @param timestamp the timestamp to use for the metrics + */ + void setTimestamp(Instant timestamp); + + /** + * Add metadata + * + * @param key the name of the metadata + * @param value the value of the metadata + */ + void addMetadata(String key, Object value); + + /** + * Set default dimensions + * + * @param dimensionSet the dimension set to use as default dimensions + */ + void setDefaultDimensions(DimensionSet dimensionSet); + + /** + * Get the default dimensions + * + * @return the default dimensions as a DimensionSet + */ + DimensionSet getDefaultDimensions(); + + /** + * Set the namespace + * + * @param namespace the namespace + */ + void setNamespace(String namespace); + + /** + * Set whether to raise an exception if no metrics are emitted + * + * @param raiseOnEmptyMetrics true to raise an exception, false otherwise + */ + void setRaiseOnEmptyMetrics(boolean raiseOnEmptyMetrics); + + /** + * Clear default dimensions + */ + void clearDefaultDimensions(); + + /** + * Flush metrics to the configured sink + */ + void flush(); + + /** + * Capture cold start metric and flush immediately + * + * @param context Lambda context + * @param dimensions custom dimensions for this metric (optional) + */ + void captureColdStartMetric(Context context, DimensionSet dimensions); + + /** + * Capture cold start metric and flush immediately + * + * @param context Lambda context + */ + default void captureColdStartMetric(Context context) { + captureColdStartMetric(context, null); + } + + /** + * Capture cold start metric without Lambda context and flush immediately + * + * @param dimensions custom dimensions for this metric (optional) + */ + void captureColdStartMetric(DimensionSet dimensions); - String service() default ""; + /** + * Capture cold start metric without Lambda context and flush immediately + */ + default void captureColdStartMetric() { + captureColdStartMetric((DimensionSet) null); + } - boolean captureColdStart() default false; + /** + * Flush a single metric with custom dimensions. This creates a separate metrics context + * that doesn't affect the default metrics context. + * + * @param name the name of the metric + * @param value the value of the metric + * @param unit the unit of the metric + * @param namespace the namespace for the metric + * @param dimensions custom dimensions for this metric (optional) + */ + void flushSingleMetric(String name, double value, MetricUnit unit, String namespace, DimensionSet dimensions); - boolean raiseOnEmptyMetrics() default false; + /** + * Flush a single metric with custom dimensions. This creates a separate metrics context + * that doesn't affect the default metrics context. + * + * @param name the name of the metric + * @param value the value of the metric + * @param unit the unit of the metric + * @param namespace the namespace for the metric + */ + default void flushSingleMetric(String name, double value, MetricUnit unit, String namespace) { + flushSingleMetric(name, value, unit, namespace, null); + } } diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsBuilder.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsBuilder.java new file mode 100644 index 000000000..2eb127b00 --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsBuilder.java @@ -0,0 +1,144 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics; + +import java.util.LinkedHashMap; +import java.util.Map; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; + +import software.amazon.lambda.powertools.metrics.provider.MetricsProvider; + +/** + * Builder for configuring the singleton Metrics instance + */ +public class MetricsBuilder { + private MetricsProvider provider; + private String namespace; + private String service; + private boolean raiseOnEmptyMetrics = false; + private final Map defaultDimensions = new LinkedHashMap<>(); + + private MetricsBuilder() { + } + + /** + * Create a new builder instance + * + * @return a new builder instance + */ + public static MetricsBuilder builder() { + return new MetricsBuilder(); + } + + /** + * Set the metrics provider + * + * @param provider the metrics provider + * @return this builder + */ + public MetricsBuilder withMetricsProvider(MetricsProvider provider) { + this.provider = provider; + return this; + } + + /** + * Set the namespace + * + * @param namespace the namespace + * @return this builder + */ + public MetricsBuilder withNamespace(String namespace) { + this.namespace = namespace; + return this; + } + + /** + * Set the service name. Does not apply if used in combination with default dimensions. If you would like to use a + * service name with default dimensions, use {@link #withDefaultDimension(String, String)} instead. + * + * @param service the service name + * @return this builder + */ + public MetricsBuilder withService(String service) { + this.service = service; + return this; + } + + /** + * Set whether to raise an exception if no metrics are emitted + * + * @param raiseOnEmptyMetrics true to raise an exception, false otherwise + * @return this builder + */ + public MetricsBuilder withRaiseOnEmptyMetrics(boolean raiseOnEmptyMetrics) { + this.raiseOnEmptyMetrics = raiseOnEmptyMetrics; + return this; + } + + /** + * Add a default dimension. + * + * @param key the dimension key + * @param value the dimension value + * @return this builder + */ + public MetricsBuilder withDefaultDimension(String key, String value) { + this.defaultDimensions.put(key, value); + return this; + } + + /** + * Add default dimensions + * + * @param dimensionSet the dimension set to add + * @return this builder + */ + public MetricsBuilder withDefaultDimensions(DimensionSet dimensionSet) { + if (dimensionSet != null) { + this.defaultDimensions.putAll(dimensionSet.getDimensions()); + } + return this; + } + + /** + * Configure and return the singleton Metrics instance + * + * @return the configured singleton Metrics instance + */ + public Metrics build() { + if (provider != null) { + MetricsFactory.setMetricsProvider(provider); + } + + Metrics metrics = MetricsFactory.getMetricsInstance(); + + if (namespace != null) { + metrics.setNamespace(namespace); + } + + metrics.setRaiseOnEmptyMetrics(raiseOnEmptyMetrics); + + if (service != null) { + metrics.setDefaultDimensions(DimensionSet.of("Service", service)); + } + + // If the user provided default dimension, we overwrite the default Service dimension again + if (!defaultDimensions.isEmpty()) { + metrics.setDefaultDimensions(DimensionSet.of(defaultDimensions)); + } + + return metrics; + } +} diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java new file mode 100644 index 000000000..1fd5f88ca --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java @@ -0,0 +1,71 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics; + +import software.amazon.lambda.powertools.common.internal.LambdaConstants; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.provider.EmfMetricsProvider; +import software.amazon.lambda.powertools.metrics.provider.MetricsProvider; + +/** + * Factory for accessing the singleton Metrics instance + */ +public final class MetricsFactory { + private static MetricsProvider provider = new EmfMetricsProvider(); + private static Metrics metrics; + + private MetricsFactory() { + } + + /** + * Get the singleton instance of the Metrics + * + * @return the singleton Metrics instance + */ + public static synchronized Metrics getMetricsInstance() { + if (metrics == null) { + metrics = provider.getMetricsInstance(); + + // Apply default configuration from environment variables + String envNamespace = System.getenv("POWERTOOLS_METRICS_NAMESPACE"); + if (envNamespace != null) { + metrics.setNamespace(envNamespace); + } + + // Only set Service dimension if it's not the default undefined value + String serviceName = LambdaHandlerProcessor.serviceName(); + if (!LambdaConstants.SERVICE_UNDEFINED.equals(serviceName)) { + metrics.setDefaultDimensions(DimensionSet.of("Service", serviceName)); + } + } + + return metrics; + } + + /** + * Set the metrics provider + * + * @param metricsProvider the metrics provider + */ + public static synchronized void setMetricsProvider(MetricsProvider metricsProvider) { + if (metricsProvider == null) { + throw new IllegalArgumentException("Metrics provider cannot be null"); + } + provider = metricsProvider; + // Reset the metrics instance so it will be recreated with the new provider + metrics = null; + } +} diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java deleted file mode 100644 index 6c3a89a65..000000000 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsUtils.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics; - -import static java.util.Optional.ofNullable; -import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; -import static software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect.REQUEST_ID_PROPERTY; -import static software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect.TRACE_ID_PROPERTY; - -import java.util.Arrays; -import java.util.Optional; -import java.util.function.Consumer; -import software.amazon.cloudwatchlogs.emf.config.SystemWrapper; -import software.amazon.cloudwatchlogs.emf.environment.EnvironmentProvider; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.MetricsContext; -import software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper; -import software.amazon.cloudwatchlogs.emf.model.Unit; - -/** - * A class used to retrieve the instance of the {@code MetricsLogger} used by - * {@code Metrics}. - *

    - * {@see Metrics} - */ -public final class MetricsUtils { - private static final MetricsLogger metricsLogger = new MetricsLogger(); - private static DimensionSet[] defaultDimensions; - - private MetricsUtils() { - } - - /** - * The instance of the {@code MetricsLogger} used by {@code Metrics}. - * - * @return The instance of the MetricsLogger used by Metrics. - */ - public static MetricsLogger metricsLogger() { - return metricsLogger; - } - - /** - * Configure default dimension to be used by logger. - * By default, @{@link Metrics} annotation captures configured service as a dimension Service - * - * @param dimensionSets Default value of dimensions set for logger - */ - public static void defaultDimensions(final DimensionSet... dimensionSets) { - MetricsUtils.defaultDimensions = dimensionSets; - } - - /** - * Add and immediately flush a single metric. It will use the default namespace - * specified either on {@link Metrics} annotation or via POWERTOOLS_METRICS_NAMESPACE env var. - * It by default captures function_request_id as property if used together with {@link Metrics} annotation. It will also - * capture xray_trace_id as property if tracing is enabled. - * - * @param name the name of the metric - * @param value the value of the metric - * @param unit the unit type of the metric - * @param logger the MetricsLogger - */ - public static void withSingleMetric(final String name, - final double value, - final Unit unit, - final Consumer logger) { - withMetricsLogger(metricsLogger -> - { - metricsLogger.putMetric(name, value, unit); - logger.accept(metricsLogger); - }); - } - - /** - * Add and immediately flush a single metric. - * It by default captures function_request_id as property if used together with {@link Metrics} annotation. It will also - * capture xray_trace_id as property if tracing is enabled. - * - * @param name the name of the metric - * @param value the value of the metric - * @param unit the unit type of the metric - * @param namespace the namespace associated with the metric - * @param logger the MetricsLogger - */ - public static void withSingleMetric(final String name, - final double value, - final Unit unit, - final String namespace, - final Consumer logger) { - withMetricsLogger(metricsLogger -> - { - metricsLogger.setNamespace(namespace); - metricsLogger.putMetric(name, value, unit); - logger.accept(metricsLogger); - }); - } - - /** - * Provide and immediately flush a {@link MetricsLogger}. It uses the default namespace - * specified either on {@link Metrics} annotation or via POWERTOOLS_METRICS_NAMESPACE env var. - * It by default captures function_request_id as property if used together with {@link Metrics} annotation. It will also - * capture xray_trace_id as property if tracing is enabled. - * - * @param logger the MetricsLogger - */ - public static void withMetricsLogger(final Consumer logger) { - MetricsLogger metricsLogger = logger(); - - try { - metricsLogger.setNamespace(defaultNameSpace()); - captureRequestAndTraceId(metricsLogger); - logger.accept(metricsLogger); - } finally { - metricsLogger.flush(); - } - } - - public static DimensionSet[] getDefaultDimensions() { - return Arrays.copyOf(defaultDimensions, defaultDimensions.length); - } - - public static boolean hasDefaultDimension() { - return null != defaultDimensions; - } - - private static void captureRequestAndTraceId(MetricsLogger metricsLogger) { - awsRequestId(). - ifPresent(requestId -> metricsLogger.putProperty(REQUEST_ID_PROPERTY, requestId)); - - getXrayTraceId() - .ifPresent(traceId -> metricsLogger.putProperty(TRACE_ID_PROPERTY, traceId)); - } - - private static String defaultNameSpace() { - MetricsContext context = MetricsLoggerHelper.metricsContext(); - if ("aws-embedded-metrics".equals(context.getNamespace())) { - String namespace = SystemWrapper.getenv("POWERTOOLS_METRICS_NAMESPACE"); - return namespace != null ? namespace : "aws-embedded-metrics"; - } else { - return context.getNamespace(); - } - } - - private static Optional awsRequestId() { - MetricsContext context = MetricsLoggerHelper.metricsContext(); - return ofNullable(context.getProperty(REQUEST_ID_PROPERTY)) - .map(Object::toString); - } - - private static MetricsLogger logger() { - MetricsContext metricsContext = new MetricsContext(); - - if (hasDefaultDimension()) { - metricsContext.setDimensions(defaultDimensions); - } - - return new MetricsLogger(new EnvironmentProvider(), metricsContext); - } -} diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java new file mode 100644 index 000000000..a55e1da5a --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java @@ -0,0 +1,326 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.internal; + +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isColdStart; + +import java.time.Instant; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.Context; + +import software.amazon.cloudwatchlogs.emf.environment.EnvironmentProvider; +import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +import software.amazon.cloudwatchlogs.emf.model.MetricsContext; +import software.amazon.cloudwatchlogs.emf.model.StorageResolution; +import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.model.MetricResolution; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; + +/** + * Implementation of Metrics that uses the EMF library. Proxies Metrics interface calls to underlying + * library {@link software.amazon.cloudwatchlogs.emf.logger.MetricsLogger}. + */ +public class EmfMetricsLogger implements Metrics { + private static final Logger LOGGER = LoggerFactory.getLogger(EmfMetricsLogger.class); + private static final String TRACE_ID_PROPERTY = "xray_trace_id"; + private static final String REQUEST_ID_PROPERTY = "function_request_id"; + private static final String COLD_START_METRIC = "ColdStart"; + private static final String METRICS_DISABLED_ENV_VAR = "POWERTOOLS_METRICS_DISABLED"; + + private final software.amazon.cloudwatchlogs.emf.logger.MetricsLogger emfLogger; + private final EnvironmentProvider environmentProvider; + private boolean raiseOnEmptyMetrics = false; + private String namespace; + private Map defaultDimensions = new HashMap<>(); + private final AtomicBoolean hasMetrics = new AtomicBoolean(false); + + public EmfMetricsLogger(EnvironmentProvider environmentProvider, MetricsContext metricsContext) { + this.emfLogger = new software.amazon.cloudwatchlogs.emf.logger.MetricsLogger(environmentProvider, + metricsContext); + this.environmentProvider = environmentProvider; + } + + @Override + public void addMetric(String key, double value, MetricUnit unit, MetricResolution resolution) { + StorageResolution storageResolution = resolution == MetricResolution.HIGH ? StorageResolution.HIGH + : StorageResolution.STANDARD; + emfLogger.putMetric(key, value, convertUnit(unit), storageResolution); + hasMetrics.set(true); + } + + @Override + public void addDimension(software.amazon.lambda.powertools.metrics.model.DimensionSet dimensionSet) { + if (dimensionSet == null) { + throw new IllegalArgumentException("DimensionSet cannot be null"); + } + + DimensionSet emfDimensionSet = new DimensionSet(); + dimensionSet.getDimensions().forEach((key, val) -> { + try { + emfDimensionSet.addDimension(key, val); + // Update our local copy of default dimensions + defaultDimensions.put(key, val); + } catch (Exception e) { + // Ignore dimension errors + } + }); + + emfLogger.putDimensions(emfDimensionSet); + } + + @Override + public void addMetadata(String key, Object value) { + emfLogger.putMetadata(key, value); + } + + @Override + public void setDefaultDimensions(software.amazon.lambda.powertools.metrics.model.DimensionSet dimensionSet) { + if (dimensionSet == null) { + throw new IllegalArgumentException("DimensionSet cannot be null"); + } + + DimensionSet emfDimensionSet = new DimensionSet(); + Map dimensions = dimensionSet.getDimensions(); + dimensions.forEach((key, value) -> { + try { + emfDimensionSet.addDimension(key, value); + } catch (Exception e) { + // Ignore dimension errors + } + }); + emfLogger.setDimensions(emfDimensionSet); + // Store a copy of the default dimensions + this.defaultDimensions = new LinkedHashMap<>(dimensions); + } + + @Override + public software.amazon.lambda.powertools.metrics.model.DimensionSet getDefaultDimensions() { + return software.amazon.lambda.powertools.metrics.model.DimensionSet.of(defaultDimensions); + } + + @Override + public void setNamespace(String namespace) { + Validator.validateNamespace(namespace); + + this.namespace = namespace; + try { + emfLogger.setNamespace(namespace); + } catch (Exception e) { + LOGGER.error("Namespace cannot be set due to an error in EMF", e); + } + } + + @Override + public void setRaiseOnEmptyMetrics(boolean raiseOnEmptyMetrics) { + this.raiseOnEmptyMetrics = raiseOnEmptyMetrics; + } + + @Override + public void setTimestamp(Instant timestamp) { + Validator.validateTimestamp(timestamp); + + emfLogger.setTimestamp(timestamp); + } + + @Override + public void clearDefaultDimensions() { + emfLogger.resetDimensions(false); + defaultDimensions.clear(); + } + + @Override + public void flush() { + if (isMetricsDisabled()) { + LOGGER.debug("Metrics are disabled, skipping flush"); + return; + } + + Validator.validateNamespace(namespace); + + if (!hasMetrics.get()) { + if (raiseOnEmptyMetrics) { + throw new IllegalStateException("No metrics were emitted"); + } else { + LOGGER.warn("No metrics were emitted"); + } + } + emfLogger.flush(); + } + + @Override + public void captureColdStartMetric(Context context, + software.amazon.lambda.powertools.metrics.model.DimensionSet dimensions) { + if (isColdStart()) { + if (isMetricsDisabled()) { + LOGGER.debug("Metrics are disabled, skipping cold start metric capture"); + return; + } + + Validator.validateNamespace(namespace); + + software.amazon.cloudwatchlogs.emf.logger.MetricsLogger coldStartLogger = new software.amazon.cloudwatchlogs.emf.logger.MetricsLogger(); + + try { + coldStartLogger.setNamespace(namespace); + } catch (Exception e) { + LOGGER.error("Namespace cannot be set for cold start metrics due to an error in EMF", e); + } + + coldStartLogger.putMetric(COLD_START_METRIC, 1, Unit.COUNT); + + // Set dimensions if provided + if (dimensions != null) { + DimensionSet emfDimensionSet = new DimensionSet(); + dimensions.getDimensions().forEach((key, val) -> { + try { + emfDimensionSet.addDimension(key, val); + } catch (Exception e) { + // Ignore dimension errors + } + }); + coldStartLogger.setDimensions(emfDimensionSet); + } + + // Add request ID from context if available + if (context != null) { + coldStartLogger.putProperty(REQUEST_ID_PROPERTY, context.getAwsRequestId()); + } + + // Add trace ID using the standard logic + getXrayTraceId().ifPresent(traceId -> coldStartLogger.putProperty(TRACE_ID_PROPERTY, traceId)); + + coldStartLogger.flush(); + } + } + + @Override + public void captureColdStartMetric(software.amazon.lambda.powertools.metrics.model.DimensionSet dimensions) { + captureColdStartMetric(null, dimensions); + } + + @Override + public void flushSingleMetric(String name, double value, MetricUnit unit, String namespace, + software.amazon.lambda.powertools.metrics.model.DimensionSet dimensions) { + if (isMetricsDisabled()) { + LOGGER.debug("Metrics are disabled, skipping single metric flush"); + return; + } + + Validator.validateNamespace(namespace); + + // Create a new logger for this single metric + software.amazon.cloudwatchlogs.emf.logger.MetricsLogger singleMetricLogger = new software.amazon.cloudwatchlogs.emf.logger.MetricsLogger( + environmentProvider); + + try { + singleMetricLogger.setNamespace(namespace); + } catch (Exception e) { + LOGGER.error("Namespace cannot be set for single metric due to an error in EMF", e); + } + + // Add the metric + singleMetricLogger.putMetric(name, value, convertUnit(unit)); + + // Set dimensions if provided + if (dimensions != null) { + DimensionSet emfDimensionSet = new DimensionSet(); + dimensions.getDimensions().forEach((key, val) -> { + try { + emfDimensionSet.addDimension(key, val); + } catch (Exception e) { + // Ignore dimension errors + } + }); + singleMetricLogger.setDimensions(emfDimensionSet); + } + + // Flush the metric + singleMetricLogger.flush(); + } + + private boolean isMetricsDisabled() { + String disabledValue = System.getenv(METRICS_DISABLED_ENV_VAR); + return "true".equalsIgnoreCase(disabledValue); + } + + private Unit convertUnit(MetricUnit unit) { + switch (unit) { + case SECONDS: + return Unit.SECONDS; + case MICROSECONDS: + return Unit.MICROSECONDS; + case MILLISECONDS: + return Unit.MILLISECONDS; + case BYTES: + return Unit.BYTES; + case KILOBYTES: + return Unit.KILOBYTES; + case MEGABYTES: + return Unit.MEGABYTES; + case GIGABYTES: + return Unit.GIGABYTES; + case TERABYTES: + return Unit.TERABYTES; + case BITS: + return Unit.BITS; + case KILOBITS: + return Unit.KILOBITS; + case MEGABITS: + return Unit.MEGABITS; + case GIGABITS: + return Unit.GIGABITS; + case TERABITS: + return Unit.TERABITS; + case PERCENT: + return Unit.PERCENT; + case COUNT: + return Unit.COUNT; + case BYTES_SECOND: + return Unit.BYTES_SECOND; + case KILOBYTES_SECOND: + return Unit.KILOBYTES_SECOND; + case MEGABYTES_SECOND: + return Unit.MEGABYTES_SECOND; + case GIGABYTES_SECOND: + return Unit.GIGABYTES_SECOND; + case TERABYTES_SECOND: + return Unit.TERABYTES_SECOND; + case BITS_SECOND: + return Unit.BITS_SECOND; + case KILOBITS_SECOND: + return Unit.KILOBITS_SECOND; + case MEGABITS_SECOND: + return Unit.MEGABITS_SECOND; + case GIGABITS_SECOND: + return Unit.GIGABITS_SECOND; + case TERABITS_SECOND: + return Unit.TERABITS_SECOND; + case COUNT_SECOND: + return Unit.COUNT_SECOND; + case NONE: + default: + return Unit.NONE; + } + } +} diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java index 56a35f67f..b214d7c52 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java @@ -14,138 +14,129 @@ package software.amazon.lambda.powertools.metrics.internal; -import static software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper.dimensionsCount; -import static software.amazon.cloudwatchlogs.emf.model.MetricsLoggerHelper.hasNoMetrics; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.coldStartDone; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.extractContext; -import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isColdStart; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isHandlerMethod; -import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.serviceName; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.hasDefaultDimension; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import com.amazonaws.services.lambda.runtime.Context; -import java.lang.reflect.Field; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.MetricsContext; -import software.amazon.cloudwatchlogs.emf.model.Unit; + +import com.amazonaws.services.lambda.runtime.Context; + +import software.amazon.lambda.powertools.common.internal.LambdaConstants; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.metrics.FlushMetrics; import software.amazon.lambda.powertools.metrics.Metrics; -import software.amazon.lambda.powertools.metrics.MetricsUtils; -import software.amazon.lambda.powertools.metrics.ValidationException; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; @Aspect public class LambdaMetricsAspect { public static final String TRACE_ID_PROPERTY = "xray_trace_id"; public static final String REQUEST_ID_PROPERTY = "function_request_id"; - private static final String NAMESPACE = System.getenv("POWERTOOLS_METRICS_NAMESPACE"); - - private static String service(Metrics metrics) { - return !"".equals(metrics.service()) ? metrics.service() : serviceName(); - } + private static final String SERVICE_DIMENSION = "Service"; + private static final String FUNCTION_NAME_ENV_VAR = "POWERTOOLS_METRICS_FUNCTION_NAME"; - // This can be simplified after this issues https://github.com/awslabs/aws-embedded-metrics-java/issues/35 is fixed - public static void refreshMetricsContext(Metrics metrics) { - try { - Field f = metricsLogger().getClass().getDeclaredField("context"); - f.setAccessible(true); - MetricsContext context = new MetricsContext(); + private String functionName(FlushMetrics metrics, Context context) { + if (!"".equals(metrics.functionName())) { + return metrics.functionName(); + } - DimensionSet[] defaultDimensions = hasDefaultDimension() ? MetricsUtils.getDefaultDimensions() - : new DimensionSet[] {DimensionSet.of("Service", service(metrics))}; + String envFunctionName = System.getenv(FUNCTION_NAME_ENV_VAR); + if (envFunctionName != null && !envFunctionName.isEmpty()) { + return envFunctionName; + } - context.setDimensions(defaultDimensions); + return context != null ? context.getFunctionName() : null; + } - f.set(metricsLogger(), context); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); + private String serviceNameWithFallback(FlushMetrics metrics) { + if (!"".equals(metrics.service())) { + return metrics.service(); } + return LambdaHandlerProcessor.serviceName(); } - @SuppressWarnings({"EmptyMethod"}) + @SuppressWarnings({ "EmptyMethod" }) @Pointcut("@annotation(metrics)") - public void callAt(Metrics metrics) { + public void callAt(FlushMetrics metrics) { + // AspectJ point cut referenced in around() method } - @Around(value = "callAt(metrics) && execution(@Metrics * *.*(..))", argNames = "pjp,metrics") + @Around(value = "callAt(metrics) && execution(@FlushMetrics * *.*(..))", argNames = "pjp,metrics") public Object around(ProceedingJoinPoint pjp, - Metrics metrics) throws Throwable { + FlushMetrics metrics) throws Throwable { Object[] proceedArgs = pjp.getArgs(); if (isHandlerMethod(pjp)) { + Metrics metricsInstance = MetricsFactory.getMetricsInstance(); - MetricsLogger logger = metricsLogger(); - - refreshMetricsContext(metrics); - - logger.setNamespace(namespace(metrics)); - - Context extractedContext = extractContext(pjp); + // The MetricsFactory applies default settings from the environment or can be configured by the + // MetricsBuilder. We only overwrite settings if they are explicitly set in the @FlushMetrics + // annotation. + if (!"".equals(metrics.namespace())) { + metricsInstance.setNamespace(metrics.namespace()); + } - if (null != extractedContext) { - coldStartSingleMetricIfApplicable(extractedContext.getAwsRequestId(), - extractedContext.getFunctionName(), metrics); - logger.putProperty(REQUEST_ID_PROPERTY, extractedContext.getAwsRequestId()); + // We only overwrite the default dimensions if the user didn't overwrite them previously. This means that + // they are either empty or only contain the default "Service" dimension. + if (!"".equals(metrics.service().trim()) + && (metricsInstance.getDefaultDimensions().getDimensionKeys().size() <= 1 + || metricsInstance.getDefaultDimensions().getDimensionKeys().contains(SERVICE_DIMENSION))) { + metricsInstance.setDefaultDimensions(DimensionSet.of(SERVICE_DIMENSION, metrics.service())); } + metricsInstance.setRaiseOnEmptyMetrics(metrics.raiseOnEmptyMetrics()); + + // Add trace ID metadata if available LambdaHandlerProcessor.getXrayTraceId() - .ifPresent(traceId -> logger.putProperty(TRACE_ID_PROPERTY, traceId)); + .ifPresent(traceId -> metricsInstance.addMetadata(TRACE_ID_PROPERTY, traceId)); + + captureColdStartMetricIfEnabled(extractContext(pjp), metrics); try { return pjp.proceed(proceedArgs); - } finally { coldStartDone(); - validateMetricsAndRefreshOnFailure(metrics); - logger.flush(); - refreshMetricsContext(metrics); + metricsInstance.flush(); } } return pjp.proceed(proceedArgs); } - private void coldStartSingleMetricIfApplicable(final String awsRequestId, - final String functionName, - final Metrics metrics) { - if (metrics.captureColdStart() - && isColdStart()) { - MetricsLogger metricsLogger = new MetricsLogger(); - metricsLogger.setNamespace(namespace(metrics)); - metricsLogger.putMetric("ColdStart", 1, Unit.COUNT); - metricsLogger.setDimensions(DimensionSet.of("Service", service(metrics), "FunctionName", functionName)); - metricsLogger.putProperty(REQUEST_ID_PROPERTY, awsRequestId); - metricsLogger.flush(); + private void captureColdStartMetricIfEnabled(Context extractedContext, FlushMetrics metrics) { + if (extractedContext == null) { + return; } - } + Metrics metricsInstance = MetricsFactory.getMetricsInstance(); + metricsInstance.addMetadata(REQUEST_ID_PROPERTY, extractedContext.getAwsRequestId()); - private void validateBeforeFlushingMetrics(Metrics metrics) { - if (metrics.raiseOnEmptyMetrics() && hasNoMetrics()) { - throw new ValidationException("No metrics captured, at least one metrics must be emitted"); - } + // Only capture cold start metrics if enabled on annotation + if (metrics.captureColdStart()) { + // Get function name from annotation or context + String funcName = functionName(metrics, extractedContext); - if (dimensionsCount() > 9) { - throw new ValidationException(String.format("Number of Dimensions must be in range of 0-9." + - " Actual size: %d.", dimensionsCount())); - } - } + DimensionSet coldStartDimensions = new DimensionSet(); - private String namespace(Metrics metrics) { - return !"".equals(metrics.namespace()) ? metrics.namespace() : NAMESPACE; - } + // Get service name from metrics instance default dimensions or fallback + String serviceName = metricsInstance.getDefaultDimensions().getDimensions().getOrDefault( + SERVICE_DIMENSION, + serviceNameWithFallback(metrics)); + + // Only add service if it is not undefined + if (!LambdaConstants.SERVICE_UNDEFINED.equals(serviceName)) { + coldStartDimensions.addDimension(SERVICE_DIMENSION, serviceName); + } + + // Add function name + coldStartDimensions.addDimension("FunctionName", + funcName != null ? funcName : extractedContext.getFunctionName()); - private void validateMetricsAndRefreshOnFailure(Metrics metrics) { - try { - validateBeforeFlushingMetrics(metrics); - } catch (ValidationException e) { - refreshMetricsContext(metrics); - throw e; + metricsInstance.captureColdStartMetric(extractedContext, coldStartDimensions); } } } diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/Validator.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/Validator.java new file mode 100644 index 000000000..eebb54739 --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/Validator.java @@ -0,0 +1,135 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.internal; + +import java.time.Instant; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.StringUtils; + +/** + * Utility class for validating metrics-related parameters. + */ +public class Validator { + private static final int MAX_DIMENSION_NAME_LENGTH = 250; + private static final int MAX_DIMENSION_VALUE_LENGTH = 1024; + private static final int MAX_NAMESPACE_LENGTH = 255; + private static final String NAMESPACE_REGEX = "^[a-zA-Z0-9._#:/-]+$"; + public static final long MAX_TIMESTAMP_PAST_AGE_SECONDS = TimeUnit.DAYS.toSeconds(14); + public static final long MAX_TIMESTAMP_FUTURE_AGE_SECONDS = TimeUnit.HOURS.toSeconds(2); + + private Validator() { + // Private constructor to prevent instantiation + } + + /** + * Validates that a namespace is properly specified. + * + * @param namespace The namespace to validate + * @throws IllegalArgumentException if the namespace is invalid + */ + public static void validateNamespace(String namespace) { + if (namespace == null || namespace.trim().isEmpty()) { + throw new IllegalArgumentException("Namespace must be specified before flushing metrics"); + } + + if (namespace.length() > MAX_NAMESPACE_LENGTH) { + throw new IllegalArgumentException( + "Namespace exceeds maximum length of " + MAX_NAMESPACE_LENGTH + ": " + namespace); + } + + if (!namespace.matches(NAMESPACE_REGEX)) { + throw new IllegalArgumentException("Namespace contains invalid characters: " + namespace); + } + } + + /** + * Validates Timestamp. + * + * @see CloudWatch + * Timestamp + * @param timestamp Timestamp + * @throws IllegalArgumentException if timestamp is invalid + */ + public static void validateTimestamp(Instant timestamp) { + if (timestamp == null) { + throw new IllegalArgumentException("Timestamp cannot be null"); + } + + if (timestamp.isAfter( + Instant.now().plusSeconds(MAX_TIMESTAMP_FUTURE_AGE_SECONDS))) { + throw new IllegalArgumentException( + "Timestamp cannot be more than " + + MAX_TIMESTAMP_FUTURE_AGE_SECONDS + + " seconds in the future"); + } + + if (timestamp.isBefore( + Instant.now().minusSeconds(MAX_TIMESTAMP_PAST_AGE_SECONDS))) { + throw new IllegalArgumentException( + "Timestamp cannot be more than " + + MAX_TIMESTAMP_PAST_AGE_SECONDS + + " seconds in the past"); + } + } + + /** + * Validates a dimension key-value pair. + * + * @param key The dimension key to validate + * @param value The dimension value to validate + * @throws IllegalArgumentException if the key or value is invalid + */ + public static void validateDimension(String key, String value) { + if (key == null || key.trim().isEmpty()) { + throw new IllegalArgumentException("Dimension key cannot be null or empty"); + } + + if (value == null || value.trim().isEmpty()) { + throw new IllegalArgumentException("Dimension value cannot be null or empty"); + } + + if (StringUtils.containsWhitespace(key)) { + throw new IllegalArgumentException("Dimension key cannot contain whitespaces: " + key); + } + + if (StringUtils.containsWhitespace(value)) { + throw new IllegalArgumentException("Dimension value cannot contain whitespaces: " + value); + } + + if (key.startsWith(":")) { + throw new IllegalArgumentException("Dimension key cannot start with colon: " + key); + } + + if (key.length() > MAX_DIMENSION_NAME_LENGTH) { + throw new IllegalArgumentException( + "Dimension name exceeds maximum length of " + MAX_DIMENSION_NAME_LENGTH + ": " + key); + } + + if (value.length() > MAX_DIMENSION_VALUE_LENGTH) { + throw new IllegalArgumentException( + "Dimension value exceeds maximum length of " + MAX_DIMENSION_VALUE_LENGTH + ": " + value); + } + + if (!StringUtils.isAsciiPrintable(key)) { + throw new IllegalArgumentException("Dimension name has invalid characters: " + key); + } + + if (!StringUtils.isAsciiPrintable(value)) { + throw new IllegalArgumentException("Dimension value has invalid characters: " + value); + } + } +} diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/DimensionSet.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/DimensionSet.java new file mode 100644 index 000000000..e93f34237 --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/DimensionSet.java @@ -0,0 +1,193 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.model; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import software.amazon.lambda.powertools.metrics.internal.Validator; + +/** + * Represents a set of dimensions for CloudWatch metrics + */ +public class DimensionSet { + private static final int MAX_DIMENSION_SET_SIZE = 30; + + private final Map dimensions = new LinkedHashMap<>(); + + /** + * Create a dimension set with a single key-value pair + * + * @param key dimension key + * @param value dimension value + * @return a new DimensionSet + */ + public static DimensionSet of(String key, String value) { + DimensionSet dimensionSet = new DimensionSet(); + dimensionSet.addDimension(key, value); + return dimensionSet; + } + + /** + * Create a dimension set with two key-value pairs + * + * @param key1 first dimension key + * @param value1 first dimension value + * @param key2 second dimension key + * @param value2 second dimension value + * @return a new DimensionSet + */ + public static DimensionSet of(String key1, String value1, String key2, String value2) { + DimensionSet dimensionSet = new DimensionSet(); + dimensionSet.addDimension(key1, value1); + dimensionSet.addDimension(key2, value2); + return dimensionSet; + } + + /** + * Create a dimension set with three key-value pairs + * + * @param key1 first dimension key + * @param value1 first dimension value + * @param key2 second dimension key + * @param value2 second dimension value + * @param key3 third dimension key + * @param value3 third dimension value + * @return a new DimensionSet + */ + public static DimensionSet of(String key1, String value1, String key2, String value2, String key3, String value3) { + DimensionSet dimensionSet = new DimensionSet(); + dimensionSet.addDimension(key1, value1); + dimensionSet.addDimension(key2, value2); + dimensionSet.addDimension(key3, value3); + return dimensionSet; + } + + /** + * Create a dimension set with four key-value pairs + * + * @param key1 first dimension key + * @param value1 first dimension value + * @param key2 second dimension key + * @param value2 second dimension value + * @param key3 third dimension key + * @param value3 third dimension value + * @param key4 fourth dimension key + * @param value4 fourth dimension value + * @return a new DimensionSet + */ + public static DimensionSet of(String key1, String value1, String key2, String value2, + String key3, String value3, String key4, String value4) { + DimensionSet dimensionSet = new DimensionSet(); + dimensionSet.addDimension(key1, value1); + dimensionSet.addDimension(key2, value2); + dimensionSet.addDimension(key3, value3); + dimensionSet.addDimension(key4, value4); + return dimensionSet; + } + + /** + * Create a dimension set with five key-value pairs + * + * @param key1 first dimension key + * @param value1 first dimension value + * @param key2 second dimension key + * @param value2 second dimension value + * @param key3 third dimension key + * @param value3 third dimension value + * @param key4 fourth dimension key + * @param value4 fourth dimension value + * @param key5 fifth dimension key + * @param value5 fifth dimension value + * @return a new DimensionSet + */ + public static DimensionSet of(String key1, String value1, String key2, String value2, + String key3, String value3, String key4, String value4, + String key5, String value5) { + DimensionSet dimensionSet = new DimensionSet(); + dimensionSet.addDimension(key1, value1); + dimensionSet.addDimension(key2, value2); + dimensionSet.addDimension(key3, value3); + dimensionSet.addDimension(key4, value4); + dimensionSet.addDimension(key5, value5); + return dimensionSet; + } + + /** + * Create a dimension set from a map of key-value pairs + * + * @param dimensions map of dimension key-value pairs + * @return a new DimensionSet + */ + public static DimensionSet of(Map dimensions) { + DimensionSet dimensionSet = new DimensionSet(); + dimensions.forEach(dimensionSet::addDimension); + return dimensionSet; + } + + /** + * Add a dimension to this dimension set + * + * @param key dimension key + * @param value dimension value + * @return this dimension set for chaining + * @throws IllegalArgumentException if key or value is invalid + * @throws IllegalStateException if adding would exceed the maximum number of dimensions + */ + public DimensionSet addDimension(String key, String value) { + validateDimension(key, value); + + if (dimensions.size() >= MAX_DIMENSION_SET_SIZE) { + throw new IllegalStateException( + "Cannot exceed " + MAX_DIMENSION_SET_SIZE + " dimensions per dimension set"); + } + + dimensions.put(key, value); + return this; + } + + /** + * Get the dimension keys in this dimension set + * + * @return set of dimension keys + */ + public Set getDimensionKeys() { + return dimensions.keySet(); + } + + /** + * Get the value for a dimension key + * + * @param key dimension key + * @return dimension value or null if not found + */ + public String getDimensionValue(String key) { + return dimensions.get(key); + } + + /** + * Get the dimensions as a map. Creates a shallow copy + * + * @return map of dimensions + */ + public Map getDimensions() { + return new LinkedHashMap<>(dimensions); + } + + private void validateDimension(String key, String value) { + Validator.validateDimension(key, value); + } +} diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/ValidationException.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/MetricResolution.java similarity index 66% rename from powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/ValidationException.java rename to powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/MetricResolution.java index a553abbbd..db514c8b7 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/ValidationException.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/MetricResolution.java @@ -12,11 +12,21 @@ * */ -package software.amazon.lambda.powertools.metrics; +package software.amazon.lambda.powertools.metrics.model; -public class ValidationException extends RuntimeException { +/** + * Resolution for metrics + */ +public enum MetricResolution { + STANDARD(60), HIGH(1); + + private final int seconds; + + MetricResolution(int seconds) { + this.seconds = seconds; + } - public ValidationException(String message) { - super(message); + public int getSeconds() { + return seconds; } } diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/MetricUnit.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/MetricUnit.java new file mode 100644 index 000000000..445d950b2 --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/model/MetricUnit.java @@ -0,0 +1,58 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.model; + +/** + * Metric units supported by CloudWatch + */ +public enum MetricUnit { + SECONDS("Seconds"), + MICROSECONDS("Microseconds"), + MILLISECONDS("Milliseconds"), + BYTES("Bytes"), + KILOBYTES("Kilobytes"), + MEGABYTES("Megabytes"), + GIGABYTES("Gigabytes"), + TERABYTES("Terabytes"), + BITS("Bits"), + KILOBITS("Kilobits"), + MEGABITS("Megabits"), + GIGABITS("Gigabits"), + TERABITS("Terabits"), + PERCENT("Percent"), + COUNT("Count"), + BYTES_SECOND("Bytes/Second"), + KILOBYTES_SECOND("Kilobytes/Second"), + MEGABYTES_SECOND("Megabytes/Second"), + GIGABYTES_SECOND("Gigabytes/Second"), + TERABYTES_SECOND("Terabytes/Second"), + BITS_SECOND("Bits/Second"), + KILOBITS_SECOND("Kilobits/Second"), + MEGABITS_SECOND("Megabits/Second"), + GIGABITS_SECOND("Gigabits/Second"), + TERABITS_SECOND("Terabits/Second"), + COUNT_SECOND("Count/Second"), + NONE("None"); + + private final String name; + + MetricUnit(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/provider/EmfMetricsProvider.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/provider/EmfMetricsProvider.java new file mode 100644 index 000000000..12c99b18f --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/provider/EmfMetricsProvider.java @@ -0,0 +1,31 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.provider; + +import software.amazon.cloudwatchlogs.emf.environment.EnvironmentProvider; +import software.amazon.cloudwatchlogs.emf.model.MetricsContext; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.internal.EmfMetricsLogger; + +/** + * Provider implementation for EMF metrics + */ +public class EmfMetricsProvider implements MetricsProvider { + + @Override + public Metrics getMetricsInstance() { + return new EmfMetricsLogger(new EnvironmentProvider(), new MetricsContext()); + } +} diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/provider/MetricsProvider.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/provider/MetricsProvider.java new file mode 100644 index 000000000..e6c79e000 --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/provider/MetricsProvider.java @@ -0,0 +1,30 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.provider; + +import software.amazon.lambda.powertools.metrics.Metrics; + +/** + * Interface for metrics provider implementations + */ +public interface MetricsProvider { + + /** + * Get a new instance of a metrics implementation + * + * @return a new metrics instance + */ + Metrics getMetricsInstance(); +} diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/jni-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/jni-config.json index 8ea90d67f..75ee9e5f5 100644 --- a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/jni-config.json +++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/jni-config.json @@ -1,22 +1,33 @@ [ -{ - "name":"java.lang.String", - "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] -}, -{ - "name":"java.lang.System", - "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] -}, -{ - "name":"org.apache.maven.surefire.booter.ForkedBooter", - "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] -}, -{ - "name":"sun.instrument.InstrumentationImpl", - "methods":[{"name":"","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] -}, -{ - "name":"sun.management.VMManagementImpl", - "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] -} + { + "name": "java.lang.Boolean", + "methods": [{ "name": "getBoolean", "parameterTypes": ["java.lang.String"] }] + }, + { + "name": "java.lang.String", + "methods": [ + { "name": "lastIndexOf", "parameterTypes": ["int"] }, + { "name": "substring", "parameterTypes": ["int"] } + ] + }, + { + "name": "java.lang.System", + "methods": [ + { "name": "getProperty", "parameterTypes": ["java.lang.String"] }, + { "name": "setProperty", "parameterTypes": ["java.lang.String", "java.lang.String"] } + ] + }, + { + "name": "sun.management.VMManagementImpl", + "fields": [ + { "name": "compTimeMonitoringSupport" }, + { "name": "currentThreadCpuTimeSupport" }, + { "name": "objectMonitorUsageSupport" }, + { "name": "otherThreadCpuTimeSupport" }, + { "name": "remoteDiagnosticCommandsSupport" }, + { "name": "synchronizerUsageSupport" }, + { "name": "threadAllocatedMemorySupport" }, + { "name": "threadContentionMonitoringSupport" } + ] + } ] diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json index bf67fc97b..43b2822d6 100644 --- a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json +++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json @@ -1,285 +1,152 @@ [ -{ - "name":"com.amazonaws.services.lambda.runtime.Context", - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] -}, -{ - "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"com.sun.tools.attach.VirtualMachine" -}, -{ - "name":"java.io.InputStream" -}, -{ - "name":"java.io.OutputStream" -}, -{ - "name":"java.io.Serializable", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true -}, -{ - "name":"java.lang.Class", - "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] -}, -{ - "name":"java.lang.ClassLoader", - "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] -}, -{ - "name":"java.lang.Comparable", - "queryAllDeclaredMethods":true -}, -{ - "name":"java.lang.Double", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true -}, -{ - "name":"java.lang.Module", - "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] -}, -{ - "name":"java.lang.Number", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true -}, -{ - "name":"java.lang.Object", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] -}, -{ - "name":"java.lang.ProcessEnvironment", - "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] -}, -{ - "name":"java.lang.ProcessHandle", - "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] -}, -{ - "name":"java.lang.Runtime", - "methods":[{"name":"version","parameterTypes":[] }] -}, -{ - "name":"java.lang.Runtime$Version", - "methods":[{"name":"feature","parameterTypes":[] }] -}, -{ - "name":"java.lang.StackWalker" -}, -{ - "name":"java.lang.System", - "methods":[{"name":"getSecurityManager","parameterTypes":[] }] -}, -{ - "name":"java.lang.annotation.Retention", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true -}, -{ - "name":"java.lang.annotation.Target", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true -}, -{ - "name":"java.lang.constant.Constable", - "queryAllDeclaredMethods":true -}, -{ - "name":"java.lang.constant.ConstantDesc", - "queryAllDeclaredMethods":true -}, -{ - "name":"java.lang.invoke.MethodHandle", - "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] -}, -{ - "name":"java.lang.invoke.MethodHandles", - "methods":[{"name":"lookup","parameterTypes":[] }] -}, -{ - "name":"java.lang.invoke.MethodHandles$Lookup", - "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] -}, -{ - "name":"java.lang.invoke.MethodType", - "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] -}, -{ - "name":"java.lang.reflect.AccessibleObject", - "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] -}, -{ - "name":"java.lang.reflect.AnnotatedArrayType", - "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.AnnotatedType", - "methods":[{"name":"getType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.Executable", - "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.Method", - "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.Parameter", - "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] -}, -{ - "name":"java.security.AccessController", - "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] -}, -{ - "name":"java.util.Collections$UnmodifiableMap", - "fields":[{"name":"m"}] -}, -{ - "name":"java.util.concurrent.ForkJoinTask", - "fields":[{"name":"aux"}, {"name":"status"}] -}, -{ - "name":"java.util.concurrent.atomic.AtomicBoolean", - "fields":[{"name":"value"}] -}, -{ - "name":"java.util.concurrent.atomic.AtomicReference", - "fields":[{"name":"value"}] -}, -{ - "name":"jdk.internal.misc.Unsafe" -}, -{ - "name":"kotlin.jvm.JvmInline" -}, -{ - "name":"org.apiguardian.api.API", - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.cloudwatchlogs.emf.logger.MetricsLogger", - "fields":[{"name":"context"}] -}, -{ - "name":"software.amazon.cloudwatchlogs.emf.model.Metadata", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"getCloudWatchMetrics","parameterTypes":[] }, {"name":"getCustomMetadata","parameterTypes":[] }, {"name":"getTimestamp","parameterTypes":[] }] -}, -{ - "name":"software.amazon.cloudwatchlogs.emf.model.MetricDefinition", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"getName","parameterTypes":[] }, {"name":"getStorageResolution","parameterTypes":[] }, {"name":"getUnit","parameterTypes":[] }] -}, -{ - "name":"software.amazon.cloudwatchlogs.emf.model.MetricDirective", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"getAllDimensionKeys","parameterTypes":[] }, {"name":"getAllMetrics","parameterTypes":[] }, {"name":"getNamespace","parameterTypes":[] }] -}, -{ - "name":"software.amazon.cloudwatchlogs.emf.model.RootNode", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"getAws","parameterTypes":[] }, {"name":"getTargetMembers","parameterTypes":[] }] -}, -{ - "name":"software.amazon.cloudwatchlogs.emf.serializers.InstantSerializer", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"software.amazon.cloudwatchlogs.emf.serializers.StorageResolutionFilter", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"software.amazon.cloudwatchlogs.emf.serializers.StorageResolutionSerializer", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"software.amazon.cloudwatchlogs.emf.serializers.UnitSerializer", - "methods":[{"name":"","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", - "fields":[{"name":"IS_COLD_START"}] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.MetricsLoggerTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":[] }, {"name":"metricsLoggerCaptureUtilityWithDefaultNameSpace","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"shouldUseTraceIdFromSystemPropertyIfEnvVarNotPresent","parameterTypes":[] }, {"name":"singleMetricsCaptureUtility","parameterTypes":[] }, {"name":"singleMetricsCaptureUtilityWithDefaultDimension","parameterTypes":[] }, {"name":"singleMetricsCaptureUtilityWithDefaultNameSpace","parameterTypes":[] }, {"name":"singleMetricsCaptureUtilityWithNullNamespace","parameterTypes":[] }, {"name":"tearDown","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsColdStartEnabledHandler", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledDefaultDimensionHandler", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledDefaultNoDimensionHandler", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledHandler", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledStreamHandler", - "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsExceptionWhenNoMetricsHandler", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsNoDimensionsHandler", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsNoExceptionWhenNoMetricsHandler", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsTooManyDimensionsHandler", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsWithExceptionInHandler", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":[] }, {"name":"allowWhenNoDimensionsSet","parameterTypes":[] }, {"name":"exceptionWhenNoMetricsEmitted","parameterTypes":[] }, {"name":"exceptionWhenTooManyDimensionsSet","parameterTypes":[] }, {"name":"metricsPublishedEvenHandlerThrowsException","parameterTypes":[] }, {"name":"metricsWithColdStart","parameterTypes":[] }, {"name":"metricsWithDefaultDimensionSpecified","parameterTypes":[] }, {"name":"metricsWithDefaultNoDimensionSpecified","parameterTypes":[] }, {"name":"metricsWithStreamHandler","parameterTypes":[] }, {"name":"metricsWithoutColdStart","parameterTypes":[] }, {"name":"noColdStartMetricsWhenColdStartDone","parameterTypes":[] }, {"name":"noExceptionWhenNoMetricsEmitted","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"tearDown","parameterTypes":[] }] -}, -{ - "name":"sun.reflect.ReflectionFactory", - "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] -} + { + "name": "com.amazonaws.services.lambda.runtime.Context", + "allDeclaredClasses": true, + "queryAllPublicMethods": true + }, + { + "name": "com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "java.io.Serializable", + "queryAllDeclaredMethods": true + }, + { + "name": "java.lang.Comparable", + "queryAllDeclaredMethods": true + }, + { + "name": "java.lang.Double", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "queryAllDeclaredConstructors": true + }, + { + "name": "java.lang.Number", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true + }, + { + "name": "java.lang.ProcessEnvironment", + "fields": [{ "name": "theCaseInsensitiveEnvironment" }, { "name": "theEnvironment" }] + }, + { + "name": "java.lang.String" + }, + { + "name": "java.lang.constant.Constable", + "queryAllDeclaredMethods": true + }, + { + "name": "java.lang.constant.ConstantDesc", + "queryAllDeclaredMethods": true + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "java.util.Map" + }, + { + "name": "java.util.concurrent.atomic.AtomicBoolean", + "fields": [{ "name": "value" }] + }, + { + "name": "java.util.concurrent.atomic.AtomicReference", + "fields": [{ "name": "value" }] + }, + { + "name": "java.util.function.Consumer", + "queryAllPublicMethods": true + }, + { + "name": "org.apiguardian.api.API", + "queryAllPublicMethods": true + }, + { + "name": "software.amazon.cloudwatchlogs.emf.model.Metadata", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "queryAllDeclaredConstructors": true, + "methods": [ + { "name": "getCloudWatchMetrics", "parameterTypes": [] }, + { "name": "getCustomMetadata", "parameterTypes": [] }, + { "name": "getTimestamp", "parameterTypes": [] } + ] + }, + { + "name": "software.amazon.cloudwatchlogs.emf.model.MetricDefinition", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "queryAllDeclaredConstructors": true, + "methods": [ + { "name": "getName", "parameterTypes": [] }, + { "name": "getStorageResolution", "parameterTypes": [] }, + { "name": "getUnit", "parameterTypes": [] } + ] + }, + { + "name": "software.amazon.cloudwatchlogs.emf.model.MetricDirective", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "queryAllDeclaredConstructors": true, + "methods": [ + { "name": "getAllDimensionKeys", "parameterTypes": [] }, + { "name": "getAllMetrics", "parameterTypes": [] }, + { "name": "getNamespace", "parameterTypes": [] } + ] + }, + { + "name": "software.amazon.cloudwatchlogs.emf.model.RootNode", + "allDeclaredFields": true, + "queryAllDeclaredMethods": true, + "queryAllDeclaredConstructors": true, + "methods": [ + { "name": "getAws", "parameterTypes": [] }, + { "name": "getTargetMembers", "parameterTypes": [] } + ] + }, + { + "name": "software.amazon.cloudwatchlogs.emf.serializers.InstantSerializer", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "software.amazon.cloudwatchlogs.emf.serializers.StorageResolutionFilter", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "software.amazon.cloudwatchlogs.emf.serializers.StorageResolutionSerializer", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "software.amazon.cloudwatchlogs.emf.serializers.UnitSerializer", + "methods": [{ "name": "", "parameterTypes": [] }] + }, + { + "name": "software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", + "fields": [{ "name": "IS_COLD_START" }], + "methods": [{ "name": "resetServiceName", "parameterTypes": [] }] + }, + { + "name": "software.amazon.lambda.powertools.metrics.Metrics", + "allDeclaredClasses": true, + "queryAllPublicMethods": true + }, + { + "name": "software.amazon.lambda.powertools.metrics.MetricsFactory", + "fields": [{ "name": "metrics" }, { "name": "provider" }] + }, + { + "name": "software.amazon.lambda.powertools.metrics.internal.EmfMetricsLogger", + "methods": [ + { "name": "convertUnit", "parameterTypes": ["software.amazon.lambda.powertools.metrics.model.MetricUnit"] } + ] + }, + { + "name": "software.amazon.lambda.powertools.metrics.provider.MetricsProvider", + "allDeclaredClasses": true, + "queryAllPublicMethods": true + } ] diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json index dd8fabec3..d47298855 100644 --- a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json +++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json @@ -1,19 +1,13 @@ { - "resources":{ - "includes":[{ - "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" - }, { - "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" - }, { - "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" - }, { - "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" - }, { - "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" - }, { - "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" - }, { - "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" - }]}, - "bundles":[] + "resources": { + "includes": [ + { + "pattern": "\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, + { + "pattern": "\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + } + ] + }, + "bundles": [] } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java new file mode 100644 index 000000000..1bf3b6a69 --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java @@ -0,0 +1,206 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetEnvironmentVariable; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; +import software.amazon.lambda.powertools.metrics.testutils.TestContext; + +/** + * Tests to verify the hierarchy of precedence for configuration: + * 1. @FlushMetrics annotation + * 2. MetricsBuilder + * 3. Environment variables + */ +class ConfigurationPrecedenceTest { + + private final PrintStream standardOut = System.out; + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + private final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp() throws Exception { + System.setOut(new PrintStream(outputStreamCaptor)); + + // Reset LambdaHandlerProcessor's SERVICE_NAME + Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); + resetServiceName.setAccessible(true); + resetServiceName.invoke(null); + + // Reset IS_COLD_START + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + coldStartField.setAccessible(true); + coldStartField.set(null, null); + } + + @AfterEach + void tearDown() throws Exception { + System.setOut(standardOut); + + // Reset the singleton state between tests + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + field.setAccessible(true); + field.set(null, null); + + field = MetricsFactory.class.getDeclaredField("provider"); + field.setAccessible(true); + field.set(null, new software.amazon.lambda.powertools.metrics.provider.EmfMetricsProvider()); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "EnvNamespace") + @SetEnvironmentVariable(key = "POWERTOOLS_SERVICE_NAME", value = "EnvService") + void annotationShouldOverrideBuilderAndEnvironment() throws Exception { + // Given + // Configure with builder first + MetricsBuilder.builder() + .withNamespace("BuilderNamespace") + .withService("BuilderService") + .build(); + + RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + // Annotation values should take precedence + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("AnnotationNamespace"); + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("AnnotationService"); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "EnvNamespace") + @SetEnvironmentVariable(key = "POWERTOOLS_SERVICE_NAME", value = "EnvService") + void builderShouldOverrideEnvironment() throws Exception { + // Given + // Configure with builder + MetricsBuilder.builder() + .withNamespace("BuilderNamespace") + .withService("BuilderService") + .build(); + + RequestHandler, String> handler = new HandlerWithDefaultMetricsAnnotation(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + // Builder values should take precedence over environment variables + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("BuilderNamespace"); + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("BuilderService"); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "EnvNamespace") + @SetEnvironmentVariable(key = "POWERTOOLS_SERVICE_NAME", value = "EnvService") + void environmentVariablesShouldBeUsedWhenNoOverrides() throws Exception { + // Given + RequestHandler, String> handler = new HandlerWithDefaultMetricsAnnotation(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + // Environment variable values should be used + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("EnvNamespace"); + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("EnvService"); + } + + @Test + void shouldUseDefaultsWhenNoConfiguration() throws Exception { + // Given + MetricsBuilder.builder() + .withNamespace("TestNamespace") + .build(); + + RequestHandler, String> handler = new HandlerWithDefaultMetricsAnnotation(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + // Default values should be used + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("TestNamespace"); + // Service dimension should not be present when service is undefined + assertThat(rootNode.has("Service")).isFalse(); + } + + private static class HandlerWithMetricsAnnotation implements RequestHandler, String> { + @Override + @FlushMetrics(namespace = "AnnotationNamespace", service = "AnnotationService") + public String handleRequest(Map input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + return "OK"; + } + } + + private static class HandlerWithDefaultMetricsAnnotation implements RequestHandler, String> { + @Override + @FlushMetrics + public String handleRequest(Map input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + return "OK"; + } + } + +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsBuilderTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsBuilderTest.java new file mode 100644 index 000000000..bd300fb6b --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsBuilderTest.java @@ -0,0 +1,186 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; +import software.amazon.lambda.powertools.metrics.provider.MetricsProvider; +import software.amazon.lambda.powertools.metrics.testutils.TestMetrics; +import software.amazon.lambda.powertools.metrics.testutils.TestMetricsProvider; + +class MetricsBuilderTest { + + private final PrintStream standardOut = System.out; + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + private final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp() { + System.setOut(new PrintStream(outputStreamCaptor)); + } + + @AfterEach + void tearDown() throws Exception { + System.setOut(standardOut); + + // Reset the singleton state between tests + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + field.setAccessible(true); + field.set(null, null); + + field = MetricsFactory.class.getDeclaredField("provider"); + field.setAccessible(true); + field.set(null, new software.amazon.lambda.powertools.metrics.provider.EmfMetricsProvider()); + } + + @Test + void shouldBuildWithCustomNamespace() throws Exception { + // When + Metrics metrics = MetricsBuilder.builder() + .withNamespace("CustomNamespace") + .build(); + + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("CustomNamespace"); + } + + @Test + void shouldBuildWithCustomService() throws Exception { + // When + Metrics metrics = MetricsBuilder.builder() + .withService("CustomService") + .withNamespace("TestNamespace") + .build(); + + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("CustomService"); + } + + @Test + void shouldBuildWithRaiseOnEmptyMetrics() { + // When + Metrics metrics = MetricsBuilder.builder() + .withRaiseOnEmptyMetrics(true) + .withNamespace("TestNamespace") + .build(); + + // Then + assertThat(metrics).isNotNull(); + assertThatThrownBy(metrics::flush) + .isInstanceOf(IllegalStateException.class) + .hasMessage("No metrics were emitted"); + } + + @Test + void shouldBuildWithDefaultDimension() throws Exception { + // When + Metrics metrics = MetricsBuilder.builder() + .withDefaultDimension("Environment", "Test") + .withNamespace("TestNamespace") + .build(); + + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("Environment")).isTrue(); + assertThat(rootNode.get("Environment").asText()).isEqualTo("Test"); + } + + @Test + void shouldBuildWithMultipleDefaultDimensions() throws Exception { + // When + Metrics metrics = MetricsBuilder.builder() + .withDefaultDimensions(DimensionSet.of("Environment", "Test", "Region", "us-west-2")) + .withNamespace("TestNamespace") + .build(); + + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("Environment")).isTrue(); + assertThat(rootNode.get("Environment").asText()).isEqualTo("Test"); + assertThat(rootNode.has("Region")).isTrue(); + assertThat(rootNode.get("Region").asText()).isEqualTo("us-west-2"); + } + + @Test + void shouldBuildWithCustomMetricsProvider() { + // Given + MetricsProvider testProvider = new TestMetricsProvider(); + + // When + Metrics metrics = MetricsBuilder.builder() + .withMetricsProvider(testProvider) + .build(); + + // Then + assertThat(metrics).isInstanceOf(TestMetrics.class); + } + + @Test + void shouldOverrideServiceWithDefaultDimensions() throws Exception { + // When + Metrics metrics = MetricsBuilder.builder() + .withService("OriginalService") + .withDefaultDimensions(DimensionSet.of("Service", "OverriddenService")) + .withNamespace("TestNamespace") + .build(); + + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("OverriddenService"); + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java new file mode 100644 index 000000000..962f2c2d7 --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java @@ -0,0 +1,166 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.Method; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetEnvironmentVariable; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; +import software.amazon.lambda.powertools.metrics.provider.MetricsProvider; +import software.amazon.lambda.powertools.metrics.testutils.TestMetrics; +import software.amazon.lambda.powertools.metrics.testutils.TestMetricsProvider; + +class MetricsFactoryTest { + + private static final String TEST_NAMESPACE = "TestNamespace"; + private static final String TEST_SERVICE = "TestService"; + + private final PrintStream standardOut = System.out; + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + private final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp() throws Exception { + System.setOut(new PrintStream(outputStreamCaptor)); + + // Reset LambdaHandlerProcessor's SERVICE_NAME + Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); + resetServiceName.setAccessible(true); + resetServiceName.invoke(null); + + // Reset IS_COLD_START + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + coldStartField.setAccessible(true); + coldStartField.set(null, null); + } + + @AfterEach + void tearDown() throws Exception { + System.setOut(standardOut); + + // Reset the singleton state between tests + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + field.setAccessible(true); + field.set(null, null); + + field = MetricsFactory.class.getDeclaredField("provider"); + field.setAccessible(true); + field.set(null, new software.amazon.lambda.powertools.metrics.provider.EmfMetricsProvider()); + } + + @Test + void shouldGetMetricsInstance() { + // When + Metrics metrics = MetricsFactory.getMetricsInstance(); + + // Then + assertThat(metrics).isNotNull(); + } + + @Test + void shouldReturnSameInstanceOnMultipleCalls() { + // When + Metrics firstInstance = MetricsFactory.getMetricsInstance(); + Metrics secondInstance = MetricsFactory.getMetricsInstance(); + + // Then + assertThat(firstInstance).isSameAs(secondInstance); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = TEST_NAMESPACE) + void shouldUseNamespaceFromEnvironmentVariable() throws Exception { + // When + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo(TEST_NAMESPACE); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_SERVICE_NAME", value = TEST_SERVICE) + void shouldUseServiceNameFromEnvironmentVariable() throws Exception { + // When + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.setNamespace("TestNamespace"); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo(TEST_SERVICE); + } + + @Test + void shouldSetCustomMetricsProvider() { + // Given + MetricsProvider testProvider = new TestMetricsProvider(); + + // When + MetricsFactory.setMetricsProvider(testProvider); + Metrics metrics = MetricsFactory.getMetricsInstance(); + + // Then + assertThat(metrics).isInstanceOf(TestMetrics.class); + } + + @Test + void shouldThrowExceptionWhenSettingNullProvider() { + // When/Then + assertThatThrownBy(() -> MetricsFactory.setMetricsProvider(null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Metrics provider cannot be null"); + } + + @Test + void shouldNotSetServiceDimensionWhenServiceUndefined() throws Exception { + // Given - no POWERTOOLS_SERVICE_NAME set, so it will use the default undefined value + + // When + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.setNamespace("TestNamespace"); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + // Service dimension should not be present + assertThat(rootNode.has("Service")).isFalse(); + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java deleted file mode 100644 index 5f99c950a..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsLoggerTest.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics; - -import static java.util.Collections.emptyMap; -import static org.assertj.core.api.Assertions.assertThat; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.Consumer; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junitpioneer.jupiter.SetEnvironmentVariable; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.StorageResolution; -import software.amazon.cloudwatchlogs.emf.model.Unit; - -@SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") -class MetricsLoggerTest { - - private final ByteArrayOutputStream out = new ByteArrayOutputStream(); - private final PrintStream originalOut = System.out; - private final ObjectMapper mapper = new ObjectMapper(); - - @BeforeEach - void setUp() { - System.setOut(new PrintStream(out)); - } - - @AfterEach - void tearDown() { - System.setOut(originalOut); - } - - @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") - void singleMetricsCaptureUtilityWithDefaultDimension() { - MetricsUtils.defaultDimensions(DimensionSet.of("Service", "Booking")); - - MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, "test", - metricsLogger -> - { - }); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "Booking") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); - }); - } - - @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") - void singleMetricsCaptureUtility() { - MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, "test", - metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Dimension1", "Value1") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=test"); - }); - } - - @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - void singleMetricsCaptureUtilityWithNullNamespace() { - // POWERTOOLS_METRICS_NAMESPACE is not defined - - MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, - metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=aws-embedded-metrics"); - }); - } - - @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "GlobalName") - @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") - void singleMetricsCaptureUtilityWithDefaultNameSpace() { - MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, - metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Dimension1", "Value1") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=GlobalName"); - }); - } - - @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "GlobalName") - @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") - void metricsLoggerCaptureUtilityWithDefaultNameSpace() { - testLogger(MetricsUtils::withMetricsLogger); - } - - @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "GlobalName") - @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") - void shouldUseTraceIdFromSystemPropertyIfEnvVarNotPresent() { - MetricsUtils.withSingleMetric("Metric1", 1, Unit.COUNT, - metricsLogger -> metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1"))); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Dimension1", "Value1") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=GlobalName"); - }); - } - - private void testLogger(Consumer> methodToTest) { - methodToTest.accept(metricsLogger -> - { - metricsLogger.setDimensions(DimensionSet.of("Dimension1", "Value1")); - metricsLogger.putMetric("Metric1", 1, Unit.COUNT); - metricsLogger.putMetric("Metric2", 1, Unit.COUNT, StorageResolution.HIGH); - }); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Dimension1", "Value1") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=GlobalName"); - - ArrayList cloudWatchMetrics = (ArrayList) aws.get("CloudWatchMetrics"); - LinkedHashMap values = - (java.util.LinkedHashMap) cloudWatchMetrics.get(0); - ArrayList metricArray = (ArrayList) values.get("Metrics"); - LinkedHashMap metricValues = (LinkedHashMap) metricArray.get(1); - assertThat(metricValues).containsEntry("StorageResolution", 1); - }); - } - - private Map readAsJson(String s) { - try { - return mapper.readValue(s, Map.class); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - return emptyMap(); - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsColdStartEnabledHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsColdStartEnabledHandler.java deleted file mode 100644 index e3a0fa22e..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsColdStartEnabledHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics.handlers; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.Unit; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class PowertoolsMetricsColdStartEnabledHandler implements RequestHandler { - - @Override - @Metrics(namespace = "ExampleApplication", service = "booking", captureColdStart = true) - public Object handleRequest(Object input, Context context) { - MetricsLogger metricsLogger = metricsLogger(); - metricsLogger.putMetric("Metric1", 1, Unit.BYTES); - - return null; - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java deleted file mode 100644 index 761c20caa..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultDimensionHandler.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics.handlers; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.defaultDimensions; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.Unit; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class PowertoolsMetricsEnabledDefaultDimensionHandler implements RequestHandler { - - static { - defaultDimensions(DimensionSet.of("CustomDimension", "booking")); - } - - @Override - @Metrics(namespace = "ExampleApplication", service = "booking") - public Object handleRequest(Object input, Context context) { - MetricsLogger metricsLogger = metricsLogger(); - metricsLogger.putMetric("Metric1", 1, Unit.BYTES); - - withSingleMetric("Metric2", 1, Unit.COUNT, log -> - { - }); - - return null; - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java deleted file mode 100644 index d968f94f5..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledDefaultNoDimensionHandler.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics.handlers; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.Unit; -import software.amazon.lambda.powertools.metrics.Metrics; -import software.amazon.lambda.powertools.metrics.MetricsUtils; - -public class PowertoolsMetricsEnabledDefaultNoDimensionHandler implements RequestHandler { - - static { - MetricsUtils.defaultDimensions(); - } - - @Override - @Metrics(namespace = "ExampleApplication", service = "booking") - public Object handleRequest(Object input, Context context) { - MetricsLogger metricsLogger = metricsLogger(); - metricsLogger.putMetric("Metric1", 1, Unit.BYTES); - - withSingleMetric("Metric2", 1, Unit.COUNT, log -> - { - }); - - return null; - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledHandler.java deleted file mode 100644 index 7cfee533d..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics.handlers; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; -import static software.amazon.lambda.powertools.metrics.MetricsUtils.withSingleMetric; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.cloudwatchlogs.emf.model.Unit; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class PowertoolsMetricsEnabledHandler implements RequestHandler { - - @Override - @Metrics(namespace = "ExampleApplication", service = "booking") - public Object handleRequest(Object input, Context context) { - MetricsLogger metricsLogger = metricsLogger(); - metricsLogger.putMetric("Metric1", 1, Unit.BYTES); - - - withSingleMetric("Metric2", 1, Unit.COUNT, - log -> log.setDimensions(DimensionSet.of("Dimension1", "Value1"))); - - return null; - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledStreamHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledStreamHandler.java deleted file mode 100644 index 1600f4a64..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsEnabledStreamHandler.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics.handlers; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import java.io.InputStream; -import java.io.OutputStream; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.Unit; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class PowertoolsMetricsEnabledStreamHandler implements RequestStreamHandler { - - @Override - @Metrics(namespace = "ExampleApplication", service = "booking") - public void handleRequest(InputStream input, OutputStream output, Context context) { - MetricsLogger metricsLogger = metricsLogger(); - metricsLogger.putMetric("Metric1", 1, Unit.BYTES); - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsExceptionWhenNoMetricsHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsExceptionWhenNoMetricsHandler.java deleted file mode 100644 index 42e0b3ad4..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsExceptionWhenNoMetricsHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics.handlers; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class PowertoolsMetricsExceptionWhenNoMetricsHandler implements RequestHandler { - - @Override - @Metrics(namespace = "ExampleApplication", service = "booking", raiseOnEmptyMetrics = true) - public Object handleRequest(Object input, Context context) { - MetricsLogger metricsLogger = metricsLogger(); - metricsLogger.putMetadata("MetaData", "MetaDataValue"); - - return null; - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoDimensionsHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoDimensionsHandler.java deleted file mode 100644 index 04b02e166..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoDimensionsHandler.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics.handlers; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class PowertoolsMetricsNoDimensionsHandler implements RequestHandler { - - @Override - @Metrics(namespace = "ExampleApplication", service = "booking") - public Object handleRequest(Object input, Context context) { - MetricsLogger metricsLogger = metricsLogger(); - metricsLogger.putMetric("CoolMetric", 1); - metricsLogger.setDimensions(new DimensionSet()); - - return null; - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoExceptionWhenNoMetricsHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoExceptionWhenNoMetricsHandler.java deleted file mode 100644 index c08ce2f86..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsNoExceptionWhenNoMetricsHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics.handlers; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class PowertoolsMetricsNoExceptionWhenNoMetricsHandler implements RequestHandler { - - @Override - @Metrics(namespace = "ExampleApplication", service = "booking") - public Object handleRequest(Object input, Context context) { - MetricsLogger metricsLogger = metricsLogger(); - metricsLogger.putMetadata("MetaData", "MetaDataValue"); - - return null; - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java deleted file mode 100644 index fd406b9cd..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsTooManyDimensionsHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics.handlers; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import java.util.stream.IntStream; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.cloudwatchlogs.emf.model.DimensionSet; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class PowertoolsMetricsTooManyDimensionsHandler implements RequestHandler { - - @Override - @Metrics(namespace = "ExampleApplication",service = "booking") - public Object handleRequest(Object input, Context context) { - MetricsLogger metricsLogger = metricsLogger(); - DimensionSet dimensionSet = new DimensionSet(); - for (int i = 0; i < 35; i++) { - dimensionSet.addDimension("Dimension" + i, "value" + i); - } - metricsLogger.setDimensions(dimensionSet); - - return null; - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsWithExceptionInHandler.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsWithExceptionInHandler.java deleted file mode 100644 index da9028a70..000000000 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/handlers/PowertoolsMetricsWithExceptionInHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2023 Amazon.com, Inc. or its affiliates. - * Licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package software.amazon.lambda.powertools.metrics.handlers; - -import static software.amazon.lambda.powertools.metrics.MetricsUtils.metricsLogger; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; -import software.amazon.lambda.powertools.metrics.Metrics; - -public class PowertoolsMetricsWithExceptionInHandler implements RequestHandler { - - @Override - @Metrics(namespace = "ExampleApplication", service = "booking") - public Object handleRequest(Object input, Context context) { - MetricsLogger metricsLogger = metricsLogger(); - metricsLogger.putMetric("CoolMetric", 1); - throw new IllegalStateException("Whoops, unexpected exception"); - } -} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java new file mode 100644 index 000000000..1b7106ece --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java @@ -0,0 +1,521 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.PrintStream; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.time.Instant; +import java.util.stream.Stream; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junitpioneer.jupiter.SetEnvironmentVariable; + +import com.amazonaws.services.lambda.runtime.Context; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.cloudwatchlogs.emf.model.Unit; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricResolution; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; +import software.amazon.lambda.powertools.metrics.testutils.TestContext; + +class EmfMetricsLoggerTest { + + private Metrics metrics; + private final ObjectMapper objectMapper = new ObjectMapper(); + private final PrintStream standardOut = System.out; + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + + @BeforeEach + void setUp() throws Exception { + // Reset LambdaHandlerProcessor's SERVICE_NAME + Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); + resetServiceName.setAccessible(true); + resetServiceName.invoke(null); + + // Reset IS_COLD_START + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + coldStartField.setAccessible(true); + coldStartField.set(null, null); + + metrics = MetricsFactory.getMetricsInstance(); + metrics.setNamespace("TestNamespace"); + System.setOut(new PrintStream(outputStreamCaptor)); + } + + @AfterEach + void tearDown() throws Exception { + System.setOut(standardOut); + + // Reset the singleton state between tests + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + field.setAccessible(true); + field.set(null, null); + } + + @ParameterizedTest + @MethodSource("unitConversionTestCases") + void shouldConvertMetricUnits(MetricUnit inputUnit, Unit expectedUnit) throws Exception { + // Given + // We access using reflection here for simplicity (even though this is not best practice) + Method convertUnitMethod = EmfMetricsLogger.class.getDeclaredMethod("convertUnit", MetricUnit.class); + convertUnitMethod.setAccessible(true); + + // When + Unit actualUnit = (Unit) convertUnitMethod.invoke(metrics, inputUnit); + + // Then + assertThat(actualUnit).isEqualTo(expectedUnit); + } + + private static Stream unitConversionTestCases() { + return Stream.of( + Arguments.of(MetricUnit.SECONDS, Unit.SECONDS), + Arguments.of(MetricUnit.MICROSECONDS, Unit.MICROSECONDS), + Arguments.of(MetricUnit.MILLISECONDS, Unit.MILLISECONDS), + Arguments.of(MetricUnit.BYTES, Unit.BYTES), + Arguments.of(MetricUnit.KILOBYTES, Unit.KILOBYTES), + Arguments.of(MetricUnit.MEGABYTES, Unit.MEGABYTES), + Arguments.of(MetricUnit.GIGABYTES, Unit.GIGABYTES), + Arguments.of(MetricUnit.TERABYTES, Unit.TERABYTES), + Arguments.of(MetricUnit.BITS, Unit.BITS), + Arguments.of(MetricUnit.KILOBITS, Unit.KILOBITS), + Arguments.of(MetricUnit.MEGABITS, Unit.MEGABITS), + Arguments.of(MetricUnit.GIGABITS, Unit.GIGABITS), + Arguments.of(MetricUnit.TERABITS, Unit.TERABITS), + Arguments.of(MetricUnit.PERCENT, Unit.PERCENT), + Arguments.of(MetricUnit.COUNT, Unit.COUNT), + Arguments.of(MetricUnit.BYTES_SECOND, Unit.BYTES_SECOND), + Arguments.of(MetricUnit.KILOBYTES_SECOND, Unit.KILOBYTES_SECOND), + Arguments.of(MetricUnit.MEGABYTES_SECOND, Unit.MEGABYTES_SECOND), + Arguments.of(MetricUnit.GIGABYTES_SECOND, Unit.GIGABYTES_SECOND), + Arguments.of(MetricUnit.TERABYTES_SECOND, Unit.TERABYTES_SECOND), + Arguments.of(MetricUnit.BITS_SECOND, Unit.BITS_SECOND), + Arguments.of(MetricUnit.KILOBITS_SECOND, Unit.KILOBITS_SECOND), + Arguments.of(MetricUnit.MEGABITS_SECOND, Unit.MEGABITS_SECOND), + Arguments.of(MetricUnit.GIGABITS_SECOND, Unit.GIGABITS_SECOND), + Arguments.of(MetricUnit.TERABITS_SECOND, Unit.TERABITS_SECOND), + Arguments.of(MetricUnit.COUNT_SECOND, Unit.COUNT_SECOND), + Arguments.of(MetricUnit.NONE, Unit.NONE)); + } + + @Test + void shouldCreateMetricWithDefaultResolution() throws Exception { + // When + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("_aws")).isTrue(); + assertThat(rootNode.get("test-metric").asDouble()).isEqualTo(100); + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Metrics").get(0).get("Unit").asText()) + .isEqualTo("Count"); + } + + @Test + void shouldCreateMetricWithHighResolution() throws Exception { + // When + metrics.addMetric("test-metric", 100, MetricUnit.COUNT, MetricResolution.HIGH); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("_aws")).isTrue(); + assertThat(rootNode.get("test-metric").asDouble()).isEqualTo(100); + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Metrics").get(0).get("Unit").asText()) + .isEqualTo("Count"); + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Metrics").get(0).get("StorageResolution") + .asInt()).isEqualTo(1); + } + + @Test + void shouldAddDimension() throws Exception { + // When + metrics.clearDefaultDimensions(); // Clear default Service dimension first for easier assertions + metrics.addDimension("CustomDimension", "CustomValue"); + metrics.addMetric("test-metric", 100); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("CustomDimension")).isTrue(); + assertThat(rootNode.get("CustomDimension").asText()).isEqualTo("CustomValue"); + + // Check that the dimension is in the CloudWatchMetrics section + JsonNode dimensions = rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Dimensions").get(0); + boolean hasDimension = false; + for (JsonNode dimension : dimensions) { + if (dimension.asText().equals("CustomDimension")) { + hasDimension = true; + break; + } + } + assertThat(hasDimension).isTrue(); + } + + @Test + void shouldSetCustomTimestamp() throws Exception { + // Given + Instant customTimestamp = Instant.now(); + + // When + metrics.setTimestamp(customTimestamp); + metrics.addMetric("test-metric", 100); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("_aws")).isTrue(); + assertThat(rootNode.get("_aws").has("Timestamp")).isTrue(); + assertThat(rootNode.get("_aws").get("Timestamp").asLong()).isEqualTo(customTimestamp.toEpochMilli()); + } + + @Test + void shouldAddDimensionSet() throws Exception { + // Given + DimensionSet dimensionSet = DimensionSet.of("Dim1", "Value1", "Dim2", "Value2"); + + // When + metrics.clearDefaultDimensions(); // Clear default Service dimension first for easier assertions + metrics.addDimension(dimensionSet); + metrics.addMetric("test-metric", 100); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("Dim1")).isTrue(); + assertThat(rootNode.get("Dim1").asText()).isEqualTo("Value1"); + assertThat(rootNode.has("Dim2")).isTrue(); + assertThat(rootNode.get("Dim2").asText()).isEqualTo("Value2"); + + // Check that the dimensions are in the CloudWatchMetrics section + JsonNode dimensions = rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Dimensions").get(0); + boolean hasDim1 = false; + boolean hasDim2 = false; + for (JsonNode dimension : dimensions) { + String dimName = dimension.asText(); + if (dimName.equals("Dim1")) { + hasDim1 = true; + } else if (dimName.equals("Dim2")) { + hasDim2 = true; + } + } + assertThat(hasDim1).isTrue(); + assertThat(hasDim2).isTrue(); + } + + @Test + void shouldThrowExceptionWhenDimensionSetIsNull() { + // When/Then + assertThatThrownBy(() -> metrics.addDimension((DimensionSet) null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("DimensionSet cannot be null"); + } + + @Test + void shouldAddMetadata() throws Exception { + // When + metrics.addMetadata("CustomMetadata", "MetadataValue"); + metrics.addMetric("test-metric", 100); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + // The metadata is added to the _aws section in the EMF output + assertThat(rootNode.get("_aws").has("CustomMetadata")).isTrue(); + assertThat(rootNode.get("_aws").get("CustomMetadata").asText()).isEqualTo("MetadataValue"); + } + + @Test + void shouldSetDefaultDimensions() throws Exception { + // Given + DimensionSet dimensionSet = DimensionSet.of("Service", "TestService", "Environment", "Test"); + + // When + metrics.setDefaultDimensions(dimensionSet); + metrics.addMetric("test-metric", 100); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("TestService"); + assertThat(rootNode.has("Environment")).isTrue(); + assertThat(rootNode.get("Environment").asText()).isEqualTo("Test"); + } + + @Test + void shouldGetDefaultDimensions() { + // Given + DimensionSet dimensionSet = DimensionSet.of("Service", "TestService", "Environment", "Test"); + + // When + metrics.setDefaultDimensions(dimensionSet); + DimensionSet dimensions = metrics.getDefaultDimensions(); + + // Then + assertThat(dimensions.getDimensions()).containsEntry("Service", "TestService"); + assertThat(dimensions.getDimensions()).containsEntry("Environment", "Test"); + } + + @Test + void shouldThrowExceptionWhenDefaultDimensionSetIsNull() { + // When/Then + assertThatThrownBy(() -> metrics.setDefaultDimensions((DimensionSet) null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("DimensionSet cannot be null"); + } + + @Test + void shouldSetNamespace() throws Exception { + // When + metrics.setNamespace("CustomNamespace"); + metrics.addMetric("test-metric", 100); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("CustomNamespace"); + } + + @Test + void shouldRaiseExceptionOnEmptyMetrics() { + // When + metrics.setRaiseOnEmptyMetrics(true); + + // Then + assertThatThrownBy(() -> metrics.flush()) + .isInstanceOf(IllegalStateException.class) + .hasMessage("No metrics were emitted"); + } + + @Test + void shouldLogWarningOnEmptyMetrics() throws Exception { + // Given + File logFile = new File("target/metrics-test.log"); + + // When + // Flushing without adding metrics + metrics.flush(); + + // Then + // Read the log file and check for the warning + String logContent = new String(Files.readAllBytes(logFile.toPath()), StandardCharsets.UTF_8); + assertThat(logContent).contains("No metrics were emitted"); + } + + @Test + void shouldClearDefaultDimensions() throws Exception { + // Given + metrics.setDefaultDimensions(DimensionSet.of("Service", "TestService", "Environment", "Test")); + + // When + metrics.clearDefaultDimensions(); + metrics.addMetric("test-metric", 100); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("Service")).isFalse(); + assertThat(rootNode.has("Environment")).isFalse(); + } + + @Test + void shouldCaptureColdStartMetric() throws Exception { + // Given + Context testContext = new TestContext(); + + // When + metrics.captureColdStartMetric(testContext); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("ColdStart")).isTrue(); + assertThat(rootNode.get("ColdStart").asDouble()).isEqualTo(1.0); + assertThat(rootNode.has("function_request_id")).isTrue(); + assertThat(rootNode.get("function_request_id").asText()).isEqualTo(testContext.getAwsRequestId()); + } + + @Test + void shouldCaptureColdStartMetricWithDimensions() throws Exception { + // Given + DimensionSet dimensions = DimensionSet.of("CustomDim", "CustomValue"); + + // When + metrics.captureColdStartMetric(dimensions); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("ColdStart")).isTrue(); + assertThat(rootNode.get("ColdStart").asDouble()).isEqualTo(1.0); + assertThat(rootNode.has("CustomDim")).isTrue(); + assertThat(rootNode.get("CustomDim").asText()).isEqualTo("CustomValue"); + } + + @Test + void shouldCaptureColdStartMetricWithoutDimensions() throws Exception { + // When + metrics.captureColdStartMetric(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("ColdStart")).isTrue(); + assertThat(rootNode.get("ColdStart").asDouble()).isEqualTo(1.0); + } + + @Test + void shouldReuseNamespaceForColdStartMetric() throws Exception { + // Given + String customNamespace = "CustomNamespace"; + metrics.setNamespace(customNamespace); + + Context testContext = new TestContext(); + + DimensionSet dimensions = DimensionSet.of("CustomDim", "CustomValue"); + + // When + metrics.captureColdStartMetric(testContext, dimensions); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("ColdStart")).isTrue(); + assertThat(rootNode.get("ColdStart").asDouble()).isEqualTo(1.0); + assertThat(rootNode.has("CustomDim")).isTrue(); + assertThat(rootNode.get("CustomDim").asText()).isEqualTo("CustomValue"); + assertThat(rootNode.has("function_request_id")).isTrue(); + assertThat(rootNode.get("function_request_id").asText()).isEqualTo(testContext.getAwsRequestId()); + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo(customNamespace); + } + + @Test + void shouldFlushSingleMetric() throws Exception { + // Given + DimensionSet dimensions = DimensionSet.of("CustomDim", "CustomValue"); + + // When + metrics.flushSingleMetric("single-metric", 200, MetricUnit.COUNT, "SingleNamespace", dimensions); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("single-metric")).isTrue(); + assertThat(rootNode.get("single-metric").asDouble()).isEqualTo(200.0); + assertThat(rootNode.has("CustomDim")).isTrue(); + assertThat(rootNode.get("CustomDim").asText()).isEqualTo("CustomValue"); + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("SingleNamespace"); + } + + @Test + void shouldFlushSingleMetricWithoutDimensions() throws Exception { + // When + metrics.flushSingleMetric("single-metric", 200, MetricUnit.COUNT, "SingleNamespace"); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("single-metric")).isTrue(); + assertThat(rootNode.get("single-metric").asDouble()).isEqualTo(200.0); + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("SingleNamespace"); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_DISABLED", value = "true") + void shouldNotFlushMetricsWhenDisabled() { + // When + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + metrics.flush(); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + assertThat(emfOutput).isEmpty(); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_DISABLED", value = "true") + void shouldNotCaptureColdStartMetricWhenDisabled() { + // Given + Context testContext = new TestContext(); + + // When + metrics.captureColdStartMetric(testContext); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + assertThat(emfOutput).isEmpty(); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_DISABLED", value = "true") + void shouldNotFlushSingleMetricWhenDisabled() { + // Given + DimensionSet dimensions = DimensionSet.of("CustomDim", "CustomValue"); + + // When + metrics.flushSingleMetric("single-metric", 200, MetricUnit.COUNT, "SingleNamespace", dimensions); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + assertThat(emfOutput).isEmpty(); + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java index 5df6003c8..068d19ccb 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java @@ -14,371 +14,315 @@ package software.amazon.lambda.powertools.metrics.internal; -import static java.util.Collections.emptyMap; -import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.io.PrintStream; +import java.lang.reflect.Method; +import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.SetEnvironmentVariable; -import org.mockito.Mock; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import software.amazon.cloudwatchlogs.emf.exception.DimensionSetExceededException; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; -import software.amazon.lambda.powertools.metrics.MetricsUtils; -import software.amazon.lambda.powertools.metrics.ValidationException; -import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsColdStartEnabledHandler; -import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledDefaultDimensionHandler; -import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledDefaultNoDimensionHandler; -import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledHandler; -import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsEnabledStreamHandler; -import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsExceptionWhenNoMetricsHandler; -import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsNoDimensionsHandler; -import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsNoExceptionWhenNoMetricsHandler; -import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsTooManyDimensionsHandler; -import software.amazon.lambda.powertools.metrics.handlers.PowertoolsMetricsWithExceptionInHandler; - -@SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") -public class LambdaMetricsAspectTest { - private final ByteArrayOutputStream out = new ByteArrayOutputStream(); - private final PrintStream originalOut = System.out; - private final ObjectMapper mapper = new ObjectMapper(); - @Mock - private Context context; - private RequestHandler requestHandler; +import software.amazon.lambda.powertools.metrics.FlushMetrics; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; +import software.amazon.lambda.powertools.metrics.testutils.TestContext; + +class LambdaMetricsAspectTest { + + private final PrintStream standardOut = System.out; + private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + private final ObjectMapper objectMapper = new ObjectMapper(); @BeforeEach - void setUp() throws IllegalAccessException { - openMocks(this); - setupContext(); - writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - System.setOut(new PrintStream(out)); + void setUp() throws Exception { + System.setOut(new PrintStream(outputStreamCaptor)); + + // Reset LambdaHandlerProcessor's SERVICE_NAME + Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); + resetServiceName.setAccessible(true); + resetServiceName.invoke(null); + + // Reset IS_COLD_START + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + coldStartField.setAccessible(true); + coldStartField.set(null, null); } @AfterEach - void tearDown() { - System.setOut(originalOut); - } + void tearDown() throws Exception { + System.setOut(standardOut); - @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") - public void metricsWithoutColdStart() { - - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsEnabledHandler(); - requestHandler.handleRequest("input", context); - - assertThat(out.toString().split("\n")) - .hasSize(2) - .satisfies(s -> - { - Map logAsJson = readAsJson(s[0]); - - assertThat(logAsJson) - .containsEntry("Metric2", 1.0) - .containsEntry("Dimension1", "Value1") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793") - .containsEntry("function_request_id", "123ABC"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=ExampleApplication"); - - logAsJson = readAsJson(s[1]); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); + // Reset the singleton state between tests + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + field.setAccessible(true); + field.set(null, null); } @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") - public void metricsWithDefaultDimensionSpecified() { - requestHandler = new PowertoolsMetricsEnabledDefaultDimensionHandler(); - - requestHandler.handleRequest("input", context); - - assertThat(out.toString().split("\n")) - .hasSize(2) - .satisfies(s -> - { - Map logAsJson = readAsJson(s[0]); - - assertThat(logAsJson) - .containsEntry("Metric2", 1.0) - .containsEntry("CustomDimension", "booking") - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793") - .containsEntry("function_request_id", "123ABC"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=ExampleApplication"); - - logAsJson = readAsJson(s[1]); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("CustomDimension", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); + void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { + // Given + RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("test-metric")).isTrue(); + assertThat(rootNode.get("test-metric").asDouble()).isEqualTo(100.0); + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("CustomNamespace"); + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("CustomService"); } @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - @SetEnvironmentVariable(key = "_X_AMZN_TRACE_ID", value = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") - public void metricsWithDefaultNoDimensionSpecified() { - requestHandler = new PowertoolsMetricsEnabledDefaultNoDimensionHandler(); - - requestHandler.handleRequest("input", context); - - assertThat(out.toString().split("\n")) - .hasSize(2) - .satisfies(s -> - { - Map logAsJson = readAsJson(s[0]); - - assertThat(logAsJson) - .containsEntry("Metric2", 1.0) - .containsKey("_aws") - .containsEntry("xray_trace_id", "1-5759e988-bd862e3fe1be46a994272793") - .containsEntry("function_request_id", "123ABC"); - - Map aws = (Map) logAsJson.get("_aws"); - - assertThat(aws.get("CloudWatchMetrics")) - .asString() - .contains("Namespace=ExampleApplication"); - - logAsJson = readAsJson(s[1]); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "EnvNamespace") + @SetEnvironmentVariable(key = "POWERTOOLS_SERVICE_NAME", value = "EnvService") + void shouldOverrideEnvironmentVariablesWithAnnotation() throws Exception { + // Given + RequestHandler, String> handler = new HandlerWithMetricsAnnotation(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("CustomNamespace"); + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("CustomService"); } @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - public void metricsWithColdStart() { - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsColdStartEnabledHandler(); - - requestHandler.handleRequest("input", context); - - assertThat(out.toString().split("\n")) - .hasSize(2) - .satisfies(s -> - { - Map logAsJson = readAsJson(s[0]); - - assertThat(logAsJson) - .doesNotContainKey("Metric1") - .containsEntry("ColdStart", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - - logAsJson = readAsJson(s[1]); - - assertThat(logAsJson) - .doesNotContainKey("ColdStart") - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "EnvNamespace") + @SetEnvironmentVariable(key = "POWERTOOLS_SERVICE_NAME", value = "EnvService") + void shouldUseEnvironmentVariablesWhenNoAnnotationOverrides() throws Exception { + // Given + RequestHandler, String> handler = new HandlerWithDefaultMetricsAnnotation(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("EnvNamespace"); + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("EnvService"); } @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - public void noColdStartMetricsWhenColdStartDone() { - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsColdStartEnabledHandler(); - - requestHandler.handleRequest("input", context); - requestHandler.handleRequest("input", context); - - assertThat(out.toString().split("\n")) - .hasSize(3) - .satisfies(s -> - { - Map logAsJson = readAsJson(s[0]); - - assertThat(logAsJson) - .doesNotContainKey("Metric1") - .containsEntry("ColdStart", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - - logAsJson = readAsJson(s[1]); - - assertThat(logAsJson) - .doesNotContainKey("ColdStart") - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - - logAsJson = readAsJson(s[2]); - - assertThat(logAsJson) - .doesNotContainKey("ColdStart") - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); + void shouldCaptureColdStartMetricWhenConfigured() throws Exception { + // Given + RequestHandler, String> handler = new HandlerWithColdStartMetricsAnnotation(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + String[] emfOutputs = emfOutput.split("\\n"); + + // There should be two EMF outputs - one for cold start and one for the handler metrics + assertThat(emfOutputs).hasSize(2); + + JsonNode coldStartNode = objectMapper.readTree(emfOutputs[0]); + assertThat(coldStartNode.has("ColdStart")).isTrue(); + assertThat(coldStartNode.get("ColdStart").asDouble()).isEqualTo(1.0); + + JsonNode metricsNode = objectMapper.readTree(emfOutputs[1]); + assertThat(metricsNode.has("test-metric")).isTrue(); } @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - public void metricsWithStreamHandler() throws IOException { - MetricsUtils.defaultDimensions(null); - RequestStreamHandler streamHandler = new PowertoolsMetricsEnabledStreamHandler(); - - streamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), context); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Metric1", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_FUNCTION_NAME", value = "EnvFunctionName") + void shouldNotIncludeServiceDimensionInColdStartMetricWhenServiceUndefined() throws Exception { + // Given - no service name set, so it will use the default undefined value + RequestHandler, String> handler = new HandlerWithColdStartMetricsAnnotation(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + String[] emfOutputs = emfOutput.split("\\n"); + + // There should be two EMF outputs - one for cold start and one for the handler metrics + assertThat(emfOutputs).hasSize(2); + + JsonNode coldStartNode = objectMapper.readTree(emfOutputs[0]); + assertThat(coldStartNode.has("ColdStart")).isTrue(); + assertThat(coldStartNode.get("ColdStart").asDouble()).isEqualTo(1.0); + + // Service dimension should not be present in cold start metrics + assertThat(coldStartNode.has("Service")).isFalse(); + + // FunctionName dimension should be present + assertThat(coldStartNode.has("FunctionName")).isTrue(); + assertThat(coldStartNode.get("FunctionName").asText()).isEqualTo("EnvFunctionName"); } @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - public void exceptionWhenNoMetricsEmitted() { - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsExceptionWhenNoMetricsHandler(); - - assertThatExceptionOfType(ValidationException.class) - .isThrownBy(() -> requestHandler.handleRequest("input", context)) - .withMessage("No metrics captured, at least one metrics must be emitted"); + void shouldUseCustomFunctionNameWhenProvidedForColdStartMetric() throws Exception { + // Given + RequestHandler, String> handler = new HandlerWithCustomFunctionName(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + String[] emfOutputs = emfOutput.split("\\n"); + + // There should be two EMF outputs - one for cold start and one for the handler metrics + assertThat(emfOutputs).hasSize(2); + + JsonNode coldStartNode = objectMapper.readTree(emfOutputs[0]); + assertThat(coldStartNode.has("FunctionName")).isTrue(); + assertThat(coldStartNode.get("FunctionName").asText()).isEqualTo("CustomFunction"); + + // Check that FunctionName is in the dimensions + JsonNode dimensions = coldStartNode.get("_aws").get("CloudWatchMetrics").get(0).get("Dimensions").get(0); + boolean hasFunctionName = false; + for (JsonNode dimension : dimensions) { + if (dimension.asText().equals("FunctionName")) { + hasFunctionName = true; + break; + } + } + assertThat(hasFunctionName).isTrue(); } @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - public void noExceptionWhenNoMetricsEmitted() { - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsNoExceptionWhenNoMetricsHandler(); - - requestHandler.handleRequest("input", context); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - - assertThat(logAsJson) - .containsEntry("Service", "booking") - .doesNotContainKey("_aws"); - }); + void shouldUseServiceNameWhenProvidedForColdStartMetric() throws Exception { + // Given + RequestHandler, String> handler = new HandlerWithServiceNameAndColdStart(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + // Should use the service name from annotation + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("CustomService"); } @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - public void allowWhenNoDimensionsSet() { - MetricsUtils.defaultDimensions(null); - - requestHandler = new PowertoolsMetricsNoDimensionsHandler(); - requestHandler.handleRequest("input", context); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - assertThat(logAsJson) - .containsEntry("CoolMetric", 1.0) - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); + void shouldHaveNoEffectOnNonHandlerMethod() { + // Given + RequestHandler, String> handler = new HandlerWithAnnotationOnWrongMethod(); + Context context = new TestContext(); + Map input = new HashMap<>(); + + // When + handler.handleRequest(input, context); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + + // Should be empty because we do not flush any metrics manually + assertThat(emfOutput).isEmpty(); } - @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - public void exceptionWhenTooManyDimensionsSet() { - MetricsUtils.defaultDimensions(null); + static class HandlerWithMetricsAnnotation implements RequestHandler, String> { + @Override + @FlushMetrics(namespace = "CustomNamespace", service = "CustomService") + public String handleRequest(Map input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + return "OK"; + } + } - requestHandler = new PowertoolsMetricsTooManyDimensionsHandler(); + static class HandlerWithDefaultMetricsAnnotation implements RequestHandler, String> { + @Override + @FlushMetrics + public String handleRequest(Map input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + return "OK"; + } + } - assertThatExceptionOfType(DimensionSetExceededException.class) - .isThrownBy(() -> requestHandler.handleRequest("input", context)) - .withMessage( - "Maximum number of dimensions allowed are 30. Account for default dimensions if not using setDimensions."); + static class HandlerWithColdStartMetricsAnnotation implements RequestHandler, String> { + @Override + @FlushMetrics(captureColdStart = true, namespace = "TestNamespace") + public String handleRequest(Map input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + return "OK"; + } } - @Test - @SetEnvironmentVariable(key = "AWS_EMF_ENVIRONMENT", value = "Lambda") - public void metricsPublishedEvenHandlerThrowsException() { - MetricsUtils.defaultDimensions(null); - requestHandler = new PowertoolsMetricsWithExceptionInHandler(); - - assertThatExceptionOfType(IllegalStateException.class) - .isThrownBy(() -> requestHandler.handleRequest("input", context)) - .withMessage("Whoops, unexpected exception"); - - assertThat(out.toString()) - .satisfies(s -> - { - Map logAsJson = readAsJson(s); - assertThat(logAsJson) - .containsEntry("CoolMetric", 1.0) - .containsEntry("Service", "booking") - .containsEntry("function_request_id", "123ABC") - .containsKey("_aws"); - }); + static class HandlerWithCustomFunctionName implements RequestHandler, String> { + @Override + @FlushMetrics(captureColdStart = true, functionName = "CustomFunction", namespace = "TestNamespace") + public String handleRequest(Map input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + return "OK"; + } } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - when(context.getAwsRequestId()).thenReturn("123ABC"); + static class HandlerWithServiceNameAndColdStart implements RequestHandler, String> { + @Override + @FlushMetrics(service = "CustomService", captureColdStart = true, namespace = "TestNamespace") + public String handleRequest(Map input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + return "OK"; + } } - private Map readAsJson(String s) { - try { - return mapper.readValue(s, Map.class); - } catch (JsonProcessingException e) { - e.printStackTrace(); + static class HandlerWithAnnotationOnWrongMethod implements RequestHandler, String> { + @Override + public String handleRequest(Map input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + someOtherMethod(); + return "OK"; + } + + @FlushMetrics + public void someOtherMethod() { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); } - return emptyMap(); } } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/ValidatorTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/ValidatorTest.java new file mode 100644 index 000000000..e5d780f9f --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/ValidatorTest.java @@ -0,0 +1,224 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.internal; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.time.Instant; + +import org.junit.jupiter.api.Test; + +class ValidatorTest { + + @Test + void shouldThrowExceptionWhenNamespaceIsNull() { + // When/Then + assertThatThrownBy(() -> Validator.validateNamespace(null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Namespace must be specified before flushing metrics"); + } + + @Test + void shouldThrowExceptionWhenNamespaceIsEmpty() { + // When/Then + assertThatThrownBy(() -> Validator.validateNamespace("")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Namespace must be specified before flushing metrics"); + } + + @Test + void shouldThrowExceptionWhenNamespaceIsBlank() { + // When/Then + assertThatThrownBy(() -> Validator.validateNamespace(" ")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Namespace must be specified before flushing metrics"); + } + + @Test + void shouldThrowExceptionWhenNamespaceExceedsMaxLength() { + // Given + String tooLongNamespace = "a".repeat(256); + + // When/Then + assertThatThrownBy(() -> Validator.validateNamespace(tooLongNamespace)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Namespace exceeds maximum length of 255"); + } + + @Test + void shouldThrowExceptionWhenNamespaceContainsInvalidCharacters() { + // When/Then + assertThatThrownBy(() -> Validator.validateNamespace("Invalid Namespace")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Namespace contains invalid characters"); + } + + @Test + void shouldAcceptValidNamespace() { + // When/Then + assertThatCode(() -> Validator.validateNamespace("Valid.Namespace_123#/")) + .doesNotThrowAnyException(); + } + + @Test + void shouldThrowExceptionWhenDimensionKeyIsNull() { + // When/Then + assertThatThrownBy(() -> Validator.validateDimension(null, "Value")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension key cannot be null or empty"); + } + + @Test + void shouldThrowExceptionWhenDimensionKeyIsEmpty() { + // When/Then + assertThatThrownBy(() -> Validator.validateDimension("", "Value")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension key cannot be null or empty"); + } + + @Test + void shouldThrowExceptionWhenDimensionValueIsNull() { + // When/Then + assertThatThrownBy(() -> Validator.validateDimension("Key", null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension value cannot be null or empty"); + } + + @Test + void shouldThrowExceptionWhenDimensionValueIsEmpty() { + // When/Then + assertThatThrownBy(() -> Validator.validateDimension("Key", "")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension value cannot be null or empty"); + } + + @Test + void shouldThrowExceptionWhenDimensionKeyContainsWhitespace() { + // When/Then + assertThatThrownBy(() -> Validator.validateDimension("Key With Space", "Value")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension key cannot contain whitespaces: Key With Space"); + } + + @Test + void shouldThrowExceptionWhenDimensionValueContainsWhitespace() { + // When/Then + assertThatThrownBy(() -> Validator.validateDimension("Key", "Value With Space")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension value cannot contain whitespaces: Value With Space"); + } + + @Test + void shouldThrowExceptionWhenDimensionKeyStartsWithColon() { + // When/Then + assertThatThrownBy(() -> Validator.validateDimension(":Key", "Value")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension key cannot start with colon: :Key"); + } + + @Test + void shouldThrowExceptionWhenDimensionKeyExceedsMaxLength() { + // Given + String longKey = "a".repeat(251); // MAX_DIMENSION_NAME_LENGTH + 1 + + // When/Then + assertThatThrownBy(() -> Validator.validateDimension(longKey, "Value")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension name exceeds maximum length of 250: " + longKey); + } + + @Test + void shouldThrowExceptionWhenDimensionValueExceedsMaxLength() { + // Given + String longValue = "a".repeat(1025); // MAX_DIMENSION_VALUE_LENGTH + 1 + + // When/Then + assertThatThrownBy(() -> Validator.validateDimension("Key", longValue)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension value exceeds maximum length of 1024: " + longValue); + } + + @Test + void shouldThrowExceptionWhenDimensionKeyContainsNonAsciiCharacters() { + // Given + String keyWithNonAscii = "Key\u0080"; // Non-ASCII character + + // When/Then + assertThatThrownBy(() -> Validator.validateDimension(keyWithNonAscii, "Value")) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension name has invalid characters: " + keyWithNonAscii); + } + + @Test + void shouldThrowExceptionWhenDimensionValueContainsNonAsciiCharacters() { + // Given + String valueWithNonAscii = "Value\u0080"; // Non-ASCII character + + // When/Then + assertThatThrownBy(() -> Validator.validateDimension("Key", valueWithNonAscii)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Dimension value has invalid characters: " + valueWithNonAscii); + } + + @Test + void shouldAcceptValidDimension() { + // When/Then + assertThatCode(() -> Validator.validateDimension("ValidKey", "ValidValue")) + .doesNotThrowAnyException(); + } + + @Test + void shouldThrowExceptionWhenTimestampIsNull() { + // When/Then + assertThatThrownBy(() -> Validator.validateTimestamp(null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Timestamp cannot be null"); + } + + @Test + void shouldThrowExceptionWhenTimestampIsTooFarInFuture() { + // Given + Instant futureTooFar = Instant.now().plusSeconds(Validator.MAX_TIMESTAMP_FUTURE_AGE_SECONDS + 1); + + // When/Then + assertThatThrownBy(() -> Validator.validateTimestamp(futureTooFar)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Timestamp cannot be more than " + Validator.MAX_TIMESTAMP_FUTURE_AGE_SECONDS + + " seconds in the future"); + } + + @Test + void shouldThrowExceptionWhenTimestampIsTooFarInPast() { + // Given + Instant pastTooFar = Instant.now().minusSeconds(Validator.MAX_TIMESTAMP_PAST_AGE_SECONDS + 1); + + // When/Then + assertThatThrownBy(() -> Validator.validateTimestamp(pastTooFar)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Timestamp cannot be more than " + Validator.MAX_TIMESTAMP_PAST_AGE_SECONDS + + " seconds in the past"); + } + + @Test + void shouldAcceptValidTimestamp() { + // Given + Instant validTimestamp = Instant.now(); + + // When/Then + assertThatCode(() -> Validator.validateTimestamp(validTimestamp)) + .doesNotThrowAnyException(); + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/model/DimensionSetTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/model/DimensionSetTest.java new file mode 100644 index 000000000..ac059f117 --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/model/DimensionSetTest.java @@ -0,0 +1,166 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.model; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.Collections; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +class DimensionSetTest { + + @Test + void shouldCreateEmptyDimensionSet() { + // When + DimensionSet dimensionSet = DimensionSet.of(Collections.emptyMap()); + + // Then + assertThat(dimensionSet.getDimensions()).isEmpty(); + assertThat(dimensionSet.getDimensionKeys()).isEmpty(); + } + + @Test + void shouldCreateDimensionSetWithSingleKeyValue() { + // When + DimensionSet dimensionSet = DimensionSet.of("Key", "Value"); + + // Then + assertThat(dimensionSet.getDimensions()).containsExactly(Map.entry("Key", "Value")); + assertThat(dimensionSet.getDimensionKeys()).containsExactly("Key"); + } + + @Test + void shouldCreateDimensionSetWithTwoKeyValues() { + // When + DimensionSet dimensionSet = DimensionSet.of("Key1", "Value1", "Key2", "Value2"); + + // Then + assertThat(dimensionSet.getDimensions()) + .containsEntry("Key1", "Value1") + .containsEntry("Key2", "Value2"); + assertThat(dimensionSet.getDimensionKeys()).containsExactly("Key1", "Key2"); + } + + @Test + void shouldCreateDimensionSetWithThreeKeyValues() { + // When + DimensionSet dimensionSet = DimensionSet.of( + "Key1", "Value1", + "Key2", "Value2", + "Key3", "Value3"); + + // Then + assertThat(dimensionSet.getDimensions()) + .containsEntry("Key1", "Value1") + .containsEntry("Key2", "Value2") + .containsEntry("Key3", "Value3"); + assertThat(dimensionSet.getDimensionKeys()).containsExactly("Key1", "Key2", "Key3"); + } + + @Test + void shouldCreateDimensionSetWithFourKeyValues() { + // When + DimensionSet dimensionSet = DimensionSet.of( + "Key1", "Value1", + "Key2", "Value2", + "Key3", "Value3", + "Key4", "Value4"); + + // Then + assertThat(dimensionSet.getDimensions()) + .containsEntry("Key1", "Value1") + .containsEntry("Key2", "Value2") + .containsEntry("Key3", "Value3") + .containsEntry("Key4", "Value4"); + assertThat(dimensionSet.getDimensionKeys()).containsExactly("Key1", "Key2", "Key3", "Key4"); + } + + @Test + void shouldCreateDimensionSetWithFiveKeyValues() { + // When + DimensionSet dimensionSet = DimensionSet.of( + "Key1", "Value1", + "Key2", "Value2", + "Key3", "Value3", + "Key4", "Value4", + "Key5", "Value5"); + + // Then + assertThat(dimensionSet.getDimensions()) + .containsEntry("Key1", "Value1") + .containsEntry("Key2", "Value2") + .containsEntry("Key3", "Value3") + .containsEntry("Key4", "Value4") + .containsEntry("Key5", "Value5"); + assertThat(dimensionSet.getDimensionKeys()).containsExactly("Key1", "Key2", "Key3", "Key4", "Key5"); + } + + @Test + void shouldCreateDimensionSetFromMap() { + // Given + Map dimensions = Map.of( + "Key1", "Value1", + "Key2", "Value2"); + + // When + DimensionSet dimensionSet = DimensionSet.of(dimensions); + + // Then + assertThat(dimensionSet.getDimensions()).isEqualTo(dimensions); + assertThat(dimensionSet.getDimensionKeys()).containsExactlyInAnyOrder("Key1", "Key2"); + } + + @Test + void shouldGetDimensionValue() { + // Given + DimensionSet dimensionSet = DimensionSet.of("Key1", "Value1", "Key2", "Value2"); + + // When + String value = dimensionSet.getDimensionValue("Key1"); + + // Then + assertThat(value).isEqualTo("Value1"); + } + + @Test + void shouldReturnNullForNonExistentDimension() { + // Given + DimensionSet dimensionSet = DimensionSet.of("Key1", "Value1"); + + // When + String value = dimensionSet.getDimensionValue("NonExistentKey"); + + // Then + assertThat(value).isNull(); + } + + @Test + void shouldThrowExceptionWhenExceedingMaxDimensions() { + // Given + // Create a dimension set with 30 dimensions (30 is maximum) + DimensionSet dimensionSet = new DimensionSet(); + for (int i = 1; i <= 30; i++) { + dimensionSet.addDimension("Key" + i, "Value" + i); + } + + // When/Then + assertThatThrownBy(() -> dimensionSet.addDimension("Key31", "Value31")) + .isInstanceOf(IllegalStateException.class) + .hasMessageContaining("Cannot exceed 30 dimensions per dimension set"); + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/provider/EmfMetricsProviderTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/provider/EmfMetricsProviderTest.java new file mode 100644 index 000000000..2b2268ea8 --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/provider/EmfMetricsProviderTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.provider; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.internal.EmfMetricsLogger; + +class EmfMetricsProviderTest { + + @Test + void shouldCreateEmfMetricsLogger() { + // Given + EmfMetricsProvider provider = new EmfMetricsProvider(); + + // When + Metrics metrics = provider.getMetricsInstance(); + + // Then + assertThat(metrics) + .isNotNull() + .isInstanceOf(EmfMetricsLogger.class); + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java new file mode 100644 index 000000000..c4f5e4455 --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java @@ -0,0 +1,77 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.testutils; + +import com.amazonaws.services.lambda.runtime.Context; + +/** + * Simple Lambda context implementation for unit tests + */ +public class TestContext implements Context { + @Override + public String getAwsRequestId() { + return "test-request-id"; + } + + @Override + public String getLogGroupName() { + return "test-log-group"; + } + + @Override + public String getLogStreamName() { + return "test-log-stream"; + } + + @Override + public String getFunctionName() { + return "test-function"; + } + + @Override + public String getFunctionVersion() { + return "test-version"; + } + + @Override + public String getInvokedFunctionArn() { + return "test-arn"; + } + + @Override + public com.amazonaws.services.lambda.runtime.CognitoIdentity getIdentity() { + return null; + } + + @Override + public com.amazonaws.services.lambda.runtime.ClientContext getClientContext() { + return null; + } + + @Override + public int getRemainingTimeInMillis() { + return 1000; + } + + @Override + public int getMemoryLimitInMB() { + return 128; + } + + @Override + public com.amazonaws.services.lambda.runtime.LambdaLogger getLogger() { + return null; + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetrics.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetrics.java new file mode 100644 index 000000000..949828a13 --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetrics.java @@ -0,0 +1,85 @@ +package software.amazon.lambda.powertools.metrics.testutils; + +import java.time.Instant; +import java.util.Collections; + +import com.amazonaws.services.lambda.runtime.Context; + +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricResolution; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; + +public class TestMetrics implements Metrics { + @Override + public void addMetric(String name, double value, MetricUnit unit) { + // Test placeholder + } + + @Override + public void flush() { + // Test placeholder + } + + @Override + public void addMetric(String key, double value, MetricUnit unit, MetricResolution resolution) { + // Test placeholder + } + + @Override + public void addDimension(DimensionSet dimensionSet) { + // Test placeholder + } + + @Override + public void addMetadata(String key, Object value) { + // Test placeholder + } + + @Override + public void setDefaultDimensions(DimensionSet dimensionSet) { + // Test placeholder + } + + @Override + public DimensionSet getDefaultDimensions() { + // Test placeholder + return DimensionSet.of(Collections.emptyMap()); + } + + @Override + public void setNamespace(String namespace) { + // Test placeholder + } + + @Override + public void setRaiseOnEmptyMetrics(boolean raiseOnEmptyMetrics) { + // Test placeholder + } + + @Override + public void clearDefaultDimensions() { + // Test placeholder + } + + @Override + public void setTimestamp(Instant timestamp) { + // Test placeholder + } + + @Override + public void captureColdStartMetric(Context context, DimensionSet dimensions) { + // Test placeholder + } + + @Override + public void captureColdStartMetric(DimensionSet dimensions) { + // Test placeholder + } + + @Override + public void flushSingleMetric(String name, double value, MetricUnit unit, String namespace, + DimensionSet dimensions) { + // Test placeholder + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetricsProvider.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetricsProvider.java new file mode 100644 index 000000000..4a5fc23dd --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetricsProvider.java @@ -0,0 +1,11 @@ +package software.amazon.lambda.powertools.metrics.testutils; + +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.provider.MetricsProvider; + +public class TestMetricsProvider implements MetricsProvider { + @Override + public Metrics getMetricsInstance() { + return new TestMetrics(); + } +} diff --git a/powertools-metrics/src/test/resources/simplelogger.properties b/powertools-metrics/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..6c626ab4d --- /dev/null +++ b/powertools-metrics/src/test/resources/simplelogger.properties @@ -0,0 +1,7 @@ +org.slf4j.simpleLogger.logFile=target/metrics-test.log +org.slf4j.simpleLogger.defaultLogLevel=warn +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS +org.slf4j.simpleLogger.showThreadName=false +org.slf4j.simpleLogger.showLogName=true +org.slf4j.simpleLogger.showShortLogName=false diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index e959204ad..9a42ebf16 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -234,8 +234,8 @@ - - + + From fa1c37dfb28196f86b70164561ce25c081e25bec Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 11 Jun 2025 14:28:06 +0200 Subject: [PATCH 241/577] docs(metrics): Add upgrade guide for re-designed Metrics utility (#1868) * Add upgrade guide for re-designed metrics utility. Update roadmap with completed items. * Apply language suggestions. Co-authored-by: Stefano Vozza --------- Co-authored-by: Stefano Vozza --- docs/roadmap.md | 5 +++-- docs/upgrade.md | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/docs/roadmap.md b/docs/roadmap.md index 4a86f1437..4ef1ef06e 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -17,7 +17,7 @@ Security and operational excellence take precedence above all else. This means b Our top priority is to establish the processes and infrastructure needed for a fully automated and secure end-to-end release process of new versions to Maven Central. -- [ ] Implement GitHub workflows and create infrastructure to release to Maven Central +- [x] [Implement GitHub workflows](https://github.com/aws-powertools/powertools-lambda-java/issues/1231){target="\_blank"} and create infrastructure to release to Maven Central - [x] [Implement end-to-end tests](https://github.com/aws-powertools/powertools-lambda-java/issues/1815){target="\_blank"} - [x] Implement [OpenSSF Scorecard](https://openssf.org/projects/scorecard/){target="\_blank"} @@ -27,9 +27,10 @@ As part of a new major version `v2` release, we prioritize the Java project's co ##### Core Utilities -- [ ] [Review public interfaces and reduce public API surface area](https://github.com/aws-powertools/powertools-lambda-java/issues/1283){target="\_blank"} +- [x] [Review public interfaces and reduce public API surface area](https://github.com/aws-powertools/powertools-lambda-java/issues/1283){target="\_blank"} - [x] [Release Logging `v2` module](https://github.com/aws-powertools/powertools-lambda-java/issues/965){target="\_blank"} allowing customers to choose the logging framework and adding support for logging deeply nested objects as JSON - [x] [Support high resolution metrics](https://github.com/aws-powertools/powertools-lambda-java/issues/1041){target="\_blank"} +- [x] [Improve modularity of metrics module](https://github.com/aws-powertools/powertools-lambda-java/issues/1848){target="\_blank"} to remove coupling with EMF library and enable future support for additional metrics providers / backends ##### Ecosystem diff --git a/docs/upgrade.md b/docs/upgrade.md index d2b1af096..d1388d95b 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -162,8 +162,53 @@ public class PaymentFunction implements RequestHandler + -The Metrics utility is currently undergoing changes to the public interface as part of GitHub issue [#1848](https://github.com/aws-powertools/powertools-lambda-java/issues/1848). We will keep this upgrade guide updated with the most recent changes as soon as they are released. Stay tuned for updates! +The Metrics utility was redesigned to be more modular and allow for the addition of new metrics providers in the future. The same EMF-based metrics logging still applies but will be called via an updated public interface. Consider the following list to understand some of changes: + +- `#!java @Metrics` was renamed to `#!java @FlushMetrics` +- `#!java MetricsLogger.metricsLogger()` was renamed to `#!java MetricsFactory.getMetricsInstance()` +- `put*` calls such as `#!java putMetric()` where replaced with `add*` nomenclature such as `#!java addMetric()` +- All direct imports from `software.amazon.cloudwatchlogs.emf` need to be replaced with Powertools counterparts from `software.amazon.lambda.powertools.metrics` (see example below) +- The `withSingleMetric` and `withMetricsLogger` methods were removed in favor of `#!java metrics.flushSingleMetric()` +- It is no longer valid to skip declaration of a namespace. If no namespace is provided, an exception will be raised instead of using the default `aws-embedded-metrics` namespace. + +The following example shows a common Lambda handler using the Metrics utility and required refactorings. + +```diff +// Metrics is not a decorator anymore but the replacement for the `MetricsLogger` Singleton +import software.amazon.lambda.powertools.metrics.Metrics; ++ import software.amazon.lambda.powertools.metrics.FlushMetrics; +- import software.amazon.lambda.powertools.metrics.MetricsUtils; ++ import software.amazon.lambda.powertools.metrics.MetricsFactory; +- import software.amazon.cloudwatchlogs.emf.logger.MetricsLogger; +- import software.amazon.cloudwatchlogs.emf.model.DimensionSet; +- import software.amazon.cloudwatchlogs.emf.model.Unit; ++ import software.amazon.lambda.powertools.metrics.model.DimensionSet; ++ import software.amazon.lambda.powertools.metrics.model.MetricUnit; + +public class MetricsEnabledHandler implements RequestHandler { + + // This is still a Singleton +- MetricsLogger metricsLogger = MetricsUtils.metricsLogger(); ++ Metrics metrics = MetricsFactory.getMetricsInstance(); + + @Override +- @Metrics(namespace = "ExampleApplication", service = "booking") ++ @FlushMetrics(namespace = "ExampleApplication", service = "booking") + public Object handleRequest(Object input, Context context) { +- metricsLogger.putDimensions(DimensionSet.of("environment", "prod")); ++ metrics.addDimension(DimensionSet.of("environment", "prod")); + // New method overload for adding 2D dimensions more conveniently ++ metrics.addDimension("environment", "prod"); +- metricsLogger.putMetric("SuccessfulBooking", 1, Unit.COUNT); ++ metrics.addMetric("SuccessfulBooking", 1, MetricUnit.COUNT); + ... + } +} +``` + +Learn more about the redesigned Metrics utility in the [Metrics documentation](./core/metrics.md). ## Deprecated capture mode related `@Tracing` annotation parameters From 20a4d94ae5ba0f429e1ace89edd930b78e37f1e1 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 11 Jun 2025 15:23:08 +0200 Subject: [PATCH 242/577] chore(v2): Remove rule preventing production release of 2.0.0 (#1867) * Remove redundant version declaration of aws-embedded-metrics.version in pom.xml * Remove maven enforcer plugin enforcing SNAPSHOT release only. --- pom.xml | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/pom.xml b/pom.xml index 81e513b8c..9cfd6a7a4 100644 --- a/pom.xml +++ b/pom.xml @@ -87,7 +87,6 @@ 3.3.1 3.2.1 5.10.0 - 1.0.6 1.14 3.1.2 0.8.12 @@ -505,28 +504,6 @@ release - - org.apache.maven.plugins - maven-enforcer-plugin - 3.5.0 - - - enforce-snapshot-versions - validate - - enforce - - - - - Release build should not have snapshot dependencies! - - - true - - - - org.apache.maven.plugins maven-gpg-plugin From 92926f399b090e1eacc02bd11cda5d72713aff3c Mon Sep 17 00:00:00 2001 From: Simon Thulbourn Date: Wed, 11 Jun 2025 15:31:01 +0200 Subject: [PATCH 243/577] fix(ci): Checkout repo on doc release (#1869) * fix(ci): Clone repo for docs job * version docs --- .github/workflows/release.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 826536136..54924b558 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -270,11 +270,9 @@ jobs: id-token: write environment: Docs steps: - - id: download_source - name: Download artifacts - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.6.1 - with: - name: source + - id: checkout + name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Build run: | mkdir -p dist @@ -290,4 +288,4 @@ jobs: run: | aws s3 sync \ dist \ - s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ inputs.version }}/ From af31d6fbbb7d999f723eb2257a9c827fd2a10889 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 11 Jun 2025 16:06:51 +0200 Subject: [PATCH 244/577] Add Maven Central required info to pom.xml and skip deploying e2e tests and parameters tests. (#1871) --- pom.xml | 13 +++++++++++++ powertools-e2e-tests/pom.xml | 2 +- .../powertools-parameters-tests/pom.xml | 14 +++++++++----- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 9cfd6a7a4..f00417387 100644 --- a/pom.xml +++ b/pom.xml @@ -27,6 +27,19 @@ A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. + + https://github.com/aws-powertools/powertools-lambda-java + scm:git:git://github.com/aws-powertools/powertools-lambda-java.git + scm:git:ssh://github.com:aws-powertools/powertools-lambda-java.git + + + + Powertools for AWS team + aws-powertools-maintainers@amazon.com + Amazon Web Services Inc. + https://aws.amazon.com + + https://aws.amazon.com/lambda/ GitHub Issues diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 9cb604f56..7ec2e83e9 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -180,7 +180,7 @@ org.apache.maven.plugins maven-deploy-plugin - ${maven.deploy.plugin.version} + 3.1.2 true diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index e62323bd6..0120cab8f 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -12,10 +12,6 @@ powertools-parameters-tests Powertools parameters tests that cut across all the parameters providers - - - true - @@ -164,8 +160,16 @@ + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.2 + + true + + - \ No newline at end of file + From e3d4c7e131cd023b4f5568b3095a92440e56f70f Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 11 Jun 2025 16:30:18 +0200 Subject: [PATCH 245/577] Fix remaining maven central properties required. (#1872) --- powertools-e2e-tests/pom.xml | 53 ++++++++++--------- powertools-idempotency/pom.xml | 6 +-- .../powertools-parameters-tests/pom.xml | 19 +++++++ powertools-serialization/pom.xml | 4 +- 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 7ec2e83e9..e09300001 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -174,31 +174,36 @@ - - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.1.2 - - true - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.13.0 - - ${maven.compiler.source} - ${maven.compiler.target} - UTF-8 - - - - - + + default + + true + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.2 + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + ${maven.compiler.source} + ${maven.compiler.target} + UTF-8 + + + + + e2e diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index fddef497a..7ff621144 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -28,9 +28,7 @@ pom Powertools for AWS Lambda (Java) library Idempotency - - - + Utility to implement idempotency of Lambda functions @@ -116,4 +114,4 @@ - \ No newline at end of file + diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 0120cab8f..dc3eab4c4 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -10,6 +10,7 @@ ../../pom.xml + Powertools for AWS Lambda (Java) library Parameters - Tests powertools-parameters-tests Powertools parameters tests that cut across all the parameters providers @@ -72,6 +73,24 @@ + + default + + true + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.2 + + true + + + + + generate-graalvm-files diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 6c45b62dd..df592476d 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -28,9 +28,7 @@ jar Powertools for AWS Lambda (Java) - Serialization Utilities - - - + Utilities for JSON serialization used across the project. From b314321840dea0abe65bdefba509f9e6dec54da2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 17:07:23 +0200 Subject: [PATCH 246/577] chore(ci): bump version to 2.0.0-RC1 (#1875) Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 40 files changed, 46 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index fd72ee148..625d3d009 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your software.amazon.lambda powertools-tracing - 2.0.0-SNAPSHOT + 2.0.0-RC1 software.amazon.lambda powertools-logging - 2.0.0-SNAPSHOT + 2.0.0-RC1 software.amazon.lambda powertools-metrics - 2.0.0-SNAPSHOT + 2.0.0-RC1 ... diff --git a/examples/pom.xml b/examples/pom.xml index 63625214c..3462be0b7 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 pom Powertools for AWS Lambda (Java) - Examples diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index b8b50b77f..275a3c96f 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ 4.0.0 software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-batch jar Powertools for AWS Lambda (Java) - Examples - Batch diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 15084d9b4..edadd6005 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-cloudformation jar diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index a959432c0..11d5497da 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-core-utilities-cdk jar diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index fca756921..0b67f20ae 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ 4.0.0 software.amazon.lambda.examples cdk - 2.0.0-SNAPSHOT + 2.0.0-RC1 UTF-8 2.162.1 diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 38cf96c1c..bf53c31eb 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.0.0-SNAPSHOT' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.0.0-SNAPSHOT' - aspect 'software.amazon.lambda:powertools-metrics:2.0.0-SNAPSHOT' + aspect 'software.amazon.lambda:powertools-tracing:2.0.0-RC1' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.0.0-RC1' + aspect 'software.amazon.lambda:powertools-metrics:2.0.0-RC1' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 3c84ce7f4..9dcac3510 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.11.3") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.0.0-SNAPSHOT") - aspect("software.amazon.lambda:powertools-logging-log4j:2.0.0-SNAPSHOT") - aspect("software.amazon.lambda:powertools-metrics:2.0.0-SNAPSHOT") + aspect("software.amazon.lambda:powertools-tracing:2.0.0-RC1") + aspect("software.amazon.lambda:powertools-logging-log4j:2.0.0-RC1") + aspect("software.amazon.lambda:powertools-metrics:2.0.0-RC1") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index d25e1fcb7..011a29c60 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-core-utilities-sam-graalvm jar diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 2db4628b4..d43094922 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-core-utilities-sam jar diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 41b5a20a1..fce13b792 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-core-utilities-serverless jar diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 7480bd013..dd9ed4685 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-core-utilities-terraform jar diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index fd673b573..f0fcf545a 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ 4.0.0 software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-idempotency jar Powertools for AWS Lambda (Java) - Examples - Idempotency diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 34f469c6c..8031710b1 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-parameters-sam-graalvm jar Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index d0d8028d6..02b991d68 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-parameters-sam jar Powertools for AWS Lambda (Java) - Examples - Parameters diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 00aba4c8d..560c08a56 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-serialization jar Powertools for AWS Lambda (Java) - Examples - Serialization diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index c021572f8..8bed7cb5e 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-examples-validation jar Powertools for AWS Lambda (Java) - Examples - Validation diff --git a/mkdocs.yml b/mkdocs.yml index ee5f77dde..6f185584b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -118,7 +118,7 @@ extra_javascript: extra: powertools: - version: 2.0.0-SNAPSHOT + version: 2.0.0-RC1 repo_url: https://github.com/aws-powertools/powertools-lambda-java edit_uri: edit/main/docs diff --git a/pom.xml b/pom.xml index f00417387..af17d6b1b 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-parent - 2.0.0-SNAPSHOT + 2.0.0-RC1 pom Powertools for AWS Lambda (Java) - Parent diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 819c19927..20dbd179b 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 2.0.0-SNAPSHOT + 2.0.0-RC1 A suite of utilities that makes batch message processing using AWS Lambda easier. diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 36392fce2..e3ab012ae 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 Powertools for AWS Lambda (Java) - Cloudformation diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 47a505325..b9a8572ea 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 Powertools for AWS Lambda (Java) - Common Internal Utilities diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index e09300001..ce9e12860 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-e2e-tests diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 7ff621144..286ea3f97 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-parent - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-idempotency diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 59b69da0f..3012406af 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-idempotency - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-idempotency-core diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index 3ab817209..e985f8f14 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-idempotency - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-idempotency-dynamodb diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index afbd0aa37..9569c9ea8 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ software.amazon.lambda powertools-parent - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-large-messages diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 62cb9c352..ade7c95fc 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 Powertools for AWS Lambda (Java) - Logging diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 96a9a7043..e85fc6567 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 ../../pom.xml diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index a94801345..212379439 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 ../../pom.xml diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 46f7bcd99..8ae52d43d 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 Powertools for AWS Lambda (Java) - Metrics diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 44292c755..ad8f14e36 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-parameters diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index f4af26062..840bb5159 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0-SNAPSHOT + 2.0.0-RC1 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index fde6c190b..1220b1eb5 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0-SNAPSHOT + 2.0.0-RC1 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index a652f14e0..93bd9a26e 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0-SNAPSHOT + 2.0.0-RC1 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index ec13c10cc..1c91824e9 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0-SNAPSHOT + 2.0.0-RC1 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index dc3eab4c4..37e266bde 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 2.0.0-SNAPSHOT + 2.0.0-RC1 ../../pom.xml diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index df592476d..ec8acab9e 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 powertools-serialization diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 140c212e3..a869679a8 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 Powertools for AWS Lambda (Java) - Tracing diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 7d460eec3..8720509bb 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0-SNAPSHOT + 2.0.0-RC1 Powertools for AWS Lambda (Java) - Validation From 9616520ce46608da67303faa3e31fc8b07c07c21 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 11:32:48 +0200 Subject: [PATCH 247/577] chore(ci): bump version to 2.0.0 (#1876) Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 40 files changed, 46 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 625d3d009..88955bca7 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your software.amazon.lambda powertools-tracing - 2.0.0-RC1 + 2.0.0 software.amazon.lambda powertools-logging - 2.0.0-RC1 + 2.0.0 software.amazon.lambda powertools-metrics - 2.0.0-RC1 + 2.0.0 ... diff --git a/examples/pom.xml b/examples/pom.xml index 3462be0b7..6bedc015e 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-examples - 2.0.0-RC1 + 2.0.0 pom Powertools for AWS Lambda (Java) - Examples diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 275a3c96f..ef3c0e4e0 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ 4.0.0 software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-batch jar Powertools for AWS Lambda (Java) - Examples - Batch diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index edadd6005..43c81b9f8 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-cloudformation jar diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 11d5497da..fa5a1927a 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-core-utilities-cdk jar diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 0b67f20ae..b869a5672 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ 4.0.0 software.amazon.lambda.examples cdk - 2.0.0-RC1 + 2.0.0 UTF-8 2.162.1 diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index bf53c31eb..4cf988a6f 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.0.0-RC1' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.0.0-RC1' - aspect 'software.amazon.lambda:powertools-metrics:2.0.0-RC1' + aspect 'software.amazon.lambda:powertools-tracing:2.0.0' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.0.0' + aspect 'software.amazon.lambda:powertools-metrics:2.0.0' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 9dcac3510..7029dc458 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.11.3") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.0.0-RC1") - aspect("software.amazon.lambda:powertools-logging-log4j:2.0.0-RC1") - aspect("software.amazon.lambda:powertools-metrics:2.0.0-RC1") + aspect("software.amazon.lambda:powertools-tracing:2.0.0") + aspect("software.amazon.lambda:powertools-logging-log4j:2.0.0") + aspect("software.amazon.lambda:powertools-metrics:2.0.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 011a29c60..b2353b86e 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-core-utilities-sam-graalvm jar diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index d43094922..813fc267f 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-core-utilities-sam jar diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index fce13b792..1aea70820 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-core-utilities-serverless jar diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index dd9ed4685..dd4c385c0 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-core-utilities-terraform jar diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index f0fcf545a..c7ceabc57 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ 4.0.0 software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-idempotency jar Powertools for AWS Lambda (Java) - Examples - Idempotency diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 8031710b1..f2ce0f21f 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-parameters-sam-graalvm jar Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 02b991d68..a797bbeed 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-parameters-sam jar Powertools for AWS Lambda (Java) - Examples - Parameters diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 560c08a56..b96d02b6b 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-serialization jar Powertools for AWS Lambda (Java) - Examples - Serialization diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 8bed7cb5e..9b6df9783 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0-RC1 + 2.0.0 powertools-examples-validation jar Powertools for AWS Lambda (Java) - Examples - Validation diff --git a/mkdocs.yml b/mkdocs.yml index 6f185584b..ee6bd7322 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -118,7 +118,7 @@ extra_javascript: extra: powertools: - version: 2.0.0-RC1 + version: 2.0.0 repo_url: https://github.com/aws-powertools/powertools-lambda-java edit_uri: edit/main/docs diff --git a/pom.xml b/pom.xml index af17d6b1b..951e155f6 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-parent - 2.0.0-RC1 + 2.0.0 pom Powertools for AWS Lambda (Java) - Parent diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 20dbd179b..59e5b8c93 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 2.0.0-RC1 + 2.0.0 A suite of utilities that makes batch message processing using AWS Lambda easier. diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index e3ab012ae..271704dea 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 Powertools for AWS Lambda (Java) - Cloudformation diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index b9a8572ea..dd6ef8e61 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 Powertools for AWS Lambda (Java) - Common Internal Utilities diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index ce9e12860..4f1c059e9 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 powertools-e2e-tests diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 286ea3f97..862cf3160 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-parent - 2.0.0-RC1 + 2.0.0 powertools-idempotency diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 3012406af..58d184fc5 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-idempotency - 2.0.0-RC1 + 2.0.0 powertools-idempotency-core diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index e985f8f14..b92d66dbc 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-idempotency - 2.0.0-RC1 + 2.0.0 powertools-idempotency-dynamodb diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 9569c9ea8..b23e3f41c 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ software.amazon.lambda powertools-parent - 2.0.0-RC1 + 2.0.0 powertools-large-messages diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index ade7c95fc..75d5853e5 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 Powertools for AWS Lambda (Java) - Logging diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index e85fc6567..75aa94a97 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 ../../pom.xml diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 212379439..8b2a5cfd5 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 ../../pom.xml diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 8ae52d43d..460eb220f 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 Powertools for AWS Lambda (Java) - Metrics diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index ad8f14e36..96f6f50b3 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 powertools-parameters diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 840bb5159..a3822d11b 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0-RC1 + 2.0.0 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 1220b1eb5..9c7030d7c 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0-RC1 + 2.0.0 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 93bd9a26e..99a308825 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0-RC1 + 2.0.0 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 1c91824e9..46cf939ba 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0-RC1 + 2.0.0 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 37e266bde..4d2b5d145 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 2.0.0-RC1 + 2.0.0 ../../pom.xml diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index ec8acab9e..986a3b1d9 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 powertools-serialization diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index a869679a8..14d6d51b1 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 Powertools for AWS Lambda (Java) - Tracing diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 8720509bb..bfedf8d40 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0-RC1 + 2.0.0 Powertools for AWS Lambda (Java) - Validation From 871a844d10d8e54180737c95d1747dd3a045cc45 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 12 Jun 2025 12:24:27 +0200 Subject: [PATCH 248/577] docs: Version documentation (#1878) * Add versioning plugin for docs and update workflows. * Add old version banner override. Remove preview wording. --- .github/workflows/build-docs.yml | 68 ++++++++++++++++++++++---------- .github/workflows/release.yml | 55 +++++++++++++++++++++----- docs/index.md | 8 ---- docs/overrides/main.html | 8 ++++ mkdocs.yml | 9 +++-- 5 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 docs/overrides/main.html diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index d4bf75a9d..5d6870171 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -1,7 +1,7 @@ -# Build Docs +# Build Latest Docs # # Description: -# Builds the docs and stores them in S3 to be served by our docs platform +# Builds the latest docs and stores them in S3 to be served by our docs platform # # The workflow allows us to build to the main location (/lambda/java/) and to an alias # (i.e. /lambda/java/preview/) if needed @@ -15,17 +15,13 @@ on: workflow_dispatch: inputs: - alias: + version: + description: "Version to build and publish docs (1.28.0, develop)" + required: true type: string - required: false - description: | - Alias to deploy the documentation into, this is mostly for testing pre-release - versions of the documentation, such as beta versions or snapshots. - https://docs.powertools.aws.dev/lambda/java/ - -name: Build Docs -run-name: Build Docs - ${{ contains(github.head_ref, 'main') && 'main' || inputs.alias }} +name: Build Latest Docs +run-name: Build Latest Docs - ${{ inputs.version }} jobs: docs: @@ -35,28 +31,58 @@ jobs: id-token: write environment: Docs steps: - - name: Sanity Check - if: ${{ github.head_ref != 'main' || inputs.alias == '' }} - run: - echo "::error::No buildable docs" - - name: Checkout Repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - with: + with: fetch-depth: 0 - name: Build run: | mkdir -p dist docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - cp -R site/* dist/ - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} - - name: Deploy + - name: Deploy Docs (Version) + env: + VERSION: ${{ inputs.version }} + ALIAS: "latest" run: | aws s3 sync \ - dist \ - s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ github.head_ref == 'main' && '' || format('{0}/', inputs.alias )}} \ No newline at end of file + site/ \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ env.VERSION }}/ + - name: Deploy Docs (Alias) + env: + VERSION: ${{ inputs.version }} + ALIAS: "latest" + run: | + aws s3 sync \ + site/ \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ env.ALIAS }}/ + - name: Deploy Docs (Version JSON) + env: + VERSION: ${{ inputs.version }} + ALIAS: "latest" + # We originally used "mike" from PyPi to manage versions for us, but since we moved to S3, we can't use it to manage versions any more. + # Instead, we're using some shell script that manages the versions. + # + # Operations: + # 1. Download the versions.json file from S3 + # 2. Find any reference to the alias and delete it from the versions file + # 3. This is voodoo (don't use JQ): + # - we assign the input as $o and the new version/alias as $n, + # - we check if the version number exists in the file already (for republishing docs) + # - if it's an alias (stage/latest/*) or old version, we do nothing and output $o (original input) + # - if it's a new version number, we add it at position 0 in the array. + # 4. Once done, we'll upload it back to S3. + run: | + aws s3 cp \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/versions.json \ + versions_old.json + jq 'del(.[].aliases[] | select(. == "${{ env.ALIAS }}"))' < versions_old.json > versions_proc.json + jq '. as $o | [{"title": "${{ env.VERSION }}", "version": "${{ env.VERSION }}", "aliases": ["${{ env.ALIAS }}"] }] as $n | $n | if .[0].title | test("[a-z]+") or any($o[].title == $n[0].title;.) then [($o | .[] | select(.title == $n[0].title).aliases += $n[0].aliases | . )] else $n + $o end' < versions_proc.json > versions.json + aws s3 cp \ + versions.json \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/versions.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 54924b558..2fa4770c2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ # # Triggers: # - workflow_dispatch -# +# # Secrets: # - RELEASE.GPG_SIGNING_KEY # - RELEASE.OSSRH_JIRA_USERNAME @@ -39,7 +39,7 @@ on: type: boolean description: Create snapshot release default: false - skip_checks: + skip_checks: type: boolean description: Skip quality checks default: false @@ -47,7 +47,7 @@ on: type: boolean description: Skip publish to Maven Central default: false - continue_on_error: + continue_on_error: type: boolean description: Continue to build if there's an error in quality checks default: false @@ -55,7 +55,7 @@ on: name: Release run-name: Release – ${{ inputs.version }} -permissions: +permissions: contents: read env: @@ -124,7 +124,7 @@ jobs: quality: runs-on: ubuntu-latest - needs: + needs: - version_seal if: ${{ inputs.skip_checks == false }} permissions: @@ -211,7 +211,7 @@ jobs: MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} MAVEN_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} - + create_pr: runs-on: ubuntu-latest if: ${{ inputs.snapshot == false && always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }} @@ -278,14 +278,49 @@ jobs: mkdir -p dist docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - cp -R site/* dist/ - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} - - name: Deploy + - name: Deploy Docs (Version) + env: + VERSION: ${{ inputs.version }} + ALIAS: 'latest' run: | aws s3 sync \ - dist \ - s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ inputs.version }}/ + site/ \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ env.VERSION }}/ + - name: Deploy Docs (Alias) + env: + VERSION: ${{ inputs.version }} + ALIAS: 'latest' + run: | + aws s3 sync \ + site/ \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/${{ env.ALIAS }}/ + - name: Deploy Docs (Version JSON) + env: + VERSION: ${{ inputs.version }} + ALIAS: 'latest' + # We originally used "mike" from PyPi to manage versions for us, but since we moved to S3, we can't use it to manage versions any more. + # Instead, we're using some shell script that manages the versions. + # + # Operations: + # 1. Download the versions.json file from S3 + # 2. Find any reference to the alias and delete it from the versions file + # 3. This is voodoo (don't use JQ): + # - we assign the input as $o and the new version/alias as $n, + # - we check if the version number exists in the file already (for republishing docs) + # - if it's an alias (stage/latest/*) or old version, we do nothing and output $o (original input) + # - if it's a new version number, we add it at position 0 in the array. + # 4. Once done, we'll upload it back to S3. + run: | + aws s3 cp \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/versions.json \ + versions_old.json + jq 'del(.[].aliases[] | select(. == "${{ env.ALIAS }}"))' < versions_old.json > versions_proc.json + jq '. as $o | [{"title": "${{ env.VERSION }}", "version": "${{ env.VERSION }}", "aliases": ["${{ env.ALIAS }}"] }] as $n | $n | if .[0].title | test("[a-z]+") or any($o[].title == $n[0].title;.) then [($o | .[] | select(.title == $n[0].title).aliases += $n[0].aliases | . )] else $n + $o end' < versions_proc.json > versions.json + aws s3 cp \ + versions.json \ + s3://${{ secrets.AWS_DOCS_BUCKET }}/lambda-java/versions.json diff --git a/docs/index.md b/docs/index.md index 43d1ea03b..3c6b9506b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,14 +3,6 @@ title: Homepage description: Powertools for AWS Lambda (Java) --- -![aws provider](https://img.shields.io/badge/provider-AWS-orange?logo=amazon-aws&color=ff9900) ![Build status](https://github.com/aws-powertools/powertools-lambda-java/actions/workflows/publish-v2-snapshot.yml/badge.svg) ![Maven Central](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Faws.oss.sonatype.org%2Fcontent%2Frepositories%2Fsnapshots%2Fsoftware%2Famazon%2Flambda%2Fpowertools-parent%2Fmaven-metadata.xml -) - -???+ warning - You are browsing the documentation for Powertools for AWS Lambda (Java) - v2. This is a snapshot release and not stable! - Check out our stable [v1](https://docs.powertools.aws.dev/lambda/java/) documentation if this is not what you wanted. - The v2 maven snapshot repository can be found [here](https://aws.oss.sonatype.org/content/repositories/snapshots/software/amazon/lambda/) . - Powertools for AWS Lambda (Java) is a suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. ???+ tip diff --git a/docs/overrides/main.html b/docs/overrides/main.html new file mode 100644 index 000000000..e4c38e21b --- /dev/null +++ b/docs/overrides/main.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% block outdated %} +You're not viewing the latest version. + + Click here to go to latest. + +{% endblock %} diff --git a/mkdocs.yml b/mkdocs.yml index ee6bd7322..82a32d49c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,7 +1,7 @@ -site_name: Powertools for AWS Lambda (Java) Preview -site_description: Powertools for AWS Lambda (Java) Preview +site_name: Powertools for AWS Lambda (Java) +site_description: Powertools for AWS Lambda (Java) site_author: Amazon Web Services -site_url: https://docs.powertools.aws.dev/lambda/java/preview/ +site_url: https://docs.powertools.aws.dev/lambda/java/ nav: - Homepage: index.md - Changelog: changelog.md @@ -119,6 +119,9 @@ extra_javascript: extra: powertools: version: 2.0.0 + version: + provider: mike + default: latest repo_url: https://github.com/aws-powertools/powertools-lambda-java edit_uri: edit/main/docs From 0b275948638450165281a1d7abb5b4d321f3aeec Mon Sep 17 00:00:00 2001 From: Simon Thulbourn Date: Fri, 13 Jun 2025 11:05:23 +0200 Subject: [PATCH 249/577] chore(ci): Update workflows to make v2 the default (#1888) * chore(ci): Make v2 the main branch * update runner size for release * update skip checks * create tag instead of release --- .github/auto_assign-issues.yml | 9 --------- .github/workflows/check-build.yml | 1 - .github/workflows/check-e2e.yml | 1 - .github/workflows/check-spotbugs.yml | 2 +- .github/workflows/release-drafter.yml | 5 ----- .github/workflows/release.yml | 17 ++++++++--------- .../workflows/security-branch-protections.yml | 2 +- .github/workflows/security-dependabot.yml | 2 +- .github/workflows/security-osv.yml | 2 -- 9 files changed, 11 insertions(+), 30 deletions(-) delete mode 100644 .github/auto_assign-issues.yml diff --git a/.github/auto_assign-issues.yml b/.github/auto_assign-issues.yml deleted file mode 100644 index fb160ed94..000000000 --- a/.github/auto_assign-issues.yml +++ /dev/null @@ -1,9 +0,0 @@ -addAssignees: true - -# The list of users to assign to new issues. -# If empty or not provided, the repository owner is assigned -assignees: - - scottgerring - - jeromevdl - - mriccia - - msailes diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index cc5931d05..b5fe372dc 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -38,7 +38,6 @@ on: push: branches: - main - - v2 paths: # add other modules when there are under e2e tests - 'powertools-batch/**' - 'powertools-core/**' diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 14eab5394..d5c95f156 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -15,7 +15,6 @@ on: push: branches: - main - - v2 paths: # add other modules when there are under e2e tests - 'powertools-batch/**' - 'powertools-core/**' diff --git a/.github/workflows/check-spotbugs.yml b/.github/workflows/check-spotbugs.yml index 0749dfaa0..fd76d9560 100644 --- a/.github/workflows/check-spotbugs.yml +++ b/.github/workflows/check-spotbugs.yml @@ -9,7 +9,7 @@ on: pull_request: branches: - - v2 + - main paths: - 'powertools-batch/**' - 'powertools-core/**' diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index f727ee25d..39d453ced 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -15,16 +15,11 @@ name: Release Drafter run-name: Release Drafter jobs: -<<<<<<< HEAD - update_release_draft: - runs-on: ubuntu-latest -======= update_release: runs-on: ubuntu-latest permissions: contents: write id-token: write ->>>>>>> 4a17172a (chore(automation): Update automation workflows (#1779)) steps: - name: Relase Drafter uses: release-drafter/release-drafter@b1476f6e6eb133afa41ed8589daba6dc69b4d3f5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2fa4770c2..dc462fbfc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -82,7 +82,7 @@ jobs: - id: base name: Base run: | - echo build_version=$(test ${{ github.ref_name }} == "v2" && echo "v2" || echo "v1") >> $GITHUB_OUTPUT + echo build_version=$(test ${{ github.ref_name }} == "main" && echo "v2" || echo "v1") >> $GITHUB_OUTPUT - id: build_matrix_v1 name: Build matrix (v1) if: ${{ steps.base.outputs.build_version == 'v1' }} @@ -123,7 +123,7 @@ jobs: retention-days: 1 quality: - runs-on: ubuntu-latest + runs-on: aws-powertools_ubuntu-latest_8-core needs: - version_seal if: ${{ inputs.skip_checks == false }} @@ -156,7 +156,7 @@ jobs: uploadSarifReport: false build: - runs-on: ubuntu-latest + runs-on: aws-powertools_ubuntu-latest_8-core needs: - setup - quality @@ -183,8 +183,8 @@ jobs: mvn -B install --file pom.xml publish: - runs-on: ubuntu-latest - if: ${{ github.repository == 'aws-powertools/powertools-lambda-java' && inputs.skip_publish == false }} + runs-on: aws-powertools_ubuntu-latest_8-core + if: ${{ github.repository == 'aws-powertools/powertools-lambda-java' && inputs.skip_publish == false && always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }} needs: - build environment: Release @@ -254,11 +254,10 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - id: tag - name: Create release + name: Create tag run: | - gh release create v${{ inputs.version }} --target $(git rev-parse HEAD) - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + git tag -a v${{ inputs.version }} -m "Release v${{ inputs.version }}" + git push origin v${{ inputs.version }} docs: runs-on: ubuntu-latest diff --git a/.github/workflows/security-branch-protections.yml b/.github/workflows/security-branch-protections.yml index dc7c06316..05a082b0b 100644 --- a/.github/workflows/security-branch-protections.yml +++ b/.github/workflows/security-branch-protections.yml @@ -43,7 +43,7 @@ jobs: # List of branches we want to monitor for protection changes branch: - main - - v2 + - v1 steps: - name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 diff --git a/.github/workflows/security-dependabot.yml b/.github/workflows/security-dependabot.yml index 095219045..e1422fb2b 100644 --- a/.github/workflows/security-dependabot.yml +++ b/.github/workflows/security-dependabot.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'aws-powertools/powertools-lambda-java' }} permissions: - pull-requests: read + pull-requests: write steps: - id: dependabot-metadata name: Fetch Dependabot metadata diff --git a/.github/workflows/security-osv.yml b/.github/workflows/security-osv.yml index b332faae3..67e2e6e3f 100644 --- a/.github/workflows/security-osv.yml +++ b/.github/workflows/security-osv.yml @@ -13,14 +13,12 @@ on: pull_request: branches: - main - - v2 workflow_dispatch: {} schedule: - cron: "30 12 * * 1" push: branches: - main - - v2 name: OpenSource Vulnerability Scanner run-name: OpenSource Vulnerability Scanner From cc1b3b11d0118f35bbc22dd318693e05fec87e71 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 16 Jun 2025 16:59:54 +0200 Subject: [PATCH 250/577] docs: Announce deprecation of v1 --- docs/processes/versioning.md | 7 ++++--- docs/upgrade.md | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/processes/versioning.md b/docs/processes/versioning.md index 8b12e0fa9..bbb60f507 100644 --- a/docs/processes/versioning.md +++ b/docs/processes/versioning.md @@ -55,6 +55,7 @@ To see the list of available major versions of Powertools for AWS Lambda and whe ### Version support matrix -| SDK | Major version | Current Phase | General Availability Date | Notes | -| -------------------------------- | ------------- | -------------------- | ------------------------- | ------------------------------------------------------------------------------------------------- | -| Powertools for AWS Lambda (Java) | 1.x | General Availability | 11/04/2020 | See [Release notes](https://github.com/aws-powertools/powertools-lambda-java/releases/tag/v1.0.0) | +| SDK | Major version | Current Phase | General Availability Date | Notes | +| -------------------------------- | ------------- | -------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| Powertools for AWS Lambda (Java) | 2.x | General Availability | 06/12/2025 | See [Release notes](https://github.com/aws-powertools/powertools-lambda-java/releases/tag/v2.0.0) | +| Powertools for AWS Lambda (Java) | 1.x | Maintenance | 11/04/2020 | End-of-support: December 12, 2025. See [upgrade guide](https://docs.powertools.aws.dev/lambda/java/latest/upgrade/) | diff --git a/docs/upgrade.md b/docs/upgrade.md index d1388d95b..5b6d16d99 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -5,7 +5,10 @@ description: Guide to update between major Powertools for AWS Lambda (Java) vers ## End of support v1 - + +!!! warning "End of support notice" + On December 12th, 2025, Powertools for AWS Lambda (Java) v1 will reach end of support and will no longer receive updates or releases. If you are still using v1, we strongly recommend you to read our upgrade guide and update to the latest version. + Given our commitment to all of our customers using Powertools for AWS Lambda (Java), we will keep [Maven Central](https://central.sonatype.com/search?q=powertools){target="\_blank"} `v1` releases and a `v1` documentation archive to prevent any disruption. From 8a040ac87a2a31662b7ac8980601b4d821cc29d8 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Mon, 16 Jun 2025 17:00:49 +0200 Subject: [PATCH 251/577] fix(metrics): Do not flush when no metrics were added to avoid printing root-level _aws dict (#1891) * fix(metrics): Do not flush when no metrics were added to avoid printing root-level _aws dict. * Fix pmd linting failures. --- .../powertools/metrics/internal/EmfMetricsLogger.java | 3 ++- .../metrics/internal/EmfMetricsLoggerTest.java | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java index a55e1da5a..1eedd270d 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java @@ -164,8 +164,9 @@ public void flush() { } else { LOGGER.warn("No metrics were emitted"); } + } else { + emfLogger.flush(); } - emfLogger.flush(); } @Override diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java index 1b7106ece..a4fc0d61c 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java @@ -51,7 +51,7 @@ class EmfMetricsLoggerTest { private Metrics metrics; private final ObjectMapper objectMapper = new ObjectMapper(); - private final PrintStream standardOut = System.out; + private static final PrintStream standardOut = System.out; private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); @BeforeEach @@ -180,7 +180,7 @@ void shouldAddDimension() throws Exception { JsonNode dimensions = rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Dimensions").get(0); boolean hasDimension = false; for (JsonNode dimension : dimensions) { - if (dimension.asText().equals("CustomDimension")) { + if ("CustomDimension".equals(dimension.asText())) { hasDimension = true; break; } @@ -233,9 +233,9 @@ void shouldAddDimensionSet() throws Exception { boolean hasDim2 = false; for (JsonNode dimension : dimensions) { String dimName = dimension.asText(); - if (dimName.equals("Dim1")) { + if ("Dim1".equals(dimName)) { hasDim1 = true; - } else if (dimName.equals("Dim2")) { + } else if ("Dim2".equals(dimName)) { hasDim2 = true; } } @@ -348,6 +348,8 @@ void shouldLogWarningOnEmptyMetrics() throws Exception { // Read the log file and check for the warning String logContent = new String(Files.readAllBytes(logFile.toPath()), StandardCharsets.UTF_8); assertThat(logContent).contains("No metrics were emitted"); + // No EMF output should be generated + assertThat(outputStreamCaptor.toString().trim()).isEmpty(); } @Test From eebc06ae150d4b04cc48bea67785ab019c7258a1 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Wed, 18 Jun 2025 19:02:43 +0200 Subject: [PATCH 252/577] feat(kafka): New Kafka utility (#1898) * Add initial code for KafkaJson and KafkaAvro request handlers. * Add deserialization via @Deserialization annotation. * Add TODOs in code. * Fix typos and make AbstractKafkaDeserializer package private. * Remove request handler implementation in favor for @Deserialization annotation. * Parse Timestamp type correctly. * Remove custom RequestHandler implementation example. * Make AspectJ version compatible with min version Java 11. * Clarify exception message when deserialization fails. * Add more advanced JSON escpaing to JSONSerializer in logging module. * Add protobuf deserialization logic and fully working example. * Add Maven profile to compile a JAR with different dependency combinations. * Add minimal kafka example. * Add missing copyright. * Add unit tests for kafka utility. * Add minimal kafka example to examples module in pom.xml. * Add some comments. * Update powertools-examples-kafka with README and make it more minimalistic. Remove powertools-examples-kafka-minimal. * Implement PR feedback from Karthik. * Fix SAM outputs. * Do not fail on unknown properties when deserializating into KafkaEvent. * Allow customers to bring their own kafka-clients dependency. * Add Kafka utility documentation. * Update project version consistently to 2.0.0. * fix: Fix bug where abbreviated _HANDLER env var did not detect the Deserialization annotation. * fix: Bug when trying to deserialize a type into itself for Lambda default behavior. We can just return the type itself. Relevant for simple String and InputStream handlers. * When falling back to Lambda default, handle conversion between InputStream and String. * Raise a runtime exception when the KafkaEvent is invalid. * docs: Announce deprecation of v1 * fix(metrics): Do not flush when no metrics were added to avoid printing root-level _aws dict (#1891) * fix(metrics): Do not flush when no metrics were added to avoid printing root-level _aws dict. * Fix pmd linting failures. * Rename docs to Kafka Consumer and add line highlights for code examples. * Fix Spotbug issues. * Reduce cognitive complexity of DeserializationUtils making it more modular and representing handler information in a simple HandlerInfo class. * Reduce cognitive complexity of AbstractKafkaDeserializer. * Enable removal policy DESTROY on e2e test for kinesis streams and SQS queues to avoid exceeding account limit. * Replace System.out with Powertools Logging. * Add notice about kafka-clients compatibility. * Add sentence stating that Avro / Protobuf classes can be autogenerated. --- docs/utilities/kafka.md | 1001 +++++++++++++++++ examples/pom.xml | 3 +- examples/powertools-examples-kafka/README.md | 77 ++ .../events/kafka-avro-event.json | 51 + .../events/kafka-json-event.json | 51 + .../events/kafka-protobuf-event.json | 51 + examples/powertools-examples-kafka/pom.xml | 232 ++++ .../src/main/avro/AvroProduct.avsc | 10 + .../kafka/AvroDeserializationFunction.java | 37 + .../kafka/JsonDeserializationFunction.java | 35 + .../src/main/java/org/demo/kafka/Product.java | 63 ++ .../ProtobufDeserializationFunction.java | 38 + .../java/org/demo/kafka/avro/AvroProduct.java | 476 ++++++++ .../demo/kafka/protobuf/ProtobufProduct.java | 636 +++++++++++ .../protobuf/ProtobufProductOrBuilder.java | 36 + .../protobuf/ProtobufProductOuterClass.java | 63 ++ .../src/main/proto/ProtobufProduct.proto | 13 + .../src/main/resources/log4j2.xml | 16 + .../powertools-examples-kafka/template.yaml | 59 + .../powertools-examples-kafka/tools/README.md | 66 ++ .../powertools-examples-kafka/tools/pom.xml | 104 ++ .../java/org/demo/kafka/avro/AvroProduct.java | 476 ++++++++ .../demo/kafka/protobuf/ProtobufProduct.java | 636 +++++++++++ .../protobuf/ProtobufProductOrBuilder.java | 36 + .../protobuf/ProtobufProductOuterClass.java | 63 ++ .../demo/kafka/tools/GenerateAvroSamples.java | 121 ++ .../demo/kafka/tools/GenerateJsonSamples.java | 126 +++ .../kafka/tools/GenerateProtobufSamples.java | 125 ++ mkdocs.yml | 7 +- pom.xml | 7 +- powertools-e2e-tests/handlers/batch/pom.xml | 2 +- .../handlers/idempotency/pom.xml | 2 +- .../handlers/largemessage/pom.xml | 2 +- .../handlers/largemessage_idempotent/pom.xml | 2 +- powertools-e2e-tests/handlers/logging/pom.xml | 2 +- powertools-e2e-tests/handlers/metrics/pom.xml | 2 +- .../handlers/parameters/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 4 +- powertools-e2e-tests/handlers/tracing/pom.xml | 2 +- .../handlers/validation-alb-event/pom.xml | 2 +- .../handlers/validation-apigw-event/pom.xml | 2 +- .../powertools/testutils/Infrastructure.java | 2 + powertools-kafka/pom.xml | 223 ++++ .../powertools/kafka/Deserialization.java | 31 + .../powertools/kafka/DeserializationType.java | 17 + .../kafka/PowertoolsSerializer.java | 67 ++ .../kafka/internal/DeserializationUtils.java | 96 ++ .../AbstractKafkaDeserializer.java | 294 +++++ .../serializers/KafkaAvroDeserializer.java | 46 + .../serializers/KafkaJsonDeserializer.java | 29 + .../KafkaProtobufDeserializer.java | 43 + .../LambdaDefaultDeserializer.java | 65 ++ .../serializers/PowertoolsDeserializer.java | 27 + ...rvices.lambda.runtime.CustomPojoSerializer | 1 + .../src/test/avro/TestProduct.avsc | 10 + .../powertools/kafka/DeserializationTest.java | 71 ++ .../kafka/DeserializationTypeTest.java | 50 + .../kafka/PowertoolsSerializerTest.java | 417 +++++++ .../internal/DeserializationUtilsTest.java | 145 +++ .../AbstractKafkaDeserializerTest.java | 473 ++++++++ .../KafkaAvroDeserializerTest.java | 73 ++ .../KafkaJsonDeserializerTest.java | 66 ++ .../KafkaProtobufDeserializerTest.java | 75 ++ .../kafka/testutils/AvroHandler.java | 30 + .../kafka/testutils/DefaultHandler.java | 29 + .../kafka/testutils/InputStreamHandler.java | 30 + .../kafka/testutils/JsonHandler.java | 29 + .../kafka/testutils/ProtobufHandler.java | 30 + .../kafka/testutils/StringHandler.java | 23 + .../kafka/testutils/TestProductPojo.java | 87 ++ .../powertools/kafka/testutils/TestUtils.java | 75 ++ .../src/test/proto/TestProduct.proto | 13 + .../test/resources/simplelogger.properties | 13 + .../internal/LambdaEcsEncoderTest.java | 2 +- .../internal/LambdaJsonEncoderTest.java | 2 +- .../logging/internal/JsonSerializer.java | 11 +- 76 files changed, 7413 insertions(+), 21 deletions(-) create mode 100644 docs/utilities/kafka.md create mode 100644 examples/powertools-examples-kafka/README.md create mode 100644 examples/powertools-examples-kafka/events/kafka-avro-event.json create mode 100644 examples/powertools-examples-kafka/events/kafka-json-event.json create mode 100644 examples/powertools-examples-kafka/events/kafka-protobuf-event.json create mode 100644 examples/powertools-examples-kafka/pom.xml create mode 100644 examples/powertools-examples-kafka/src/main/avro/AvroProduct.avsc create mode 100644 examples/powertools-examples-kafka/src/main/java/org/demo/kafka/AvroDeserializationFunction.java create mode 100644 examples/powertools-examples-kafka/src/main/java/org/demo/kafka/JsonDeserializationFunction.java create mode 100644 examples/powertools-examples-kafka/src/main/java/org/demo/kafka/Product.java create mode 100644 examples/powertools-examples-kafka/src/main/java/org/demo/kafka/ProtobufDeserializationFunction.java create mode 100644 examples/powertools-examples-kafka/src/main/java/org/demo/kafka/avro/AvroProduct.java create mode 100644 examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java create mode 100644 examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java create mode 100644 examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java create mode 100644 examples/powertools-examples-kafka/src/main/proto/ProtobufProduct.proto create mode 100644 examples/powertools-examples-kafka/src/main/resources/log4j2.xml create mode 100644 examples/powertools-examples-kafka/template.yaml create mode 100644 examples/powertools-examples-kafka/tools/README.md create mode 100644 examples/powertools-examples-kafka/tools/pom.xml create mode 100644 examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/avro/AvroProduct.java create mode 100644 examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java create mode 100644 examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java create mode 100644 examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java create mode 100644 examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateAvroSamples.java create mode 100644 examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateJsonSamples.java create mode 100644 examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java create mode 100644 powertools-kafka/pom.xml create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/Deserialization.java create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/DeserializationType.java create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializer.java create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/DeserializationUtils.java create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializer.java create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializer.java create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializer.java create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/LambdaDefaultDeserializer.java create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/PowertoolsDeserializer.java create mode 100644 powertools-kafka/src/main/resources/META-INF/services/com.amazonaws.services.lambda.runtime.CustomPojoSerializer create mode 100644 powertools-kafka/src/test/avro/TestProduct.avsc create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/DeserializationTest.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/DeserializationTypeTest.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializerTest.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/DeserializationUtilsTest.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializerTest.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializerTest.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializerTest.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/AvroHandler.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/DefaultHandler.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/InputStreamHandler.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/JsonHandler.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/ProtobufHandler.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/StringHandler.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/TestProductPojo.java create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/TestUtils.java create mode 100644 powertools-kafka/src/test/proto/TestProduct.proto create mode 100644 powertools-kafka/src/test/resources/simplelogger.properties diff --git a/docs/utilities/kafka.md b/docs/utilities/kafka.md new file mode 100644 index 000000000..da179bc5c --- /dev/null +++ b/docs/utilities/kafka.md @@ -0,0 +1,1001 @@ +--- +title: Kafka Consumer +description: Utility +status: new +--- + + + +The Kafka utility transparently handles message deserialization, provides an intuitive developer experience, and integrates seamlessly with the rest of the Powertools for AWS Lambda ecosystem. + +```mermaid +flowchart LR + KafkaTopic["Kafka Topic"] --> MSK["Amazon MSK"] + KafkaTopic --> MSKServerless["Amazon MSK Serverless"] + KafkaTopic --> SelfHosted["Self-hosted Kafka"] + MSK --> EventSourceMapping["Event Source Mapping"] + MSKServerless --> EventSourceMapping + SelfHosted --> EventSourceMapping + EventSourceMapping --> Lambda["Lambda Function"] + Lambda --> KafkaUtility["Kafka Utility"] + KafkaUtility --> Deserialization["Deserialization"] + Deserialization --> YourLogic["Your Business Logic"] +``` + +## Key features + +- Automatic deserialization of Kafka messages (JSON, Avro, and Protocol Buffers) +- Simplified event record handling with familiar Kafka `ConsumerRecords` interface +- Support for key and value deserialization +- Support for ESM with and without Schema Registry integration +- Proper error handling for deserialization issues + +## Terminology + +**Event Source Mapping (ESM)** A Lambda feature that reads from streaming sources (like Kafka) and invokes your Lambda function. It manages polling, batching, and error handling automatically, eliminating the need for consumer management code. + +**Record Key and Value** A Kafka messages contain two important parts: an optional key that determines the partition and a value containing the actual message data. Both are base64-encoded in Lambda events and can be independently deserialized. + +**Deserialization** Is the process of converting binary data (base64-encoded in Lambda events) into usable Java objects according to a specific format like JSON, Avro, or Protocol Buffers. Powertools handles this conversion automatically. + +**DeserializationType enum** Contains parameters that tell Powertools how to interpret message data, including the format type (JSON, Avro, Protocol Buffers). + +**Schema Registry** Is a centralized service that stores and validates schemas, ensuring producers and consumers maintain compatibility when message formats evolve over time. + +## Moving from traditional Kafka consumers + +Lambda processes Kafka messages as discrete events rather than continuous streams, requiring a different approach to consumer development that Powertools for AWS helps standardize. + +| Aspect | Traditional Kafka Consumers | Lambda Kafka Consumer | +| --------------------- | ----------------------------------- | -------------------------------------------------------------- | +| **Model** | Pull-based (you poll for messages) | Push-based (Lambda invoked with messages) | +| **Scaling** | Manual scaling configuration | Automatic scaling to partition count | +| **State** | Long-running application with state | Stateless, ephemeral executions | +| **Offsets** | Manual offset management | Automatic offset commitment | +| **Schema Validation** | Client-side schema validation | Optional Schema Registry integration with Event Source Mapping | +| **Error Handling** | Per-message retry control | Batch-level retry policies | + +## Getting started + +### Installation + +Add the Powertools for AWS Lambda Kafka dependency to your project. Make sure to also add the `kafka-clients` library as a dependency. The utility supports `kafka-clients >= 3.0.0`. + +=== "Maven" + + ```xml + + software.amazon.lambda + powertools-kafka + {{ powertools.version }} + + + + org.apache.kafka + kafka-clients + 4.0.0 + + ``` + +=== "Gradle" + + ```gradle + dependencies { + implementation 'software.amazon.lambda:powertools-kafka:{{ powertools.version }}' + // Kafka clients dependency - compatibility works for >= 3.0.0 + implementation 'org.apache.kafka:kafka-clients:4.0.0' + } + ``` + +### Required resources + +To use the Kafka utility, you need an AWS Lambda function configured with a Kafka event source. This can be Amazon MSK, MSK Serverless, or a self-hosted Kafka cluster. + +=== "getting_started_with_msk.yaml" + + ```yaml + AWSTemplateFormatVersion: '2010-09-09' + Transform: AWS::Serverless-2016-10-31 + Resources: + KafkaConsumerFunction: + Type: AWS::Serverless::Function + Properties: + Handler: org.example.KafkaHandler::handleRequest + Runtime: java21 + Timeout: 30 + Events: + MSKEvent: + Type: MSK + Properties: + StartingPosition: LATEST + Stream: !GetAtt MyMSKCluster.Arn + Topics: + - my-topic-1 + - my-topic-2 + Policies: + - AWSLambdaMSKExecutionRole + ``` + +### Using ESM with Schema Registry + +The Event Source Mapping configuration determines which mode is used. With `JSON`, Lambda converts all messages to JSON before invoking your function. With `SOURCE` mode, Lambda preserves the original format, requiring you function to handle the appropriate deserialization. + +Powertools for AWS supports both Schema Registry integration modes in your Event Source Mapping configuration. + +### Processing Kafka events + +The Kafka utility transforms raw Lambda Kafka events into an intuitive format for processing. To handle messages effectively, you'll need to configure the `@Deserialization` annotation that matches your data format. Based on the deserializer you choose, incoming records are directly transformed into your business objects which can be auto-generated classes from Avro / Protobuf or simple POJOs. + + +???+ tip "Using Avro is recommended" + We recommend Avro for production Kafka implementations due to its schema evolution capabilities, compact binary format, and integration with Schema Registry. This offers better type safety and forward/backward compatibility compared to JSON. + +=== "Avro Messages" + + ```java hl_lines="18 21" + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.logging.Logging; + + public class AvroKafkaHandler implements RequestHandler, String> { + private static final Logger LOGGER = LoggerFactory.getLogger(AvroKafkaHandler.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_AVRO) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord record : records) { + User user = record.value(); // User class is auto-generated from Avro schema + LOGGER.info("Processing user: {}, age {}", user.getName(), user.getAge()); + } + return "OK"; + } + } + ``` + +=== "Protocol Buffers" + + ```java hl_lines="18 21" + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.logging.Logging; + + public class ProtobufKafkaHandler implements RequestHandler, String> { + private static final Logger LOGGER = LoggerFactory.getLogger(ProtobufKafkaHandler.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_PROTOBUF) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord record : records) { + UserProto.User user = record.value(); // UserProto.User class is auto-generated from Protocol Buffer schema + LOGGER.info("Processing user: {}, age {}", user.getName(), user.getAge()); + } + return "OK"; + } + } + ``` + +=== "JSON Messages" + + ```java hl_lines="18 21" + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.logging.Logging; + + public class JsonKafkaHandler implements RequestHandler, String> { + private static final Logger LOGGER = LoggerFactory.getLogger(JsonKafkaHandler.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_JSON) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord record : records) { + User user = record.value(); // Deserialized JSON object into User POJO + LOGGER.info("Processing user: {}, age {}", user.getName(), user.getAge()); + } + return "OK"; + } + } + ``` + + +???+ tip "Full examples on GitHub" + A full example including how to generate Avro and Protobuf Java classes can be found on GitHub at [https://github.com/aws-powertools/powertools-lambda-java/tree/main/examples/powertools-examples-kafka](https://github.com/aws-powertools/powertools-lambda-java/tree/main/examples/powertools-examples-kafka). + +### Deserializing keys and values + +The `@Deserialization` annotation deserializes both keys and values based on your type configuration. This flexibility allows you to work with different data formats in the same message. + +=== "Key and Value Deserialization" + + ```java hl_lines="22" + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.logging.Logging; + + public class KeyValueKafkaHandler implements RequestHandler, String> { + private static final Logger LOGGER = LoggerFactory.getLogger(KeyValueKafkaHandler.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_AVRO) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord record : records) { + // Access both deserialized components + ProductKey key = record.key(); // ProductKey class is auto-generated from Avro schema + ProductInfo product = record.value(); // ProductInfo class is auto-generated from Avro schema + + LOGGER.info("Processing product ID: {}", key.getProductId()); + LOGGER.info("Product: {} - ${}", product.getName(), product.getPrice()); + } + return "OK"; + } + } + ``` + +=== "Value-Only Deserialization" + + ```java hl_lines="22" + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.logging.Logging; + + public class ValueOnlyKafkaHandler implements RequestHandler, String> { + private static final Logger LOGGER = LoggerFactory.getLogger(ValueOnlyKafkaHandler.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_JSON) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord record : records) { + // Key remains as string (if present) + String key = record.key(); + if (key != null) { + LOGGER.info("Message key: {}", key); + } + + // Value is deserialized as JSON + Order order = record.value(); + LOGGER.info("Order #{} - Total: ${}", order.getOrderId(), order.getTotal()); + } + return "OK"; + } + } + ``` + +### Handling primitive types + +When working with primitive data types (strings, integers, etc.) rather than structured objects, you can use any deserialization type such as `KAFKA_JSON`. Simply place the primitive type like `Integer` or `String` in the `ConsumerRecords` generic type parameters, and the library will automatically handle primitive type deserialization. + + +???+ tip "Common pattern: Keys with primitive values" + Using primitive types (strings, integers) as Kafka message keys is a common pattern for partitioning and identifying messages. Powertools automatically handles these primitive keys without requiring special configuration, making it easy to implement this popular design pattern. + +=== "Primitive key" + + ```java hl_lines="18 22" + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.logging.Logging; + + public class PrimitiveKeyHandler implements RequestHandler, String> { + private static final Logger LOGGER = LoggerFactory.getLogger(PrimitiveKeyHandler.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_JSON) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord record : records) { + // Key is automatically deserialized as Integer + Integer key = record.key(); + + // Value is deserialized as JSON + Customer customer = record.value(); + + LOGGER.info("Key: {}", key); + LOGGER.info("Name: {}", customer.getName()); + LOGGER.info("Email: {}", customer.getEmail()); + } + return "OK"; + } + } + ``` + +=== "Primitive key and value" + + ```java hl_lines="18 22" + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.logging.Logging; + + public class PrimitiveHandler implements RequestHandler, String> { + private static final Logger LOGGER = LoggerFactory.getLogger(PrimitiveHandler.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_JSON) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord record : records) { + // Key is automatically deserialized as String + String key = record.key(); + + // Value is automatically deserialized as String + String value = record.value(); + + LOGGER.info("Key: {}", key); + LOGGER.info("Value: {}", value); + } + return "OK"; + } + } + ``` + +### Message format support and comparison + +The Kafka utility supports multiple serialization formats to match your existing Kafka implementation. Choose the format that best suits your needs based on performance, schema evolution requirements, and ecosystem compatibility. + + +???+ tip "Selecting the right format" + For new applications, consider Avro or Protocol Buffers over JSON. Both provide schema validation, evolution support, and significantly better performance with smaller message sizes. Avro is particularly well-suited for Kafka due to its built-in schema evolution capabilities. + +=== "Supported Formats" + + | Format | DeserializationType | Description | Required Dependencies | + |--------|---------------------|-------------|----------------------| + | **JSON** | `KAFKA_JSON` | Human-readable text format | Jackson | + | **Avro** | `KAFKA_AVRO` | Compact binary format with schema | Apache Avro | + | **Protocol Buffers** | `KAFKA_PROTOBUF` | Efficient binary format | Protocol Buffers | + | **Lambda Default** | `LAMBDA_DEFAULT` | Uses Lambda's built-in deserialization (equivalent to removing the `@Deserialization` annotation) | None | + +=== "Format Comparison" + + | Feature | JSON | Avro | Protocol Buffers | + |---------|------|------|-----------------| + | **Schema Definition** | Optional | Required schema file | Required .proto file | + | **Schema Evolution** | None | Strong support | Strong support | + | **Size Efficiency** | Low | High | Highest | + | **Processing Speed** | Slower | Fast | Fastest | + | **Human Readability** | High | Low | Low | + | **Implementation Complexity** | Low | Medium | Medium | + | **Additional Dependencies** | None | Apache Avro | Protocol Buffers | + +Choose the serialization format that best fits your needs: + +- **JSON**: Best for simplicity and when schema flexibility is important +- **Avro**: Best for systems with evolving schemas and when compatibility is critical +- **Protocol Buffers**: Best for performance-critical systems with structured data +- **Lambda Default**: Best for simple string-based messages or when using Lambda's built-in deserialization + +## Advanced + +### Accessing record metadata + +Each Kafka record contains important metadata that you can access alongside the deserialized message content. This metadata helps with message processing, troubleshooting, and implementing advanced patterns like exactly-once processing. + +=== "Working with Record Metadata" + + ```java + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.apache.kafka.common.header.Header; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.logging.Logging; + + public class MetadataKafkaHandler implements RequestHandler, String> { + private static final Logger LOGGER = LoggerFactory.getLogger(MetadataKafkaHandler.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_AVRO) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord record : records) { + // Log record coordinates for tracing + LOGGER.info("Processing message from topic '{}'", record.topic()); + LOGGER.info(" Partition: {}, Offset: {}", record.partition(), record.offset()); + LOGGER.info(" Produced at: {}", record.timestamp()); + + // Process message headers + if (record.headers() != null) { + for (Header header : record.headers()) { + LOGGER.info(" Header: {} = {}", + header.key(), new String(header.value())); + } + } + + // Access the Avro deserialized message content + Customer customer = record.value(); // Customer class is auto-generated from Avro schema + LOGGER.info("Processing order for: {}", customer.getName()); + LOGGER.info("Order total: ${}", customer.getOrderTotal()); + } + return "OK"; + } + } + ``` + +#### Available metadata properties + +| Property | Description | Example Use Case | +| ----------------- | ----------------------------------------------- | ------------------------------------------- | +| `topic()` | Topic name the record was published to | Routing logic in multi-topic consumers | +| `partition()` | Kafka partition number | Tracking message distribution | +| `offset()` | Position in the partition | De-duplication, exactly-once processing | +| `timestamp()` | Unix timestamp when record was created | Event timing analysis | +| `timestampType()` | Timestamp type (CREATE_TIME or LOG_APPEND_TIME) | Data lineage verification | +| `headers()` | Key-value pairs attached to the message | Cross-cutting concerns like correlation IDs | +| `key()` | Deserialized message key | Customer ID or entity identifier | +| `value()` | Deserialized message content | The actual business data | + +### Error handling + +Handle errors gracefully when processing Kafka messages to ensure your application maintains resilience and provides clear diagnostic information. The Kafka utility integrates with standard Java exception handling patterns. + + +!!! info "Treating Deserialization errors" + Read [Deserialization failures](#deserialization-failures). Deserialization failures will fail the whole batch and do not execute your handler. + +=== "Error Handling" + + ```java + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.metrics.FlushMetrics; + import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.MetricsFactory; + import software.amazon.lambda.powertools.metrics.model.MetricUnit; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + + public class ErrorHandlingKafkaHandler implements RequestHandler, String> { + + private static final Logger LOGGER = LoggerFactory.getLogger(ErrorHandlingKafkaHandler.class); + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + + @Override + @Logging + @FlushMetrics(namespace = "KafkaProcessing", service = "order-processing") + @Deserialization(type = DeserializationType.KAFKA_AVRO) + public String handleRequest(ConsumerRecords records, Context context) { + metrics.addMetric("TotalRecords", records.count(), MetricUnit.COUNT); + int successfulRecords = 0; + int failedRecords = 0; + + for (ConsumerRecord record : records) { + try { + Order order = record.value(); // Order class is auto-generated from Avro schema + processOrder(order); + successfulRecords++; + metrics.addMetric("ProcessedRecords", 1, MetricUnit.COUNT); + } catch (Exception e) { + failedRecords++; + LOGGER.error("Error processing Kafka message from topic: {}, partition: {}, offset: {}", + record.topic(), record.partition(), record.offset(), e); + metrics.addMetric("ProcessingErrors", 1, MetricUnit.COUNT); + // Optionally send to DLQ or error topic + sendToDlq(record); + } + } + + return String.format("Processed %d records successfully, %d failed", + successfulRecords, failedRecords); + } + + private void processOrder(Order order) { + // Your business logic here + LOGGER.info("Processing order: {}", order.getOrderId()); + } + + private void sendToDlq(ConsumerRecord record) { + // Implementation to send failed records to dead letter queue + } + } + ``` + +### Integrating with Idempotency + +When processing Kafka messages in Lambda, failed batches can result in message reprocessing. The idempotency utility prevents duplicate processing by tracking which messages have already been handled, ensuring each message is processed exactly once. + +The Idempotency utility automatically stores the result of each successful operation, returning the cached result if the same message is processed again, which prevents potentially harmful duplicate operations like double-charging customers or double-counting metrics. + +=== "Idempotent Kafka Processing" + + ```java + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.idempotency.Idempotency; + import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; + import software.amazon.lambda.powertools.idempotency.Idempotent; + import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; + import software.amazon.lambda.powertools.logging.Logging; + + public class IdempotentKafkaHandler implements RequestHandler, String> { + private static final Logger LOGGER = LoggerFactory.getLogger(IdempotentKafkaHandler.class); + + public IdempotentKafkaHandler() { + // Configure idempotency with DynamoDB persistence store + Idempotency.config() + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withTableName("IdempotencyTable") + .build()) + .configure(); + } + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_JSON) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord record : records) { + // Payment class deserialized from JSON + Payment payment = record.value(); + + // Process each message with idempotency protection + processPayment(payment); + } + return "OK"; + } + + @Idempotent + private void processPayment(Payment payment) { + LOGGER.info("Processing payment {}", payment.getPaymentId()); + + // Your business logic here + PaymentService.process(payment.getPaymentId(), payment.getCustomerId(), payment.getAmount()); + } + } + ``` + + +???+ tip "Ensuring exactly-once processing" + The `@Idempotent` annotation will use the JSON representation of the Payment object to make sure that the same object is only processed exactly once. Even if a batch fails and Lambda retries the messages, each unique payment will be processed exactly once. + +### Best practices + +#### Batch size configuration + +The number of Kafka records processed per Lambda invocation is controlled by your Event Source Mapping configuration. Properly sized batches optimize cost and performance. + +=== "Batch size configuration" + + ```yaml + Resources: + OrderProcessingFunction: + Type: AWS::Serverless::Function + Properties: + Handler: org.example.OrderHandler::handleRequest + Runtime: java21 + Events: + KafkaEvent: + Type: MSK + Properties: + Stream: !GetAtt OrdersMSKCluster.Arn + Topics: + - order-events + - payment-events + # Configuration for optimal throughput/latency balance + BatchSize: 100 + MaximumBatchingWindowInSeconds: 5 + StartingPosition: LATEST + # Enable partial batch success reporting + FunctionResponseTypes: + - ReportBatchItemFailures + ``` + +Different workloads benefit from different batch configurations: + +- **High-volume, simple processing**: Use larger batches (100-500 records) with short timeout +- **Complex processing with database operations**: Use smaller batches (10-50 records) +- **Mixed message sizes**: Set appropriate batching window (1-5 seconds) to handle variability + +#### Cross-language compatibility + +When using binary serialization formats across multiple programming languages, ensure consistent schema handling to prevent deserialization failures. + +=== "Using Python naming convention" + + ```java hl_lines="33 36 39 42 56" + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.kafka.Deserialization; + import software.amazon.lambda.powertools.kafka.DeserializationType; + import software.amazon.lambda.powertools.logging.Logging; + import com.fasterxml.jackson.annotation.JsonProperty; + import java.time.Instant; + + public class CrossLanguageKafkaHandler implements RequestHandler, String> { + private static final Logger LOGGER = LoggerFactory.getLogger(CrossLanguageKafkaHandler.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_JSON) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord record : records) { + OrderEvent order = record.value(); // OrderEvent class handles JSON with Python field names + LOGGER.info("Processing order {} from {}", + order.getOrderId(), order.getOrderDate()); + } + return "OK"; + } + } + + // Example class that handles Python snake_case field names + public class OrderEvent { + @JsonProperty("order_id") + private String orderId; + + @JsonProperty("customer_id") + private String customerId; + + @JsonProperty("total_amount") + private double totalAmount; + + @JsonProperty("order_date") + private long orderDateMillis; + + // Getters and setters + public String getOrderId() { return orderId; } + public void setOrderId(String orderId) { this.orderId = orderId; } + + public String getCustomerId() { return customerId; } + public void setCustomerId(String customerId) { this.customerId = customerId; } + + public double getTotalAmount() { return totalAmount; } + public void setTotalAmount(double totalAmount) { this.totalAmount = totalAmount; } + + public Instant getOrderDate() { + return Instant.ofEpochMilli(orderDateMillis); + } + public void setOrderDate(long orderDateMillis) { + this.orderDateMillis = orderDateMillis; + } + } + ``` + +Common cross-language challenges to address: + +- **Field naming conventions**: camelCase in Java vs snake_case in Python +- **Date/time**: representation differences +- **Numeric precision handling**: especially decimals + +### Troubleshooting + +#### Deserialization failures + +The Java Kafka utility registers a [custom Lambda serializer](https://docs.aws.amazon.com/lambda/latest/dg/java-custom-serialization.html) that performs **eager deserialization** of all records in the batch before your handler method is invoked. + +This means that if any record in the batch fails deserialization, a `RuntimeException` will be thrown with a concrete error message explaining why deserialization failed, and your handler method will never be called. + +**Key implications:** + +- **Batch-level failure**: If one record fails deserialization, the entire batch fails +- **Early failure detection**: Deserialization errors are caught before your business logic runs +- **Clear error messages**: The `RuntimeException` provides specific details about what went wrong +- **No partial processing**: You cannot process some records while skipping failed ones within the same batch + +**Example of deserialization failure:** + +```java +// If any record in the batch has invalid Avro data, you'll see: +// RuntimeException: Failed to deserialize Kafka record: Invalid Avro schema for record at offset 12345 +``` + + +!!! warning "Handler method not invoked on deserialization failure" + When deserialization fails, your `handleRequest` method will not be invoked at all. The `RuntimeException` is thrown before your handler code runs, preventing any processing of the batch. + +**Handling deserialization failures:** + +Since deserialization happens before your handler is called, you cannot catch these exceptions within your handler method. Instead, configure your Event Source Mapping with appropriate error handling: + +- **Dead Letter Queue (DLQ)**: Configure a DLQ to capture failed batches for later analysis +- **Maximum Retry Attempts**: Set appropriate retry limits to avoid infinite retries +- **Batch Size**: Use smaller batch sizes to minimize the impact of individual record failures + +```yaml +# Example SAM template configuration for error handling +Events: + KafkaEvent: + Type: MSK + Properties: + # ... other properties + BatchSize: 10 # Smaller batches reduce failure impact + MaximumRetryAttempts: 3 + DestinationConfig: + OnFailure: + Type: SQS + Destination: !GetAtt DeadLetterQueue.Arn +``` + +#### Schema compatibility issues + +Schema compatibility issues often manifest as successful connections but failed deserialization. Common causes include: + +- **Schema evolution without backward compatibility**: New producer schema is incompatible with consumer schema +- **Field type mismatches**: For example, a field changed from String to Integer across systems +- **Missing required fields**: Fields required by the consumer schema but absent in the message +- **Default value discrepancies**: Different handling of default values between languages + +When using Schema Registry, verify schema compatibility rules are properly configured for your topics and that all applications use the same registry. + +#### Memory and timeout optimization + +Lambda functions processing Kafka messages may encounter resource constraints, particularly with large batches or complex processing logic. + +For memory errors: + +- Increase Lambda memory allocation, which also provides more CPU resources +- Process fewer records per batch by adjusting the `BatchSize` parameter in your event source mapping +- Consider optimizing your message format to reduce memory footprint + +For timeout issues: + +- Extend your Lambda function timeout setting to accommodate processing time +- Implement chunked or asynchronous processing patterns for time-consuming operations +- Monitor and optimize database operations, external API calls, or other I/O operations in your handler + + +???+ tip "Monitoring memory usage" + Use CloudWatch metrics to track your function's memory utilization. If it consistently exceeds 80% of allocated memory, consider increasing the memory allocation or optimizing your code. + +## Kafka workflow + +### Using ESM with Schema Registry validation (SOURCE) + +

    +```mermaid +sequenceDiagram + participant Kafka + participant ESM as Event Source Mapping + participant SchemaRegistry as Schema Registry + participant Lambda + participant KafkaUtility + participant YourCode + Kafka->>+ESM: Send batch of records + ESM->>+SchemaRegistry: Validate schema + SchemaRegistry-->>-ESM: Confirm schema is valid + ESM->>+Lambda: Invoke with validated records (still encoded) + Lambda->>+KafkaUtility: Pass Kafka event + KafkaUtility->>KafkaUtility: Parse event structure + loop For each record + KafkaUtility->>KafkaUtility: Decode base64 data + KafkaUtility->>KafkaUtility: Deserialize based on DeserializationType + end + KafkaUtility->>+YourCode: Provide ConsumerRecords + YourCode->>YourCode: Process records + YourCode-->>-KafkaUtility: Return result + KafkaUtility-->>-Lambda: Pass result back + Lambda-->>-ESM: Return response + ESM-->>-Kafka: Acknowledge processed batch +``` +
    + +### Using ESM with Schema Registry deserialization (JSON) + +
    +```mermaid +sequenceDiagram + participant Kafka + participant ESM as Event Source Mapping + participant SchemaRegistry as Schema Registry + participant Lambda + participant KafkaUtility + participant YourCode + Kafka->>+ESM: Send batch of records + ESM->>+SchemaRegistry: Validate and deserialize + SchemaRegistry->>SchemaRegistry: Deserialize records + SchemaRegistry-->>-ESM: Return deserialized data + ESM->>+Lambda: Invoke with pre-deserialized JSON records + Lambda->>+KafkaUtility: Pass Kafka event + KafkaUtility->>KafkaUtility: Parse event structure + loop For each record + KafkaUtility->>KafkaUtility: Decode base64 data + KafkaUtility->>KafkaUtility: Record is already deserialized + KafkaUtility->>KafkaUtility: Map to POJO (if specified) + end + KafkaUtility->>+YourCode: Provide ConsumerRecords + YourCode->>YourCode: Process records + YourCode-->>-KafkaUtility: Return result + KafkaUtility-->>-Lambda: Pass result back + Lambda-->>-ESM: Return response + ESM-->>-Kafka: Acknowledge processed batch +``` +
    + +### Using ESM without Schema Registry integration + +
    +```mermaid +sequenceDiagram + participant Kafka + participant Lambda + participant KafkaUtility + participant YourCode + Kafka->>+Lambda: Invoke with batch of records (direct integration) + Lambda->>+KafkaUtility: Pass raw Kafka event + KafkaUtility->>KafkaUtility: Parse event structure + loop For each record + KafkaUtility->>KafkaUtility: Decode base64 data + KafkaUtility->>KafkaUtility: Deserialize based on DeserializationType + end + KafkaUtility->>+YourCode: Provide ConsumerRecords + YourCode->>YourCode: Process records + YourCode-->>-KafkaUtility: Return result + KafkaUtility-->>-Lambda: Pass result back + Lambda-->>-Kafka: Acknowledge processed batch +``` +
    + +## Testing your code + +Testing Kafka consumer functions is straightforward with JUnit. You can construct Kafka `ConsumerRecords` in the default way provided by the kafka-clients library without needing a real Kafka cluster. + +=== "Testing your code" + + ```java + package org.example; + + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.events.KafkaEvent; + import org.apache.kafka.clients.consumer.ConsumerRecord; + import org.apache.kafka.clients.consumer.ConsumerRecords; + import org.apache.kafka.common.TopicPartition; + import org.junit.jupiter.api.Test; + import org.junit.jupiter.api.extension.ExtendWith; + import org.mockito.Mock; + import org.mockito.junit.jupiter.MockitoExtension; + import java.util.*; + + import static org.junit.jupiter.api.Assertions.*; + import static org.mockito.Mockito.*; + + @ExtendWith(MockitoExtension.class) + class KafkaHandlerTest { + + @Mock + private Context context; + + @Test + void testProcessJsonMessage() { + // Create a test Kafka event with JSON data + Order testOrder = new Order("12345", 99.95); + ConsumerRecord record = new ConsumerRecord<>( + "orders-topic", 0, 15L, null, testOrder); + + Map>> recordsMap = new HashMap<>(); + recordsMap.put(new TopicPartition("orders-topic", 0), Arrays.asList(record)); + ConsumerRecords records = new ConsumerRecords<>(recordsMap); + + // Create handler and invoke + JsonKafkaHandler handler = new JsonKafkaHandler(); + String response = handler.handleRequest(records, context); + + // Verify the response + assertEquals("OK", response); + } + + @Test + void testProcessMultipleRecords() { + // Create a test event with multiple records + Customer customer1 = new Customer("A1", "Alice"); + Customer customer2 = new Customer("B2", "Bob"); + + List> recordList = Arrays.asList( + new ConsumerRecord<>("customers-topic", 0, 10L, null, customer1), + new ConsumerRecord<>("customers-topic", 0, 11L, null, customer2) + ); + + Map>> recordsMap = new HashMap<>(); + recordsMap.put(new TopicPartition("customers-topic", 0), recordList); + ConsumerRecords records = new ConsumerRecords<>(recordsMap); + + // Create handler and invoke + JsonKafkaHandler handler = new JsonKafkaHandler(); + String response = handler.handleRequest(records, context); + + // Verify the response + assertEquals("OK", response); + } + } + ``` + +## Extra Resources + +### Lambda Custom Serializers Compatibility + +This Kafka utility uses [Lambda custom serializers](https://docs.aws.amazon.com/lambda/latest/dg/java-custom-serialization.html) to provide automatic deserialization of Kafka messages. + +**Important compatibility considerations:** + +- **Existing custom serializers**: This utility will not be compatible if you already use your own custom Lambda serializer in your project +- **Non-Kafka handlers**: Installing this library will not affect default Lambda serialization behavior for non-Kafka related handlers +- **Kafka-specific**: The custom serialization only applies to handlers annotated with `@Deserialization` +- **Lambda default fallback**: Using `@Deserialization(type = DeserializationType.LAMBDA_DEFAULT)` will proxy to Lambda's default serialization behavior + +**Need help with compatibility?** + +If you are blocked from adopting this utility due to existing custom serializers or other compatibility concerns, please contact us with your specific use-cases. We'd like to understand your requirements and explore potential solutions. + +For more information about Lambda custom serialization, see the [official AWS documentation](https://docs.aws.amazon.com/lambda/latest/dg/java-custom-serialization.html). diff --git a/examples/pom.xml b/examples/pom.xml index 6bedc015e..ea1e8d542 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -39,6 +39,7 @@ powertools-examples-parameters/sam powertools-examples-parameters/sam-graalvm powertools-examples-serialization + powertools-examples-kafka powertools-examples-batch powertools-examples-validation powertools-examples-cloudformation @@ -58,4 +59,4 @@ - \ No newline at end of file + diff --git a/examples/powertools-examples-kafka/README.md b/examples/powertools-examples-kafka/README.md new file mode 100644 index 000000000..76cd81cb9 --- /dev/null +++ b/examples/powertools-examples-kafka/README.md @@ -0,0 +1,77 @@ +# Powertools for AWS Lambda (Java) - Kafka Example + +This project demonstrates how to use Powertools for AWS Lambda (Java) to deserialize Kafka Lambda events directly into strongly typed Kafka ConsumerRecords using different serialization formats. + +## Overview + +The example showcases automatic deserialization of Kafka Lambda events into ConsumerRecords using three formats: +- JSON - Using standard JSON serialization +- Avro - Using Apache Avro schema-based serialization +- Protobuf - Using Google Protocol Buffers serialization + +Each format has its own Lambda function handler that demonstrates how to use the `@Deserialization` annotation with the appropriate `DeserializationType`, eliminating the need to handle complex deserialization logic manually. + +## Build and Deploy + +### Prerequisites +- [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) +- Java 11+ +- Maven + +### Build + +```bash +# Build the application +sam build +``` + +### Deploy + +```bash +# Deploy the application to AWS +sam deploy --guided +``` + +During the guided deployment, you'll be prompted to provide values for required parameters. After deployment, SAM will output the ARNs of the deployed Lambda functions. + +### Build with Different Serialization Formats + +The project includes Maven profiles to build with different serialization formats: + +```bash +# Build with JSON only (no Avro or Protobuf) +mvn clean package -P base + +# Build with Avro only +mvn clean package -P avro-only + +# Build with Protobuf only +mvn clean package -P protobuf-only + +# Build with all formats (default) +mvn clean package -P full +``` + +## Testing + +The `events` directory contains sample events for each serialization format: +- `kafka-json-event.json` - Sample event with JSON-serialized products +- `kafka-avro-event.json` - Sample event with Avro-serialized products +- `kafka-protobuf-event.json` - Sample event with Protobuf-serialized products + +You can use these events to test the Lambda functions: + +```bash +# Test the JSON deserialization function +sam local invoke JsonDeserializationFunction --event events/kafka-json-event.json + +# Test the Avro deserialization function +sam local invoke AvroDeserializationFunction --event events/kafka-avro-event.json + +# Test the Protobuf deserialization function +sam local invoke ProtobufDeserializationFunction --event events/kafka-protobuf-event.json +``` + +## Sample Generator Tool + +The project includes a tool to generate sample JSON, Avro, and Protobuf serialized data. See the [tools/README.md](tools/README.md) for more information. \ No newline at end of file diff --git a/examples/powertools-examples-kafka/events/kafka-avro-event.json b/examples/powertools-examples-kafka/events/kafka-avro-event.json new file mode 100644 index 000000000..8d6ef2210 --- /dev/null +++ b/examples/powertools-examples-kafka/events/kafka-avro-event.json @@ -0,0 +1,51 @@ +{ + "eventSource": "aws:kafka", + "eventSourceArn": "arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4", + "bootstrapServers": "b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092", + "records": { + "mytopic-0": [ + { + "topic": "mytopic", + "partition": 0, + "offset": 15, + "timestamp": 1545084650987, + "timestampType": "CREATE_TIME", + "key": "NDI=", + "value": "0g8MTGFwdG9wUrgehes/j0A=", + "headers": [ + { + "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] + } + ] + }, + { + "topic": "mytopic", + "partition": 0, + "offset": 16, + "timestamp": 1545084650988, + "timestampType": "CREATE_TIME", + "key": "NDI=", + "value": "1A8UU21hcnRwaG9uZVK4HoXrv4JA", + "headers": [ + { + "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] + } + ] + }, + { + "topic": "mytopic", + "partition": 0, + "offset": 17, + "timestamp": 1545084650989, + "timestampType": "CREATE_TIME", + "key": null, + "value": "1g8USGVhZHBob25lc0jhehSuv2JA", + "headers": [ + { + "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] + } + ] + } + ] + } +} diff --git a/examples/powertools-examples-kafka/events/kafka-json-event.json b/examples/powertools-examples-kafka/events/kafka-json-event.json new file mode 100644 index 000000000..7ffb9a3a6 --- /dev/null +++ b/examples/powertools-examples-kafka/events/kafka-json-event.json @@ -0,0 +1,51 @@ +{ + "eventSource": "aws:kafka", + "eventSourceArn": "arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4", + "bootstrapServers": "b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092", + "records": { + "mytopic-0": [ + { + "topic": "mytopic", + "partition": 0, + "offset": 15, + "timestamp": 1545084650987, + "timestampType": "CREATE_TIME", + "key": "NDI=", + "value": "eyJwcmljZSI6OTk5Ljk5LCJuYW1lIjoiTGFwdG9wIiwiaWQiOjEwMDF9", + "headers": [ + { + "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] + } + ] + }, + { + "topic": "mytopic", + "partition": 0, + "offset": 15, + "timestamp": 1545084650987, + "timestampType": "CREATE_TIME", + "key": "NDI=", + "value": "eyJwcmljZSI6NTk5Ljk5LCJuYW1lIjoiU21hcnRwaG9uZSIsImlkIjoxMDAyfQ==", + "headers": [ + { + "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] + } + ] + }, + { + "topic": "mytopic", + "partition": 0, + "offset": 15, + "timestamp": 1545084650987, + "timestampType": "CREATE_TIME", + "key": null, + "value": "eyJwcmljZSI6MTQ5Ljk5LCJuYW1lIjoiSGVhZHBob25lcyIsImlkIjoxMDAzfQ==", + "headers": [ + { + "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] + } + ] + } + ] + } +} diff --git a/examples/powertools-examples-kafka/events/kafka-protobuf-event.json b/examples/powertools-examples-kafka/events/kafka-protobuf-event.json new file mode 100644 index 000000000..b3e0139e3 --- /dev/null +++ b/examples/powertools-examples-kafka/events/kafka-protobuf-event.json @@ -0,0 +1,51 @@ +{ + "eventSource": "aws:kafka", + "eventSourceArn": "arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4", + "bootstrapServers": "b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092", + "records": { + "mytopic-0": [ + { + "topic": "mytopic", + "partition": 0, + "offset": 15, + "timestamp": 1545084650987, + "timestampType": "CREATE_TIME", + "key": "NDI=", + "value": "COkHEgZMYXB0b3AZUrgehes/j0A=", + "headers": [ + { + "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] + } + ] + }, + { + "topic": "mytopic", + "partition": 0, + "offset": 16, + "timestamp": 1545084650988, + "timestampType": "CREATE_TIME", + "key": "NDI=", + "value": "COoHEgpTbWFydHBob25lGVK4HoXrv4JA", + "headers": [ + { + "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] + } + ] + }, + { + "topic": "mytopic", + "partition": 0, + "offset": 17, + "timestamp": 1545084650989, + "timestampType": "CREATE_TIME", + "key": null, + "value": "COsHEgpIZWFkcGhvbmVzGUjhehSuv2JA", + "headers": [ + { + "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] + } + ] + } + ] + } +} diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml new file mode 100644 index 000000000..a745ac75d --- /dev/null +++ b/examples/powertools-examples-kafka/pom.xml @@ -0,0 +1,232 @@ + + 4.0.0 + software.amazon.lambda.examples + 2.0.0 + powertools-examples-kafka + jar + Powertools for AWS Lambda (Java) - Examples - Kafka + + + 11 + 11 + 1.9.20.1 + 1.12.0 + 4.31.0 + + + + + software.amazon.lambda + powertools-kafka + ${project.version} + + + org.apache.kafka + kafka-clients + 4.0.0 + + + org.apache.avro + avro + ${avro.version} + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + + + software.amazon.lambda + powertools-logging-log4j + ${project.version} + + + org.aspectj + aspectjrt + ${aspectj.version} + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.1.4 + + true + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.0 + + + package + + shade + + + false + + + + + + + + + org.apache.logging.log4j + log4j-transform-maven-shade-plugin-extensions + 0.2.0 + + + + + dev.aspectj + aspectj-maven-plugin + 1.14 + + ${maven.compiler.source} + ${maven.compiler.target} + ${maven.compiler.target} + + + software.amazon.lambda + powertools-logging + + + + + + + compile + + + + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + org.apache.avro + avro-maven-plugin + ${avro.version} + + + generate-sources + + schema + + + ${project.basedir}/src/main/avro/ + ${project.basedir}/src/main/java/ + String + + + + + + + io.github.ascopes + protobuf-maven-plugin + 3.3.0 + + + + generate + + generate-sources + + ${protobuf.version} + + ${project.basedir}/src/main/proto + + ${project.basedir}/src/main/java + false + + + + + + + + + + + base + + base + + + + + org.apache.avro + avro + ${avro.version} + provided + + + com.google.protobuf + protobuf-java + ${protobuf.version} + provided + + + + + + + avro-only + + avro-only + + + + com.google.protobuf + protobuf-java + ${protobuf.version} + provided + + + + + + + protobuf-only + + protobuf-only + + + + org.apache.avro + avro + ${avro.version} + provided + + + + + + + full + + true + + + full + + + + diff --git a/examples/powertools-examples-kafka/src/main/avro/AvroProduct.avsc b/examples/powertools-examples-kafka/src/main/avro/AvroProduct.avsc new file mode 100644 index 000000000..7155857ea --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/avro/AvroProduct.avsc @@ -0,0 +1,10 @@ +{ + "namespace": "org.demo.kafka.avro", + "type": "record", + "name": "AvroProduct", + "fields": [ + {"name": "id", "type": "int"}, + {"name": "name", "type": "string"}, + {"name": "price", "type": "double"} + ] +} diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/AvroDeserializationFunction.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/AvroDeserializationFunction.java new file mode 100644 index 000000000..72f383eef --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/AvroDeserializationFunction.java @@ -0,0 +1,37 @@ +package org.demo.kafka; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.demo.kafka.avro.AvroProduct; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.kafka.Deserialization; +import software.amazon.lambda.powertools.kafka.DeserializationType; +import software.amazon.lambda.powertools.logging.Logging; + +public class AvroDeserializationFunction implements RequestHandler, String> { + + private static final Logger LOGGER = LoggerFactory.getLogger(AvroDeserializationFunction.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_AVRO) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord consumerRecord : records) { + LOGGER.info("ConsumerRecord: {}", consumerRecord); + + AvroProduct product = consumerRecord.value(); + LOGGER.info("AvroProduct: {}", product); + + String key = consumerRecord.key(); + LOGGER.info("Key: {}", key); + } + + return "OK"; + } + +} diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/JsonDeserializationFunction.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/JsonDeserializationFunction.java new file mode 100644 index 000000000..c1d7f13ae --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/JsonDeserializationFunction.java @@ -0,0 +1,35 @@ +package org.demo.kafka; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.kafka.Deserialization; +import software.amazon.lambda.powertools.kafka.DeserializationType; +import software.amazon.lambda.powertools.logging.Logging; + +public class JsonDeserializationFunction implements RequestHandler, String> { + + private static final Logger LOGGER = LoggerFactory.getLogger(JsonDeserializationFunction.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_JSON) + public String handleRequest(ConsumerRecords consumerRecords, Context context) { + for (ConsumerRecord consumerRecord : consumerRecords) { + LOGGER.info("ConsumerRecord: {}", consumerRecord); + + Product product = consumerRecord.value(); + LOGGER.info("Product: {}", product); + + String key = consumerRecord.key(); + LOGGER.info("Key: {}", key); + } + + return "OK"; + } +} diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/Product.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/Product.java new file mode 100644 index 000000000..c6166090c --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/Product.java @@ -0,0 +1,63 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.demo.kafka; + +public class Product { + private long id; + private String name; + private double price; + + public Product() { + } + + public Product(long id, String name, double price) { + this.id = id; + this.name = name; + this.price = price; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + @Override + public String toString() { + return "Product{" + + "id=" + id + + ", name='" + name + '\'' + + ", price=" + price + + '}'; + } +} diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/ProtobufDeserializationFunction.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/ProtobufDeserializationFunction.java new file mode 100644 index 000000000..1978e8890 --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/ProtobufDeserializationFunction.java @@ -0,0 +1,38 @@ +package org.demo.kafka; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.demo.kafka.protobuf.ProtobufProduct; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.kafka.Deserialization; +import software.amazon.lambda.powertools.kafka.DeserializationType; +import software.amazon.lambda.powertools.logging.Logging; + +public class ProtobufDeserializationFunction + implements RequestHandler, String> { + + private static final Logger LOGGER = LoggerFactory.getLogger(ProtobufDeserializationFunction.class); + + @Override + @Logging + @Deserialization(type = DeserializationType.KAFKA_PROTOBUF) + public String handleRequest(ConsumerRecords records, Context context) { + for (ConsumerRecord consumerRecord : records) { + LOGGER.info("ConsumerRecord: {}", consumerRecord); + + ProtobufProduct product = consumerRecord.value(); + LOGGER.info("ProtobufProduct: {}", product); + + String key = consumerRecord.key(); + LOGGER.info("Key: {}", key); + } + + return "OK"; + } + +} diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/avro/AvroProduct.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/avro/AvroProduct.java new file mode 100644 index 000000000..fad7e2fbf --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/avro/AvroProduct.java @@ -0,0 +1,476 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package org.demo.kafka.avro; + +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class AvroProduct extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = -2929699301240218341L; + + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"AvroProduct\",\"namespace\":\"org.demo.kafka.avro\",\"fields\":[{\"name\":\"id\",\"type\":\"int\"},{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"price\",\"type\":\"double\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static final SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder ENCODER = + new BinaryMessageEncoder<>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder DECODER = + new BinaryMessageDecoder<>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this AvroProduct to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a AvroProduct from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a AvroProduct instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static AvroProduct fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + private int id; + private java.lang.String name; + private double price; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use newBuilder(). + */ + public AvroProduct() {} + + /** + * All-args constructor. + * @param id The new value for id + * @param name The new value for name + * @param price The new value for price + */ + public AvroProduct(java.lang.Integer id, java.lang.String name, java.lang.Double price) { + this.id = id; + this.name = name; + this.price = price; + } + + @Override + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + + @Override + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + + // Used by DatumWriter. Applications should not call. + @Override + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return id; + case 1: return name; + case 2: return price; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + // Used by DatumReader. Applications should not call. + @Override + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: id = (java.lang.Integer)value$; break; + case 1: name = value$ != null ? value$.toString() : null; break; + case 2: price = (java.lang.Double)value$; break; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + /** + * Gets the value of the 'id' field. + * @return The value of the 'id' field. + */ + public int getId() { + return id; + } + + + /** + * Sets the value of the 'id' field. + * @param value the value to set. + */ + public void setId(int value) { + this.id = value; + } + + /** + * Gets the value of the 'name' field. + * @return The value of the 'name' field. + */ + public java.lang.String getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value the value to set. + */ + public void setName(java.lang.String value) { + this.name = value; + } + + /** + * Gets the value of the 'price' field. + * @return The value of the 'price' field. + */ + public double getPrice() { + return price; + } + + + /** + * Sets the value of the 'price' field. + * @param value the value to set. + */ + public void setPrice(double value) { + this.price = value; + } + + /** + * Creates a new AvroProduct RecordBuilder. + * @return A new AvroProduct RecordBuilder + */ + public static org.demo.kafka.avro.AvroProduct.Builder newBuilder() { + return new org.demo.kafka.avro.AvroProduct.Builder(); + } + + /** + * Creates a new AvroProduct RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new AvroProduct RecordBuilder + */ + public static org.demo.kafka.avro.AvroProduct.Builder newBuilder(org.demo.kafka.avro.AvroProduct.Builder other) { + if (other == null) { + return new org.demo.kafka.avro.AvroProduct.Builder(); + } else { + return new org.demo.kafka.avro.AvroProduct.Builder(other); + } + } + + /** + * Creates a new AvroProduct RecordBuilder by copying an existing AvroProduct instance. + * @param other The existing instance to copy. + * @return A new AvroProduct RecordBuilder + */ + public static org.demo.kafka.avro.AvroProduct.Builder newBuilder(org.demo.kafka.avro.AvroProduct other) { + if (other == null) { + return new org.demo.kafka.avro.AvroProduct.Builder(); + } else { + return new org.demo.kafka.avro.AvroProduct.Builder(other); + } + } + + /** + * RecordBuilder for AvroProduct instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase + implements org.apache.avro.data.RecordBuilder { + + private int id; + private java.lang.String name; + private double price; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$, MODEL$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(org.demo.kafka.avro.AvroProduct.Builder other) { + super(other); + if (isValidValue(fields()[0], other.id)) { + this.id = data().deepCopy(fields()[0].schema(), other.id); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.name)) { + this.name = data().deepCopy(fields()[1].schema(), other.name); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.price)) { + this.price = data().deepCopy(fields()[2].schema(), other.price); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + } + + /** + * Creates a Builder by copying an existing AvroProduct instance + * @param other The existing instance to copy. + */ + private Builder(org.demo.kafka.avro.AvroProduct other) { + super(SCHEMA$, MODEL$); + if (isValidValue(fields()[0], other.id)) { + this.id = data().deepCopy(fields()[0].schema(), other.id); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.name)) { + this.name = data().deepCopy(fields()[1].schema(), other.name); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.price)) { + this.price = data().deepCopy(fields()[2].schema(), other.price); + fieldSetFlags()[2] = true; + } + } + + /** + * Gets the value of the 'id' field. + * @return The value. + */ + public int getId() { + return id; + } + + + /** + * Sets the value of the 'id' field. + * @param value The value of 'id'. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder setId(int value) { + validate(fields()[0], value); + this.id = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'id' field has been set. + * @return True if the 'id' field has been set, false otherwise. + */ + public boolean hasId() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'id' field. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder clearId() { + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'name' field. + * @return The value. + */ + public java.lang.String getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value The value of 'name'. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder setName(java.lang.String value) { + validate(fields()[1], value); + this.name = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'name' field has been set. + * @return True if the 'name' field has been set, false otherwise. + */ + public boolean hasName() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'name' field. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder clearName() { + name = null; + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'price' field. + * @return The value. + */ + public double getPrice() { + return price; + } + + + /** + * Sets the value of the 'price' field. + * @param value The value of 'price'. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder setPrice(double value) { + validate(fields()[2], value); + this.price = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'price' field has been set. + * @return True if the 'price' field has been set, false otherwise. + */ + public boolean hasPrice() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'price' field. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder clearPrice() { + fieldSetFlags()[2] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public AvroProduct build() { + try { + AvroProduct record = new AvroProduct(); + record.id = fieldSetFlags()[0] ? this.id : (java.lang.Integer) defaultValue(fields()[0]); + record.name = fieldSetFlags()[1] ? this.name : (java.lang.String) defaultValue(fields()[1]); + record.price = fieldSetFlags()[2] ? this.price : (java.lang.Double) defaultValue(fields()[2]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter + WRITER$ = (org.apache.avro.io.DatumWriter)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader + READER$ = (org.apache.avro.io.DatumReader)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeInt(this.id); + + out.writeString(this.name); + + out.writeDouble(this.price); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.id = in.readInt(); + + this.name = in.readString(); + + this.price = in.readDouble(); + + } else { + for (int i = 0; i < 3; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.id = in.readInt(); + break; + + case 1: + this.name = in.readString(); + break; + + case 2: + this.price = in.readDouble(); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java new file mode 100644 index 000000000..6da9113fc --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java @@ -0,0 +1,636 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: ProtobufProduct.proto +// Protobuf Java Version: 4.31.0 + +package org.demo.kafka.protobuf; + +/** + * Protobuf type {@code org.demo.kafka.protobuf.ProtobufProduct} + */ +@com.google.protobuf.Generated +public final class ProtobufProduct extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:org.demo.kafka.protobuf.ProtobufProduct) + ProtobufProductOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 31, + /* patch= */ 0, + /* suffix= */ "", + ProtobufProduct.class.getName()); + } + // Use ProtobufProduct.newBuilder() to construct. + private ProtobufProduct(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private ProtobufProduct() { + name_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.demo.kafka.protobuf.ProtobufProductOuterClass.internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.demo.kafka.protobuf.ProtobufProductOuterClass.internal_static_org_demo_kafka_protobuf_ProtobufProduct_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.demo.kafka.protobuf.ProtobufProduct.class, org.demo.kafka.protobuf.ProtobufProduct.Builder.class); + } + + public static final int ID_FIELD_NUMBER = 1; + private int id_ = 0; + /** + * int32 id = 1; + * @return The id. + */ + @java.lang.Override + public int getId() { + return id_; + } + + public static final int NAME_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + * string name = 2; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + * string name = 2; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PRICE_FIELD_NUMBER = 3; + private double price_ = 0D; + /** + * double price = 3; + * @return The price. + */ + @java.lang.Override + public double getPrice() { + return price_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (id_ != 0) { + output.writeInt32(1, id_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, name_); + } + if (java.lang.Double.doubleToRawLongBits(price_) != 0) { + output.writeDouble(3, price_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (id_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, id_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, name_); + } + if (java.lang.Double.doubleToRawLongBits(price_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeDoubleSize(3, price_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.demo.kafka.protobuf.ProtobufProduct)) { + return super.equals(obj); + } + org.demo.kafka.protobuf.ProtobufProduct other = (org.demo.kafka.protobuf.ProtobufProduct) obj; + + if (getId() + != other.getId()) return false; + if (!getName() + .equals(other.getName())) return false; + if (java.lang.Double.doubleToLongBits(getPrice()) + != java.lang.Double.doubleToLongBits( + other.getPrice())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + PRICE_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + java.lang.Double.doubleToLongBits(getPrice())); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.demo.kafka.protobuf.ProtobufProduct parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.demo.kafka.protobuf.ProtobufProduct parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.demo.kafka.protobuf.ProtobufProduct prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.demo.kafka.protobuf.ProtobufProduct} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:org.demo.kafka.protobuf.ProtobufProduct) + org.demo.kafka.protobuf.ProtobufProductOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.demo.kafka.protobuf.ProtobufProductOuterClass.internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.demo.kafka.protobuf.ProtobufProductOuterClass.internal_static_org_demo_kafka_protobuf_ProtobufProduct_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.demo.kafka.protobuf.ProtobufProduct.class, org.demo.kafka.protobuf.ProtobufProduct.Builder.class); + } + + // Construct using org.demo.kafka.protobuf.ProtobufProduct.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + id_ = 0; + name_ = ""; + price_ = 0D; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.demo.kafka.protobuf.ProtobufProductOuterClass.internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor; + } + + @java.lang.Override + public org.demo.kafka.protobuf.ProtobufProduct getDefaultInstanceForType() { + return org.demo.kafka.protobuf.ProtobufProduct.getDefaultInstance(); + } + + @java.lang.Override + public org.demo.kafka.protobuf.ProtobufProduct build() { + org.demo.kafka.protobuf.ProtobufProduct result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.demo.kafka.protobuf.ProtobufProduct buildPartial() { + org.demo.kafka.protobuf.ProtobufProduct result = new org.demo.kafka.protobuf.ProtobufProduct(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.demo.kafka.protobuf.ProtobufProduct result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.id_ = id_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.name_ = name_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.price_ = price_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.demo.kafka.protobuf.ProtobufProduct) { + return mergeFrom((org.demo.kafka.protobuf.ProtobufProduct)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.demo.kafka.protobuf.ProtobufProduct other) { + if (other == org.demo.kafka.protobuf.ProtobufProduct.getDefaultInstance()) return this; + if (other.getId() != 0) { + setId(other.getId()); + } + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (java.lang.Double.doubleToRawLongBits(other.getPrice()) != 0) { + setPrice(other.getPrice()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + id_ = input.readInt32(); + bitField0_ |= 0x00000001; + break; + } // case 8 + case 18: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 25: { + price_ = input.readDouble(); + bitField0_ |= 0x00000004; + break; + } // case 25 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private int id_ ; + /** + * int32 id = 1; + * @return The id. + */ + @java.lang.Override + public int getId() { + return id_; + } + /** + * int32 id = 1; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId(int value) { + + id_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * int32 id = 1; + * @return This builder for chaining. + */ + public Builder clearId() { + bitField0_ = (bitField0_ & ~0x00000001); + id_ = 0; + onChanged(); + return this; + } + + private java.lang.Object name_ = ""; + /** + * string name = 2; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string name = 2; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string name = 2; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * string name = 2; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + * string name = 2; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private double price_ ; + /** + * double price = 3; + * @return The price. + */ + @java.lang.Override + public double getPrice() { + return price_; + } + /** + * double price = 3; + * @param value The price to set. + * @return This builder for chaining. + */ + public Builder setPrice(double value) { + + price_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * double price = 3; + * @return This builder for chaining. + */ + public Builder clearPrice() { + bitField0_ = (bitField0_ & ~0x00000004); + price_ = 0D; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:org.demo.kafka.protobuf.ProtobufProduct) + } + + // @@protoc_insertion_point(class_scope:org.demo.kafka.protobuf.ProtobufProduct) + private static final org.demo.kafka.protobuf.ProtobufProduct DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.demo.kafka.protobuf.ProtobufProduct(); + } + + public static org.demo.kafka.protobuf.ProtobufProduct getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ProtobufProduct parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.demo.kafka.protobuf.ProtobufProduct getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java new file mode 100644 index 000000000..9c1518db3 --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java @@ -0,0 +1,36 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: ProtobufProduct.proto +// Protobuf Java Version: 4.31.0 + +package org.demo.kafka.protobuf; + +@com.google.protobuf.Generated +public interface ProtobufProductOrBuilder extends + // @@protoc_insertion_point(interface_extends:org.demo.kafka.protobuf.ProtobufProduct) + com.google.protobuf.MessageOrBuilder { + + /** + * int32 id = 1; + * @return The id. + */ + int getId(); + + /** + * string name = 2; + * @return The name. + */ + java.lang.String getName(); + /** + * string name = 2; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + * double price = 3; + * @return The price. + */ + double getPrice(); +} diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java new file mode 100644 index 000000000..6a99f35ec --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java @@ -0,0 +1,63 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: ProtobufProduct.proto +// Protobuf Java Version: 4.31.0 + +package org.demo.kafka.protobuf; + +@com.google.protobuf.Generated +public final class ProtobufProductOuterClass { + private ProtobufProductOuterClass() {} + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 31, + /* patch= */ 0, + /* suffix= */ "", + ProtobufProductOuterClass.class.getName()); + } + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + static final com.google.protobuf.Descriptors.Descriptor + internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_demo_kafka_protobuf_ProtobufProduct_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\025ProtobufProduct.proto\022\027org.demo.kafka." + + "protobuf\":\n\017ProtobufProduct\022\n\n\002id\030\001 \001(\005\022" + + "\014\n\004name\030\002 \001(\t\022\r\n\005price\030\003 \001(\001B6\n\027org.demo" + + ".kafka.protobufB\031ProtobufProductOuterCla" + + "ssP\001b\006proto3" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }); + internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_org_demo_kafka_protobuf_ProtobufProduct_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor, + new java.lang.String[] { "Id", "Name", "Price", }); + descriptor.resolveAllFeaturesImmutable(); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/examples/powertools-examples-kafka/src/main/proto/ProtobufProduct.proto b/examples/powertools-examples-kafka/src/main/proto/ProtobufProduct.proto new file mode 100644 index 000000000..4d3338a6f --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/proto/ProtobufProduct.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +package org.demo.kafka.protobuf; + +option java_package = "org.demo.kafka.protobuf"; +option java_outer_classname = "ProtobufProductOuterClass"; +option java_multiple_files = true; + +message ProtobufProduct { + int32 id = 1; + string name = 2; + double price = 3; +} \ No newline at end of file diff --git a/examples/powertools-examples-kafka/src/main/resources/log4j2.xml b/examples/powertools-examples-kafka/src/main/resources/log4j2.xml new file mode 100644 index 000000000..fe943d707 --- /dev/null +++ b/examples/powertools-examples-kafka/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/powertools-examples-kafka/template.yaml b/examples/powertools-examples-kafka/template.yaml new file mode 100644 index 000000000..509b13ca3 --- /dev/null +++ b/examples/powertools-examples-kafka/template.yaml @@ -0,0 +1,59 @@ +AWSTemplateFormatVersion: "2010-09-09" +Transform: AWS::Serverless-2016-10-31 +Description: > + Kafka Deserialization example with Kafka Lambda ESM + +Globals: + Function: + Timeout: 20 + Runtime: java11 + MemorySize: 512 + Tracing: Active + +Resources: + JsonDeserializationFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: org.demo.kafka.JsonDeserializationFunction::handleRequest + Environment: + Variables: + JAVA_TOOL_OPTIONS: "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" + POWERTOOLS_LOG_LEVEL: DEBUG + POWERTOOLS_SERVICE_NAME: JsonDeserialization + POWERTOOLS_METRICS_NAMESPACE: JsonDeserializationFunction + + AvroDeserializationFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: org.demo.kafka.AvroDeserializationFunction::handleRequest + Environment: + Variables: + JAVA_TOOL_OPTIONS: "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" + POWERTOOLS_LOG_LEVEL: DEBUG + POWERTOOLS_SERVICE_NAME: AvroDeserialization + POWERTOOLS_METRICS_NAMESPACE: AvroDeserializationFunction + + ProtobufDeserializationFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: org.demo.kafka.ProtobufDeserializationFunction::handleRequest + Environment: + Variables: + JAVA_TOOL_OPTIONS: "-XX:+TieredCompilation -XX:TieredStopAtLevel=1" + POWERTOOLS_LOG_LEVEL: DEBUG + POWERTOOLS_SERVICE_NAME: ProtobufDeserialization + POWERTOOLS_METRICS_NAMESPACE: ProtobufDeserializationFunction + +Outputs: + JsonFunction: + Description: "Kafka JSON Lambda Function ARN" + Value: !GetAtt JsonDeserializationFunction.Arn + AvroFunction: + Description: "Kafka Avro Lambda Function ARN" + Value: !GetAtt AvroDeserializationFunction.Arn + ProtobufFunction: + Description: "Kafka Protobuf Lambda Function ARN" + Value: !GetAtt ProtobufDeserializationFunction.Arn diff --git a/examples/powertools-examples-kafka/tools/README.md b/examples/powertools-examples-kafka/tools/README.md new file mode 100644 index 000000000..53d07b0c4 --- /dev/null +++ b/examples/powertools-examples-kafka/tools/README.md @@ -0,0 +1,66 @@ +# Kafka Sample Generator Tool + +This tool generates base64-encoded serialized products for testing the Kafka consumer functions with different serialization formats. + +## Supported Formats + +- **JSON**: Generates base64-encoded JSON serialized products +- **Avro**: Generates base64-encoded Avro serialized products +- **Protobuf**: Generates base64-encoded Protobuf serialized products + +## Usage + +Run the following Maven commands from this directory: + +```bash +# Generate Avro and Protobuf classes from schemas +mvn generate-sources + +# Compile the code +mvn compile +``` + +### Generate JSON Samples + +```bash +# Run the JSON sample generator +mvn exec:java -Dexec.mainClass="org.demo.kafka.tools.GenerateJsonSamples" +``` + +The tool will output base64-encoded values for JSON products that can be used in `../events/kafka-json-event.json`. + +### Generate Avro Samples + +```bash +# Run the Avro sample generator +mvn exec:java -Dexec.mainClass="org.demo.kafka.tools.GenerateAvroSamples" +``` + +The tool will output base64-encoded values for Avro products that can be used in `../events/kafka-avro-event.json`. + +### Generate Protobuf Samples + +```bash +# Run the Protobuf sample generator +mvn exec:java -Dexec.mainClass="org.demo.kafka.tools.GenerateProtobufSamples" +``` + +The tool will output base64-encoded values for Protobuf products that can be used in `../events/kafka-protobuf-event.json`. + +## Output + +Each generator produces: + +1. Three different products (Laptop, Smartphone, Headphones) +2. An integer key (42) and one entry with a nullish key to test for edge-cases +3. A complete sample event structure that can be used directly for testing + +## Example + +After generating the samples, you can copy the output into the respective event files: + +- `../events/kafka-json-event.json` for JSON samples +- `../events/kafka-avro-event.json` for Avro samples +- `../events/kafka-protobuf-event.json` for Protobuf samples + +These event files can then be used to test the Lambda functions with the appropriate deserializer. diff --git a/examples/powertools-examples-kafka/tools/pom.xml b/examples/powertools-examples-kafka/tools/pom.xml new file mode 100644 index 000000000..97231e5bd --- /dev/null +++ b/examples/powertools-examples-kafka/tools/pom.xml @@ -0,0 +1,104 @@ + + + 4.0.0 + + software.amazon.lambda.examples + powertools-examples-kafka-tools + 2.0.0 + + + 11 + 11 + 1.12.0 + 4.31.0 + + + + + org.apache.avro + avro + ${avro.version} + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + com.fasterxml.jackson.core + jackson-databind + 2.19.0 + + + + + + + org.apache.avro + avro-maven-plugin + ${avro.version} + + + generate-sources + + schema + + + ${project.basedir}/../src/main/avro/ + ${project.basedir}/src/main/java/ + String + + + + + + io.github.ascopes + protobuf-maven-plugin + 3.3.0 + + + + generate + + generate-sources + + ${protobuf.version} + + ${project.basedir}/../src/main/proto + + ${project.basedir}/src/main/java + false + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + generate-json-samples + + org.demo.kafka.tools.GenerateJsonSamples + + + + generate-avro-samples + + org.demo.kafka.tools.GenerateAvroSamples + + + + generate-protobuf-samples + + org.demo.kafka.tools.GenerateProtobufSamples + + + + + + + diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/avro/AvroProduct.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/avro/AvroProduct.java new file mode 100644 index 000000000..fad7e2fbf --- /dev/null +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/avro/AvroProduct.java @@ -0,0 +1,476 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package org.demo.kafka.avro; + +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class AvroProduct extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = -2929699301240218341L; + + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"AvroProduct\",\"namespace\":\"org.demo.kafka.avro\",\"fields\":[{\"name\":\"id\",\"type\":\"int\"},{\"name\":\"name\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"price\",\"type\":\"double\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static final SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder ENCODER = + new BinaryMessageEncoder<>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder DECODER = + new BinaryMessageDecoder<>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this AvroProduct to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a AvroProduct from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a AvroProduct instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static AvroProduct fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + private int id; + private java.lang.String name; + private double price; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use newBuilder(). + */ + public AvroProduct() {} + + /** + * All-args constructor. + * @param id The new value for id + * @param name The new value for name + * @param price The new value for price + */ + public AvroProduct(java.lang.Integer id, java.lang.String name, java.lang.Double price) { + this.id = id; + this.name = name; + this.price = price; + } + + @Override + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + + @Override + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + + // Used by DatumWriter. Applications should not call. + @Override + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return id; + case 1: return name; + case 2: return price; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + // Used by DatumReader. Applications should not call. + @Override + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: id = (java.lang.Integer)value$; break; + case 1: name = value$ != null ? value$.toString() : null; break; + case 2: price = (java.lang.Double)value$; break; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + /** + * Gets the value of the 'id' field. + * @return The value of the 'id' field. + */ + public int getId() { + return id; + } + + + /** + * Sets the value of the 'id' field. + * @param value the value to set. + */ + public void setId(int value) { + this.id = value; + } + + /** + * Gets the value of the 'name' field. + * @return The value of the 'name' field. + */ + public java.lang.String getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value the value to set. + */ + public void setName(java.lang.String value) { + this.name = value; + } + + /** + * Gets the value of the 'price' field. + * @return The value of the 'price' field. + */ + public double getPrice() { + return price; + } + + + /** + * Sets the value of the 'price' field. + * @param value the value to set. + */ + public void setPrice(double value) { + this.price = value; + } + + /** + * Creates a new AvroProduct RecordBuilder. + * @return A new AvroProduct RecordBuilder + */ + public static org.demo.kafka.avro.AvroProduct.Builder newBuilder() { + return new org.demo.kafka.avro.AvroProduct.Builder(); + } + + /** + * Creates a new AvroProduct RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new AvroProduct RecordBuilder + */ + public static org.demo.kafka.avro.AvroProduct.Builder newBuilder(org.demo.kafka.avro.AvroProduct.Builder other) { + if (other == null) { + return new org.demo.kafka.avro.AvroProduct.Builder(); + } else { + return new org.demo.kafka.avro.AvroProduct.Builder(other); + } + } + + /** + * Creates a new AvroProduct RecordBuilder by copying an existing AvroProduct instance. + * @param other The existing instance to copy. + * @return A new AvroProduct RecordBuilder + */ + public static org.demo.kafka.avro.AvroProduct.Builder newBuilder(org.demo.kafka.avro.AvroProduct other) { + if (other == null) { + return new org.demo.kafka.avro.AvroProduct.Builder(); + } else { + return new org.demo.kafka.avro.AvroProduct.Builder(other); + } + } + + /** + * RecordBuilder for AvroProduct instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase + implements org.apache.avro.data.RecordBuilder { + + private int id; + private java.lang.String name; + private double price; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$, MODEL$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(org.demo.kafka.avro.AvroProduct.Builder other) { + super(other); + if (isValidValue(fields()[0], other.id)) { + this.id = data().deepCopy(fields()[0].schema(), other.id); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.name)) { + this.name = data().deepCopy(fields()[1].schema(), other.name); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.price)) { + this.price = data().deepCopy(fields()[2].schema(), other.price); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + } + + /** + * Creates a Builder by copying an existing AvroProduct instance + * @param other The existing instance to copy. + */ + private Builder(org.demo.kafka.avro.AvroProduct other) { + super(SCHEMA$, MODEL$); + if (isValidValue(fields()[0], other.id)) { + this.id = data().deepCopy(fields()[0].schema(), other.id); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.name)) { + this.name = data().deepCopy(fields()[1].schema(), other.name); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.price)) { + this.price = data().deepCopy(fields()[2].schema(), other.price); + fieldSetFlags()[2] = true; + } + } + + /** + * Gets the value of the 'id' field. + * @return The value. + */ + public int getId() { + return id; + } + + + /** + * Sets the value of the 'id' field. + * @param value The value of 'id'. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder setId(int value) { + validate(fields()[0], value); + this.id = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'id' field has been set. + * @return True if the 'id' field has been set, false otherwise. + */ + public boolean hasId() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'id' field. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder clearId() { + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'name' field. + * @return The value. + */ + public java.lang.String getName() { + return name; + } + + + /** + * Sets the value of the 'name' field. + * @param value The value of 'name'. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder setName(java.lang.String value) { + validate(fields()[1], value); + this.name = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'name' field has been set. + * @return True if the 'name' field has been set, false otherwise. + */ + public boolean hasName() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'name' field. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder clearName() { + name = null; + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'price' field. + * @return The value. + */ + public double getPrice() { + return price; + } + + + /** + * Sets the value of the 'price' field. + * @param value The value of 'price'. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder setPrice(double value) { + validate(fields()[2], value); + this.price = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'price' field has been set. + * @return True if the 'price' field has been set, false otherwise. + */ + public boolean hasPrice() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'price' field. + * @return This builder. + */ + public org.demo.kafka.avro.AvroProduct.Builder clearPrice() { + fieldSetFlags()[2] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public AvroProduct build() { + try { + AvroProduct record = new AvroProduct(); + record.id = fieldSetFlags()[0] ? this.id : (java.lang.Integer) defaultValue(fields()[0]); + record.name = fieldSetFlags()[1] ? this.name : (java.lang.String) defaultValue(fields()[1]); + record.price = fieldSetFlags()[2] ? this.price : (java.lang.Double) defaultValue(fields()[2]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter + WRITER$ = (org.apache.avro.io.DatumWriter)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader + READER$ = (org.apache.avro.io.DatumReader)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeInt(this.id); + + out.writeString(this.name); + + out.writeDouble(this.price); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.id = in.readInt(); + + this.name = in.readString(); + + this.price = in.readDouble(); + + } else { + for (int i = 0; i < 3; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.id = in.readInt(); + break; + + case 1: + this.name = in.readString(); + break; + + case 2: + this.price = in.readDouble(); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java new file mode 100644 index 000000000..6da9113fc --- /dev/null +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java @@ -0,0 +1,636 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: ProtobufProduct.proto +// Protobuf Java Version: 4.31.0 + +package org.demo.kafka.protobuf; + +/** + * Protobuf type {@code org.demo.kafka.protobuf.ProtobufProduct} + */ +@com.google.protobuf.Generated +public final class ProtobufProduct extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:org.demo.kafka.protobuf.ProtobufProduct) + ProtobufProductOrBuilder { +private static final long serialVersionUID = 0L; + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 31, + /* patch= */ 0, + /* suffix= */ "", + ProtobufProduct.class.getName()); + } + // Use ProtobufProduct.newBuilder() to construct. + private ProtobufProduct(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private ProtobufProduct() { + name_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.demo.kafka.protobuf.ProtobufProductOuterClass.internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.demo.kafka.protobuf.ProtobufProductOuterClass.internal_static_org_demo_kafka_protobuf_ProtobufProduct_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.demo.kafka.protobuf.ProtobufProduct.class, org.demo.kafka.protobuf.ProtobufProduct.Builder.class); + } + + public static final int ID_FIELD_NUMBER = 1; + private int id_ = 0; + /** + * int32 id = 1; + * @return The id. + */ + @java.lang.Override + public int getId() { + return id_; + } + + public static final int NAME_FIELD_NUMBER = 2; + @SuppressWarnings("serial") + private volatile java.lang.Object name_ = ""; + /** + * string name = 2; + * @return The name. + */ + @java.lang.Override + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + * string name = 2; + * @return The bytes for name. + */ + @java.lang.Override + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int PRICE_FIELD_NUMBER = 3; + private double price_ = 0D; + /** + * double price = 3; + * @return The price. + */ + @java.lang.Override + public double getPrice() { + return price_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (id_ != 0) { + output.writeInt32(1, id_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, name_); + } + if (java.lang.Double.doubleToRawLongBits(price_) != 0) { + output.writeDouble(3, price_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (id_ != 0) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(1, id_); + } + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(name_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, name_); + } + if (java.lang.Double.doubleToRawLongBits(price_) != 0) { + size += com.google.protobuf.CodedOutputStream + .computeDoubleSize(3, price_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof org.demo.kafka.protobuf.ProtobufProduct)) { + return super.equals(obj); + } + org.demo.kafka.protobuf.ProtobufProduct other = (org.demo.kafka.protobuf.ProtobufProduct) obj; + + if (getId() + != other.getId()) return false; + if (!getName() + .equals(other.getName())) return false; + if (java.lang.Double.doubleToLongBits(getPrice()) + != java.lang.Double.doubleToLongBits( + other.getPrice())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ID_FIELD_NUMBER; + hash = (53 * hash) + getId(); + hash = (37 * hash) + NAME_FIELD_NUMBER; + hash = (53 * hash) + getName().hashCode(); + hash = (37 * hash) + PRICE_FIELD_NUMBER; + hash = (53 * hash) + com.google.protobuf.Internal.hashLong( + java.lang.Double.doubleToLongBits(getPrice())); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + public static org.demo.kafka.protobuf.ProtobufProduct parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input); + } + + public static org.demo.kafka.protobuf.ProtobufProduct parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input); + } + public static org.demo.kafka.protobuf.ProtobufProduct parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.demo.kafka.protobuf.ProtobufProduct prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.demo.kafka.protobuf.ProtobufProduct} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:org.demo.kafka.protobuf.ProtobufProduct) + org.demo.kafka.protobuf.ProtobufProductOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.demo.kafka.protobuf.ProtobufProductOuterClass.internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.demo.kafka.protobuf.ProtobufProductOuterClass.internal_static_org_demo_kafka_protobuf_ProtobufProduct_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.demo.kafka.protobuf.ProtobufProduct.class, org.demo.kafka.protobuf.ProtobufProduct.Builder.class); + } + + // Construct using org.demo.kafka.protobuf.ProtobufProduct.newBuilder() + private Builder() { + + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + + } + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + id_ = 0; + name_ = ""; + price_ = 0D; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.demo.kafka.protobuf.ProtobufProductOuterClass.internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor; + } + + @java.lang.Override + public org.demo.kafka.protobuf.ProtobufProduct getDefaultInstanceForType() { + return org.demo.kafka.protobuf.ProtobufProduct.getDefaultInstance(); + } + + @java.lang.Override + public org.demo.kafka.protobuf.ProtobufProduct build() { + org.demo.kafka.protobuf.ProtobufProduct result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public org.demo.kafka.protobuf.ProtobufProduct buildPartial() { + org.demo.kafka.protobuf.ProtobufProduct result = new org.demo.kafka.protobuf.ProtobufProduct(this); + if (bitField0_ != 0) { buildPartial0(result); } + onBuilt(); + return result; + } + + private void buildPartial0(org.demo.kafka.protobuf.ProtobufProduct result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.id_ = id_; + } + if (((from_bitField0_ & 0x00000002) != 0)) { + result.name_ = name_; + } + if (((from_bitField0_ & 0x00000004) != 0)) { + result.price_ = price_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.demo.kafka.protobuf.ProtobufProduct) { + return mergeFrom((org.demo.kafka.protobuf.ProtobufProduct)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.demo.kafka.protobuf.ProtobufProduct other) { + if (other == org.demo.kafka.protobuf.ProtobufProduct.getDefaultInstance()) return this; + if (other.getId() != 0) { + setId(other.getId()); + } + if (!other.getName().isEmpty()) { + name_ = other.name_; + bitField0_ |= 0x00000002; + onChanged(); + } + if (java.lang.Double.doubleToRawLongBits(other.getPrice()) != 0) { + setPrice(other.getPrice()); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 8: { + id_ = input.readInt32(); + bitField0_ |= 0x00000001; + break; + } // case 8 + case 18: { + name_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000002; + break; + } // case 18 + case 25: { + price_ = input.readDouble(); + bitField0_ |= 0x00000004; + break; + } // case 25 + default: { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + private int bitField0_; + + private int id_ ; + /** + * int32 id = 1; + * @return The id. + */ + @java.lang.Override + public int getId() { + return id_; + } + /** + * int32 id = 1; + * @param value The id to set. + * @return This builder for chaining. + */ + public Builder setId(int value) { + + id_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + /** + * int32 id = 1; + * @return This builder for chaining. + */ + public Builder clearId() { + bitField0_ = (bitField0_ & ~0x00000001); + id_ = 0; + onChanged(); + return this; + } + + private java.lang.Object name_ = ""; + /** + * string name = 2; + * @return The name. + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * string name = 2; + * @return The bytes for name. + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * string name = 2; + * @param value The name to set. + * @return This builder for chaining. + */ + public Builder setName( + java.lang.String value) { + if (value == null) { throw new NullPointerException(); } + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + /** + * string name = 2; + * @return This builder for chaining. + */ + public Builder clearName() { + name_ = getDefaultInstance().getName(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + return this; + } + /** + * string name = 2; + * @param value The bytes for name to set. + * @return This builder for chaining. + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { throw new NullPointerException(); } + checkByteStringIsUtf8(value); + name_ = value; + bitField0_ |= 0x00000002; + onChanged(); + return this; + } + + private double price_ ; + /** + * double price = 3; + * @return The price. + */ + @java.lang.Override + public double getPrice() { + return price_; + } + /** + * double price = 3; + * @param value The price to set. + * @return This builder for chaining. + */ + public Builder setPrice(double value) { + + price_ = value; + bitField0_ |= 0x00000004; + onChanged(); + return this; + } + /** + * double price = 3; + * @return This builder for chaining. + */ + public Builder clearPrice() { + bitField0_ = (bitField0_ & ~0x00000004); + price_ = 0D; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:org.demo.kafka.protobuf.ProtobufProduct) + } + + // @@protoc_insertion_point(class_scope:org.demo.kafka.protobuf.ProtobufProduct) + private static final org.demo.kafka.protobuf.ProtobufProduct DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.demo.kafka.protobuf.ProtobufProduct(); + } + + public static org.demo.kafka.protobuf.ProtobufProduct getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public ProtobufProduct parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public org.demo.kafka.protobuf.ProtobufProduct getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + +} + diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java new file mode 100644 index 000000000..9c1518db3 --- /dev/null +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java @@ -0,0 +1,36 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: ProtobufProduct.proto +// Protobuf Java Version: 4.31.0 + +package org.demo.kafka.protobuf; + +@com.google.protobuf.Generated +public interface ProtobufProductOrBuilder extends + // @@protoc_insertion_point(interface_extends:org.demo.kafka.protobuf.ProtobufProduct) + com.google.protobuf.MessageOrBuilder { + + /** + * int32 id = 1; + * @return The id. + */ + int getId(); + + /** + * string name = 2; + * @return The name. + */ + java.lang.String getName(); + /** + * string name = 2; + * @return The bytes for name. + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + * double price = 3; + * @return The price. + */ + double getPrice(); +} diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java new file mode 100644 index 000000000..6a99f35ec --- /dev/null +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java @@ -0,0 +1,63 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: ProtobufProduct.proto +// Protobuf Java Version: 4.31.0 + +package org.demo.kafka.protobuf; + +@com.google.protobuf.Generated +public final class ProtobufProductOuterClass { + private ProtobufProductOuterClass() {} + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 31, + /* patch= */ 0, + /* suffix= */ "", + ProtobufProductOuterClass.class.getName()); + } + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistryLite registry) { + } + + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + registerAllExtensions( + (com.google.protobuf.ExtensionRegistryLite) registry); + } + static final com.google.protobuf.Descriptors.Descriptor + internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor; + static final + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_demo_kafka_protobuf_ProtobufProduct_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\025ProtobufProduct.proto\022\027org.demo.kafka." + + "protobuf\":\n\017ProtobufProduct\022\n\n\002id\030\001 \001(\005\022" + + "\014\n\004name\030\002 \001(\t\022\r\n\005price\030\003 \001(\001B6\n\027org.demo" + + ".kafka.protobufB\031ProtobufProductOuterCla" + + "ssP\001b\006proto3" + }; + descriptor = com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }); + internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_org_demo_kafka_protobuf_ProtobufProduct_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor, + new java.lang.String[] { "Id", "Name", "Price", }); + descriptor.resolveAllFeaturesImmutable(); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateAvroSamples.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateAvroSamples.java new file mode 100644 index 000000000..4bd6ebd13 --- /dev/null +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateAvroSamples.java @@ -0,0 +1,121 @@ +package org.demo.kafka.tools; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Base64; + +import org.apache.avro.io.BinaryEncoder; +import org.apache.avro.io.DatumWriter; +import org.apache.avro.io.EncoderFactory; +import org.apache.avro.specific.SpecificDatumWriter; +import org.demo.kafka.avro.AvroProduct; + +/** + * Utility class to generate base64-encoded Avro serialized products + * for use in test events. + */ +public class GenerateAvroSamples { + + public static void main(String[] args) throws IOException { + // Create three different products + AvroProduct product1 = new AvroProduct(1001, "Laptop", 999.99); + AvroProduct product2 = new AvroProduct(1002, "Smartphone", 599.99); + AvroProduct product3 = new AvroProduct(1003, "Headphones", 149.99); + + // Serialize and encode each product + String encodedProduct1 = serializeAndEncode(product1); + String encodedProduct2 = serializeAndEncode(product2); + String encodedProduct3 = serializeAndEncode(product3); + + // Serialize and encode an integer key + String encodedKey = serializeAndEncodeInteger(42); + + // Print the results + System.out.println("Base64 encoded Avro products for use in kafka-avro-event.json:"); + System.out.println("\nProduct 1 (with key):"); + System.out.println("key: \"" + encodedKey + "\","); + System.out.println("value: \"" + encodedProduct1 + "\","); + + System.out.println("\nProduct 2 (with key):"); + System.out.println("key: \"" + encodedKey + "\","); + System.out.println("value: \"" + encodedProduct2 + "\","); + + System.out.println("\nProduct 3 (without key):"); + System.out.println("key: null,"); + System.out.println("value: \"" + encodedProduct3 + "\","); + + // Print a sample event structure + System.out.println("\nSample event structure:"); + printSampleEvent(encodedKey, encodedProduct1, encodedProduct2, encodedProduct3); + } + + private static String serializeAndEncode(AvroProduct product) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(baos, null); + DatumWriter writer = new SpecificDatumWriter<>(AvroProduct.class); + + writer.write(product, encoder); + encoder.flush(); + + return Base64.getEncoder().encodeToString(baos.toByteArray()); + } + + private static String serializeAndEncodeInteger(Integer value) throws IOException { + // For simple types like integers, we'll just convert to string and encode + return Base64.getEncoder().encodeToString(value.toString().getBytes()); + } + + private static void printSampleEvent(String key, String product1, String product2, String product3) { + System.out.println("{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"eventSourceArn\": \"arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4\",\n" + + " \"bootstrapServers\": \"b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092\",\n" + + " \"records\": {\n" + + " \"mytopic-0\": [\n" + + " {\n" + + " \"topic\": \"mytopic\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": \"" + key + "\",\n" + + " \"value\": \"" + product1 + "\",\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"topic\": \"mytopic\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 16,\n" + + " \"timestamp\": 1545084650988,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": \"" + key + "\",\n" + + " \"value\": \"" + product2 + "\",\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"topic\": \"mytopic\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 17,\n" + + " \"timestamp\": 1545084650989,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": \"" + product3 + "\",\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"); + } +} diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateJsonSamples.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateJsonSamples.java new file mode 100644 index 000000000..a4fd6565a --- /dev/null +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateJsonSamples.java @@ -0,0 +1,126 @@ +package org.demo.kafka.tools; + +import java.io.IOException; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Utility class to generate base64-encoded JSON serialized products + * for use in test events. + */ +public class GenerateJsonSamples { + + public static void main(String[] args) throws IOException { + // Create three different products + Map product1 = new HashMap<>(); + product1.put("id", 1001); + product1.put("name", "Laptop"); + product1.put("price", 999.99); + + Map product2 = new HashMap<>(); + product2.put("id", 1002); + product2.put("name", "Smartphone"); + product2.put("price", 599.99); + + Map product3 = new HashMap<>(); + product3.put("id", 1003); + product3.put("name", "Headphones"); + product3.put("price", 149.99); + + // Serialize and encode each product + String encodedProduct1 = serializeAndEncode(product1); + String encodedProduct2 = serializeAndEncode(product2); + String encodedProduct3 = serializeAndEncode(product3); + + // Serialize and encode an integer key + String encodedKey = serializeAndEncodeInteger(42); + + // Print the results + System.out.println("Base64 encoded JSON products for use in kafka-json-event.json:"); + System.out.println("\nProduct 1 (with key):"); + System.out.println("key: \"" + encodedKey + "\","); + System.out.println("value: \"" + encodedProduct1 + "\","); + + System.out.println("\nProduct 2 (with key):"); + System.out.println("key: \"" + encodedKey + "\","); + System.out.println("value: \"" + encodedProduct2 + "\","); + + System.out.println("\nProduct 3 (without key):"); + System.out.println("key: null,"); + System.out.println("value: \"" + encodedProduct3 + "\","); + + // Print a sample event structure + System.out.println("\nSample event structure:"); + printSampleEvent(encodedKey, encodedProduct1, encodedProduct2, encodedProduct3); + } + + private static String serializeAndEncode(Map product) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(product); + return Base64.getEncoder().encodeToString(json.getBytes()); + } + + private static String serializeAndEncodeInteger(Integer value) { + // For simple types like integers, we'll just convert to string and encode + return Base64.getEncoder().encodeToString(value.toString().getBytes()); + } + + private static void printSampleEvent(String key, String product1, String product2, String product3) { + System.out.println("{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"eventSourceArn\": \"arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4\",\n" + + + " \"bootstrapServers\": \"b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092\",\n" + + + " \"records\": {\n" + + " \"mytopic-0\": [\n" + + " {\n" + + " \"topic\": \"mytopic\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": \"" + key + "\",\n" + + " \"value\": \"" + product1 + "\",\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"topic\": \"mytopic\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": \"" + key + "\",\n" + + " \"value\": \"" + product2 + "\",\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"topic\": \"mytopic\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": \"" + product3 + "\",\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"); + } +} diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java new file mode 100644 index 000000000..ae078a28a --- /dev/null +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java @@ -0,0 +1,125 @@ +package org.demo.kafka.tools; + +import java.io.IOException; +import java.util.Base64; + +import org.demo.kafka.protobuf.ProtobufProduct; + +/** + * Utility class to generate base64-encoded Protobuf serialized products + * for use in test events. + */ +public class GenerateProtobufSamples { + + public static void main(String[] args) throws IOException { + // Create three different products + ProtobufProduct product1 = ProtobufProduct.newBuilder() + .setId(1001) + .setName("Laptop") + .setPrice(999.99) + .build(); + + ProtobufProduct product2 = ProtobufProduct.newBuilder() + .setId(1002) + .setName("Smartphone") + .setPrice(599.99) + .build(); + + ProtobufProduct product3 = ProtobufProduct.newBuilder() + .setId(1003) + .setName("Headphones") + .setPrice(149.99) + .build(); + + // Serialize and encode each product + String encodedProduct1 = serializeAndEncode(product1); + String encodedProduct2 = serializeAndEncode(product2); + String encodedProduct3 = serializeAndEncode(product3); + + // Serialize and encode an integer key + String encodedKey = serializeAndEncodeInteger(42); + + // Print the results + System.out.println("Base64 encoded Protobuf products for use in kafka-protobuf-event.json:"); + System.out.println("\nProduct 1 (with key):"); + System.out.println("key: \"" + encodedKey + "\","); + System.out.println("value: \"" + encodedProduct1 + "\","); + + System.out.println("\nProduct 2 (with key):"); + System.out.println("key: \"" + encodedKey + "\","); + System.out.println("value: \"" + encodedProduct2 + "\","); + + System.out.println("\nProduct 3 (without key):"); + System.out.println("key: null,"); + System.out.println("value: \"" + encodedProduct3 + "\","); + + // Print a sample event structure + System.out.println("\nSample event structure:"); + printSampleEvent(encodedKey, encodedProduct1, encodedProduct2, encodedProduct3); + } + + private static String serializeAndEncode(ProtobufProduct product) { + return Base64.getEncoder().encodeToString(product.toByteArray()); + } + + private static String serializeAndEncodeInteger(Integer value) { + // For simple types like integers, we'll just convert to string and encode + return Base64.getEncoder().encodeToString(value.toString().getBytes()); + } + + private static void printSampleEvent(String key, String product1, String product2, String product3) { + System.out.println("{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"eventSourceArn\": \"arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4\",\n" + + + " \"bootstrapServers\": \"b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092\",\n" + + + " \"records\": {\n" + + " \"mytopic-0\": [\n" + + " {\n" + + " \"topic\": \"mytopic\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": \"" + key + "\",\n" + + " \"value\": \"" + product1 + "\",\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"topic\": \"mytopic\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 16,\n" + + " \"timestamp\": 1545084650988,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": \"" + key + "\",\n" + + " \"value\": \"" + product2 + "\",\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + + " }\n" + + " ]\n" + + " },\n" + + " {\n" + + " \"topic\": \"mytopic\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 17,\n" + + " \"timestamp\": 1545084650989,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": \"" + product3 + "\",\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"); + } +} diff --git a/mkdocs.yml b/mkdocs.yml index 82a32d49c..07be3c175 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -15,8 +15,9 @@ nav: - Utilities: - utilities/idempotency.md - utilities/parameters.md - - utilities/large_messages.md - utilities/batch.md + - utilities/kafka.md + - utilities/large_messages.md - utilities/validation.md - utilities/custom_resources.md - utilities/serialization.md @@ -101,8 +102,9 @@ plugins: Utilities: - utilities/idempotency.md - utilities/parameters.md - - utilities/large_messages.md - utilities/batch.md + - utilities/kafka.md + - utilities/large_messages.md - utilities/validation.md - utilities/custom_resources.md - utilities/serialization.md @@ -115,6 +117,7 @@ extra_css: extra_javascript: - javascript/aws-amplify.min.js - javascript/extra.js + - https://docs.powertools.aws.dev/shared/mermaid.min.js extra: powertools: diff --git a/pom.xml b/pom.xml index 951e155f6..f27ffc497 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,7 @@ powertools-common powertools-serialization + powertools-kafka powertools-logging powertools-logging/powertools-logging-log4j powertools-logging/powertools-logging-logback @@ -113,7 +114,9 @@ 1.12.781 2.18.0 1.6.0 - 5.17.0 + 5.18.0 + 5.18.0 + 2.3.0 @@ -355,7 +358,7 @@ org.mockito mockito-junit-jupiter - ${mockito.version} + ${mockito-junit-jupiter.version} test diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index a36d464ea..3b7238b4e 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 e2e-test-handler-batch diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index e3a67a5b5..dfa97225a 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 e2e-test-handler-idempotency diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index 0728404bf..ce3fbbdd5 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 e2e-test-handler-largemessage diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index b57063346..e9e87da2b 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 e2e-test-handler-large-msg-idempotent diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml index 88feda09b..62f2f7530 100644 --- a/powertools-e2e-tests/handlers/logging/pom.xml +++ b/powertools-e2e-tests/handlers/logging/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 e2e-test-handler-logging diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 68059e67e..e543c2cd0 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 e2e-test-handler-metrics diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index 2d6a9a06a..471e79d8f 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 e2e-test-handler-parameters diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index b55cf436a..988ae3d55 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -4,13 +4,13 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 pom Handlers for End-to-End tests Fake handlers that use Powertools for AWS Lambda (Java). - 2.0.0-SNAPSHOT + 2.0.0 UTF-8 11 11 diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index b96fcef0a..b1bc14c05 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 e2e-test-handler-tracing diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml index be50094c1..36695b9a4 100644 --- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 e2e-test-handler-validation-alb-event diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml index f204a8a9f..8bb927778 100644 --- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml @@ -5,7 +5,7 @@ software.amazon.lambda e2e-test-handlers-parent - 2.0.0-SNAPSHOT + 2.0.0 e2e-test-handler-validation-apigw-event diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java index 143409989..07d816112 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java @@ -290,6 +290,7 @@ private Stack createStackWithLambda() { .queueName(queue) .visibilityTimeout(Duration.seconds(timeout * 6)) .retentionPeriod(Duration.seconds(timeout * 6)) + .removalPolicy(RemovalPolicy.DESTROY) .build(); DeadLetterQueue.builder() .queue(sqsQueue) @@ -314,6 +315,7 @@ private Stack createStackWithLambda() { .create(e2eStack, "KinesisStream") .streamMode(StreamMode.ON_DEMAND) .streamName(kinesisStream) + .removalPolicy(RemovalPolicy.DESTROY) .build(); stream.grantRead(function); diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml new file mode 100644 index 000000000..f5b80012c --- /dev/null +++ b/powertools-kafka/pom.xml @@ -0,0 +1,223 @@ + + + + + 4.0.0 + + + powertools-parent + software.amazon.lambda + 2.0.0 + + + powertools-kafka + jar + + Powertools for AWS Lambda (Java) - Kafka Consumer + + + + 4.0.0 + 1.12.0 + 4.31.0 + 1.1.5 + + + + + org.slf4j + slf4j-api + + + com.amazonaws + aws-lambda-java-core + + + com.amazonaws + aws-lambda-java-events + + + org.apache.kafka + kafka-clients + ${kafka-clients.version} + provided + + + org.apache.avro + avro + ${avro.version} + + + com.google.protobuf + protobuf-java + ${protobuf.version} + + + com.fasterxml.jackson.core + jackson-databind + + + com.amazonaws + aws-lambda-java-serialization + ${lambda-serialization.version} + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.mockito + mockito-junit-jupiter + test + + + org.mockito + mockito-core + test + + + org.junit-pioneer + junit-pioneer + test + + + org.slf4j + slf4j-simple + test + + + org.assertj + assertj-core + test + + + + + + + src/main/resources + + + + + src/test/resources + + + + + dev.aspectj + aspectj-maven-plugin + ${aspectj-maven-plugin.version} + + true + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + + @{argLine} + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + org.apache.avro + avro-maven-plugin + ${avro.version} + + + generate-test-sources + generate-test-sources + + schema + + + ${project.basedir}/src/test/avro/ + ${project.basedir}/target/generated-test-sources/avro/ + String + ${project.basedir}/src/test/avro/ + ${project.basedir}/target/generated-test-sources/avro/ + + + + + + + io.github.ascopes + protobuf-maven-plugin + 3.3.0 + + + generate-test-sources + + generate-test + + generate-test-sources + + ${protobuf.version} + + ${project.basedir}/src/test/proto + + ${project.basedir}/target/generated-test-sources/protobuf + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.6.0 + + + add-test-source + generate-test-sources + + add-test-source + + + + ${project.basedir}/target/generated-test-sources/avro + ${project.basedir}/target/generated-test-sources/protobuf + + + + + + + + + diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/Deserialization.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/Deserialization.java new file mode 100644 index 000000000..4b96c49db --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/Deserialization.java @@ -0,0 +1,31 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to specify the deserialization type for Kafka messages. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Deserialization { + /** + * The type of deserialization to use. + * @return the deserialization type + */ + DeserializationType type(); +} diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/DeserializationType.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/DeserializationType.java new file mode 100644 index 000000000..a4ac95389 --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/DeserializationType.java @@ -0,0 +1,17 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka; + +public enum DeserializationType { + LAMBDA_DEFAULT, KAFKA_JSON, KAFKA_AVRO, KAFKA_PROTOBUF +} diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializer.java new file mode 100644 index 000000000..be8563b8e --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializer.java @@ -0,0 +1,67 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka; + +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Type; +import java.util.Map; + +import com.amazonaws.services.lambda.runtime.CustomPojoSerializer; +import com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory; + +import software.amazon.lambda.powertools.kafka.internal.DeserializationUtils; +import software.amazon.lambda.powertools.kafka.serializers.KafkaAvroDeserializer; +import software.amazon.lambda.powertools.kafka.serializers.KafkaJsonDeserializer; +import software.amazon.lambda.powertools.kafka.serializers.KafkaProtobufDeserializer; +import software.amazon.lambda.powertools.kafka.serializers.LambdaDefaultDeserializer; +import software.amazon.lambda.powertools.kafka.serializers.PowertoolsDeserializer; + +/** + * Custom Lambda serializer supporting Kafka events. It delegates to the appropriate deserializer based on the + * deserialization type specified by {@link software.amazon.lambda.powertools.kafka.Deserialization} annotation. + * + * Kafka serializers need to be specified explicitly, otherwise, the default Lambda serializer from + * {@link com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory} will be used. + */ +public class PowertoolsSerializer implements CustomPojoSerializer { + private static final Map DESERIALIZERS = Map.of( + DeserializationType.KAFKA_JSON, new KafkaJsonDeserializer(), + DeserializationType.KAFKA_AVRO, new KafkaAvroDeserializer(), + DeserializationType.KAFKA_PROTOBUF, new KafkaProtobufDeserializer(), + DeserializationType.LAMBDA_DEFAULT, new LambdaDefaultDeserializer()); + + private final PowertoolsDeserializer deserializer; + + public PowertoolsSerializer() { + this.deserializer = DESERIALIZERS.getOrDefault( + DeserializationUtils.determineDeserializationType(), + new LambdaDefaultDeserializer()); + } + + @Override + public T fromJson(InputStream input, Type type) { + return deserializer.fromJson(input, type); + } + + @Override + public T fromJson(String input, Type type) { + return deserializer.fromJson(input, type); + } + + @Override + public void toJson(T value, OutputStream output, Type type) { + // This is the Lambda default Output serialization + JacksonFactory.getInstance().getSerializer(type).toJson(value, output); + } +} diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/DeserializationUtils.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/DeserializationUtils.java new file mode 100644 index 000000000..1d2fe9aca --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/DeserializationUtils.java @@ -0,0 +1,96 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.internal; + +import java.lang.reflect.Method; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.kafka.Deserialization; +import software.amazon.lambda.powertools.kafka.DeserializationType; + +/** + * Utility class to determine the deserialization type from Lambda request handler methods annotated with + * {@link Deserialization} utility. + * + * Relies on the Lambda _HANDLER environment variable to detect the currently active handler method. + */ +public final class DeserializationUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(DeserializationUtils.class); + + private DeserializationUtils() { + } + + public static DeserializationType determineDeserializationType() { + String handler = System.getenv("_HANDLER"); + if (handler == null || handler.trim().isEmpty()) { + LOGGER.error("Cannot determine deserialization type. No valid handler found in _HANDLER: {}", handler); + return DeserializationType.LAMBDA_DEFAULT; + } + + try { + HandlerInfo handlerInfo = parseHandler(handler); + Class handlerClazz = Class.forName(handlerInfo.className); + + if (!RequestHandler.class.isAssignableFrom(handlerClazz)) { + LOGGER.warn("Class '{}' does not implement RequestHandler. Ignoring.", handlerInfo.className); + return DeserializationType.LAMBDA_DEFAULT; + } + + return findDeserializationType(handlerClazz, handlerInfo.methodName); + } catch (Exception e) { + LOGGER.warn("Cannot determine deserialization type. Defaulting to standard.", e); + return DeserializationType.LAMBDA_DEFAULT; + } + } + + private static HandlerInfo parseHandler(String handler) { + if (handler.contains("::")) { + int separatorIndex = handler.indexOf("::"); + String className = handler.substring(0, separatorIndex); + String methodName = handler.substring(separatorIndex + 2); + return new HandlerInfo(className, methodName); + } + + return new HandlerInfo(handler); + } + + private static DeserializationType findDeserializationType(Class handlerClass, String methodName) { + for (Method method : handlerClass.getDeclaredMethods()) { + if (method.getName().equals(methodName) && method.isAnnotationPresent(Deserialization.class)) { + Deserialization annotation = method.getAnnotation(Deserialization.class); + LOGGER.debug("Found deserialization type: {}", annotation.type()); + return annotation.type(); + } + } + + return DeserializationType.LAMBDA_DEFAULT; + } + + private static class HandlerInfo { + final String className; + final String methodName; + + HandlerInfo(String className) { + this(className, "handleRequest"); + } + + HandlerInfo(String className, String methodName) { + this.className = className; + this.methodName = methodName; + } + } +} diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializer.java new file mode 100644 index 000000000..8d0fc8f61 --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializer.java @@ -0,0 +1,294 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.serializers; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.common.TopicPartition; +import org.apache.kafka.common.header.Headers; +import org.apache.kafka.common.header.internals.RecordHeaders; +import org.apache.kafka.common.record.TimestampType; + +import com.amazonaws.services.lambda.runtime.events.KafkaEvent; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Abstract base class for Kafka deserializers that implements common functionality. + */ +abstract class AbstractKafkaDeserializer implements PowertoolsDeserializer { + protected static final ObjectMapper objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + /** + * Deserialize JSON from InputStream into ConsumerRecords + * + * @param input InputStream containing JSON data + * @param type Type representing ConsumerRecords + * @param The type to deserialize to + * @return Deserialized ConsumerRecords object + * @throws IllegalArgumentException if type is not ConsumerRecords + */ + @SuppressWarnings("unchecked") + @Override + public T fromJson(InputStream input, Type type) { + if (!isConsumerRecordsType(type)) { + throw new IllegalArgumentException("Type must be ConsumerRecords when using this deserializer"); + } + + try { + // Parse the KafkaEvent from the input stream + KafkaEvent kafkaEvent = objectMapper.readValue(input, KafkaEvent.class); + + // Extract the key and value types from the ConsumerRecords type + ParameterizedType parameterizedType = (ParameterizedType) type; + Type[] typeArguments = parameterizedType.getActualTypeArguments(); + Class keyType = (Class) typeArguments[0]; + Class valueType = (Class) typeArguments[1]; + + // Convert KafkaEvent to ConsumerRecords + return (T) convertToConsumerRecords(kafkaEvent, keyType, valueType); + } catch (IOException e) { + throw new RuntimeException("Failed to deserialize Lambda handler input to ConsumerRecords", e); + } + } + + /** + * Deserialize JSON from String into ConsumerRecords + * + * @param input String containing JSON data + * @param type Type representing ConsumerRecords + * @param The type to deserialize to + * @return Deserialized ConsumerRecords object + * @throws IllegalArgumentException if type is not ConsumerRecords + */ + @SuppressWarnings("unchecked") + @Override + public T fromJson(String input, Type type) { + if (!isConsumerRecordsType(type)) { + throw new IllegalArgumentException("Type must be ConsumerRecords when using this deserializer"); + } + + try { + // Parse the KafkaEvent from the input string + KafkaEvent kafkaEvent = objectMapper.readValue(input, KafkaEvent.class); + + // Extract the key and value types from the ConsumerRecords type + ParameterizedType parameterizedType = (ParameterizedType) type; + Type[] typeArguments = parameterizedType.getActualTypeArguments(); + Class keyType = (Class) typeArguments[0]; + Class valueType = (Class) typeArguments[1]; + + // Convert KafkaEvent to ConsumerRecords + return (T) convertToConsumerRecords(kafkaEvent, keyType, valueType); + } catch (IOException e) { + throw new RuntimeException("Failed to deserialize Lambda handler input to ConsumerRecords", e); + } + } + + private boolean isConsumerRecordsType(Type type) { + if (!(type instanceof ParameterizedType)) { + return false; + } + + ParameterizedType parameterizedType = (ParameterizedType) type; + return parameterizedType.getRawType().equals(ConsumerRecords.class); + } + + private ConsumerRecords convertToConsumerRecords(KafkaEvent kafkaEvent, Class keyType, + Class valueType) { + // Validate that this is actually a Kafka event by checking for required properties + if (kafkaEvent == null || kafkaEvent.getEventSource() == null) { + throw new RuntimeException( + "Failed to deserialize Lambda handler input to ConsumerRecords: Input is not a valid Kafka event."); + } + + if (kafkaEvent.getRecords() == null) { + return ConsumerRecords.empty(); + } + + Map>> recordsMap = new HashMap<>(); + + for (Map.Entry> entry : kafkaEvent.getRecords().entrySet()) { + String topic = entry.getKey(); + + for (KafkaEvent.KafkaEventRecord eventRecord : entry.getValue()) { + ConsumerRecord consumerRecord = convertToConsumerRecord(topic, eventRecord, keyType, valueType); + + TopicPartition topicPartition = new TopicPartition(topic, eventRecord.getPartition()); + recordsMap.computeIfAbsent(topicPartition, k -> new ArrayList<>()).add(consumerRecord); + } + } + + return createConsumerRecords(recordsMap); + } + + /** + * Creates ConsumerRecords with compatibility for both Kafka 3.x.x and 4.x.x. + * + * @param Key type + * @param Value type + * @param records Map of records by topic partition + * @return ConsumerRecords instance + */ + protected ConsumerRecords createConsumerRecords( + Map>> records) { + try { + // Try to use the Kafka 4.x.x constructor with nextOffsets parameter + return new ConsumerRecords<>(records, Map.of()); + } catch (NoSuchMethodError e) { + // Fall back to Kafka 3.x.x constructor if 4.x.x is not available + return new ConsumerRecords<>(records); + } + } + + private ConsumerRecord convertToConsumerRecord( + String topic, + KafkaEvent.KafkaEventRecord eventRecord, + Class keyType, + Class valueType) { + + K key = deserializeField(eventRecord.getKey(), keyType, "key"); + V value = deserializeField(eventRecord.getValue(), valueType, "value"); + Headers headers = extractHeaders(eventRecord); + + return new ConsumerRecord<>( + topic, + eventRecord.getPartition(), + eventRecord.getOffset(), + eventRecord.getTimestamp(), + TimestampType.valueOf(eventRecord.getTimestampType()), + // We set these to NULL_SIZE since they are not relevant in the Lambda environment due to ESM + // pre-processing. + ConsumerRecord.NULL_SIZE, + ConsumerRecord.NULL_SIZE, + key, + value, + headers, + Optional.empty()); + } + + private T deserializeField(String encodedData, Class type, String fieldName) { + if (encodedData == null) { + return null; + } + + try { + byte[] decodedBytes = Base64.getDecoder().decode(encodedData); + return deserialize(decodedBytes, type); + } catch (Exception e) { + throw new RuntimeException("Failed to deserialize Kafka record " + fieldName + ".", e); + } + } + + private Headers extractHeaders(KafkaEvent.KafkaEventRecord eventRecord) { + Headers headers = new RecordHeaders(); + if (eventRecord.getHeaders() != null) { + for (Map headerMap : eventRecord.getHeaders()) { + for (Map.Entry header : headerMap.entrySet()) { + if (header.getValue() != null) { + headers.add(header.getKey(), header.getValue()); + } + } + } + } + + return headers; + } + + /** + * Template method to be implemented by subclasses for specific deserialization logic + * for complex types (non-primitives). + * + * @param The type to deserialize to + * @param data The byte array to deserialize coming from the base64 decoded Kafka field + * @param type The class type to deserialize to + * @return The deserialized object + * @throws IOException If deserialization fails + */ + protected abstract T deserializeObject(byte[] data, Class type) throws IOException; + + /** + * Main deserialize method that handles primitive types and delegates to subclasses for complex types. + * + * @param The type to deserialize to + * @param data The byte array to deserialize + * @param type The class type to deserialize to + * @return The deserialized object + * @throws IOException If deserialization fails + */ + private T deserialize(byte[] data, Class type) throws IOException { + // First try to deserialize as a primitive type + T result = deserializePrimitive(data, type); + if (result != null) { + return result; + } + + // Delegate to subclass for complex type deserialization + return deserializeObject(data, type); + } + + /** + * Helper method for handling primitive types and String deserialization. + * + * @param The type to deserialize to + * @param data The byte array to deserialize + * @param type The class type to deserialize to + * @return The deserialized primitive or String, or null if not a primitive or String + */ + @SuppressWarnings("unchecked") + private T deserializePrimitive(byte[] data, Class type) { + // Handle String type + if (type == String.class) { + return (T) new String(data, StandardCharsets.UTF_8); + } + + // Handle primitive types and their wrappers + String str = new String(data, StandardCharsets.UTF_8); + + if (type == Integer.class || type == int.class) { + return (T) Integer.valueOf(str); + } else if (type == Long.class || type == long.class) { + return (T) Long.valueOf(str); + } else if (type == Double.class || type == double.class) { + return (T) Double.valueOf(str); + } else if (type == Float.class || type == float.class) { + return (T) Float.valueOf(str); + } else if (type == Boolean.class || type == boolean.class) { + return (T) Boolean.valueOf(str); + } else if (type == Byte.class || type == byte.class) { + return (T) Byte.valueOf(str); + } else if (type == Short.class || type == short.class) { + return (T) Short.valueOf(str); + } else if (type == Character.class || type == char.class) { + if (!str.isEmpty()) { + return (T) Character.valueOf(str.charAt(0)); + } + throw new IllegalArgumentException("Cannot convert empty string to char"); + } + + return null; + } +} diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializer.java new file mode 100644 index 000000000..ddf09d4ff --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializer.java @@ -0,0 +1,46 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.serializers; + +import java.io.IOException; + +import org.apache.avro.io.DatumReader; +import org.apache.avro.io.Decoder; +import org.apache.avro.io.DecoderFactory; +import org.apache.avro.specific.SpecificDatumReader; +import org.apache.avro.specific.SpecificRecordBase; + +/** + * Deserializer for Kafka records using Avro format. + */ +public class KafkaAvroDeserializer extends AbstractKafkaDeserializer { + + @Override + protected T deserializeObject(byte[] data, Class type) throws IOException { + // If no Avro generated class is passed we cannot deserialize using Avro + if (SpecificRecordBase.class.isAssignableFrom(type)) { + try { + DatumReader datumReader = new SpecificDatumReader<>(type); + Decoder decoder = DecoderFactory.get().binaryDecoder(data, null); + + return datumReader.read(null, decoder); + } catch (Exception e) { + throw new IOException("Failed to deserialize Avro data.", e); + } + } else { + throw new IOException("Unsupported type for Avro deserialization: " + type.getName() + ". " + + "Avro deserialization requires a type of org.apache.avro.specific.SpecificRecord. " + + "Consider using an alternative Deserializer."); + } + } +} diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializer.java new file mode 100644 index 000000000..ed64f3786 --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializer.java @@ -0,0 +1,29 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.serializers; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +/** + * Deserializer for Kafka records using JSON format. + */ +public class KafkaJsonDeserializer extends AbstractKafkaDeserializer { + + @Override + protected T deserializeObject(byte[] data, Class type) throws IOException { + String decodedStr = new String(data, StandardCharsets.UTF_8); + + return objectMapper.readValue(decodedStr, type); + } +} diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java new file mode 100644 index 000000000..025f203c4 --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java @@ -0,0 +1,43 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.serializers; + +import java.io.IOException; +import com.google.protobuf.Message; +import com.google.protobuf.Parser; + +/** + * Deserializer for Kafka records using Protocol Buffers format. + */ +public class KafkaProtobufDeserializer extends AbstractKafkaDeserializer { + + @Override + @SuppressWarnings("unchecked") + protected T deserializeObject(byte[] data, Class type) throws IOException { + // If no Protobuf generated class is passed we cannot deserialize using Protobuf + if (Message.class.isAssignableFrom(type)) { + try { + // Get the parser from the generated Protobuf class + Parser parser = (Parser) type.getMethod("parser").invoke(null); + Message message = parser.parseFrom(data); + return type.cast(message); + } catch (Exception e) { + throw new IOException("Failed to deserialize Protobuf data.", e); + } + } else { + throw new IOException("Unsupported type for Protobuf deserialization: " + type.getName() + ". " + + "Protobuf deserialization requires a type of com.google.protobuf.Message. " + + "Consider using an alternative Deserializer."); + } + } +} diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/LambdaDefaultDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/LambdaDefaultDeserializer.java new file mode 100644 index 000000000..a7ea15d2f --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/LambdaDefaultDeserializer.java @@ -0,0 +1,65 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.serializers; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; + +import com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory; + +/** + * Default deserializer for Kafka events proxying to Lambda default behavior. + * + * This deserializer uses the default Jackson ObjectMapper to deserialize the event from + * {@link com.amazonaws.services.lambda.runtime.serialization}. + */ +public class LambdaDefaultDeserializer implements PowertoolsDeserializer { + + @SuppressWarnings("unchecked") + @Override + public T fromJson(InputStream input, Type type) { + // If the target type does not require conversion, simply return the value itself + if (type.equals(InputStream.class)) { + return (T) input; + } + + // If the target type is String, read the input stream as a String + if (type.equals(String.class)) { + try { + return (T) new String(input.readAllBytes(), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new RuntimeException("Failed to read input stream as String", e); + } + } + + return (T) JacksonFactory.getInstance().getSerializer(type).fromJson(input); + } + + @SuppressWarnings("unchecked") + @Override + public T fromJson(String input, Type type) { + // If the target type does not require conversion, simply return the value itself + if (type.equals(String.class)) { + return (T) input; + } + + // If the target type is InputStream, read the input stream as a String + if (type.equals(InputStream.class)) { + return (T) input.getBytes(StandardCharsets.UTF_8); + } + + return (T) JacksonFactory.getInstance().getSerializer(type).fromJson(input); + } +} diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/PowertoolsDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/PowertoolsDeserializer.java new file mode 100644 index 000000000..1ac0ca0ba --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/PowertoolsDeserializer.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.serializers; + +import java.io.InputStream; +import java.lang.reflect.Type; + +/** + * Interface for deserializers that can handle both String and InputStream inputs. + * + * Similar to {@link com.amazonaws.services.lambda.runtime.CustomPojoSerializer} but only for input deserialization. + */ +public interface PowertoolsDeserializer { + T fromJson(InputStream input, Type type); + + T fromJson(String input, Type type); +} diff --git a/powertools-kafka/src/main/resources/META-INF/services/com.amazonaws.services.lambda.runtime.CustomPojoSerializer b/powertools-kafka/src/main/resources/META-INF/services/com.amazonaws.services.lambda.runtime.CustomPojoSerializer new file mode 100644 index 000000000..abc84b035 --- /dev/null +++ b/powertools-kafka/src/main/resources/META-INF/services/com.amazonaws.services.lambda.runtime.CustomPojoSerializer @@ -0,0 +1 @@ +software.amazon.lambda.powertools.kafka.PowertoolsSerializer diff --git a/powertools-kafka/src/test/avro/TestProduct.avsc b/powertools-kafka/src/test/avro/TestProduct.avsc new file mode 100644 index 000000000..aad903d40 --- /dev/null +++ b/powertools-kafka/src/test/avro/TestProduct.avsc @@ -0,0 +1,10 @@ +{ + "namespace": "software.amazon.lambda.powertools.kafka.serializers.test.avro", + "type": "record", + "name": "TestProduct", + "fields": [ + {"name": "id", "type": "int"}, + {"name": "name", "type": "string"}, + {"name": "price", "type": "double"} + ] +} \ No newline at end of file diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/DeserializationTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/DeserializationTest.java new file mode 100644 index 000000000..964498d99 --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/DeserializationTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.lang.reflect.Method; + +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.junit.jupiter.api.Test; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +class DeserializationTest { + + @Test + void shouldHaveCorrectAnnotationRetention() { + // Given + Class annotationClass = Deserialization.class; + + // When/Then + assertThat(annotationClass.isAnnotation()).isTrue(); + assertThat(annotationClass.getAnnotation(java.lang.annotation.Retention.class).value()) + .isEqualTo(java.lang.annotation.RetentionPolicy.RUNTIME); + assertThat(annotationClass.getAnnotation(java.lang.annotation.Target.class).value()) + .contains(java.lang.annotation.ElementType.METHOD); + } + + @Test + void shouldHaveTypeMethod() throws NoSuchMethodException { + // Given + Class annotationClass = Deserialization.class; + + // When + java.lang.reflect.Method typeMethod = annotationClass.getMethod("type"); + + // Then + assertThat(typeMethod.getReturnType()).isEqualTo(DeserializationType.class); + } + + @Test + void shouldBeAccessibleReflectivelyAtRuntime() throws NoSuchMethodException, SecurityException { + // Given + class TestHandler implements RequestHandler, String> { + @Override + @Deserialization(type = DeserializationType.KAFKA_JSON) + public String handleRequest(ConsumerRecords input, Context context) { + return "OK"; + } + } + + // When + Method handleRequestMethod = TestHandler.class.getMethod("handleRequest", ConsumerRecords.class, Context.class); + + // Then + Deserialization annotation = handleRequestMethod.getAnnotation(Deserialization.class); + assertThat(annotation).isNotNull(); + assertThat(annotation.type()).isEqualTo(DeserializationType.KAFKA_JSON); + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/DeserializationTypeTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/DeserializationTypeTest.java new file mode 100644 index 000000000..6999b66d4 --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/DeserializationTypeTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +// Mainly present to remind us to write unit tests once we add support for a new Deserializer. If we add a new type in +// the enum it will fail this test. +class DeserializationTypeTest { + + @Test + void shouldHaveExpectedEnumValues() { + // Given/When + DeserializationType[] values = DeserializationType.values(); + + // Then + assertThat(values).contains( + DeserializationType.LAMBDA_DEFAULT, + DeserializationType.KAFKA_JSON, + DeserializationType.KAFKA_AVRO, + DeserializationType.KAFKA_PROTOBUF); + } + + @Test + void shouldBeAbleToValueOf() { + // Given/When + DeserializationType jsonType = DeserializationType.valueOf("KAFKA_JSON"); + DeserializationType avroType = DeserializationType.valueOf("KAFKA_AVRO"); + DeserializationType protobufType = DeserializationType.valueOf("KAFKA_PROTOBUF"); + DeserializationType defaultType = DeserializationType.valueOf("LAMBDA_DEFAULT"); + + // Then + assertThat(jsonType).isEqualTo(DeserializationType.KAFKA_JSON); + assertThat(avroType).isEqualTo(DeserializationType.KAFKA_AVRO); + assertThat(protobufType).isEqualTo(DeserializationType.KAFKA_PROTOBUF); + assertThat(defaultType).isEqualTo(DeserializationType.LAMBDA_DEFAULT); + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializerTest.java new file mode 100644 index 000000000..6ce57ecd5 --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializerTest.java @@ -0,0 +1,417 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static software.amazon.lambda.powertools.kafka.testutils.TestUtils.createConsumerRecordsType; +import static software.amazon.lambda.powertools.kafka.testutils.TestUtils.serializeAvro; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.stream.Stream; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.common.TopicPartition; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junitpioneer.jupiter.SetEnvironmentVariable; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.kafka.serializers.LambdaDefaultDeserializer; +import software.amazon.lambda.powertools.kafka.serializers.PowertoolsDeserializer; +import software.amazon.lambda.powertools.kafka.testutils.TestProductPojo; + +// This is testing the whole serializer end-to-end. More detailed serializer tests are placed in serializers folder. +@ExtendWith(MockitoExtension.class) +class PowertoolsSerializerTest { + + @Mock + private PowertoolsDeserializer mockDeserializer; + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + // CustomPojoSerializer has fromJson(String input, ...) and fromJson(InputStream input, ...). We want to test both. + static Stream inputTypes() { + return Stream.of(InputType.INPUT_STREAM, InputType.STRING); + } + + @ParameterizedTest + @MethodSource("inputTypes") + @SetEnvironmentVariable(key = "_HANDLER", value = "") + void shouldUseDefaultDeserializerWhenHandlerNotFound(InputType inputType) throws JsonProcessingException { + // When + PowertoolsSerializer serializer = new PowertoolsSerializer(); + + // Then + TestProductPojo product = new TestProductPojo(123, "Test Product", 99.99, Arrays.asList("tag1", "tag2")); + String json = objectMapper.writeValueAsString(product); + + // This will use the Lambda default deserializer (no Kafka logic) + TestProductPojo result; + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream input = new ByteArrayInputStream(json.getBytes()); + result = serializer.fromJson(input, TestProductPojo.class); + } else { + result = serializer.fromJson(json, TestProductPojo.class); + } + + assertThat(result.getId()).isEqualTo(123); + assertThat(result.getName()).isEqualTo("Test Product"); + assertThat(result.getPrice()).isEqualTo(99.99); + assertThat(result.getTags()).containsExactly("tag1", "tag2"); + } + + @ParameterizedTest + @MethodSource("inputTypes") + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.DefaultHandler::handleRequest") + void shouldUseLambdaDefaultDeserializer(InputType inputType) throws JsonProcessingException { + // When + PowertoolsSerializer serializer = new PowertoolsSerializer(); + + // Then + TestProductPojo product = new TestProductPojo(123, "Test Product", 99.99, Arrays.asList("tag1", "tag2")); + String json = objectMapper.writeValueAsString(product); + + // This will use the Lambda default deserializer (no Kafka logic) + TestProductPojo result; + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream input = new ByteArrayInputStream(json.getBytes()); + result = serializer.fromJson(input, TestProductPojo.class); + } else { + result = serializer.fromJson(json, TestProductPojo.class); + } + + assertThat(result.getId()).isEqualTo(123); + assertThat(result.getName()).isEqualTo("Test Product"); + assertThat(result.getPrice()).isEqualTo(99.99); + assertThat(result.getTags()).containsExactly("tag1", "tag2"); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.StringHandler::handleRequest") + void shouldHandleStringInputType() { + // When + PowertoolsSerializer serializer = new PowertoolsSerializer(); + + // Then + String testInput = "This is a test string"; + + // This should directly return the input string + String result = serializer.fromJson(testInput, String.class); + + assertThat(result).isEqualTo(testInput); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.InputStreamHandler::handleRequest") + void shouldHandleInputStreamType() throws IOException { + // When + PowertoolsSerializer serializer = new PowertoolsSerializer(); + + // Then + String testInput = "This is a test string"; + ByteArrayInputStream inputStream = new ByteArrayInputStream(testInput.getBytes()); + + // This should return the input stream directly + InputStream result = serializer.fromJson(inputStream, InputStream.class); + + // Read the content to verify it's the same + String resultString = new String(result.readAllBytes()); + assertThat(resultString).isEqualTo(testInput); + } + + @Test + void shouldConvertInputStreamToString() { + // When + LambdaDefaultDeserializer deserializer = new LambdaDefaultDeserializer(); + + // Then + String expected = "This is a test string"; + ByteArrayInputStream inputStream = new ByteArrayInputStream(expected.getBytes()); + + // Convert InputStream to String + String result = deserializer.fromJson(inputStream, String.class); + + // Verify the result + assertThat(result).isEqualTo(expected); + } + + @Test + void shouldThrowRuntimeExceptionWhenInputStreamIsInvalid() { + // When + LambdaDefaultDeserializer deserializer = new LambdaDefaultDeserializer(); + + // Create a problematic InputStream that throws IOException when read + InputStream problematicStream = new InputStream() { + @Override + public int read() throws IOException { + throw new IOException("Simulated IO error"); + } + + @Override + public byte[] readAllBytes() throws IOException { + throw new IOException("Simulated IO error"); + } + }; + + // Then + assertThatThrownBy(() -> deserializer.fromJson(problematicStream, String.class)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to read input stream as String"); + } + + @Test + void shouldConvertStringToByteArray() { + // When + LambdaDefaultDeserializer deserializer = new LambdaDefaultDeserializer(); + + // Then + String input = "This is a test string"; + + // Convert String to InputStream + byte[] result = deserializer.fromJson(input, InputStream.class); + + // Verify the result + String resultString = new String(result); + assertThat(resultString).isEqualTo(input); + } + + @ParameterizedTest + @MethodSource("inputTypes") + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.JsonHandler::handleRequest") + void shouldUseKafkaJsonDeserializer(InputType inputType) throws JsonProcessingException { + // When + PowertoolsSerializer serializer = new PowertoolsSerializer(); + + // Create a TestProductPojo and serialize it + TestProductPojo product = new TestProductPojo(123, "Test Product", 99.99, Arrays.asList("tag1", "tag2")); + String productJson = objectMapper.writeValueAsString(product); + String base64Value = Base64.getEncoder().encodeToString(productJson.getBytes()); + + // Then + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": \"" + base64Value + "\",\n" + + " \"headers\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + + Type type = createConsumerRecordsType(String.class, TestProductPojo.class); + + // This should use the KafkaJsonDeserializer + ConsumerRecords records; + + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream input = new ByteArrayInputStream(kafkaJson.getBytes()); + records = serializer.fromJson(input, type); + } else { + records = serializer.fromJson(kafkaJson, type); + } + + // Verify we got a valid ConsumerRecords object + assertThat(records).isNotNull(); + + // Get the record and verify its content + TopicPartition tp = new TopicPartition("test-topic-1", 0); + List> topicRecords = records.records(tp); + assertThat(topicRecords).hasSize(1); + + ConsumerRecord consumerRecord = topicRecords.get(0); + TestProductPojo deserializedProduct = consumerRecord.value(); + + assertThat(deserializedProduct.getId()).isEqualTo(123); + assertThat(deserializedProduct.getName()).isEqualTo("Test Product"); + assertThat(deserializedProduct.getPrice()).isEqualTo(99.99); + assertThat(deserializedProduct.getTags()).containsExactly("tag1", "tag2"); + } + + @ParameterizedTest + @MethodSource("inputTypes") + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.AvroHandler::handleRequest") + void shouldUseKafkaAvroDeserializer(InputType inputType) throws IOException { + // When + PowertoolsSerializer serializer = new PowertoolsSerializer(); + + // Create an Avro TestProduct and serialize it + software.amazon.lambda.powertools.kafka.serializers.test.avro.TestProduct product = new software.amazon.lambda.powertools.kafka.serializers.test.avro.TestProduct( + 123, "Test Product", 99.99); + String base64Value = Base64.getEncoder().encodeToString(serializeAvro(product)); + + // Then + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": \"" + base64Value + "\",\n" + + " \"headers\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + + Type type = createConsumerRecordsType(String.class, + software.amazon.lambda.powertools.kafka.serializers.test.avro.TestProduct.class); + + // This should use the KafkaAvroDeserializer + ConsumerRecords records; + + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream input = new ByteArrayInputStream(kafkaJson.getBytes()); + records = serializer.fromJson(input, type); + } else { + records = serializer.fromJson(kafkaJson, type); + } + + // Verify we got a valid ConsumerRecords object + assertThat(records).isNotNull(); + + // Get the record and verify its content + TopicPartition tp = new TopicPartition("test-topic-1", 0); + List> topicRecords = records + .records(tp); + assertThat(topicRecords).hasSize(1); + + ConsumerRecord consumerRecord = topicRecords + .get(0); + software.amazon.lambda.powertools.kafka.serializers.test.avro.TestProduct deserializedProduct = consumerRecord + .value(); + + assertThat(deserializedProduct.getId()).isEqualTo(123); + assertThat(deserializedProduct.getName()).isEqualTo("Test Product"); + assertThat(deserializedProduct.getPrice()).isEqualTo(99.99); + } + + @ParameterizedTest + @MethodSource("inputTypes") + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.ProtobufHandler::handleRequest") + void shouldUseKafkaProtobufDeserializer(InputType inputType) { + // When + PowertoolsSerializer serializer = new PowertoolsSerializer(); + + // Create a Protobuf TestProduct and serialize it + software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct product = software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct + .newBuilder() + .setId(123) + .setName("Test Product") + .setPrice(99.99) + .build(); + String base64Value = Base64.getEncoder().encodeToString(product.toByteArray()); + + // Then + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": \"" + base64Value + "\",\n" + + " \"headers\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + + Type type = createConsumerRecordsType(String.class, + software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct.class); + + // This should use the KafkaProtobufDeserializer + ConsumerRecords records; + + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream input = new ByteArrayInputStream(kafkaJson.getBytes()); + records = serializer.fromJson(input, type); + } else { + records = serializer.fromJson(kafkaJson, type); + } + + // Verify we got a valid ConsumerRecords object + assertThat(records).isNotNull(); + + // Get the record and verify its content + TopicPartition tp = new TopicPartition("test-topic-1", 0); + List> topicRecords = records + .records(tp); + assertThat(topicRecords).hasSize(1); + + ConsumerRecord consumerRecord = topicRecords + .get(0); + software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct deserializedProduct = consumerRecord + .value(); + + assertThat(deserializedProduct.getId()).isEqualTo(123); + assertThat(deserializedProduct.getName()).isEqualTo("Test Product"); + assertThat(deserializedProduct.getPrice()).isEqualTo(99.99); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "") + void shouldDelegateToJsonOutput() { + // Given + PowertoolsSerializer serializer = new PowertoolsSerializer(); + + // When + TestProductPojo product = new TestProductPojo(123, "Test Product", 99.99, Arrays.asList("tag1", "tag2")); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + + // Then + serializer.toJson(product, output, TestProductPojo.class); + String json = output.toString(); + + // Verify the output is valid JSON + assertThat(json).contains("\"id\":123") + .contains("\"name\":\"Test Product\"") + .contains("\"price\":99.99") + .contains("\"tags\":[\"tag1\",\"tag2\"]"); + } + + private enum InputType { + INPUT_STREAM, STRING + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/DeserializationUtilsTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/DeserializationUtilsTest.java new file mode 100644 index 000000000..21f38d9ab --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/DeserializationUtilsTest.java @@ -0,0 +1,145 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.internal; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.SetEnvironmentVariable; + +import software.amazon.lambda.powertools.kafka.DeserializationType; + +class DeserializationUtilsTest { + + // NOTE: We don't use a parameterized test here because this is not compatible with the @SetEnvironmentVariable + // annotation. + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "") + void shouldReturnDefaultDeserializationTypeWhenHandlerIsEmpty() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.LAMBDA_DEFAULT); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = " ") + void shouldReturnDefaultDeserializationTypeWhenHandlerIsWhitespaceOnly() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.LAMBDA_DEFAULT); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "InvalidHandlerFormat") + void shouldReturnDefaultDeserializationTypeWhenHandlerFormatIsInvalid() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.LAMBDA_DEFAULT); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "com.example.NonExistentClass::handleRequest") + void shouldReturnDefaultDeserializationTypeWhenClassNotFound() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.LAMBDA_DEFAULT); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "java.lang.String::toString") + void shouldReturnDefaultDeserializationTypeWhenClassIsNotRequestHandler() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.LAMBDA_DEFAULT); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.internal.DeserializationUtilsTest$TestHandler::nonExistentMethod") + void shouldReturnDefaultDeserializationTypeWhenMethodNotFound() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.LAMBDA_DEFAULT); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.JsonHandler::handleRequest") + void shouldReturnJsonDeserializationTypeFromAnnotation() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.KAFKA_JSON); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.AvroHandler::handleRequest") + void shouldReturnAvroDeserializationTypeFromAnnotation() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.KAFKA_AVRO); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.ProtobufHandler::handleRequest") + void shouldReturnProtobufDeserializationTypeFromAnnotation() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.KAFKA_PROTOBUF); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.JsonHandler") + void shouldReturnJsonDeserializationTypeFromAnnotationWithAbbreviatedHandler() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.KAFKA_JSON); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.AvroHandler") + void shouldReturnAvroDeserializationTypeFromAnnotationWithAbbreviatedHandler() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.KAFKA_AVRO); + } + + @Test + @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.ProtobufHandler") + void shouldReturnProtobufDeserializationTypeFromAnnotationWithAbbreviatedHandler() { + // When + DeserializationType type = DeserializationUtils.determineDeserializationType(); + + // Then + assertThat(type).isEqualTo(DeserializationType.KAFKA_PROTOBUF); + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializerTest.java new file mode 100644 index 000000000..512058bca --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializerTest.java @@ -0,0 +1,473 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.serializers; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Base64; +import java.util.List; +import java.util.stream.Stream; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.common.TopicPartition; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.kafka.testutils.TestProductPojo; +import software.amazon.lambda.powertools.kafka.testutils.TestUtils; + +class AbstractKafkaDeserializerTest { + + private TestDeserializer deserializer; + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp() { + deserializer = new TestDeserializer(); + } + + // CustomPojoSerializer has fromJson(String input, ...) and fromJson(InputStream input, ...). We want to test both. + static Stream inputTypes() { + return Stream.of(InputType.INPUT_STREAM, InputType.STRING); + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldThrowExceptionWhenTypeIsNotConsumerRecords(InputType inputType) { + // Given + String json = "{}"; + + // When/Then + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(json.getBytes()); + assertThatThrownBy(() -> deserializer.fromJson(inputStream, String.class)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Type must be ConsumerRecords"); + } else { + assertThatThrownBy(() -> deserializer.fromJson(json, String.class)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessageContaining("Type must be ConsumerRecords"); + } + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldThrowExceptionWhenJsonIsInvalid(InputType inputType) { + // Given + String invalidJson = "{invalid json"; + Type type = TestUtils.createConsumerRecordsType(String.class, TestProductPojo.class); + + // When/Then + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(invalidJson.getBytes()); + assertThatThrownBy(() -> deserializer.fromJson(inputStream, type)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to deserialize Lambda handler input to ConsumerRecords"); + } else { + assertThatThrownBy(() -> deserializer.fromJson(invalidJson, type)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to deserialize Lambda handler input to ConsumerRecords"); + } + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldThrowExceptionWhenKeyDeserializationFails(InputType inputType) { + // Given + // Create a Kafka event with invalid Base64 for the key + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": \"invalid-base64!\",\n" + + " \"value\": \"eyJrZXkiOiJ2YWx1ZSJ9\",\n" + + " \"headers\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(String.class, TestProductPojo.class); + + // When/Then + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + assertThatThrownBy(() -> deserializer.fromJson(inputStream, type)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to deserialize Kafka record key"); + } else { + assertThatThrownBy(() -> deserializer.fromJson(kafkaJson, type)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to deserialize Kafka record key"); + } + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldThrowExceptionWhenValueDeserializationFails(InputType inputType) { + // Given + // Create a Kafka event with invalid Base64 for the value + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": \"invalid-base64!\",\n" + + " \"headers\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(String.class, TestProductPojo.class); + + // When/Then + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + assertThatThrownBy(() -> deserializer.fromJson(inputStream, type)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to deserialize Kafka record value"); + } else { + assertThatThrownBy(() -> deserializer.fromJson(kafkaJson, type)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to deserialize Kafka record value"); + } + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldHandleNullKeyAndValue(InputType inputType) { + // Given + // Create a Kafka event with null key and value + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": null,\n" + + " \"headers\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(String.class, TestProductPojo.class); + + // When + ConsumerRecords records; + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + records = deserializer.fromJson(inputStream, type); + } else { + records = deserializer.fromJson(kafkaJson, type); + } + + // Then + assertThat(records).isNotNull(); + TopicPartition tp = new TopicPartition("test-topic-1", 0); + List> topicRecords = records.records(tp); + assertThat(topicRecords).hasSize(1); + + ConsumerRecord consumerRecord = topicRecords.get(0); + assertThat(consumerRecord.key()).isNull(); + assertThat(consumerRecord.value()).isNull(); + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldHandleHeadersCorrectly(InputType inputType) { + // Given + // Create a Kafka event with headers + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": null,\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey1\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101, 49],\n" + + " \"headerKey2\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101, 50]\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(String.class, TestProductPojo.class); + + // When + ConsumerRecords records; + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + records = deserializer.fromJson(inputStream, type); + } else { + records = deserializer.fromJson(kafkaJson, type); + } + + // Then + assertThat(records).isNotNull(); + TopicPartition tp = new TopicPartition("test-topic-1", 0); + List> topicRecords = records.records(tp); + assertThat(topicRecords).hasSize(1); + + ConsumerRecord consumerRecord = topicRecords.get(0); + assertThat(consumerRecord.headers()).isNotNull(); + assertThat(consumerRecord.headers().toArray()).hasSize(2); + assertThat(new String(consumerRecord.headers().lastHeader("headerKey1").value())).isEqualTo("headerValue1"); + assertThat(new String(consumerRecord.headers().lastHeader("headerKey2").value())).isEqualTo("headerValue2"); + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldHandleEmptyRecords(InputType inputType) { + // Given + // Create a Kafka event with no records + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {}\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(String.class, TestProductPojo.class); + + // When + ConsumerRecords records; + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + records = deserializer.fromJson(inputStream, type); + } else { + records = deserializer.fromJson(kafkaJson, type); + } + + // Then + assertThat(records).isNotNull(); + assertThat(records.count()).isZero(); + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldHandleNullRecords(InputType inputType) { + // Given + // Create a Kafka event with null records + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\"\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(String.class, TestProductPojo.class); + + // When + ConsumerRecords records; + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + records = deserializer.fromJson(inputStream, type); + } else { + records = deserializer.fromJson(kafkaJson, type); + } + + // Then + assertThat(records).isNotNull(); + assertThat(records.count()).isZero(); + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldThrowExceptionWhenEventSourceIsNull(InputType inputType) { + // Given + // Create a JSON without eventSource property + String kafkaJson = "{\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": null,\n" + + " \"headers\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(String.class, TestProductPojo.class); + + // When/Then + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + assertThatThrownBy(() -> deserializer.fromJson(inputStream, type)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Input is not a valid Kafka event"); + } else { + assertThatThrownBy(() -> deserializer.fromJson(kafkaJson, type)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Input is not a valid Kafka event"); + } + } + + static Stream primitiveTypesProvider() { + return Stream.of( + // For each primitive type, test with both INPUT_STREAM and STRING + Arguments.of("String-InputStream", String.class, "test-string", "test-string", InputType.INPUT_STREAM), + Arguments.of("String-String", String.class, "test-string", "test-string", InputType.STRING), + Arguments.of("Integer-InputStream", Integer.class, "123", 123, InputType.INPUT_STREAM), + Arguments.of("Integer-String", Integer.class, "123", 123, InputType.STRING), + Arguments.of("Long-InputStream", Long.class, "123456789", 123456789L, InputType.INPUT_STREAM), + Arguments.of("Long-String", Long.class, "123456789", 123456789L, InputType.STRING), + Arguments.of("Double-InputStream", Double.class, "123.456", 123.456, InputType.INPUT_STREAM), + Arguments.of("Double-String", Double.class, "123.456", 123.456, InputType.STRING), + Arguments.of("Float-InputStream", Float.class, "123.45", 123.45f, InputType.INPUT_STREAM), + Arguments.of("Float-String", Float.class, "123.45", 123.45f, InputType.STRING), + Arguments.of("Boolean-InputStream", Boolean.class, "true", true, InputType.INPUT_STREAM), + Arguments.of("Boolean-String", Boolean.class, "true", true, InputType.STRING), + Arguments.of("Byte-InputStream", Byte.class, "127", (byte) 127, InputType.INPUT_STREAM), + Arguments.of("Byte-String", Byte.class, "127", (byte) 127, InputType.STRING), + Arguments.of("Short-InputStream", Short.class, "32767", (short) 32767, InputType.INPUT_STREAM), + Arguments.of("Short-String", Short.class, "32767", (short) 32767, InputType.STRING), + Arguments.of("Character-InputStream", Character.class, "A", 'A', InputType.INPUT_STREAM), + Arguments.of("Character-String", Character.class, "A", 'A', InputType.STRING)); + } + + @ParameterizedTest(name = "Should handle {0}") + @MethodSource("primitiveTypesProvider") + void shouldHandlePrimitiveTypes(String testName, Class keyType, String keyValue, T expectedKey, + InputType inputType) throws IOException { + // Given + // Create a TestProductPojo and serialize it to JSON + TestProductPojo product = new TestProductPojo(123, "Test Product", 99.99, null); + String productJson = objectMapper.writeValueAsString(product); + String base64Value = Base64.getEncoder().encodeToString(productJson.getBytes()); + String base64Key = Base64.getEncoder().encodeToString(keyValue.getBytes()); + + // Create a Kafka event with primitive type for key + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": \"" + base64Key + "\",\n" + + " \"value\": \"" + base64Value + "\",\n" + + " \"headers\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(keyType, TestProductPojo.class); + + // When + ConsumerRecords records; + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + records = deserializer.fromJson(inputStream, type); + } else { + records = deserializer.fromJson(kafkaJson, type); + } + + // Then + assertThat(records).isNotNull(); + TopicPartition tp = new TopicPartition("test-topic-1", 0); + List> topicRecords = records.records(tp); + assertThat(topicRecords).hasSize(1); + + ConsumerRecord consumerRecord = topicRecords.get(0); + assertThat(consumerRecord.key()).isEqualTo(expectedKey); + assertThat(consumerRecord.value()).isNotNull(); + assertThat(consumerRecord.value().getId()).isEqualTo(123); + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldThrowExceptionWhenConvertingEmptyStringToChar(InputType inputType) { + // Given + String base64EmptyString = Base64.getEncoder().encodeToString("".getBytes()); + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": \"" + base64EmptyString + "\",\n" + + " \"value\": null,\n" + + " \"headers\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(Character.class, TestProductPojo.class); + + // When/Then + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + assertThatThrownBy(() -> deserializer.fromJson(inputStream, type)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to deserialize Kafka record key") + .hasRootCauseInstanceOf(IllegalArgumentException.class) + .hasRootCauseMessage("Cannot convert empty string to char"); + } else { + assertThatThrownBy(() -> deserializer.fromJson(kafkaJson, type)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to deserialize Kafka record key") + .hasRootCauseInstanceOf(IllegalArgumentException.class) + .hasRootCauseMessage("Cannot convert empty string to char"); + } + } + + // Test implementation of AbstractKafkaDeserializer + private static class TestDeserializer extends AbstractKafkaDeserializer { + @Override + protected T deserializeObject(byte[] data, Class type) throws IOException { + return objectMapper.readValue(data, type); + } + } + + enum InputType { + INPUT_STREAM, STRING + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializerTest.java new file mode 100644 index 000000000..a0b59b136 --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializerTest.java @@ -0,0 +1,73 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.serializers; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static software.amazon.lambda.powertools.kafka.testutils.TestUtils.serializeAvro; + +import java.io.IOException; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import software.amazon.lambda.powertools.kafka.serializers.test.avro.TestProduct; + +class KafkaAvroDeserializerTest { + + private KafkaAvroDeserializer deserializer; + + @BeforeEach + void setUp() { + deserializer = new KafkaAvroDeserializer(); + } + + @Test + void shouldThrowExceptionWhenTypeIsNotAvroSpecificRecord() { + // Given + byte[] data = new byte[] { 1, 2, 3 }; + + // When/Then + assertThatThrownBy(() -> deserializer.deserializeObject(data, String.class)) + .isInstanceOf(IOException.class) + .hasMessageContaining("Unsupported type for Avro deserialization"); + } + + @Test + void shouldDeserializeValidAvroData() throws IOException { + // Given + TestProduct product = new TestProduct(123, "Test Product", 99.99); + byte[] avroData = serializeAvro(product); + + // When + TestProduct result = deserializer.deserializeObject(avroData, TestProduct.class); + + // Then + assertThat(result).isNotNull(); + assertThat(result.getId()).isEqualTo(123); + assertThat(result.getName()).isEqualTo("Test Product"); + assertThat(result.getPrice()).isEqualTo(99.99); + } + + @Test + void shouldThrowExceptionWhenDeserializingInvalidAvroData() { + // Given + byte[] invalidAvroData = new byte[] { 1, 2, 3, 4, 5 }; + + // When/Then + assertThatThrownBy(() -> deserializer.deserializeObject(invalidAvroData, TestProduct.class)) + .isInstanceOf(IOException.class) + .hasMessageContaining("Failed to deserialize Avro data"); + } + +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializerTest.java new file mode 100644 index 000000000..0cfb2498b --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializerTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.serializers; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.IOException; +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.kafka.testutils.TestProductPojo; + +class KafkaJsonDeserializerTest { + + private KafkaJsonDeserializer deserializer; + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp() { + deserializer = new KafkaJsonDeserializer(); + } + + @Test + void shouldThrowExceptionWhenTypeIsNotSupportedForJson() { + // Given + byte[] data = new byte[] { 1, 2, 3 }; + + // When/Then + assertThatThrownBy(() -> deserializer.deserializeObject(data, Object.class)) + .isInstanceOf(JsonParseException.class); + } + + @Test + void shouldDeserializeValidJsonData() throws IOException { + // Given + TestProductPojo product = new TestProductPojo(123, "Test Product", 99.99, Arrays.asList("tag1", "tag2")); + byte[] jsonData = objectMapper.writeValueAsBytes(product); + + // When + TestProductPojo result = deserializer.deserializeObject(jsonData, TestProductPojo.class); + + // Then + assertThat(result).isNotNull(); + assertThat(result.getId()).isEqualTo(123); + assertThat(result.getName()).isEqualTo("Test Product"); + assertThat(result.getPrice()).isEqualTo(99.99); + assertThat(result.getTags()).containsExactly("tag1", "tag2"); + } + +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java new file mode 100644 index 000000000..2d506de4b --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.serializers; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.io.IOException; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct; + +class KafkaProtobufDeserializerTest { + + private KafkaProtobufDeserializer deserializer; + + @BeforeEach + void setUp() { + deserializer = new KafkaProtobufDeserializer(); + } + + @Test + void shouldThrowExceptionWhenTypeIsNotProtobufMessage() { + // Given + byte[] data = new byte[] { 1, 2, 3 }; + + // When/Then + assertThatThrownBy(() -> deserializer.deserializeObject(data, String.class)) + .isInstanceOf(IOException.class) + .hasMessageContaining("Unsupported type for Protobuf deserialization"); + } + + @Test + void shouldDeserializeValidProtobufData() throws IOException { + // Given + TestProduct product = TestProduct.newBuilder() + .setId(123) + .setName("Test Product") + .setPrice(99.99) + .build(); + byte[] protobufData = product.toByteArray(); + + // When + TestProduct result = deserializer.deserializeObject(protobufData, TestProduct.class); + + // Then + assertThat(result).isNotNull(); + assertThat(result.getId()).isEqualTo(123); + assertThat(result.getName()).isEqualTo("Test Product"); + assertThat(result.getPrice()).isEqualTo(99.99); + } + + @Test + void shouldThrowExceptionWhenDeserializingInvalidProtobufData() { + // Given + byte[] invalidProtobufData = new byte[] { 1, 2, 3, 4, 5 }; + + // When/Then + assertThatThrownBy(() -> deserializer.deserializeObject(invalidProtobufData, TestProduct.class)) + .isInstanceOf(IOException.class) + .hasMessageContaining("Failed to deserialize Protobuf data"); + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/AvroHandler.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/AvroHandler.java new file mode 100644 index 000000000..d0fc9c1ba --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/AvroHandler.java @@ -0,0 +1,30 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.testutils; + +import org.apache.kafka.clients.consumer.ConsumerRecords; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.kafka.Deserialization; +import software.amazon.lambda.powertools.kafka.DeserializationType; +import software.amazon.lambda.powertools.kafka.serializers.test.avro.TestProduct; + +public class AvroHandler implements RequestHandler, String> { + @Override + @Deserialization(type = DeserializationType.KAFKA_AVRO) + public String handleRequest(ConsumerRecords input, Context context) { + return "OK"; + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/DefaultHandler.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/DefaultHandler.java new file mode 100644 index 000000000..31e93d872 --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/DefaultHandler.java @@ -0,0 +1,29 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.testutils; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.kafka.Deserialization; +import software.amazon.lambda.powertools.kafka.DeserializationType; + +// This is a non-Kafka specific handler. Just a handler using default deserialization into a Pojo. Used for testing +// fallback to default Lambda serialization. +public class DefaultHandler implements RequestHandler { + @Override + @Deserialization(type = DeserializationType.LAMBDA_DEFAULT) + public String handleRequest(TestProductPojo input, Context context) { + return "OK"; + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/InputStreamHandler.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/InputStreamHandler.java new file mode 100644 index 000000000..63e225ab8 --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/InputStreamHandler.java @@ -0,0 +1,30 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.testutils; + +import java.io.IOException; +import java.io.InputStream; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +public class InputStreamHandler implements RequestHandler { + @Override + public String handleRequest(InputStream input, Context context) { + try { + return new String(input.readAllBytes()); + } catch (IOException e) { + throw new RuntimeException("Failed to read input stream", e); + } + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/JsonHandler.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/JsonHandler.java new file mode 100644 index 000000000..b6422f73c --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/JsonHandler.java @@ -0,0 +1,29 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.testutils; + +import org.apache.kafka.clients.consumer.ConsumerRecords; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.kafka.Deserialization; +import software.amazon.lambda.powertools.kafka.DeserializationType; + +public class JsonHandler implements RequestHandler, String> { + @Override + @Deserialization(type = DeserializationType.KAFKA_JSON) + public String handleRequest(ConsumerRecords input, Context context) { + return "OK"; + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/ProtobufHandler.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/ProtobufHandler.java new file mode 100644 index 000000000..a4ce61765 --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/ProtobufHandler.java @@ -0,0 +1,30 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.testutils; + +import org.apache.kafka.clients.consumer.ConsumerRecords; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.kafka.Deserialization; +import software.amazon.lambda.powertools.kafka.DeserializationType; +import software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct; + +public class ProtobufHandler implements RequestHandler, String> { + @Override + @Deserialization(type = DeserializationType.KAFKA_PROTOBUF) + public String handleRequest(ConsumerRecords input, Context context) { + return "OK"; + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/StringHandler.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/StringHandler.java new file mode 100644 index 000000000..3ac5649f1 --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/StringHandler.java @@ -0,0 +1,23 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.testutils; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +public class StringHandler implements RequestHandler { + @Override + public String handleRequest(String input, Context context) { + return input; + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/TestProductPojo.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/TestProductPojo.java new file mode 100644 index 000000000..8cd261aef --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/TestProductPojo.java @@ -0,0 +1,87 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.testutils; + +import java.util.List; +import java.util.Objects; + +/** + * Simple POJO for testing JSON deserialization + */ +public class TestProductPojo { + private int id; + private String name; + private double price; + private List tags; + + // Default constructor required for Jackson + public TestProductPojo() { + } + + public TestProductPojo(int id, String name, double price, List tags) { + this.id = id; + this.name = name; + this.price = price; + this.tags = tags; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + public List getTags() { + return tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + TestProductPojo that = (TestProductPojo) o; + return id == that.id && + Double.compare(that.price, price) == 0 && + Objects.equals(name, that.name) && + Objects.equals(tags, that.tags); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, price, tags); + } +} diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/TestUtils.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/TestUtils.java new file mode 100644 index 000000000..33623a9b2 --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/testutils/TestUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package software.amazon.lambda.powertools.kafka.testutils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import org.apache.avro.io.BinaryEncoder; +import org.apache.avro.io.DatumWriter; +import org.apache.avro.io.EncoderFactory; +import org.apache.avro.specific.SpecificDatumWriter; +import org.apache.avro.specific.SpecificRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; + +/** + * Utility class for common test functions + */ +public class TestUtils { + + /** + * Helper method to create a ParameterizedType for ConsumerRecords + * + * @param keyClass The class for the key type + * @param valueClass The class for the value type + * @return A Type representing ConsumerRecords + */ + public static Type createConsumerRecordsType(final Class keyClass, final Class valueClass) { + return new ParameterizedType() { + @Override + public Type[] getActualTypeArguments() { + return new Type[] { keyClass, valueClass }; + } + + @Override + public Type getRawType() { + return ConsumerRecords.class; + } + + @Override + public Type getOwnerType() { + return null; + } + }; + } + + /** + * Helper method to serialize an Avro object + * + * @param The type of the Avro record + * @param consumerRecord The Avro record to serialize + * @return The serialized bytes + * @throws IOException If serialization fails + */ + public static byte[] serializeAvro(T consumerRecord) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(baos, null); + @SuppressWarnings("unchecked") + DatumWriter writer = new SpecificDatumWriter<>((Class) consumerRecord.getClass()); + writer.write(consumerRecord, encoder); + encoder.flush(); + return baos.toByteArray(); + } +} diff --git a/powertools-kafka/src/test/proto/TestProduct.proto b/powertools-kafka/src/test/proto/TestProduct.proto new file mode 100644 index 000000000..53c654494 --- /dev/null +++ b/powertools-kafka/src/test/proto/TestProduct.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; + +package software.amazon.lambda.powertools.kafka.serializers.test.protobuf; + +option java_package = "software.amazon.lambda.powertools.kafka.serializers.test.protobuf"; +option java_outer_classname = "TestProductOuterClass"; +option java_multiple_files = true; + +message TestProduct { + int32 id = 1; + string name = 2; + double price = 3; +} \ No newline at end of file diff --git a/powertools-kafka/src/test/resources/simplelogger.properties b/powertools-kafka/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..167581f74 --- /dev/null +++ b/powertools-kafka/src/test/resources/simplelogger.properties @@ -0,0 +1,13 @@ +# SLF4J Simple Logger configuration for tests +org.slf4j.simpleLogger.defaultLogLevel=debug +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss.SSS +org.slf4j.simpleLogger.showThreadName=true +org.slf4j.simpleLogger.showLogName=true +org.slf4j.simpleLogger.showShortLogName=false + +# Redirect logs to a file instead of console to avoid bloated console output during tests +org.slf4j.simpleLogger.logFile=target/test.log + +# Set specific logger levels +org.slf4j.simpleLogger.log.software.amazon.lambda.powertools=debug diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java index 5dcca2fb2..7e8977508 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java @@ -150,7 +150,7 @@ void shouldLogException() { result = new String(encoded, StandardCharsets.UTF_8); // THEN (stack is logged with root cause first) - assertThat(result).contains("\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"java.lang.IllegalStateException: Unexpected value\n"); + assertThat(result).contains("\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"java.lang.IllegalStateException: Unexpected value\\n"); } private void setMDC() { diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 4a7067540..81e830045 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -419,7 +419,7 @@ void shouldLogException() { // THEN (stack is logged with root cause first) assertThat(result).contains("\"message\":\"Unexpected value\"") .contains("\"name\":\"java.lang.IllegalStateException\"") - .contains("\"stack\":\"java.lang.IllegalStateException: Unexpected value\n"); + .contains("\"stack\":\"java.lang.IllegalStateException: Unexpected value\\n"); } private void setupContext() { diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java index 82bc76a38..c69789519 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/JsonSerializer.java @@ -84,8 +84,15 @@ public void writeString(String text) { if (text == null) { writeNull(); } else { - // Escape double quotes to avoid breaking JSON format - builder.append("\"").append(text.replace("\"", "\\\"")).append("\""); + // Escape special characters to avoid breaking JSON format + String escaped = text.replace("\\", "\\\\") + .replace("\"", "\\\"") + .replace("\n", "\\n") + .replace("\r", "\\r") + .replace("\t", "\\t") + .replace("\b", "\\b") + .replace("\f", "\\f"); + builder.append("\"").append(escaped).append("\""); } } From f563d2349d5a569d5a6996d9404023fdceed64a3 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 19 Jun 2025 15:09:17 +0200 Subject: [PATCH 253/577] fix(kafka): Add support for confluent message indices. (#1902) * fix(kafka): Add support for confluent message indices. * Make Generator classes non-instantiable (they are static utility classes). * Make generator classes final. --- .../events/kafka-protobuf-event.json | 4 +- .../powertools-examples-kafka/tools/README.md | 9 +- .../demo/kafka/tools/GenerateAvroSamples.java | 34 ++--- .../demo/kafka/tools/GenerateJsonSamples.java | 6 +- .../kafka/tools/GenerateProtobufSamples.java | 117 ++++++++++++------ .../KafkaProtobufDeserializer.java | 58 ++++++++- .../KafkaProtobufDeserializerTest.java | 77 ++++++++++++ 7 files changed, 246 insertions(+), 59 deletions(-) diff --git a/examples/powertools-examples-kafka/events/kafka-protobuf-event.json b/examples/powertools-examples-kafka/events/kafka-protobuf-event.json index b3e0139e3..e0547ad88 100644 --- a/examples/powertools-examples-kafka/events/kafka-protobuf-event.json +++ b/examples/powertools-examples-kafka/events/kafka-protobuf-event.json @@ -25,7 +25,7 @@ "timestamp": 1545084650988, "timestampType": "CREATE_TIME", "key": "NDI=", - "value": "COoHEgpTbWFydHBob25lGVK4HoXrv4JA", + "value": "AAjpBxIGTGFwdG9wGVK4HoXrP49A", "headers": [ { "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] @@ -39,7 +39,7 @@ "timestamp": 1545084650989, "timestampType": "CREATE_TIME", "key": null, - "value": "COsHEgpIZWFkcGhvbmVzGUjhehSuv2JA", + "value": "AgEACOkHEgZMYXB0b3AZUrgehes/j0A=", "headers": [ { "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] diff --git a/examples/powertools-examples-kafka/tools/README.md b/examples/powertools-examples-kafka/tools/README.md index 53d07b0c4..02e8dde9b 100644 --- a/examples/powertools-examples-kafka/tools/README.md +++ b/examples/powertools-examples-kafka/tools/README.md @@ -45,7 +45,7 @@ The tool will output base64-encoded values for Avro products that can be used in mvn exec:java -Dexec.mainClass="org.demo.kafka.tools.GenerateProtobufSamples" ``` -The tool will output base64-encoded values for Protobuf products that can be used in `../events/kafka-protobuf-event.json`. +The tool will output base64-encoded values for Protobuf products that can be used in `../events/kafka-protobuf-event.json`. This generator creates samples with and without Confluent message-indexes to test different serialization scenarios. ## Output @@ -55,6 +55,13 @@ Each generator produces: 2. An integer key (42) and one entry with a nullish key to test for edge-cases 3. A complete sample event structure that can be used directly for testing +The Protobuf generators additionally create samples with different Confluent message-index formats: +- Standard protobuf (no message indexes) +- Simple message index (single 0 byte) +- Complex message index (length-prefixed array) + +For more information about Confluent Schema Registry serialization formats and wire format specifications, see the [Confluent documentation](https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format). + ## Example After generating the samples, you can copy the output into the respective event files: diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateAvroSamples.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateAvroSamples.java index 4bd6ebd13..e6f4d38fd 100644 --- a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateAvroSamples.java +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateAvroSamples.java @@ -14,62 +14,68 @@ * Utility class to generate base64-encoded Avro serialized products * for use in test events. */ -public class GenerateAvroSamples { +public final class GenerateAvroSamples { + + private GenerateAvroSamples() { + // Utility class + } public static void main(String[] args) throws IOException { // Create three different products AvroProduct product1 = new AvroProduct(1001, "Laptop", 999.99); AvroProduct product2 = new AvroProduct(1002, "Smartphone", 599.99); AvroProduct product3 = new AvroProduct(1003, "Headphones", 149.99); - + // Serialize and encode each product String encodedProduct1 = serializeAndEncode(product1); String encodedProduct2 = serializeAndEncode(product2); String encodedProduct3 = serializeAndEncode(product3); - + // Serialize and encode an integer key String encodedKey = serializeAndEncodeInteger(42); - + // Print the results System.out.println("Base64 encoded Avro products for use in kafka-avro-event.json:"); System.out.println("\nProduct 1 (with key):"); System.out.println("key: \"" + encodedKey + "\","); System.out.println("value: \"" + encodedProduct1 + "\","); - + System.out.println("\nProduct 2 (with key):"); System.out.println("key: \"" + encodedKey + "\","); System.out.println("value: \"" + encodedProduct2 + "\","); - + System.out.println("\nProduct 3 (without key):"); System.out.println("key: null,"); System.out.println("value: \"" + encodedProduct3 + "\","); - + // Print a sample event structure System.out.println("\nSample event structure:"); printSampleEvent(encodedKey, encodedProduct1, encodedProduct2, encodedProduct3); } - + private static String serializeAndEncode(AvroProduct product) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(baos, null); DatumWriter writer = new SpecificDatumWriter<>(AvroProduct.class); - + writer.write(product, encoder); encoder.flush(); - + return Base64.getEncoder().encodeToString(baos.toByteArray()); } - + private static String serializeAndEncodeInteger(Integer value) throws IOException { // For simple types like integers, we'll just convert to string and encode return Base64.getEncoder().encodeToString(value.toString().getBytes()); } - + private static void printSampleEvent(String key, String product1, String product2, String product3) { System.out.println("{\n" + " \"eventSource\": \"aws:kafka\",\n" + - " \"eventSourceArn\": \"arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4\",\n" + - " \"bootstrapServers\": \"b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092\",\n" + + " \"eventSourceArn\": \"arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4\",\n" + + + " \"bootstrapServers\": \"b-2.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092,b-1.demo-cluster-1.a1bcde.c1.kafka.us-east-1.amazonaws.com:9092\",\n" + + " \"records\": {\n" + " \"mytopic-0\": [\n" + " {\n" + diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateJsonSamples.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateJsonSamples.java index a4fd6565a..d0ef7cb55 100644 --- a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateJsonSamples.java +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateJsonSamples.java @@ -11,7 +11,11 @@ * Utility class to generate base64-encoded JSON serialized products * for use in test events. */ -public class GenerateJsonSamples { +public final class GenerateJsonSamples { + + private GenerateJsonSamples() { + // Utility class + } public static void main(String[] args) throws IOException { // Create three different products diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java index ae078a28a..eecd3e1cc 100644 --- a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java @@ -1,73 +1,110 @@ package org.demo.kafka.tools; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Base64; import org.demo.kafka.protobuf.ProtobufProduct; +import com.google.protobuf.CodedOutputStream; + /** * Utility class to generate base64-encoded Protobuf serialized products * for use in test events. */ -public class GenerateProtobufSamples { +public final class GenerateProtobufSamples { + + private GenerateProtobufSamples() { + // Utility class + } public static void main(String[] args) throws IOException { - // Create three different products - ProtobufProduct product1 = ProtobufProduct.newBuilder() + // Create a single product that will be used for all three scenarios + ProtobufProduct product = ProtobufProduct.newBuilder() .setId(1001) .setName("Laptop") .setPrice(999.99) .build(); - ProtobufProduct product2 = ProtobufProduct.newBuilder() - .setId(1002) - .setName("Smartphone") - .setPrice(599.99) - .build(); - - ProtobufProduct product3 = ProtobufProduct.newBuilder() - .setId(1003) - .setName("Headphones") - .setPrice(149.99) - .build(); - - // Serialize and encode each product - String encodedProduct1 = serializeAndEncode(product1); - String encodedProduct2 = serializeAndEncode(product2); - String encodedProduct3 = serializeAndEncode(product3); + // Create three different serializations of the same product + String standardProduct = serializeAndEncode(product); + String productWithSimpleIndex = serializeWithSimpleMessageIndex(product); + String productWithComplexIndex = serializeWithComplexMessageIndex(product); - // Serialize and encode an integer key + // Serialize and encode an integer key (same for all records) String encodedKey = serializeAndEncodeInteger(42); // Print the results - System.out.println("Base64 encoded Protobuf products for use in kafka-protobuf-event.json:"); - System.out.println("\nProduct 1 (with key):"); - System.out.println("key: \"" + encodedKey + "\","); - System.out.println("value: \"" + encodedProduct1 + "\","); - - System.out.println("\nProduct 2 (with key):"); - System.out.println("key: \"" + encodedKey + "\","); - System.out.println("value: \"" + encodedProduct2 + "\","); - - System.out.println("\nProduct 3 (without key):"); - System.out.println("key: null,"); - System.out.println("value: \"" + encodedProduct3 + "\","); - - // Print a sample event structure - System.out.println("\nSample event structure:"); - printSampleEvent(encodedKey, encodedProduct1, encodedProduct2, encodedProduct3); + System.out.println("Base64 encoded Protobuf products with different message index scenarios:"); + System.out.println("\n1. Standard Protobuf (no message index):"); + System.out.println("value: \"" + standardProduct + "\""); + + System.out.println("\n2. Simple Message Index (single 0):"); + System.out.println("value: \"" + productWithSimpleIndex + "\""); + + System.out.println("\n3. Complex Message Index (array [1,0]):"); + System.out.println("value: \"" + productWithComplexIndex + "\""); + + // Print the merged event structure + System.out.println("\n" + "=".repeat(80)); + System.out.println("MERGED EVENT WITH ALL THREE SCENARIOS"); + System.out.println("=".repeat(80)); + printSampleEvent(encodedKey, standardProduct, productWithSimpleIndex, productWithComplexIndex); } private static String serializeAndEncode(ProtobufProduct product) { return Base64.getEncoder().encodeToString(product.toByteArray()); } + /** + * Serializes a protobuf product with a simple Confluent message index (single 0). + * Format: [0][protobuf_data] + * + * @see {@link https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format} + */ + private static String serializeWithSimpleMessageIndex(ProtobufProduct product) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(baos); + + // Write simple message index (single 0) + codedOutput.writeUInt32NoTag(0); + + // Write the protobuf data + product.writeTo(codedOutput); + + codedOutput.flush(); + return Base64.getEncoder().encodeToString(baos.toByteArray()); + } + + /** + * Serializes a protobuf product with a complex Confluent message index (array [1,0]). + * Format: [2][1][0][protobuf_data] where 2 is the array length + * + * @see {@link https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format} + */ + private static String serializeWithComplexMessageIndex(ProtobufProduct product) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(baos); + + // Write complex message index array [1,0] + codedOutput.writeUInt32NoTag(2); // Array length + codedOutput.writeUInt32NoTag(1); // First index value + codedOutput.writeUInt32NoTag(0); // Second index value + + // Write the protobuf data + product.writeTo(codedOutput); + + codedOutput.flush(); + return Base64.getEncoder().encodeToString(baos.toByteArray()); + } + private static String serializeAndEncodeInteger(Integer value) { // For simple types like integers, we'll just convert to string and encode return Base64.getEncoder().encodeToString(value.toString().getBytes()); } - private static void printSampleEvent(String key, String product1, String product2, String product3) { + private static void printSampleEvent(String key, String standardProduct, String simpleIndexProduct, + String complexIndexProduct) { System.out.println("{\n" + " \"eventSource\": \"aws:kafka\",\n" + " \"eventSourceArn\": \"arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4\",\n" @@ -83,7 +120,7 @@ private static void printSampleEvent(String key, String product1, String product " \"timestamp\": 1545084650987,\n" + " \"timestampType\": \"CREATE_TIME\",\n" + " \"key\": \"" + key + "\",\n" + - " \"value\": \"" + product1 + "\",\n" + + " \"value\": \"" + standardProduct + "\",\n" + " \"headers\": [\n" + " {\n" + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + @@ -97,7 +134,7 @@ private static void printSampleEvent(String key, String product1, String product " \"timestamp\": 1545084650988,\n" + " \"timestampType\": \"CREATE_TIME\",\n" + " \"key\": \"" + key + "\",\n" + - " \"value\": \"" + product2 + "\",\n" + + " \"value\": \"" + simpleIndexProduct + "\",\n" + " \"headers\": [\n" + " {\n" + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + @@ -111,7 +148,7 @@ private static void printSampleEvent(String key, String product1, String product " \"timestamp\": 1545084650989,\n" + " \"timestampType\": \"CREATE_TIME\",\n" + " \"key\": null,\n" + - " \"value\": \"" + product3 + "\",\n" + + " \"value\": \"" + complexIndexProduct + "\",\n" + " \"headers\": [\n" + " {\n" + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java index 025f203c4..c15be552f 100644 --- a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java @@ -13,14 +13,27 @@ package software.amazon.lambda.powertools.kafka.serializers; import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.protobuf.CodedInputStream; import com.google.protobuf.Message; import com.google.protobuf.Parser; /** * Deserializer for Kafka records using Protocol Buffers format. + * Supports both standard protobuf serialization and Confluent Schema Registry serialization using messages indices. + * + * For Confluent-serialized data, assumes the magic byte and schema ID have already been stripped + * by the Kafka ESM, leaving only the message index (if present) and protobuf data. + * + * @see {@link https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format} */ public class KafkaProtobufDeserializer extends AbstractKafkaDeserializer { + private static final Logger LOGGER = LoggerFactory.getLogger(KafkaProtobufDeserializer.class); + @Override @SuppressWarnings("unchecked") protected T deserializeObject(byte[] data, Class type) throws IOException { @@ -29,7 +42,9 @@ protected T deserializeObject(byte[] data, Class type) throws IOException try { // Get the parser from the generated Protobuf class Parser parser = (Parser) type.getMethod("parser").invoke(null); - Message message = parser.parseFrom(data); + + // Try to deserialize the data, handling potential Confluent message indices + Message message = deserializeWithMessageIndexHandling(data, parser); return type.cast(message); } catch (Exception e) { throw new IOException("Failed to deserialize Protobuf data.", e); @@ -40,4 +55,45 @@ protected T deserializeObject(byte[] data, Class type) throws IOException + "Consider using an alternative Deserializer."); } } + + private Message deserializeWithMessageIndexHandling(byte[] data, Parser parser) throws IOException { + try { + LOGGER.debug("Attempting to deserialize as standard protobuf data"); + return parser.parseFrom(data); + } catch (Exception e) { + LOGGER.debug("Standard protobuf parsing failed, attempting Confluent message-index handling"); + return deserializeWithMessageIndex(data, parser); + } + } + + private Message deserializeWithMessageIndex(byte[] data, Parser parser) throws IOException { + CodedInputStream codedInputStream = CodedInputStream.newInstance(data); + + try { + // https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format + // Read the first varint - this could be: + // 1. A single 0 (simple case - first message type) + // 2. The length of the message index array (complex case) + int firstValue = codedInputStream.readUInt32(); + + if (firstValue == 0) { + // Simple case: Single 0 byte means first message type + LOGGER.debug("Found simple message-index case (single 0), parsing remaining data as protobuf"); + return parser.parseFrom(codedInputStream); + } else { + // Complex case: firstValue is the length of the message index array + LOGGER.debug("Found complex message-index case with array length: {}, skipping {} message index values", + firstValue, firstValue); + for (int i = 0; i < firstValue; i++) { + codedInputStream.readUInt32(); // Skip each message index value + } + // Now the remaining data should be the actual protobuf message + LOGGER.debug("Finished skipping message indexes, parsing remaining data as protobuf"); + return parser.parseFrom(codedInputStream); + } + + } catch (Exception e) { + throw new IOException("Failed to parse protobuf data with or without message index", e); + } + } } diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java index 2d506de4b..3315e1172 100644 --- a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java @@ -15,11 +15,14 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import java.io.ByteArrayOutputStream; import java.io.IOException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.google.protobuf.CodedOutputStream; + import software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct; class KafkaProtobufDeserializerTest { @@ -72,4 +75,78 @@ void shouldThrowExceptionWhenDeserializingInvalidProtobufData() { .isInstanceOf(IOException.class) .hasMessageContaining("Failed to deserialize Protobuf data"); } + + @Test + void shouldDeserializeProtobufDataWithSimpleMessageIndex() throws IOException { + // Given + TestProduct product = TestProduct.newBuilder() + .setId(456) + .setName("Simple Index Product") + .setPrice(199.99) + .build(); + + // Create protobuf data with simple message index (single 0) + byte[] protobufDataWithSimpleIndex = createProtobufDataWithSimpleMessageIndex(product); + + // When + TestProduct result = deserializer.deserializeObject(protobufDataWithSimpleIndex, TestProduct.class); + + // Then + assertThat(result).isNotNull(); + assertThat(result.getId()).isEqualTo(456); + assertThat(result.getName()).isEqualTo("Simple Index Product"); + assertThat(result.getPrice()).isEqualTo(199.99); + } + + @Test + void shouldDeserializeProtobufDataWithComplexMessageIndex() throws IOException { + // Given + TestProduct product = TestProduct.newBuilder() + .setId(789) + .setName("Complex Index Product") + .setPrice(299.99) + .build(); + + // Create protobuf data with complex message index (array [1,0]) + byte[] protobufDataWithComplexIndex = createProtobufDataWithComplexMessageIndex(product); + + // When + TestProduct result = deserializer.deserializeObject(protobufDataWithComplexIndex, TestProduct.class); + + // Then + assertThat(result).isNotNull(); + assertThat(result.getId()).isEqualTo(789); + assertThat(result.getName()).isEqualTo("Complex Index Product"); + assertThat(result.getPrice()).isEqualTo(299.99); + } + + private byte[] createProtobufDataWithSimpleMessageIndex(TestProduct product) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(baos); + + // Write simple message index (single 0) + codedOutput.writeUInt32NoTag(0); + + // Write the protobuf data + product.writeTo(codedOutput); + + codedOutput.flush(); + return baos.toByteArray(); + } + + private byte[] createProtobufDataWithComplexMessageIndex(TestProduct product) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + CodedOutputStream codedOutput = CodedOutputStream.newInstance(baos); + + // Write complex message index array [1,0] + codedOutput.writeUInt32NoTag(2); // Array length + codedOutput.writeUInt32NoTag(1); // First index value + codedOutput.writeUInt32NoTag(0); // Second index value + + // Write the protobuf data + product.writeTo(codedOutput); + + codedOutput.flush(); + return baos.toByteArray(); + } } From cf01e91eb0b398b89b8fb442edfe27e1532a5810 Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Thu, 19 Jun 2025 15:31:48 +0200 Subject: [PATCH 254/577] fix(ci): Add maven project description to Kafka utility. (#1903) --- powertools-kafka/pom.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index f5b80012c..f96c1eb82 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -28,7 +28,10 @@ jar Powertools for AWS Lambda (Java) - Kafka Consumer - + + The Kafka utility transparently handles message deserialization, provides an intuitive developer experience, + and integrates seamlessly with the rest of the Powertools for AWS Lambda ecosystem. + 4.0.0 From 8f70e83b28fc939f884d4cea150dfb3f3ee3c75e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 19 Jun 2025 15:52:21 +0200 Subject: [PATCH 255/577] chore(ci): bump version to 2.1.0 (#1904) Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 42 files changed, 48 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 88955bca7..165458a65 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your software.amazon.lambda powertools-tracing - 2.0.0 + 2.1.0 software.amazon.lambda powertools-logging - 2.0.0 + 2.1.0 software.amazon.lambda powertools-metrics - 2.0.0 + 2.1.0 ... diff --git a/examples/pom.xml b/examples/pom.xml index ea1e8d542..496c933c3 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-examples - 2.0.0 + 2.1.0 pom Powertools for AWS Lambda (Java) - Examples diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index ef3c0e4e0..1cf1e6f65 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ 4.0.0 software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-batch jar Powertools for AWS Lambda (Java) - Examples - Batch diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 43c81b9f8..74a0090fe 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-cloudformation jar diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index fa5a1927a..0c4dec217 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-core-utilities-cdk jar diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index b869a5672..2ddd389a9 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ 4.0.0 software.amazon.lambda.examples cdk - 2.0.0 + 2.1.0 UTF-8 2.162.1 diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 4cf988a6f..37d9f4554 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.0.0' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.0.0' - aspect 'software.amazon.lambda:powertools-metrics:2.0.0' + aspect 'software.amazon.lambda:powertools-tracing:2.1.0' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.1.0' + aspect 'software.amazon.lambda:powertools-metrics:2.1.0' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 7029dc458..de820300d 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.11.3") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.0.0") - aspect("software.amazon.lambda:powertools-logging-log4j:2.0.0") - aspect("software.amazon.lambda:powertools-metrics:2.0.0") + aspect("software.amazon.lambda:powertools-tracing:2.1.0") + aspect("software.amazon.lambda:powertools-logging-log4j:2.1.0") + aspect("software.amazon.lambda:powertools-metrics:2.1.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index b2353b86e..ead4625f5 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-core-utilities-sam-graalvm jar diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 813fc267f..44f171698 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-core-utilities-sam jar diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 1aea70820..42d70ba76 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-core-utilities-serverless jar diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index dd4c385c0..a9ab410e3 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-core-utilities-terraform jar diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index c7ceabc57..06a50c16b 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ 4.0.0 software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-idempotency jar Powertools for AWS Lambda (Java) - Examples - Idempotency diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index a745ac75d..185790b64 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-kafka jar Powertools for AWS Lambda (Java) - Examples - Kafka diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index f2ce0f21f..320ed42cd 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-parameters-sam-graalvm jar Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index a797bbeed..ea8029b8c 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-parameters-sam jar Powertools for AWS Lambda (Java) - Examples - Parameters diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index b96d02b6b..f9408012c 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-serialization jar Powertools for AWS Lambda (Java) - Examples - Serialization diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 9b6df9783..3b9d9baeb 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.0.0 + 2.1.0 powertools-examples-validation jar Powertools for AWS Lambda (Java) - Examples - Validation diff --git a/mkdocs.yml b/mkdocs.yml index 07be3c175..1880e543d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -121,7 +121,7 @@ extra_javascript: extra: powertools: - version: 2.0.0 + version: 2.1.0 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index f27ffc497..0542295bb 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-parent - 2.0.0 + 2.1.0 pom Powertools for AWS Lambda (Java) - Parent diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 59e5b8c93..4f6b78f5e 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 2.0.0 + 2.1.0 A suite of utilities that makes batch message processing using AWS Lambda easier. diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 271704dea..657d42e42 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 Powertools for AWS Lambda (Java) - Cloudformation diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index dd6ef8e61..8e0229bb4 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 Powertools for AWS Lambda (Java) - Common Internal Utilities diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 4f1c059e9..c49e6824a 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 powertools-e2e-tests diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 862cf3160..169953642 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-parent - 2.0.0 + 2.1.0 powertools-idempotency diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 58d184fc5..846dea2d8 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-idempotency - 2.0.0 + 2.1.0 powertools-idempotency-core diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index b92d66dbc..099eb12ab 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-idempotency - 2.0.0 + 2.1.0 powertools-idempotency-dynamodb diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index f96c1eb82..deac5cc3e 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 powertools-kafka diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index b23e3f41c..8eb0e143f 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ software.amazon.lambda powertools-parent - 2.0.0 + 2.1.0 powertools-large-messages diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 75d5853e5..2ee71ae67 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 Powertools for AWS Lambda (Java) - Logging diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 75aa94a97..6fe11ea93 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 ../../pom.xml diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 8b2a5cfd5..6fd411c47 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 ../../pom.xml diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 460eb220f..19b185f4d 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 Powertools for AWS Lambda (Java) - Metrics diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 96f6f50b3..d61e76322 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 powertools-parameters diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index a3822d11b..52b15296b 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0 + 2.1.0 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 9c7030d7c..0b82087c9 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0 + 2.1.0 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 99a308825..c90cf1c69 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0 + 2.1.0 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 46cf939ba..f03983fff 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.0.0 + 2.1.0 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 4d2b5d145..9f8b12911 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 2.0.0 + 2.1.0 ../../pom.xml diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 986a3b1d9..d6e04b3b8 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 powertools-serialization diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 14d6d51b1..d76ddffcb 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 Powertools for AWS Lambda (Java) - Tracing diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index bfedf8d40..a7403d6b3 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.0.0 + 2.1.0 Powertools for AWS Lambda (Java) - Validation From 4a8511d95a2a9227f0d57ef74803202bb950491b Mon Sep 17 00:00:00 2001 From: Philipp Page Date: Fri, 20 Jun 2025 13:29:08 +0200 Subject: [PATCH 256/577] fix(kafka): Handle message indices in proto data also for Glue Schema Registry (#1907) * Bug fix to handle message indices in proto data * Removing links and changing log level from info to debug * Upgrade lambda.events.version tp 3.16.0 * Update Glue schema id to 36. Add some tests to increase coverage. Use Kafka ByteUtils also in unit tests. * Update lambda java events to 3.16.0 everywhere. * Add sample generation code for all Protobuf cases. --------- Co-authored-by: Karthik Puttaswamy --- .../cdk/app/pom.xml | 2 +- .../gradle/build.gradle | 2 +- .../kotlin/build.gradle.kts | 4 +- .../sam-graalvm/pom.xml | 2 +- .../sam/pom.xml | 2 +- .../serverless/pom.xml | 2 +- .../terraform/pom.xml | 2 +- .../powertools-examples-idempotency/pom.xml | 2 +- .../events/kafka-protobuf-event.json | 32 ++++- .../powertools-examples-kafka/tools/pom.xml | 6 + .../kafka/tools/GenerateProtobufSamples.java | 115 +++++++++++++----- .../sam-graalvm/pom.xml | 2 +- .../sam/pom.xml | 2 +- .../powertools-examples-serialization/pom.xml | 2 +- pom.xml | 2 +- .../AbstractKafkaDeserializer.java | 60 +++++++-- .../serializers/KafkaAvroDeserializer.java | 3 +- .../serializers/KafkaJsonDeserializer.java | 3 +- .../KafkaProtobufDeserializer.java | 93 +++++++------- .../AbstractKafkaDeserializerTest.java | 111 ++++++++++++++++- .../KafkaAvroDeserializerTest.java | 17 +-- .../KafkaJsonDeserializerTest.java | 8 +- .../KafkaProtobufDeserializerTest.java | 96 +++++++++++---- 23 files changed, 433 insertions(+), 137 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 0c4dec217..87bea4b38 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -41,7 +41,7 @@ com.amazonaws aws-lambda-java-events - 3.15.0 + 3.16.0 org.apache.logging.log4j diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 37d9f4554..b86e49659 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -26,7 +26,7 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-core:1.2.2' implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.2' implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2' - implementation 'com.amazonaws:aws-lambda-java-events:3.11.0' + implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' aspect 'software.amazon.lambda:powertools-tracing:2.1.0' diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index de820300d..23c84a0d3 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -12,7 +12,7 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-core:1.2.3") implementation("com.fasterxml.jackson.core:jackson-annotations:2.15.1") implementation("com.fasterxml.jackson.core:jackson-databind:2.15.3") - implementation("com.amazonaws:aws-lambda-java-events:3.11.3") + implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") aspect("software.amazon.lambda:powertools-tracing:2.1.0") @@ -23,4 +23,4 @@ dependencies { kotlin { jvmToolchain(11) -} \ No newline at end of file +} diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index ead4625f5..d691c02a5 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -39,7 +39,7 @@ com.amazonaws aws-lambda-java-events - 3.11.3 + 3.16.0 org.aspectj diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 44f171698..f37319ea1 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -38,7 +38,7 @@ com.amazonaws aws-lambda-java-events - 3.15.0 + 3.16.0 org.aspectj diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 42d70ba76..1f4e0a2fc 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -38,7 +38,7 @@ com.amazonaws aws-lambda-java-events - 3.15.0 + 3.16.0 org.aspectj diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index a9ab410e3..6dcd2f8c6 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -38,7 +38,7 @@ com.amazonaws aws-lambda-java-events - 3.15.0 + 3.16.0 org.aspectj diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 06a50c16b..c7ca6a058 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -52,7 +52,7 @@ com.amazonaws aws-lambda-java-events - 3.15.0 + 3.16.0 org.aspectj diff --git a/examples/powertools-examples-kafka/events/kafka-protobuf-event.json b/examples/powertools-examples-kafka/events/kafka-protobuf-event.json index e0547ad88..6f5ec58ae 100644 --- a/examples/powertools-examples-kafka/events/kafka-protobuf-event.json +++ b/examples/powertools-examples-kafka/events/kafka-protobuf-event.json @@ -30,7 +30,11 @@ { "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] } - ] + ], + "valueSchemaMetadata": { + "schemaId": "123", + "dataFormat": "PROTOBUF" + } }, { "topic": "mytopic", @@ -39,12 +43,34 @@ "timestamp": 1545084650989, "timestampType": "CREATE_TIME", "key": null, - "value": "AgEACOkHEgZMYXB0b3AZUrgehes/j0A=", + "value": "BAIACOkHEgZMYXB0b3AZUrgehes/j0A=", "headers": [ { "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] } - ] + ], + "valueSchemaMetadata": { + "schemaId": "456", + "dataFormat": "PROTOBUF" + } + }, + { + "topic": "mytopic", + "partition": 0, + "offset": 18, + "timestamp": 1545084650990, + "timestampType": "CREATE_TIME", + "key": "NDI=", + "value": "AQjpBxIGTGFwdG9wGVK4HoXrP49A", + "headers": [ + { + "headerKey": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101] + } + ], + "valueSchemaMetadata": { + "schemaId": "12345678-1234-1234-1234-123456789012", + "dataFormat": "PROTOBUF" + } } ] } diff --git a/examples/powertools-examples-kafka/tools/pom.xml b/examples/powertools-examples-kafka/tools/pom.xml index 97231e5bd..80ed6c264 100644 --- a/examples/powertools-examples-kafka/tools/pom.xml +++ b/examples/powertools-examples-kafka/tools/pom.xml @@ -13,6 +13,7 @@ 11 1.12.0 4.31.0 + 4.0.0 @@ -26,6 +27,11 @@ protobuf-java ${protobuf.version} + + org.apache.kafka + kafka-clients + ${kafka-clients.version} + com.fasterxml.jackson.core jackson-databind diff --git a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java index eecd3e1cc..aa5f6e330 100644 --- a/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java +++ b/examples/powertools-examples-kafka/tools/src/main/java/org/demo/kafka/tools/GenerateProtobufSamples.java @@ -2,8 +2,10 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; import java.util.Base64; +import org.apache.kafka.common.utils.ByteUtils; import org.demo.kafka.protobuf.ProtobufProduct; import com.google.protobuf.CodedOutputStream; @@ -19,37 +21,42 @@ private GenerateProtobufSamples() { } public static void main(String[] args) throws IOException { - // Create a single product that will be used for all three scenarios + // Create a single product that will be used for all four scenarios ProtobufProduct product = ProtobufProduct.newBuilder() .setId(1001) .setName("Laptop") .setPrice(999.99) .build(); - // Create three different serializations of the same product + // Create four different serializations of the same product String standardProduct = serializeAndEncode(product); - String productWithSimpleIndex = serializeWithSimpleMessageIndex(product); - String productWithComplexIndex = serializeWithComplexMessageIndex(product); + String productWithConfluentSimpleIndex = serializeWithConfluentSimpleMessageIndex(product); + String productWithConfluentComplexIndex = serializeWithConfluentComplexMessageIndex(product); + String productWithGlueMagicByte = serializeWithGlueMagicByte(product); // Serialize and encode an integer key (same for all records) String encodedKey = serializeAndEncodeInteger(42); // Print the results - System.out.println("Base64 encoded Protobuf products with different message index scenarios:"); - System.out.println("\n1. Standard Protobuf (no message index):"); + System.out.println("Base64 encoded Protobuf products with different scenarios:"); + System.out.println("\n1. Plain Protobuf (no schema registry):"); System.out.println("value: \"" + standardProduct + "\""); - System.out.println("\n2. Simple Message Index (single 0):"); - System.out.println("value: \"" + productWithSimpleIndex + "\""); + System.out.println("\n2. Confluent with Simple Message Index (optimized single 0):"); + System.out.println("value: \"" + productWithConfluentSimpleIndex + "\""); - System.out.println("\n3. Complex Message Index (array [1,0]):"); - System.out.println("value: \"" + productWithComplexIndex + "\""); + System.out.println("\n3. Confluent with Complex Message Index (array [1,0]):"); + System.out.println("value: \"" + productWithConfluentComplexIndex + "\""); + + System.out.println("\n4. Glue with Magic Byte:"); + System.out.println("value: \"" + productWithGlueMagicByte + "\""); // Print the merged event structure System.out.println("\n" + "=".repeat(80)); - System.out.println("MERGED EVENT WITH ALL THREE SCENARIOS"); + System.out.println("MERGED EVENT WITH ALL FOUR SCENARIOS"); System.out.println("=".repeat(80)); - printSampleEvent(encodedKey, standardProduct, productWithSimpleIndex, productWithComplexIndex); + printSampleEvent(encodedKey, standardProduct, productWithConfluentSimpleIndex, productWithConfluentComplexIndex, + productWithGlueMagicByte); } private static String serializeAndEncode(ProtobufProduct product) { @@ -57,39 +64,59 @@ private static String serializeAndEncode(ProtobufProduct product) { } /** - * Serializes a protobuf product with a simple Confluent message index (single 0). + * Serializes a protobuf product with a simple Confluent message index (optimized single 0). * Format: [0][protobuf_data] * * @see {@link https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format} */ - private static String serializeWithSimpleMessageIndex(ProtobufProduct product) throws IOException { + private static String serializeWithConfluentSimpleMessageIndex(ProtobufProduct product) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - CodedOutputStream codedOutput = CodedOutputStream.newInstance(baos); - // Write simple message index (single 0) - codedOutput.writeUInt32NoTag(0); + // Write optimized simple message index for Confluent (single 0 byte for [0]) + baos.write(0); // Write the protobuf data - product.writeTo(codedOutput); + baos.write(product.toByteArray()); - codedOutput.flush(); return Base64.getEncoder().encodeToString(baos.toByteArray()); } /** * Serializes a protobuf product with a complex Confluent message index (array [1,0]). - * Format: [2][1][0][protobuf_data] where 2 is the array length + * Format: [2][1][0][protobuf_data] where 2 is the array length using varint encoding * * @see {@link https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format} */ - private static String serializeWithComplexMessageIndex(ProtobufProduct product) throws IOException { + private static String serializeWithConfluentComplexMessageIndex(ProtobufProduct product) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + // Write complex message index array [1,0] using ByteUtils + ByteBuffer buffer = ByteBuffer.allocate(1024); + ByteUtils.writeVarint(2, buffer); // Array length + ByteUtils.writeVarint(1, buffer); // First index value + ByteUtils.writeVarint(0, buffer); // Second index value + + buffer.flip(); + byte[] indexData = new byte[buffer.remaining()]; + buffer.get(indexData); + baos.write(indexData); + + // Write the protobuf data + baos.write(product.toByteArray()); + + return Base64.getEncoder().encodeToString(baos.toByteArray()); + } + + /** + * Serializes a protobuf product with Glue magic byte. + * Format: [1][protobuf_data] where 1 is the magic byte + */ + private static String serializeWithGlueMagicByte(ProtobufProduct product) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); CodedOutputStream codedOutput = CodedOutputStream.newInstance(baos); - // Write complex message index array [1,0] - codedOutput.writeUInt32NoTag(2); // Array length - codedOutput.writeUInt32NoTag(1); // First index value - codedOutput.writeUInt32NoTag(0); // Second index value + // Write Glue magic byte (single UInt32) + codedOutput.writeUInt32NoTag(1); // Write the protobuf data product.writeTo(codedOutput); @@ -103,8 +130,8 @@ private static String serializeAndEncodeInteger(Integer value) { return Base64.getEncoder().encodeToString(value.toString().getBytes()); } - private static void printSampleEvent(String key, String standardProduct, String simpleIndexProduct, - String complexIndexProduct) { + private static void printSampleEvent(String key, String standardProduct, String confluentSimpleProduct, + String confluentComplexProduct, String glueProduct) { System.out.println("{\n" + " \"eventSource\": \"aws:kafka\",\n" + " \"eventSourceArn\": \"arn:aws:kafka:us-east-1:0123456789019:cluster/SalesCluster/abcd1234-abcd-cafe-abab-9876543210ab-4\",\n" @@ -134,12 +161,16 @@ private static void printSampleEvent(String key, String standardProduct, String " \"timestamp\": 1545084650988,\n" + " \"timestampType\": \"CREATE_TIME\",\n" + " \"key\": \"" + key + "\",\n" + - " \"value\": \"" + simpleIndexProduct + "\",\n" + + " \"value\": \"" + confluentSimpleProduct + "\",\n" + " \"headers\": [\n" + " {\n" + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + " }\n" + - " ]\n" + + " ],\n" + + " \"valueSchemaMetadata\": {\n" + + " \"schemaId\": \"123\",\n" + + " \"dataFormat\": \"PROTOBUF\"\n" + + " }\n" + " },\n" + " {\n" + " \"topic\": \"mytopic\",\n" + @@ -148,12 +179,34 @@ private static void printSampleEvent(String key, String standardProduct, String " \"timestamp\": 1545084650989,\n" + " \"timestampType\": \"CREATE_TIME\",\n" + " \"key\": null,\n" + - " \"value\": \"" + complexIndexProduct + "\",\n" + + " \"value\": \"" + confluentComplexProduct + "\",\n" + " \"headers\": [\n" + " {\n" + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + " }\n" + - " ]\n" + + " ],\n" + + " \"valueSchemaMetadata\": {\n" + + " \"schemaId\": \"456\",\n" + + " \"dataFormat\": \"PROTOBUF\"\n" + + " }\n" + + " },\n" + + " {\n" + + " \"topic\": \"mytopic\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 18,\n" + + " \"timestamp\": 1545084650990,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": \"" + key + "\",\n" + + " \"value\": \"" + glueProduct + "\",\n" + + " \"headers\": [\n" + + " {\n" + + " \"headerKey\": [104, 101, 97, 100, 101, 114, 86, 97, 108, 117, 101]\n" + + " }\n" + + " ],\n" + + " \"valueSchemaMetadata\": {\n" + + " \"schemaId\": \"12345678-1234-1234-1234-123456789012\",\n" + + " \"dataFormat\": \"PROTOBUF\"\n" + + " }\n" + " }\n" + " ]\n" + " }\n" + diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 320ed42cd..643b8f134 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -39,7 +39,7 @@ com.amazonaws aws-lambda-java-events - 3.15.0 + 3.16.0 org.aspectj diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index ea8029b8c..e8ce66e11 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -38,7 +38,7 @@ com.amazonaws aws-lambda-java-events - 3.15.0 + 3.16.0 org.aspectj diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index f9408012c..eedce8b87 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -31,7 +31,7 @@ com.amazonaws aws-lambda-java-events - 3.15.0 + 3.16.0 diff --git a/pom.xml b/pom.xml index 0542295bb..1033c3f6e 100644 --- a/pom.xml +++ b/pom.xml @@ -89,7 +89,7 @@ 2.2.0 UTF-8 1.2.3 - 3.15.0 + 3.16.0 1.1.5 3.13.0 1.9.7 diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializer.java index 8d0fc8f61..3de8320a5 100644 --- a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializer.java +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializer.java @@ -41,6 +41,11 @@ abstract class AbstractKafkaDeserializer implements PowertoolsDeserializer { protected static final ObjectMapper objectMapper = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + private static final Integer GLUE_SCHEMA_ID_LENGTH = 36; + + public enum SchemaRegistryType { + CONFLUENT, GLUE, NONE + } /** * Deserialize JSON from InputStream into ConsumerRecords @@ -170,8 +175,8 @@ private ConsumerRecord convertToConsumerRecord( Class keyType, Class valueType) { - K key = deserializeField(eventRecord.getKey(), keyType, "key"); - V value = deserializeField(eventRecord.getValue(), valueType, "value"); + K key = deserializeField(eventRecord.getKey(), keyType, "key", extractSchemaRegistryType(eventRecord)); + V value = deserializeField(eventRecord.getValue(), valueType, "value", extractSchemaRegistryType(eventRecord)); Headers headers = extractHeaders(eventRecord); return new ConsumerRecord<>( @@ -190,14 +195,15 @@ private ConsumerRecord convertToConsumerRecord( Optional.empty()); } - private T deserializeField(String encodedData, Class type, String fieldName) { + private T deserializeField(String encodedData, Class type, String fieldName, + SchemaRegistryType schemaRegistryType) { if (encodedData == null) { return null; } try { byte[] decodedBytes = Base64.getDecoder().decode(encodedData); - return deserialize(decodedBytes, type); + return deserialize(decodedBytes, type, schemaRegistryType); } catch (Exception e) { throw new RuntimeException("Failed to deserialize Kafka record " + fieldName + ".", e); } @@ -218,28 +224,60 @@ private Headers extractHeaders(KafkaEvent.KafkaEventRecord eventRecord) { return headers; } + private String extractKeySchemaId(KafkaEvent.KafkaEventRecord eventRecord) { + if (eventRecord.getKeySchemaMetadata() != null) { + return eventRecord.getKeySchemaMetadata().getSchemaId(); + } + return null; + } + + private String extractValueSchemaId(KafkaEvent.KafkaEventRecord eventRecord) { + if (eventRecord.getValueSchemaMetadata() != null) { + return eventRecord.getValueSchemaMetadata().getSchemaId(); + } + return null; + } + + private SchemaRegistryType extractSchemaRegistryType(KafkaEvent.KafkaEventRecord eventRecord) { + // This method is used for both key and value, so we try to extract the schema id from both fields + String schemaId = extractValueSchemaId(eventRecord); + if (schemaId == null) { + schemaId = extractKeySchemaId(eventRecord); + } + + if (schemaId == null) { + return SchemaRegistryType.NONE; + } + + return schemaId.length() == GLUE_SCHEMA_ID_LENGTH ? SchemaRegistryType.GLUE : SchemaRegistryType.CONFLUENT; + } + /** * Template method to be implemented by subclasses for specific deserialization logic - * for complex types (non-primitives). - * + * for complex types (non-primitives) and for specific Schema Registry type. + * * @param The type to deserialize to * @param data The byte array to deserialize coming from the base64 decoded Kafka field * @param type The class type to deserialize to + * @param schemaRegistryType Schema Registry type * @return The deserialized object * @throws IOException If deserialization fails */ - protected abstract T deserializeObject(byte[] data, Class type) throws IOException; + protected abstract T deserializeObject(byte[] data, Class type, SchemaRegistryType schemaRegistryType) + throws IOException; /** - * Main deserialize method that handles primitive types and delegates to subclasses for complex types. - * + * Main deserialize method that handles primitive types and delegates to subclasses for complex types and + * for specific Schema Registry type. + * * @param The type to deserialize to * @param data The byte array to deserialize * @param type The class type to deserialize to + * @param schemaRegistryType Schema Registry type * @return The deserialized object * @throws IOException If deserialization fails */ - private T deserialize(byte[] data, Class type) throws IOException { + private T deserialize(byte[] data, Class type, SchemaRegistryType schemaRegistryType) throws IOException { // First try to deserialize as a primitive type T result = deserializePrimitive(data, type); if (result != null) { @@ -247,7 +285,7 @@ private T deserialize(byte[] data, Class type) throws IOException { } // Delegate to subclass for complex type deserialization - return deserializeObject(data, type); + return deserializeObject(data, type, schemaRegistryType); } /** diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializer.java index ddf09d4ff..70e4affac 100644 --- a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializer.java +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializer.java @@ -26,7 +26,8 @@ public class KafkaAvroDeserializer extends AbstractKafkaDeserializer { @Override - protected T deserializeObject(byte[] data, Class type) throws IOException { + protected T deserializeObject(byte[] data, Class type, SchemaRegistryType schemaRegistryType) + throws IOException { // If no Avro generated class is passed we cannot deserialize using Avro if (SpecificRecordBase.class.isAssignableFrom(type)) { try { diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializer.java index ed64f3786..733fe5d7d 100644 --- a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializer.java +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializer.java @@ -21,7 +21,8 @@ public class KafkaJsonDeserializer extends AbstractKafkaDeserializer { @Override - protected T deserializeObject(byte[] data, Class type) throws IOException { + protected T deserializeObject(byte[] data, Class type, SchemaRegistryType schemaRegistryType) + throws IOException { String decodedStr = new String(data, StandardCharsets.UTF_8); return objectMapper.readValue(decodedStr, type); diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java index c15be552f..1a8085a61 100644 --- a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializer.java @@ -13,7 +13,10 @@ package software.amazon.lambda.powertools.kafka.serializers; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.nio.ByteBuffer; +import org.apache.kafka.common.utils.ByteUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,7 +26,8 @@ /** * Deserializer for Kafka records using Protocol Buffers format. - * Supports both standard protobuf serialization and Confluent Schema Registry serialization using messages indices. + * Supports both standard protobuf serialization and Confluent / Glue Schema Registry serialization using messages + * indices. * * For Confluent-serialized data, assumes the magic byte and schema ID have already been stripped * by the Kafka ESM, leaving only the message index (if present) and protobuf data. @@ -33,19 +37,22 @@ public class KafkaProtobufDeserializer extends AbstractKafkaDeserializer { private static final Logger LOGGER = LoggerFactory.getLogger(KafkaProtobufDeserializer.class); + private static final String PROTOBUF_PARSER_METHOD = "parser"; @Override - @SuppressWarnings("unchecked") - protected T deserializeObject(byte[] data, Class type) throws IOException { - // If no Protobuf generated class is passed we cannot deserialize using Protobuf + protected T deserializeObject(byte[] data, Class type, SchemaRegistryType schemaRegistryType) + throws IOException { + // If no Protobuf generated class is passed, we cannot deserialize using Protobuf if (Message.class.isAssignableFrom(type)) { try { - // Get the parser from the generated Protobuf class - Parser parser = (Parser) type.getMethod("parser").invoke(null); - - // Try to deserialize the data, handling potential Confluent message indices - Message message = deserializeWithMessageIndexHandling(data, parser); - return type.cast(message); + switch (schemaRegistryType) { + case GLUE: + return glueDeserializer(data, type); + case CONFLUENT: + return confluentDeserializer(data, type); + default: + return defaultDeserializer(data, type); + } } catch (Exception e) { throw new IOException("Failed to deserialize Protobuf data.", e); } @@ -56,44 +63,48 @@ protected T deserializeObject(byte[] data, Class type) throws IOException } } - private Message deserializeWithMessageIndexHandling(byte[] data, Parser parser) throws IOException { + @SuppressWarnings("unchecked") + private T defaultDeserializer(byte[] data, Class type) throws IOException { try { - LOGGER.debug("Attempting to deserialize as standard protobuf data"); - return parser.parseFrom(data); + LOGGER.debug("Using default Protobuf deserializer"); + Parser parser = (Parser) type.getMethod(PROTOBUF_PARSER_METHOD).invoke(null); + Message message = parser.parseFrom(data); + return type.cast(message); } catch (Exception e) { - LOGGER.debug("Standard protobuf parsing failed, attempting Confluent message-index handling"); - return deserializeWithMessageIndex(data, parser); + throw new IOException("Failed to deserialize Protobuf data.", e); } } - private Message deserializeWithMessageIndex(byte[] data, Parser parser) throws IOException { - CodedInputStream codedInputStream = CodedInputStream.newInstance(data); - - try { - // https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format - // Read the first varint - this could be: - // 1. A single 0 (simple case - first message type) - // 2. The length of the message index array (complex case) - int firstValue = codedInputStream.readUInt32(); + @SuppressWarnings("unchecked") + private T confluentDeserializer(byte[] data, Class type) + throws IOException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + LOGGER.debug("Using Confluent Deserializer"); + Parser parser = (Parser) type.getMethod(PROTOBUF_PARSER_METHOD).invoke(null); + ByteBuffer buffer = ByteBuffer.wrap(data); + int size = ByteUtils.readVarint(buffer); - if (firstValue == 0) { - // Simple case: Single 0 byte means first message type - LOGGER.debug("Found simple message-index case (single 0), parsing remaining data as protobuf"); - return parser.parseFrom(codedInputStream); - } else { - // Complex case: firstValue is the length of the message index array - LOGGER.debug("Found complex message-index case with array length: {}, skipping {} message index values", - firstValue, firstValue); - for (int i = 0; i < firstValue; i++) { - codedInputStream.readUInt32(); // Skip each message index value - } - // Now the remaining data should be the actual protobuf message - LOGGER.debug("Finished skipping message indexes, parsing remaining data as protobuf"); - return parser.parseFrom(codedInputStream); + // Only if the size is greater than zero, continue reading varInt. + // https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format + if (size > 0) { + for (int i = 0; i < size; i++) { + ByteUtils.readVarint(buffer); } - - } catch (Exception e) { - throw new IOException("Failed to parse protobuf data with or without message index", e); } + Message message = parser.parseFrom(buffer); + return type.cast(message); + } + + @SuppressWarnings("unchecked") + private T glueDeserializer(byte[] data, Class type) + throws IOException, IllegalAccessException, InvocationTargetException, NoSuchMethodException { + LOGGER.debug("Using Glue Deserializer"); + CodedInputStream codedInputStream = CodedInputStream.newInstance(data); + Parser parser = (Parser) type.getMethod(PROTOBUF_PARSER_METHOD).invoke(null); + + // Seek one byte forward. Based on Glue Proto deserializer implementation + codedInputStream.readUInt32(); + + Message message = parser.parseFrom(codedInputStream); + return type.cast(message); } } diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializerTest.java index 512058bca..b40a2a2b0 100644 --- a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializerTest.java +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/AbstractKafkaDeserializerTest.java @@ -459,10 +459,117 @@ void shouldThrowExceptionWhenConvertingEmptyStringToChar(InputType inputType) { } } + @ParameterizedTest + @MethodSource("inputTypes") + void shouldHandleGlueSchemaMetadata(InputType inputType) throws IOException { + // Given + TestProductPojo product = new TestProductPojo(123, "Test Product", 99.99, null); + String productJson = objectMapper.writeValueAsString(product); + String base64Value = Base64.getEncoder().encodeToString(productJson.getBytes()); + + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": \"" + base64Value + "\",\n" + + " \"headers\": [],\n" + + " \"keySchemaMetadata\": {\n" + + " \"schemaId\": \"12345678-1234-1234-1234-123456789012\",\n" + + " \"dataFormat\": \"PROTOBUF\"\n" + + " },\n" + + " \"valueSchemaMetadata\": {\n" + + " \"schemaId\": \"87654321-4321-4321-4321-210987654321\",\n" + + " \"dataFormat\": \"PROTOBUF\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(String.class, TestProductPojo.class); + + // When + ConsumerRecords records; + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + records = deserializer.fromJson(inputStream, type); + } else { + records = deserializer.fromJson(kafkaJson, type); + } + + // Then + assertThat(records).isNotNull(); + TopicPartition tp = new TopicPartition("test-topic-1", 0); + List> topicRecords = records.records(tp); + assertThat(topicRecords).hasSize(1); + + ConsumerRecord consumerRecord = topicRecords.get(0); + assertThat(consumerRecord.value()).isNotNull(); + assertThat(consumerRecord.value().getId()).isEqualTo(123); + } + + @ParameterizedTest + @MethodSource("inputTypes") + void shouldHandleConfluentSchemaMetadata(InputType inputType) throws IOException { + // Given + TestProductPojo product = new TestProductPojo(456, "Confluent Product", 199.99, null); + String productJson = objectMapper.writeValueAsString(product); + String base64Value = Base64.getEncoder().encodeToString(productJson.getBytes()); + + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"test-topic-1\": [\n" + + " {\n" + + " \"topic\": \"test-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 15,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": \"" + base64Value + "\",\n" + + " \"headers\": [],\n" + + " \"keySchemaMetadata\": {\n" + + " \"schemaId\": \"123\",\n" + + " \"dataFormat\": \"PROTOBUF\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + Type type = TestUtils.createConsumerRecordsType(String.class, TestProductPojo.class); + + // When + ConsumerRecords records; + if (inputType == InputType.INPUT_STREAM) { + ByteArrayInputStream inputStream = new ByteArrayInputStream(kafkaJson.getBytes()); + records = deserializer.fromJson(inputStream, type); + } else { + records = deserializer.fromJson(kafkaJson, type); + } + + // Then + assertThat(records).isNotNull(); + TopicPartition tp = new TopicPartition("test-topic-1", 0); + List> topicRecords = records.records(tp); + assertThat(topicRecords).hasSize(1); + + ConsumerRecord consumerRecord = topicRecords.get(0); + assertThat(consumerRecord.value()).isNotNull(); + assertThat(consumerRecord.value().getId()).isEqualTo(456); + } + // Test implementation of AbstractKafkaDeserializer - private static class TestDeserializer extends AbstractKafkaDeserializer { + private static final class TestDeserializer extends AbstractKafkaDeserializer { @Override - protected T deserializeObject(byte[] data, Class type) throws IOException { + protected T deserializeObject(byte[] data, Class type, SchemaRegistryType schemaRegistryType) + throws IOException { return objectMapper.readValue(data, type); } } diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializerTest.java index a0b59b136..f501d7d98 100644 --- a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializerTest.java +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaAvroDeserializerTest.java @@ -38,9 +38,10 @@ void shouldThrowExceptionWhenTypeIsNotAvroSpecificRecord() { byte[] data = new byte[] { 1, 2, 3 }; // When/Then - assertThatThrownBy(() -> deserializer.deserializeObject(data, String.class)) - .isInstanceOf(IOException.class) - .hasMessageContaining("Unsupported type for Avro deserialization"); + assertThatThrownBy(() -> deserializer.deserializeObject(data, String.class, + AbstractKafkaDeserializer.SchemaRegistryType.NONE)) + .isInstanceOf(IOException.class) + .hasMessageContaining("Unsupported type for Avro deserialization"); } @Test @@ -50,7 +51,8 @@ void shouldDeserializeValidAvroData() throws IOException { byte[] avroData = serializeAvro(product); // When - TestProduct result = deserializer.deserializeObject(avroData, TestProduct.class); + TestProduct result = deserializer.deserializeObject(avroData, TestProduct.class, + AbstractKafkaDeserializer.SchemaRegistryType.NONE); // Then assertThat(result).isNotNull(); @@ -65,9 +67,10 @@ void shouldThrowExceptionWhenDeserializingInvalidAvroData() { byte[] invalidAvroData = new byte[] { 1, 2, 3, 4, 5 }; // When/Then - assertThatThrownBy(() -> deserializer.deserializeObject(invalidAvroData, TestProduct.class)) - .isInstanceOf(IOException.class) - .hasMessageContaining("Failed to deserialize Avro data"); + assertThatThrownBy(() -> deserializer.deserializeObject(invalidAvroData, TestProduct.class, + AbstractKafkaDeserializer.SchemaRegistryType.NONE)) + .isInstanceOf(IOException.class) + .hasMessageContaining("Failed to deserialize Avro data"); } } diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializerTest.java index 0cfb2498b..c01e09d8d 100644 --- a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializerTest.java +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaJsonDeserializerTest.java @@ -42,8 +42,9 @@ void shouldThrowExceptionWhenTypeIsNotSupportedForJson() { byte[] data = new byte[] { 1, 2, 3 }; // When/Then - assertThatThrownBy(() -> deserializer.deserializeObject(data, Object.class)) - .isInstanceOf(JsonParseException.class); + assertThatThrownBy(() -> deserializer.deserializeObject(data, Object.class, + AbstractKafkaDeserializer.SchemaRegistryType.NONE)) + .isInstanceOf(JsonParseException.class); } @Test @@ -53,7 +54,8 @@ void shouldDeserializeValidJsonData() throws IOException { byte[] jsonData = objectMapper.writeValueAsBytes(product); // When - TestProductPojo result = deserializer.deserializeObject(jsonData, TestProductPojo.class); + TestProductPojo result = deserializer.deserializeObject(jsonData, TestProductPojo.class, + AbstractKafkaDeserializer.SchemaRegistryType.NONE); // Then assertThat(result).isNotNull(); diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java index 3315e1172..34a376947 100644 --- a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/serializers/KafkaProtobufDeserializerTest.java @@ -17,7 +17,9 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; +import org.apache.kafka.common.utils.ByteUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -40,9 +42,10 @@ void shouldThrowExceptionWhenTypeIsNotProtobufMessage() { byte[] data = new byte[] { 1, 2, 3 }; // When/Then - assertThatThrownBy(() -> deserializer.deserializeObject(data, String.class)) - .isInstanceOf(IOException.class) - .hasMessageContaining("Unsupported type for Protobuf deserialization"); + assertThatThrownBy(() -> deserializer.deserializeObject(data, String.class, + AbstractKafkaDeserializer.SchemaRegistryType.NONE)) + .isInstanceOf(IOException.class) + .hasMessageContaining("Unsupported type for Protobuf deserialization"); } @Test @@ -56,7 +59,8 @@ void shouldDeserializeValidProtobufData() throws IOException { byte[] protobufData = product.toByteArray(); // When - TestProduct result = deserializer.deserializeObject(protobufData, TestProduct.class); + TestProduct result = deserializer.deserializeObject(protobufData, TestProduct.class, + AbstractKafkaDeserializer.SchemaRegistryType.NONE); // Then assertThat(result).isNotNull(); @@ -71,13 +75,14 @@ void shouldThrowExceptionWhenDeserializingInvalidProtobufData() { byte[] invalidProtobufData = new byte[] { 1, 2, 3, 4, 5 }; // When/Then - assertThatThrownBy(() -> deserializer.deserializeObject(invalidProtobufData, TestProduct.class)) - .isInstanceOf(IOException.class) - .hasMessageContaining("Failed to deserialize Protobuf data"); + assertThatThrownBy(() -> deserializer.deserializeObject(invalidProtobufData, TestProduct.class, + AbstractKafkaDeserializer.SchemaRegistryType.NONE)) + .isInstanceOf(IOException.class) + .hasMessageContaining("Failed to deserialize Protobuf data"); } @Test - void shouldDeserializeProtobufDataWithSimpleMessageIndex() throws IOException { + void shouldDeserializeProtobufDataWithSimpleMessageIndexGlue() throws IOException { // Given TestProduct product = TestProduct.newBuilder() .setId(456) @@ -86,10 +91,11 @@ void shouldDeserializeProtobufDataWithSimpleMessageIndex() throws IOException { .build(); // Create protobuf data with simple message index (single 0) - byte[] protobufDataWithSimpleIndex = createProtobufDataWithSimpleMessageIndex(product); + byte[] protobufDataWithSimpleIndex = createProtobufDataWithGlueMagicByte(product); // When - TestProduct result = deserializer.deserializeObject(protobufDataWithSimpleIndex, TestProduct.class); + TestProduct result = deserializer.deserializeObject(protobufDataWithSimpleIndex, TestProduct.class, + AbstractKafkaDeserializer.SchemaRegistryType.GLUE); // Then assertThat(result).isNotNull(); @@ -107,11 +113,12 @@ void shouldDeserializeProtobufDataWithComplexMessageIndex() throws IOException { .setPrice(299.99) .build(); - // Create protobuf data with complex message index (array [1,0]) - byte[] protobufDataWithComplexIndex = createProtobufDataWithComplexMessageIndex(product); + // Create protobuf data with complex message index (array [2,2]) + byte[] protobufDataWithComplexIndex = createProtobufDataWithComplexMessageIndexConfluent(product); // When - TestProduct result = deserializer.deserializeObject(protobufDataWithComplexIndex, TestProduct.class); + TestProduct result = deserializer.deserializeObject(protobufDataWithComplexIndex, TestProduct.class, + AbstractKafkaDeserializer.SchemaRegistryType.CONFLUENT); // Then assertThat(result).isNotNull(); @@ -120,12 +127,35 @@ void shouldDeserializeProtobufDataWithComplexMessageIndex() throws IOException { assertThat(result.getPrice()).isEqualTo(299.99); } - private byte[] createProtobufDataWithSimpleMessageIndex(TestProduct product) throws IOException { + @Test + void shouldDeserializeProtobufDataWithSimpleMessageIndexConfluent() throws IOException { + // Given + TestProduct product = TestProduct.newBuilder() + .setId(789) + .setName("Complex Index Product") + .setPrice(299.99) + .build(); + + // Create protobuf data with simple message index for Confluent + byte[] protobufDataWithComplexIndex = createProtobufDataWithSimpleMessageIndexConfluent(product); + + // When + TestProduct result = deserializer.deserializeObject(protobufDataWithComplexIndex, TestProduct.class, + AbstractKafkaDeserializer.SchemaRegistryType.CONFLUENT); + + // Then + assertThat(result).isNotNull(); + assertThat(result.getId()).isEqualTo(789); + assertThat(result.getName()).isEqualTo("Complex Index Product"); + assertThat(result.getPrice()).isEqualTo(299.99); + } + + private byte[] createProtobufDataWithGlueMagicByte(TestProduct product) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); CodedOutputStream codedOutput = CodedOutputStream.newInstance(baos); - // Write simple message index (single 0) - codedOutput.writeUInt32NoTag(0); + // Write simple message index for Glue (single UInt32) + codedOutput.writeUInt32NoTag(1); // Write the protobuf data product.writeTo(codedOutput); @@ -134,19 +164,37 @@ private byte[] createProtobufDataWithSimpleMessageIndex(TestProduct product) thr return baos.toByteArray(); } - private byte[] createProtobufDataWithComplexMessageIndex(TestProduct product) throws IOException { + private byte[] createProtobufDataWithSimpleMessageIndexConfluent(TestProduct product) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - CodedOutputStream codedOutput = CodedOutputStream.newInstance(baos); - // Write complex message index array [1,0] - codedOutput.writeUInt32NoTag(2); // Array length - codedOutput.writeUInt32NoTag(1); // First index value - codedOutput.writeUInt32NoTag(0); // Second index value + // Write optimized simple message index for Confluent (single 0 byte for [0]) + // https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format + baos.write(0); // Write the protobuf data - product.writeTo(codedOutput); + baos.write(product.toByteArray()); + + return baos.toByteArray(); + } + + private byte[] createProtobufDataWithComplexMessageIndexConfluent(TestProduct product) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + // Write complex message index array [1,0] using ByteUtils + // https://docs.confluent.io/platform/current/schema-registry/fundamentals/serdes-develop/index.html#wire-format + ByteBuffer buffer = ByteBuffer.allocate(1024); + ByteUtils.writeVarint(2, buffer); // Array length + ByteUtils.writeVarint(1, buffer); // First index value + ByteUtils.writeVarint(0, buffer); // Second index value + + buffer.flip(); + byte[] indexData = new byte[buffer.remaining()]; + buffer.get(indexData); + baos.write(indexData); + + // Write the protobuf data + baos.write(product.toByteArray()); - codedOutput.flush(); return baos.toByteArray(); } } From 984036ca2e3afb92b2c838bcfa2e48a51c3d7a64 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 20 Jun 2025 13:53:09 +0200 Subject: [PATCH 257/577] chore(ci): bump version to 2.1.1 (#1910) Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 42 files changed, 48 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 165458a65..7e33bf19e 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your software.amazon.lambda powertools-tracing - 2.1.0 + 2.1.1 software.amazon.lambda powertools-logging - 2.1.0 + 2.1.1 software.amazon.lambda powertools-metrics - 2.1.0 + 2.1.1 ... diff --git a/examples/pom.xml b/examples/pom.xml index 496c933c3..cd076d099 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-examples - 2.1.0 + 2.1.1 pom Powertools for AWS Lambda (Java) - Examples diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 1cf1e6f65..f1ae54c46 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ 4.0.0 software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-batch jar Powertools for AWS Lambda (Java) - Examples - Batch diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 74a0090fe..ea31c3caa 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ 4.0.0 software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-cloudformation jar diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 87bea4b38..e9f2318a9 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-core-utilities-cdk jar diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 2ddd389a9..4af44d146 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ 4.0.0 software.amazon.lambda.examples cdk - 2.1.0 + 2.1.1 UTF-8 2.162.1 diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index b86e49659..04368e29c 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.1.0' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.1.0' - aspect 'software.amazon.lambda:powertools-metrics:2.1.0' + aspect 'software.amazon.lambda:powertools-tracing:2.1.1' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.1.1' + aspect 'software.amazon.lambda:powertools-metrics:2.1.1' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 23c84a0d3..2b3d184d7 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.1.0") - aspect("software.amazon.lambda:powertools-logging-log4j:2.1.0") - aspect("software.amazon.lambda:powertools-metrics:2.1.0") + aspect("software.amazon.lambda:powertools-tracing:2.1.1") + aspect("software.amazon.lambda:powertools-logging-log4j:2.1.1") + aspect("software.amazon.lambda:powertools-metrics:2.1.1") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index d691c02a5..25517be25 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-core-utilities-sam-graalvm jar diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index f37319ea1..db4fbc2b3 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-core-utilities-sam jar diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 1f4e0a2fc..b9b9304b3 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-core-utilities-serverless jar diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 6dcd2f8c6..82be84f06 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-core-utilities-terraform jar diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index c7ca6a058..b5864de27 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ 4.0.0 software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-idempotency jar Powertools for AWS Lambda (Java) - Examples - Idempotency diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 185790b64..6921f2793 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-kafka jar Powertools for AWS Lambda (Java) - Examples - Kafka diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 643b8f134..06dba9c56 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-parameters-sam-graalvm jar Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index e8ce66e11..6c152479e 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-parameters-sam jar Powertools for AWS Lambda (Java) - Examples - Parameters diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index eedce8b87..35d0f76d1 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-serialization jar Powertools for AWS Lambda (Java) - Examples - Serialization diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 3b9d9baeb..9beb3d014 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 software.amazon.lambda.examples - 2.1.0 + 2.1.1 powertools-examples-validation jar Powertools for AWS Lambda (Java) - Examples - Validation diff --git a/mkdocs.yml b/mkdocs.yml index 1880e543d..0008ef9dd 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -121,7 +121,7 @@ extra_javascript: extra: powertools: - version: 2.1.0 + version: 2.1.1 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index 1033c3f6e..407fa518b 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ software.amazon.lambda powertools-parent - 2.1.0 + 2.1.1 pom Powertools for AWS Lambda (Java) - Parent diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 4f6b78f5e..c5036e74a 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 2.1.0 + 2.1.1 A suite of utilities that makes batch message processing using AWS Lambda easier. diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 657d42e42..1f3329325 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 Powertools for AWS Lambda (Java) - Cloudformation diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 8e0229bb4..20060bae7 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 Powertools for AWS Lambda (Java) - Common Internal Utilities diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index c49e6824a..779476eae 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 powertools-e2e-tests diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 169953642..029fa4163 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-parent - 2.1.0 + 2.1.1 powertools-idempotency diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 846dea2d8..c8ea35d4b 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-idempotency - 2.1.0 + 2.1.1 powertools-idempotency-core diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index 099eb12ab..4ae37f00c 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ software.amazon.lambda powertools-idempotency - 2.1.0 + 2.1.1 powertools-idempotency-dynamodb diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index deac5cc3e..5eb79913b 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 powertools-kafka diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 8eb0e143f..1b975739d 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ software.amazon.lambda powertools-parent - 2.1.0 + 2.1.1 powertools-large-messages diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 2ee71ae67..af9f066b3 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 Powertools for AWS Lambda (Java) - Logging diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 6fe11ea93..2cfcd967d 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 ../../pom.xml diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 6fd411c47..cb2054b87 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 ../../pom.xml diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 19b185f4d..3501c7b0e 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 Powertools for AWS Lambda (Java) - Metrics diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index d61e76322..d4da33a8d 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 powertools-parameters diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 52b15296b..206d259e1 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.1.0 + 2.1.1 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 0b82087c9..3959ff65b 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.1.0 + 2.1.1 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index c90cf1c69..9885fcef1 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.1.0 + 2.1.1 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index f03983fff..e9f33a24b 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ software.amazon.lambda powertools-parent - 2.1.0 + 2.1.1 ../../pom.xml diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 9f8b12911..21ce5639e 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ software.amazon.lambda powertools-parent - 2.1.0 + 2.1.1 ../../pom.xml diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index d6e04b3b8..891a1582a 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 powertools-serialization diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index d76ddffcb..5239e7b6c 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 Powertools for AWS Lambda (Java) - Tracing diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index a7403d6b3..3ab6e51fc 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ powertools-parent software.amazon.lambda - 2.1.0 + 2.1.1 Powertools for AWS Lambda (Java) - Validation From 8b6d484c37b44359bcb534083e2506107c385fd9 Mon Sep 17 00:00:00 2001 From: Simon Thulbourn Date: Tue, 24 Jun 2025 09:46:59 +0100 Subject: [PATCH 258/577] chore(ci): Update branch protection rules (#1914) --- .github/branch_protection_settings/1.x.x.json | 53 +++++++++++++++++++ .github/branch_protection_settings/main.json | 42 +++++++++------ 2 files changed, 79 insertions(+), 16 deletions(-) create mode 100644 .github/branch_protection_settings/1.x.x.json diff --git a/.github/branch_protection_settings/1.x.x.json b/.github/branch_protection_settings/1.x.x.json new file mode 100644 index 000000000..e52aba745 --- /dev/null +++ b/.github/branch_protection_settings/1.x.x.json @@ -0,0 +1,53 @@ +{ + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection", + "required_status_checks": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection/required_status_checks", + "strict": true, + "contexts": [ + "SonarCloud" + ], + "contexts_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection/required_status_checks/contexts", + "checks": [ + { + "context": "SonarCloud", + "app_id": null + } + ] + }, + "required_pull_request_reviews": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection/required_pull_request_reviews", + "dismiss_stale_reviews": false, + "require_code_owner_reviews": false, + "require_last_push_approval": false, + "required_approving_review_count": 0 + }, + "required_signatures": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection/required_signatures", + "enabled": false + }, + "enforce_admins": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection/enforce_admins", + "enabled": true + }, + "required_linear_history": { + "enabled": false + }, + "allow_force_pushes": { + "enabled": false + }, + "allow_deletions": { + "enabled": false + }, + "block_creations": { + "enabled": false + }, + "required_conversation_resolution": { + "enabled": false + }, + "lock_branch": { + "enabled": false + }, + "allow_fork_syncing": { + "enabled": false + } +} diff --git a/.github/branch_protection_settings/main.json b/.github/branch_protection_settings/main.json index d283b3d5f..9fc6cc07d 100644 --- a/.github/branch_protection_settings/main.json +++ b/.github/branch_protection_settings/main.json @@ -3,23 +3,33 @@ "required_status_checks": { "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_status_checks", "strict": true, - "contexts": [ - "SonarCloud" - ], + "contexts": [], "contexts_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_status_checks/contexts", - "checks": [ - { - "context": "SonarCloud", - "app_id": 57789 - } - ] + "checks": [] + }, + "restrictions": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/restrictions", + "users_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/restrictions/users", + "teams_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/restrictions/teams", + "apps_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/restrictions/apps", + "users": [], + "teams": [], + "apps": [] }, "required_pull_request_reviews": { "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_pull_request_reviews", - "dismiss_stale_reviews": false, + "dismiss_stale_reviews": true, "require_code_owner_reviews": false, - "require_last_push_approval": false, - "required_approving_review_count": 0 + "require_last_push_approval": true, + "required_approving_review_count": 1, + "dismissal_restrictions": { + "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/dismissal_restrictions", + "users_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/dismissal_restrictions/users", + "teams_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/dismissal_restrictions/teams", + "users": [], + "teams": [], + "apps": [] + } }, "required_signatures": { "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_signatures", @@ -27,10 +37,10 @@ }, "enforce_admins": { "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/enforce_admins", - "enabled": true + "enabled": false }, "required_linear_history": { - "enabled": false + "enabled": true }, "allow_force_pushes": { "enabled": false @@ -39,10 +49,10 @@ "enabled": false }, "block_creations": { - "enabled": false + "enabled": true }, "required_conversation_resolution": { - "enabled": false + "enabled": true }, "lock_branch": { "enabled": false From ffd88b96a6d57ea350e5ee3af4c980ef6ccffc7e Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Mon, 7 Jul 2025 12:37:44 +0200 Subject: [PATCH 259/577] chore: update issue, PR, and discussion templates (#1915) * chore: update issue & discussion templates * chore: update PR template * Update .github/PULL_REQUEST_TEMPLATE.md * Update .github/DISCUSSION_TEMPLATE/rfcs.yml * Update .github/DISCUSSION_TEMPLATE/rfcs.yml --------- Co-authored-by: Philipp Page --- .../rfc.md => DISCUSSION_TEMPLATE/rfcs.yml} | 32 ++++++------ .../{bug_report.md => bug_report.yml} | 3 +- .github/ISSUE_TEMPLATE/config.yml | 5 +- .github/ISSUE_TEMPLATE/feature_request.md | 20 ------- .github/ISSUE_TEMPLATE/feature_request.yml | 52 +++++++++++++++++++ .github/ISSUE_TEMPLATE/share_your_work.yml | 2 +- .github/ISSUE_TEMPLATE/support_powertools.yml | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 33 ++++++------ 8 files changed, 94 insertions(+), 55 deletions(-) rename .github/{ISSUE_TEMPLATE/rfc.md => DISCUSSION_TEMPLATE/rfcs.yml} (78%) rename .github/ISSUE_TEMPLATE/{bug_report.md => bug_report.yml} (98%) delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml diff --git a/.github/ISSUE_TEMPLATE/rfc.md b/.github/DISCUSSION_TEMPLATE/rfcs.yml similarity index 78% rename from .github/ISSUE_TEMPLATE/rfc.md rename to .github/DISCUSSION_TEMPLATE/rfcs.yml index ae2337402..55909514f 100644 --- a/.github/ISSUE_TEMPLATE/rfc.md +++ b/.github/DISCUSSION_TEMPLATE/rfcs.yml @@ -1,7 +1,4 @@ -name: Request for Comments (RFC) -description: Feature design and detailed proposals -title: "RFC: TITLE" -labels: ["RFC", "triage"] +title: "RFC: " body: - type: markdown attributes: @@ -15,21 +12,18 @@ body: - type: dropdown id: area attributes: - label: Which Powertools for AWS Lambda (Java) utility does this relate to? + label: Which area does this RFC relate to? options: - Tracer - Logger - Metrics - - Middleware factory - Parameters - - Batch processing - - Typing + - Large Messages + - Batch Processing - Validation - - Event Source Data Classes - - Parser - Idempotency - - Feature flags - - JMESPath functions + - Custom Resources + - Serialization - Other validations: required: true @@ -81,7 +75,7 @@ body: attributes: label: Alternative solutions description: Please describe what alternative solutions to this use case, if any - render: markdown + render: Markdown validations: required: false - type: checkboxes @@ -89,7 +83,7 @@ body: attributes: label: Acknowledgment options: - - label: This feature request meets [Powertools for AWS Lambda (Java) Tenets](https://docs.powertools.aws.dev/lambda/Java/#tenets) + - label: This RFC meets [Powertools for AWS Lambda (Java) Tenets](https://docs.powertools.aws.dev/lambda/java/latest/#tenets) required: true - label: Should this be considered in other Powertools for AWS Lambda languages? i.e. [Python](https://github.com/aws-powertools/powertools-lambda-python/), [TypeScript](https://github.com/aws-powertools/powertools-lambda-typescript/), and [.NET](https://github.com/aws-powertools/powertools-lambda-dotnet/) required: false @@ -98,10 +92,16 @@ body: value: | --- - **Disclaimer**: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful. + **Disclaimer**: After creating an RFC, please wait until it is reviewed and signed-off by a maintainer before implementing it. This will reduce amount of rework and the chance that a pull request gets rejected. Metadata information for admin purposes, please leave them empty. * RFC PR: * Approved by: '' - * Reviewed by: '' \ No newline at end of file + * Reviewed by: '' + - type: input + id: notes + attributes: + label: Future readers + description: Please not edit this field + value: "Please react with 👍 and your use case to help us understand customer demand." \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.yml similarity index 98% rename from .github/ISSUE_TEMPLATE/bug_report.md rename to .github/ISSUE_TEMPLATE/bug_report.yml index 8810605b9..2b0ae71e8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,6 +1,7 @@ name: Bug report description: Report a reproducible bug to help us improve title: "Bug: TITLE" +type: "Bug" labels: ["bug", "triage"] body: - type: markdown @@ -49,7 +50,7 @@ body: id: version attributes: label: Powertools for AWS Lambda (Java) version - placeholder: "latest, 1.19.0" + placeholder: "latest, 2.0.1" value: latest validations: required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 9eae2e167..01a8d495b 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,4 +2,7 @@ blank_issues_enabled: false contact_links: - name: Ask a question url: https://github.com/aws-powertools/powertools-lambda-java/discussions/new - about: Ask a general question about Lambda Powertools + about: Ask a general question about Powertools for AWS Lambda + - name: Join Community Discord Server + url: https://discord.gg/B8zZKbbyET + about: "Check out the #java channel" diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index b837b7ad5..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: feature-request, triage -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] --> - -**Describe the solution you'd like** -<!-- A clear and concise description of what you want to happen. --> - -**Describe alternatives you've considered** -<!-- A clear and concise description of any alternative solutions or features you've considered. --> - -**Additional context** -<!-- Add any other context or screenshots about the feature request here. --> diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 000000000..6aaef0718 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,52 @@ +name: Feature request +description: Suggest an idea for Powertools for AWS Lambda +title: "Feature request: TITLE" +labels: ["feature-request", "triage"] +body: + - type: markdown + attributes: + value: | + Thank you for taking the time to suggest an idea to the Powertools for AWS Lambda (Java) project. + - type: textarea + id: problem + attributes: + label: Use case + description: Please help us understand your use case or problem you're facing + validations: + required: true + - type: textarea + id: suggestion + attributes: + label: Solution/User Experience + description: Please share what a good solution would look like to this use case + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternative solutions + description: Please describe what alternative solutions to this use case, if any + render: Markdown + validations: + required: false + - type: checkboxes + id: acknowledgment + attributes: + label: Acknowledgment + options: + - label: This feature request meets [Powertools for AWS Lambda (Java) Tenets](https://docs.powertools.aws.dev/lambda/java/latest/#tenets) + required: true + - label: Should this be considered in other Powertools for AWS Lambda languages? i.e. [Python](https://github.com/aws-powertools/powertools-lambda-python/), [TypeScript](https://github.com/aws-powertools/powertools-lambda-typescript/), and [.NET](https://github.com/aws-powertools/powertools-lambda-dotnet/) + required: false + - type: markdown + attributes: + value: | + --- + + **Disclaimer**: After creating an issue, please wait until it is triaged and confirmed by a maintainer before implementing it. This will reduce amount of rework and the chance that a pull request gets rejected. + - type: input + id: notes + attributes: + label: Future readers + description: Please not edit this field + value: "Please react with 👍 and your use case to help us understand customer demand." \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/share_your_work.yml b/.github/ISSUE_TEMPLATE/share_your_work.yml index 01dae4fdf..f0f879225 100644 --- a/.github/ISSUE_TEMPLATE/share_your_work.yml +++ b/.github/ISSUE_TEMPLATE/share_your_work.yml @@ -1,7 +1,7 @@ name: I Made This (showcase your work) description: Share what you did with Powertools for AWS Lambda (Java) 💞💞. Blog post, workshops, presentation, sample apps, etc. title: "[I Made This]: <TITLE>" -labels: ["community-content"] +labels: ["community-content", "triage"] body: - type: markdown attributes: diff --git a/.github/ISSUE_TEMPLATE/support_powertools.yml b/.github/ISSUE_TEMPLATE/support_powertools.yml index 8623c2b73..9067d47ec 100644 --- a/.github/ISSUE_TEMPLATE/support_powertools.yml +++ b/.github/ISSUE_TEMPLATE/support_powertools.yml @@ -1,7 +1,7 @@ name: Support Powertools for AWS Lambda (Java) (become a reference) description: Add your organization's name or logo to the Powertools for AWS Lambda (Java) documentation title: "[Support Powertools for AWS Lambda (Java)]: <your organization name>" -labels: ["customer-reference"] +labels: ["customer-reference", "triage"] body: - type: markdown attributes: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d4b6d17ff..f30703bb4 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,25 +1,28 @@ -**Issue #, if available:** +## Summary -## Description of changes: +### Changes -<!--- One or two sentences as a summary of what's being changed --> +> Please provide a summary of what's being changed -**Checklist** +<!-- What is this PR solving? Write a clear description or reference the issue(s) it addresses. --> -<!--- Leave unchecked if your change doesn't seem to apply --> +> Please add the issue number below, if no issue is present the PR might get blocked and not be reviewed -* [ ] [Meet tenets criteria](https://docs.powertools.aws.dev/lambda-java/#tenets) -* [ ] Update tests -* [ ] Update docs -* [ ] PR title follows [conventional commit semantics](https://www.conventionalcommits.org/en/v1.0.0/) +**Issue number:** -## Breaking change checklist +<!------- +Before creating the pull request, please make sure you do the following: -<!--- Ignore if it's not a breaking change --> +- Read the Contributing Guidelines at https://github.com/aws-powertools/powertools-lambda-java/blob/main/CONTRIBUTING.md#sending-a-pull-request +- Check that there isn't already a PR that addresses the same issue. If you find a duplicate, please leave a comment under the existing PR so we can discuss how to move forward +- Check that the change meets the project's tenets https://docs.powertools.aws.dev/lambda/java/latest/#tenets +- Add a PR title that follows the conventional commit semantics - https://www.conventionalcommits.org/en/v1.0.0/ +- If relevant, add tests that prove that the change is effective and works +- Whenever relevant, make sure to comment functions/methods/types and make appropriate changes to the documentation +-------> -**RFC issue #**: - -* [ ] Migration process documented -* [ ] Implement warnings (if it can live side by side) +--- By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. + +**Disclaimer**: We value your time and bandwidth. As such, any pull requests created on non-triaged issues might not be successful. \ No newline at end of file From 64ddf340e814f276dcc0056c25b1756a9d83f2de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 14:53:21 +0200 Subject: [PATCH 260/577] build(deps): bump org.jacoco:jacoco-maven-plugin from 0.8.12 to 0.8.13 (#1849) Bumps [org.jacoco:jacoco-maven-plugin](https://github.com/jacoco/jacoco) from 0.8.12 to 0.8.13. - [Release notes](https://github.com/jacoco/jacoco/releases) - [Commits](https://github.com/jacoco/jacoco/compare/v0.8.12...v0.8.13) --- updated-dependencies: - dependency-name: org.jacoco:jacoco-maven-plugin dependency-version: 0.8.13 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 407fa518b..4d4c15db2 100644 --- a/pom.xml +++ b/pom.xml @@ -103,7 +103,7 @@ <junit.version>5.10.0</junit.version> <aspectj-maven-plugin.version>1.14</aspectj-maven-plugin.version> <maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version> - <jacoco-maven-plugin.version>0.8.12</jacoco-maven-plugin.version> + <jacoco-maven-plugin.version>0.8.13</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version> <maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version> <maven-source-plugin.version>3.3.0</maven-source-plugin.version> From f73dee8e2638719bea7a1cc2b96a7521a7cc5c70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:02:53 +0200 Subject: [PATCH 261/577] build(deps): bump aws.sdk.version from 2.31.40 to 2.31.62 (#1886) Bumps `aws.sdk.version` from 2.31.40 to 2.31.62. Updates `software.amazon.awssdk:bom` from 2.31.40 to 2.31.62 Updates `software.amazon.awssdk:http-client-spi` from 2.31.40 to 2.31.62 Updates `software.amazon.awssdk:url-connection-client` from 2.30.31 to 2.31.62 Updates `software.amazon.awssdk:dynamodb` from 2.31.40 to 2.31.62 Updates `software.amazon.awssdk:s3` from 2.30.31 to 2.31.62 Updates `software.amazon.awssdk:lambda` from 2.31.40 to 2.31.62 Updates `software.amazon.awssdk:kinesis` from 2.30.31 to 2.31.62 Updates `software.amazon.awssdk:cloudwatch` from 2.31.40 to 2.31.62 Updates `software.amazon.awssdk:xray` from 2.31.40 to 2.31.62 Updates `software.amazon.awssdk:sqs` from 2.30.31 to 2.31.62 Updates `software.amazon.awssdk:cloudformation` from 2.31.40 to 2.31.62 Updates `software.amazon.awssdk:sts` from 2.31.40 to 2.31.62 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.31.62 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.31.62 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.31.62 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.31.62 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.31.62 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.31.62 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.31.62 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.31.62 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.31.62 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.31.62 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.31.62 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.31.62 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index ea31c3caa..ae96e2f8e 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.2.3</lambda.core.version> <lambda.events.version>3.15.0</lambda.events.version> - <aws.sdk.version>2.31.40</aws.sdk.version> + <aws.sdk.version>2.31.62</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 4d4c15db2..b641f3216 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <log4j.version>2.24.3</log4j.version> <slf4j.version>2.0.7</slf4j.version> <jackson.version>2.17.2</jackson.version> - <aws.sdk.version>2.31.40</aws.sdk.version> + <aws.sdk.version>2.31.62</aws.sdk.version> <aws.xray.recorder.version>2.18.2</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> From d8443dc003e8d3c666433db9ad31ac76964fca3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:07:36 +0200 Subject: [PATCH 262/577] build(deps): bump commons-io:commons-io from 2.16.1 to 2.19.0 (#1852) Bumps commons-io:commons-io from 2.16.1 to 2.19.0. --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-version: 2.19.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 779476eae..708a57d4e 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -103,7 +103,7 @@ <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> - <version>2.16.1</version> + <version>2.19.0</version> </dependency> <dependency> From c67848d6f0293392762232f670c688f3c635677f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:08:10 +0200 Subject: [PATCH 263/577] build(deps): bump org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions (#1853) Bumps org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions from 0.1.0 to 0.2.0. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions dependency-version: 0.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- examples/powertools-examples-core-utilities/serverless/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index f1ae54c46..50042c8ea 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -139,7 +139,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> </dependencies> </plugin> diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index ae96e2f8e..84a8bbe1a 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -136,7 +136,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> </dependencies> </plugin> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index e9f2318a9..69ab7c86c 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -124,7 +124,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> </dependencies> </plugin> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index db4fbc2b3..87c7d51f4 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -109,7 +109,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> </dependencies> </plugin> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index b9b9304b3..312074f5d 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -110,7 +110,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> </dependencies> </plugin> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 82be84f06..eed3bacc4 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -110,7 +110,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> </dependencies> </plugin> diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index b5864de27..430087957 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -169,7 +169,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> </dependencies> </plugin> From 8b24f270bfc0d00593e93331ece61d3ac7d14445 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:08:38 +0200 Subject: [PATCH 264/577] build(deps): bump org.junit.jupiter:junit-jupiter-engine (#1865) Bumps [org.junit.jupiter:junit-jupiter-engine](https://github.com/junit-team/junit5) from 5.9.3 to 5.13.1. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.9.3...r5.13.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter-engine dependency-version: 5.13.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 06dba9c56..ed4e1b7b6 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -88,7 +88,7 @@ <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> - <version>5.9.3</version> + <version>5.13.1</version> <scope>test</scope> </dependency> </dependencies> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 6c152479e..30ff856ed 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -62,7 +62,7 @@ <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> - <version>5.9.3</version> + <version>5.13.1</version> <scope>test</scope> </dependency> </dependencies> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 9beb3d014..b1819ab21 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -65,7 +65,7 @@ <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> - <version>5.9.3</version> + <version>5.13.1</version> <scope>test</scope> </dependency> </dependencies> From c72e4c245faeab6f3fb87368d60192230af30e49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:19:39 +0200 Subject: [PATCH 265/577] build(deps): bump org.junit-pioneer:junit-pioneer from 1.9.1 to 2.0.0 (#1884) Dependabot couldn't find the original pull request head commit, 0d85e87e3a1668c4007abb86a845439f6d3691b5. Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b641f3216..12d779423 100644 --- a/pom.xml +++ b/pom.xml @@ -311,7 +311,7 @@ <dependency> <groupId>org.junit-pioneer</groupId> <artifactId>junit-pioneer</artifactId> - <version>1.9.1</version> + <version>2.0.0</version> <scope>test</scope> </dependency> <dependency> From 6bc057a3efd900e72bccedf690113a70b9a791d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:22:30 +0200 Subject: [PATCH 266/577] build(deps): bump com.amazonaws:aws-lambda-java-core from 1.2.3 to 1.3.0 (#1892) Bumps [com.amazonaws:aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs) from 1.2.3 to 1.3.0. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-core dependency-version: 1.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- examples/powertools-examples-core-utilities/serverless/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- examples/powertools-examples-serialization/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- pom.xml | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 50042c8ea..53db49e17 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -36,7 +36,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 84a8bbe1a..62c60b00b 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -12,7 +12,7 @@ <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> - <lambda.core.version>1.2.3</lambda.core.version> + <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.15.0</lambda.events.version> <aws.sdk.version>2.31.62</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 69ab7c86c..9e38e64e1 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -36,7 +36,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 25517be25..99aeefee8 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -34,7 +34,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 87c7d51f4..62bff0cd4 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -33,7 +33,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 312074f5d..a042e098e 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -33,7 +33,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index eed3bacc4..418dc20af 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -33,7 +33,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 430087957..932da03b4 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -47,7 +47,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index ed4e1b7b6..f0742e86e 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -34,7 +34,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 30ff856ed..a4f8d975b 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -33,7 +33,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/pom.xml index 35d0f76d1..bd249bb25 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/pom.xml @@ -26,7 +26,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index b1819ab21..272ff663f 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -41,7 +41,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.2.3</version> + <version>1.3.0</version> </dependency> <dependency> <groupId>org.aspectj</groupId> diff --git a/pom.xml b/pom.xml index 12d779423..dac6214c4 100644 --- a/pom.xml +++ b/pom.xml @@ -88,7 +88,7 @@ <aws.xray.recorder.version>2.18.2</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <lambda.core.version>1.2.3</lambda.core.version> + <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.0</lambda.events.version> <lambda.serial.version>1.1.5</lambda.serial.version> <maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version> From 484cf77d3e77d36fa9fc3e3064ecb3a726941053 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:24:37 +0200 Subject: [PATCH 267/577] build(deps): bump log4j.version from 2.24.0 to 2.24.3 (#1893) Bumps `log4j.version` from 2.24.0 to 2.24.3. Updates `org.apache.logging.log4j:log4j-core` from 2.24.0 to 2.24.3 Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.24.3 to 2.24.3 Updates `org.apache.logging.log4j:log4j-slf4j2-impl` from 2.24.0 to 2.24.3 Updates `org.apache.logging.log4j:log4j-api` from 2.24.0 to 2.24.3 Updates `org.apache.logging.log4j:log4j-layout-template-json` from 2.24.0 to 2.24.3 Updates `org.apache.logging.log4j:log4j-jcl` from 2.24.3 to 2.24.3 --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-version: 2.24.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-slf4j-impl dependency-version: 2.24.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-slf4j2-impl dependency-version: 2.24.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-api dependency-version: 2.24.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-layout-template-json dependency-version: 2.24.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-jcl dependency-version: 2.24.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 99aeefee8..aef211af6 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -9,7 +9,7 @@ <packaging>jar</packaging> <properties> - <log4j.version>2.24.0</log4j.version> + <log4j.version>2.24.3</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index f0742e86e..9ce76725b 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -8,7 +8,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> <properties> - <log4j.version>2.24.0</log4j.version> + <log4j.version>2.24.3</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> From 4e6aa451cb32995d502690cf1ed362db51794afe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 15:25:23 +0200 Subject: [PATCH 268/577] build(deps): bump com.amazonaws:aws-lambda-java-events (#1913) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-events dependency-version: 3.16.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 62c60b00b..f7f48e309 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -13,7 +13,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> - <lambda.events.version>3.15.0</lambda.events.version> + <lambda.events.version>3.16.0</lambda.events.version> <aws.sdk.version>2.31.62</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> From d9ee495a7221c2ea0c1d10c1d74a6b87d84b2454 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 10 Jul 2025 11:21:47 +0200 Subject: [PATCH 269/577] build(deps): Move wiremock to new version with patched CVEs. (#1923) --- pom.xml | 6 +++--- powertools-cloudformation/pom.xml | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index dac6214c4..b450f5b8e 100644 --- a/pom.xml +++ b/pom.xml @@ -374,9 +374,9 @@ <scope>test</scope> </dependency> <dependency> - <groupId>com.github.tomakehurst</groupId> - <artifactId>wiremock-jre8</artifactId> - <version>2.35.2</version> + <groupId>org.wiremock</groupId> + <artifactId>wiremock</artifactId> + <version>3.13.1</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 1f3329325..c30b47884 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -14,8 +14,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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>powertools-cloudformation</artifactId> @@ -91,8 +91,8 @@ <scope>test</scope> </dependency> <dependency> - <groupId>com.github.tomakehurst</groupId> - <artifactId>wiremock-jre8</artifactId> + <groupId>org.wiremock</groupId> + <artifactId>wiremock</artifactId> <scope>test</scope> </dependency> </dependencies> From 3f23077c76aab267a652a023cb108d74ae559eba Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 10 Jul 2025 13:18:10 +0200 Subject: [PATCH 270/577] chore(ci): remove v2 dependabot configuration. Restore OSSF scorecard workflow. (#1924) --- .github/dependabot.yml | 13 ------ .github/workflows/security-scorecard.yml | 57 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/security-scorecard.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 28adf2bc1..73f454162 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,16 +7,3 @@ updates: labels: - "maven" - "dependencies" - ignore: - # Ignore Mockito 5.X.X as it does not support Java 8 - - dependency-name: "org.mockito:mockito-*" - update-types: ["version-update:semver-major"] - - - package-ecosystem: "maven" - directory: "/" - target-branch: "v2" - schedule: - interval: "weekly" - labels: - - "maven" - - "dependencies" diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml new file mode 100644 index 000000000..28c1ab261 --- /dev/null +++ b/.github/workflows/security-scorecard.yml @@ -0,0 +1,57 @@ +# Runs OSSF +# +# Description: +# Runs OpenSSF Scorecard scan on the project +# +# Triggers: +# - branch_protection_rule +# - cron: 09:00AM +# - push +# - workflow_dispatch +# +# Secrets: +# - Security.SCORECARD_TOKEN + +on: + branch_protection_rule: + schedule: + - cron: "0 9 * * *" + push: + branches: [main] + workflow_dispatch: {} + +name: OpenSSF Scorecard +run-name: OpenSSF Scorecard + +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + environment: Security + permissions: + security-events: write + id-token: write + steps: + - name: Checkout Repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + - name: Run Analysis + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + repo_token: ${{ secrets.SCORECARD_TOKEN }} + - name: Upload Results + uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + - name: Upload to Code-Scanning + uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + with: + sarif_file: results.sarif From 0bd73b605e017d437e33d1100a13f22b6c78d99a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:14:05 +0200 Subject: [PATCH 271/577] build(deps): bump aws.sdk.version from 2.31.62 to 2.31.78 (#1925) Bumps `aws.sdk.version` from 2.31.62 to 2.31.78. Updates `software.amazon.awssdk:bom` from 2.31.62 to 2.31.78 Updates `software.amazon.awssdk:http-client-spi` from 2.31.62 to 2.31.78 Updates `software.amazon.awssdk:url-connection-client` from 2.30.31 to 2.31.78 Updates `software.amazon.awssdk:dynamodb` from 2.31.62 to 2.31.78 Updates `software.amazon.awssdk:s3` from 2.30.31 to 2.31.78 Updates `software.amazon.awssdk:lambda` from 2.31.62 to 2.31.78 Updates `software.amazon.awssdk:kinesis` from 2.30.31 to 2.31.78 Updates `software.amazon.awssdk:cloudwatch` from 2.31.62 to 2.31.78 Updates `software.amazon.awssdk:xray` from 2.31.62 to 2.31.78 Updates `software.amazon.awssdk:sqs` from 2.30.31 to 2.31.78 Updates `software.amazon.awssdk:cloudformation` from 2.31.62 to 2.31.78 Updates `software.amazon.awssdk:sts` from 2.31.62 to 2.31.78 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.31.78 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.31.78 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index f7f48e309..7b0c9a21f 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.0</lambda.events.version> - <aws.sdk.version>2.31.62</aws.sdk.version> + <aws.sdk.version>2.31.78</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index b450f5b8e..2bed1815a 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <log4j.version>2.24.3</log4j.version> <slf4j.version>2.0.7</slf4j.version> <jackson.version>2.17.2</jackson.version> - <aws.sdk.version>2.31.62</aws.sdk.version> + <aws.sdk.version>2.31.78</aws.sdk.version> <aws.xray.recorder.version>2.18.2</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> From 3afe39e0168d7ea2922e4347808483fef1ad58fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:14:24 +0200 Subject: [PATCH 272/577] build(deps): bump org.assertj:assertj-core from 3.26.3 to 3.27.3 (#1926) Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.26.3 to 3.27.3. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.26.3...assertj-build-3.27.3) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-version: 3.27.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2bed1815a..5f862eb2c 100644 --- a/pom.xml +++ b/pom.xml @@ -323,7 +323,7 @@ <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> - <version>3.26.3</version> + <version>3.27.3</version> <scope>test</scope> <exclusions> <exclusion> From a666d94c2486929bb47adcb6a91008fbe50011b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:15:05 +0200 Subject: [PATCH 273/577] build(deps): bump com.amazonaws:aws-lambda-java-runtime-interface-client (#1927) Bumps [com.amazonaws:aws-lambda-java-runtime-interface-client](https://github.com/aws/aws-lambda-java-libs) from 2.1.1 to 2.8.2. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-runtime-interface-client dependency-version: 2.8.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index aef211af6..f5539567b 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -49,7 +49,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.1.1</version> + <version>2.8.2</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 9ce76725b..c7aecd7e3 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -49,7 +49,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.1.1</version> + <version>2.8.2</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> From 49c8e53bdb0f9fa822b3a734bdcd22d05838dba1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:15:51 +0200 Subject: [PATCH 274/577] build(deps-dev): bump com.amazonaws:amazon-sqs-java-extended-client-lib (#1929) Bumps [com.amazonaws:amazon-sqs-java-extended-client-lib](https://github.com/awslabs/amazon-sqs-java-extended-client-lib) from 2.1.0 to 2.1.2. - [Release notes](https://github.com/awslabs/amazon-sqs-java-extended-client-lib/releases) - [Commits](https://github.com/awslabs/amazon-sqs-java-extended-client-lib/compare/2.1.0...2.1.2) --- updated-dependencies: - dependency-name: com.amazonaws:amazon-sqs-java-extended-client-lib dependency-version: 2.1.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 708a57d4e..dbeb8b1ca 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -84,7 +84,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>amazon-sqs-java-extended-client-lib</artifactId> - <version>2.1.0</version> + <version>2.1.2</version> <scope>test</scope> </dependency> From b7f70e6443aa86ddaf4e240b430d7f11d64be538 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Jul 2025 10:44:23 +0200 Subject: [PATCH 275/577] build(deps): bump jackson.version from 2.17.2 to 2.19.1 (#1928) Bumps `jackson.version` from 2.17.2 to 2.19.1. Updates `com.fasterxml.jackson.core:jackson-databind` from 2.17.2 to 2.19.1 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.core:jackson-core` from 2.17.2 to 2.19.1 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.17.2...jackson-core-2.19.1) Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.17.2 to 2.19.1 --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-version: 2.19.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-version: 2.19.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-version: 2.19.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5f862eb2c..e86602f2f 100644 --- a/pom.xml +++ b/pom.xml @@ -83,7 +83,7 @@ <maven.deploy.plugin.version>3.1.2</maven.deploy.plugin.version> <log4j.version>2.24.3</log4j.version> <slf4j.version>2.0.7</slf4j.version> - <jackson.version>2.17.2</jackson.version> + <jackson.version>2.19.1</jackson.version> <aws.sdk.version>2.31.78</aws.sdk.version> <aws.xray.recorder.version>2.18.2</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> From 0d478de8a3da89e1b8da31136d997b466daef8f7 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Fri, 11 Jul 2025 11:28:26 +0200 Subject: [PATCH 276/577] build(deps): Upgrade DynamoDBLocal to 2.6.0 (#1931) * Upgrade DynamoDBLocal to 2.6.0 * Downgrade DynamoDBLocal to 2.2.0 to keep Java11 support --- docs/utilities/idempotency.md | 4 +++- .../powertools-idempotency-dynamodb/pom.xml | 12 +++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index 3953949d1..83f256e6b 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -983,7 +983,9 @@ To unit test your function with DynamoDB Local, you can refer to this guide to [ <dependency> <groupId>com.amazonaws</groupId> <artifactId>DynamoDBLocal</artifactId> - <version>[1.12,2.0)</version> + <!-- Use newest version if you are on Java >11 --> + <!-- https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocalHistory.html --> + <version>2.2.0</version> <scope>test</scope> </dependency> <!-- Needed when building locally on M1 Mac --> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index 4ae37f00c..4dd59a476 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -14,8 +14,8 @@ --> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xmlns="http://maven.apache.org/POM/4.0.0" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -62,7 +62,9 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>DynamoDBLocal</artifactId> - <version>[1.12,2.0)</version> + <!-- >2.2.0 is not compatible with Java 11 anymore --> + <!-- https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocalHistory.html --> + <version>2.2.0</version> <scope>test</scope> </dependency> <!--Needed when building locally on M1 Mac--> @@ -85,7 +87,7 @@ <manifestEntries> <Automatic-Module-Name>software.amazon.awssdk.enhanced.dynamodb</Automatic-Module-Name> </manifestEntries> - </archive> + </archive> </configuration> </plugin> <plugin> @@ -123,4 +125,4 @@ </plugin> </plugins> </build> -</project> \ No newline at end of file +</project> From 22b8e6cf9c56d44665d991adb591b510432d023a Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Fri, 11 Jul 2025 11:53:08 +0200 Subject: [PATCH 277/577] build(deps): Upgrade logback. (#1933) --- powertools-logging/powertools-logging-logback/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index cb2054b87..d729dba23 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -28,11 +28,11 @@ <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> - <version>1.5.7</version> + <version>1.5.18</version> <exclusions> <exclusion> <groupId>com.sun.mail</groupId> - <artifactId>javax.mail</artifactId> + <artifactId>javax.mail</artifactId> </exclusion> </exclusions> </dependency> From 0f3615079699e2bff01cae9098858d6e2ae1ad27 Mon Sep 17 00:00:00 2001 From: Jeroen Reijn <j.reijn@gmail.com> Date: Fri, 11 Jul 2025 13:07:34 +0200 Subject: [PATCH 278/577] feat(serialization): Add GraalVM metadata configuration (#1905) * feat(serialization): Add graalvm metadata. Move metadata for tests to test package. * feat(serialization): Split SAM and SAM native example * feat(serialization): Update documentation and makefile * feat(serialization): Bump version * Update examples/powertools-examples-serialization/sam-graalvm/README.md Fix documentation url Co-authored-by: Philipp Page <philipp.page@yahoo.de> * Update examples/powertools-examples-serialization/sam-graalvm/README.md Made URL for curl command generic instead of containing specific ids or regions Co-authored-by: Philipp Page <philipp.page@yahoo.de> * feat(serialization): Bump lambda-java-core and runtime-interface to match other dependencies * feat(serialization): Update metadata to reflect new lambda-java-runtime-client changes --------- Co-authored-by: Philipp Page <philipp.page@yahoo.de> --- examples/pom.xml | 3 +- .../sam-graalvm/Dockerfile | 14 +++ .../sam-graalvm/Makefile | 13 ++ .../sam-graalvm/README.md | 111 ++++++++++++++++++ .../events/APIGatewayEvent.json | 0 .../{ => sam-graalvm}/events/SQSEvent.json | 0 .../sam-graalvm/pom.xml | 89 ++++++++++++++ .../sam-graalvm/src/main/config/bootstrap | 4 + ...GatewayRequestDeserializationFunction.java | 0 .../java/org/demo/serialization/Product.java | 0 .../SQSEventDeserializationFunction.java | 0 .../aws-lambda-java-core/reflect-config.json | 13 ++ .../reflect-config.json | 35 ++++++ .../jni-config.json | 11 ++ .../native-image.properties | 1 + .../reflect-config.json | 38 ++++++ .../resource-config.json | 19 +++ .../reflect-config.json | 25 ++++ .../helloworld/native-image.properties | 3 + .../helloworld/reflect-config.json | 29 +++++ .../helloworld/resource-config.json | 7 ++ .../src/main/resources/log4j2.xml | 0 .../sam-graalvm/template.yaml | 64 ++++++++++ .../{ => sam}/README.md | 2 +- .../sam/events/APIGatewayEvent.json | 63 ++++++++++ .../sam/events/SQSEvent.json | 39 ++++++ .../{ => sam}/pom.xml | 2 +- ...GatewayRequestDeserializationFunction.java | 53 +++++++++ .../java/org/demo/serialization/Product.java | 63 ++++++++++ .../SQSEventDeserializationFunction.java | 40 +++++++ .../sam/src/main/resources/log4j2.xml | 16 +++ .../{ => sam}/template.yaml | 0 powertools-serialization/pom.xml | 38 +++--- .../powertools-serialization/jni-config.json | 18 --- .../reflect-config.json | 45 +------ .../resource-config.json | 32 +---- .../reflect-config.json | 45 +++++++ .../resource-config.json | 51 ++++++++ 38 files changed, 873 insertions(+), 113 deletions(-) create mode 100644 examples/powertools-examples-serialization/sam-graalvm/Dockerfile create mode 100644 examples/powertools-examples-serialization/sam-graalvm/Makefile create mode 100644 examples/powertools-examples-serialization/sam-graalvm/README.md rename examples/powertools-examples-serialization/{ => sam-graalvm}/events/APIGatewayEvent.json (100%) rename examples/powertools-examples-serialization/{ => sam-graalvm}/events/SQSEvent.json (100%) create mode 100644 examples/powertools-examples-serialization/sam-graalvm/pom.xml create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/config/bootstrap rename examples/powertools-examples-serialization/{ => sam-graalvm}/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java (100%) rename examples/powertools-examples-serialization/{ => sam-graalvm}/src/main/java/org/demo/serialization/Product.java (100%) rename examples/powertools-examples-serialization/{ => sam-graalvm}/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java (100%) create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json create mode 100644 examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json rename examples/powertools-examples-serialization/{ => sam-graalvm}/src/main/resources/log4j2.xml (100%) create mode 100644 examples/powertools-examples-serialization/sam-graalvm/template.yaml rename examples/powertools-examples-serialization/{ => sam}/README.md (97%) create mode 100644 examples/powertools-examples-serialization/sam/events/APIGatewayEvent.json create mode 100644 examples/powertools-examples-serialization/sam/events/SQSEvent.json rename examples/powertools-examples-serialization/{ => sam}/pom.xml (96%) create mode 100644 examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java create mode 100644 examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/Product.java create mode 100644 examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java create mode 100644 examples/powertools-examples-serialization/sam/src/main/resources/log4j2.xml rename examples/powertools-examples-serialization/{ => sam}/template.yaml (100%) delete mode 100644 powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/jni-config.json create mode 100644 powertools-serialization/src/test/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json create mode 100644 powertools-serialization/src/test/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json diff --git a/examples/pom.xml b/examples/pom.xml index cd076d099..2487a4d14 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -38,7 +38,8 @@ <module>powertools-examples-idempotency</module> <module>powertools-examples-parameters/sam</module> <module>powertools-examples-parameters/sam-graalvm</module> - <module>powertools-examples-serialization</module> + <module>powertools-examples-serialization/sam</module> + <module>powertools-examples-serialization/sam-graalvm</module> <module>powertools-examples-kafka</module> <module>powertools-examples-batch</module> <module>powertools-examples-validation</module> diff --git a/examples/powertools-examples-serialization/sam-graalvm/Dockerfile b/examples/powertools-examples-serialization/sam-graalvm/Dockerfile new file mode 100644 index 000000000..a690606ad --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/Dockerfile @@ -0,0 +1,14 @@ +#Use the official AWS SAM base image for Java 21 +FROM public.ecr.aws/sam/build-java21:latest + +#Install GraalVM dependencies +RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz +RUN mv graalvm-jdk-21.* /usr/lib/graalvm + +#Make native image and mvn available on CLI +RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image +RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn + +#Set GraalVM as default +ENV JAVA_HOME=/usr/lib/graalvm +ENV PATH=/usr/lib/graalvm/bin:$PATH diff --git a/examples/powertools-examples-serialization/sam-graalvm/Makefile b/examples/powertools-examples-serialization/sam-graalvm/Makefile new file mode 100644 index 000000000..304b66239 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/Makefile @@ -0,0 +1,13 @@ +build-APIGatewayDeserializationFunction: + mvn clean package -P native-image + chmod +x target/hello-world + cp target/hello-world $(ARTIFACTS_DIR) # (ARTIFACTS_DIR --> https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/custom_make/DESIGN.md#implementation) + chmod +x src/main/config/bootstrap + cp src/main/config/bootstrap $(ARTIFACTS_DIR) + +build-SQSEventDeserializationFunction: + mvn clean package -P native-image + chmod +x target/hello-world + cp target/hello-world $(ARTIFACTS_DIR) # (ARTIFACTS_DIR --> https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/custom_make/DESIGN.md#implementation) + chmod +x src/main/config/bootstrap + cp src/main/config/bootstrap $(ARTIFACTS_DIR) diff --git a/examples/powertools-examples-serialization/sam-graalvm/README.md b/examples/powertools-examples-serialization/sam-graalvm/README.md new file mode 100644 index 000000000..01be98085 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/README.md @@ -0,0 +1,111 @@ +# Powertools for AWS Lambda (Java) - Serialization Example + +This project contains an example of Lambda function using the serialization utilities module of Powertools for AWS Lambda (Java). For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda-java/latest/utilities/serialization/). + +The project contains two `RequestHandler`s - + +* [APIGatewayRequestDeserializationFunction](src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java) - Uses the serialization library to deserialize an API Gateway request body +* [SQSEventDeserializationFunction](src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java) - Uses the serialization library to deserialize an SQS message body + +In both cases, the output of the serialized message will be printed to the function logs. The message format +in JSON looks like this: + +```json +{ + "id":1234, + "name":"product", + "price":42 +} +``` + +## Deploy the sample application + +This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting +started with SAM in [the examples directory](../../README.md) + +## Configuration + +- Set the environment to use GraalVM + +```shell +export JAVA_HOME=<path to GraalVM> +``` + +## Build the sample application + +- Build the Docker image that will be used as the environment for SAM build: + +```shell +docker build --platform linux/amd64 . -t powertools-examples-serialization-sam-graalvm +``` + +- Build the SAM project using the docker image + +```shell +sam build --use-container --build-image powertools-examples-serialization-sam-graalvm +``` + +#### [Optional] Building with -SNAPSHOT versions of PowerTools + +- If you are testing the example with a -SNAPSHOT version of PowerTools, the maven build inside the docker image will fail. This is because the -SNAPSHOT version of the PowerTools library that you are working on is still not available in maven central/snapshot repository. + To get around this, follow these steps: + - Create the native image using the `docker` command below on your development machine. The native image is created in the `target` directory. + - `` docker run --platform linux/amd64 -it -v `pwd`:`pwd` -w `pwd` -v ~/.m2:/root/.m2 powertools-examples-serialization-sam-graalvm mvn clean -Pnative-image package -DskipTests `` + - Edit the [`Makefile`](Makefile) remove this line + - `mvn clean package -P native-image` + - Build the SAM project using the docker image + - `sam build --use-container --build-image powertools-examples-serialization-sam-graalvm` + + +## Test the application + +### 1. API Gateway Endpoint + +To test the HTTP endpoint, we can post a product to the test URL: + +```bash +curl -X POST https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/product/ -H "Content-Type: application/json" -d '{"id": 1234, "name": "product", "price": 42}' +``` + +The result will indicate that the handler has successfully deserialized the request body: + +``` +Received request for productId: 1234 +``` + +If we look at the logs using `sam logs --tail --stack-name $MY_STACK`, we will see the full deserialized request: + +```json +{ + ... + "level": "INFO", + "loggerName": "org.demo.serialization.APIGatewayRequestDeserializationFunction", + "message": "product=Product{id=1234, name='product', price=42.0}\n", + ... +} +``` + +### 2. SQS Queue +For the SQS handler, we have to send a request to our queue. We can either construct the Queue URL (see below), or +find it from the SQS section of the AWS console. + +```bash + aws sqs send-message --queue-url "https://sqs.[REGION].amazonaws.com/[ACCOUNT-ID]/sqs-event-deserialization-queue" --message-body '{"id": 1234, "name": "product", "price": 123}' +``` + +Here we can find the message by filtering through the logs for messages that have come back from our SQS handler: + +```bash +sam logs --tail --stack-name $MY_STACK --filter SQS +``` + +```bash + { + ... + "level": "INFO", + "loggerName": "org.demo.serialization.SQSEventDeserializationFunction", + "message": "products=[Product{id=1234, name='product', price=42.0}]\n", + ... +} + +``` diff --git a/examples/powertools-examples-serialization/events/APIGatewayEvent.json b/examples/powertools-examples-serialization/sam-graalvm/events/APIGatewayEvent.json similarity index 100% rename from examples/powertools-examples-serialization/events/APIGatewayEvent.json rename to examples/powertools-examples-serialization/sam-graalvm/events/APIGatewayEvent.json diff --git a/examples/powertools-examples-serialization/events/SQSEvent.json b/examples/powertools-examples-serialization/sam-graalvm/events/SQSEvent.json similarity index 100% rename from examples/powertools-examples-serialization/events/SQSEvent.json rename to examples/powertools-examples-serialization/sam-graalvm/events/SQSEvent.json diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml new file mode 100644 index 000000000..370a3ec60 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -0,0 +1,89 @@ +<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 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>software.amazon.lambda.examples</groupId> + <version>2.1.1</version> + <artifactId>powertools-examples-serialization-sam-graalvm</artifactId> + <packaging>jar</packaging> + <name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name> + + <properties> + <maven.compiler.source>11</maven.compiler.source> + <maven.compiler.target>11</maven.compiler.target> + </properties> + + <dependencies> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging-log4j</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-serialization</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + <version>1.3.0</version> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-events</artifactId> + <version>3.16.0</version> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + <version>2.8.2</version> + </dependency> + </dependencies> + + <build> + <plugins> + <!-- Don't deploy the example --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <version>3.1.2</version> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + <version>0.10.1</version> + <extensions>true</extensions> + <executions> + <execution> + <id>build-native</id> + <goals> + <goal>build</goal> + </goals> + <phase>package</phase> + </execution> + </executions> + <configuration> + <imageName>hello-world</imageName> + <mainClass>com.amazonaws.services.lambda.runtime.api.client.AWSLambda</mainClass> + <buildArgs> + <!-- required for AWS Lambda Runtime Interface Client --> + <arg>--enable-url-protocols=http</arg> + <arg>--add-opens java.base/java.util=ALL-UNNAMED</arg> + </buildArgs> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/config/bootstrap b/examples/powertools-examples-serialization/sam-graalvm/src/main/config/bootstrap new file mode 100644 index 000000000..8e7928cd3 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/config/bootstrap @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +./hello-world $_HANDLER \ No newline at end of file diff --git a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java b/examples/powertools-examples-serialization/sam-graalvm/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java similarity index 100% rename from examples/powertools-examples-serialization/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java rename to examples/powertools-examples-serialization/sam-graalvm/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java diff --git a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/Product.java b/examples/powertools-examples-serialization/sam-graalvm/src/main/java/org/demo/serialization/Product.java similarity index 100% rename from examples/powertools-examples-serialization/src/main/java/org/demo/serialization/Product.java rename to examples/powertools-examples-serialization/sam-graalvm/src/main/java/org/demo/serialization/Product.java diff --git a/examples/powertools-examples-serialization/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java b/examples/powertools-examples-serialization/sam-graalvm/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java similarity index 100% rename from examples/powertools-examples-serialization/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java rename to examples/powertools-examples-serialization/sam-graalvm/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..962962055 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,38 @@ +[ + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"<init>","parameterTypes":[] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields":[{"name":"logger"}] + }, + { + "name":"java.lang.Void", + "methods":[{"name":"<init>","parameterTypes":[] }] + }, + { + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] + }, + { + "name":"jdk.internal.module.IllegalAccessLogger", + "fields":[{"name":"logger"}] + }, + { + "name":"sun.misc.Unsafe", + "fields":[{"name":"theUnsafe"}] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + }, + { + "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", + "fields":[{"name":"IS_COLD_START"},{"name":"SERVICE_NAME"}] + } +] \ No newline at end of file diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties new file mode 100644 index 000000000..a2249e17d --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/native-image.properties @@ -0,0 +1,3 @@ +Args = --enable-url-protocols=http,https \ +--initialize-at-run-time=\ + software.amazon.lambda.powertools.core.internal.LambdaHandlerProcessor \ No newline at end of file diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json new file mode 100644 index 000000000..e35ca7c4f --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json @@ -0,0 +1,29 @@ +[ + { + "name": "org.demo.serialization.APIGatewayRequestDeserializationFunction", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "org.demo.serialization.Product", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "org.demo.serialization.SQSEventDeserializationFunction", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/examples/powertools-examples-serialization/src/main/resources/log4j2.xml b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/log4j2.xml similarity index 100% rename from examples/powertools-examples-serialization/src/main/resources/log4j2.xml rename to examples/powertools-examples-serialization/sam-graalvm/src/main/resources/log4j2.xml diff --git a/examples/powertools-examples-serialization/sam-graalvm/template.yaml b/examples/powertools-examples-serialization/sam-graalvm/template.yaml new file mode 100644 index 000000000..39fd22928 --- /dev/null +++ b/examples/powertools-examples-serialization/sam-graalvm/template.yaml @@ -0,0 +1,64 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + serialization utils demo + +Globals: + Function: + Timeout: 20 + MemorySize: 512 + Tracing: Active + + +Resources: + APIGatewayDeserializationFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: org.demo.serialization.APIGatewayRequestDeserializationFunction::handleRequest + Runtime: provided.al2023 + Events: + Product: + Type: Api + Properties: + Path: /product + Method: post + + DemoSqsQueue: + Type: AWS::SQS::Queue + Properties: + QueueName: "sqs-event-deserialization-queue" + + SQSEventDeserializationFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: org.demo.serialization.SQSEventDeserializationFunction::handleRequest + Runtime: provided.al2023 + Policies: + - Statement: + - Sid: SQSSendMessageBatch + Effect: Allow + Action: + - sqs:SendMessageBatch + - sqs:SendMessage + Resource: !GetAtt DemoSqsQueue.Arn + Events: + SQSEvent: + Type: SQS + Properties: + Queue: !GetAtt DemoSqsQueue.Arn + BatchSize: 2 + MaximumBatchingWindowInSeconds: 30 + + +Outputs: + Api: + Description: "API Gateway endpoint URL for Prod stage for Serialization function" + Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/product/" + Function: + Description: "Serialization Lambda Function ARN" + Value: !GetAtt APIGatewayDeserializationFunction.Arn + DemoSqsQueue: + Description: "ARN for SQS queue" + Value: !GetAtt DemoSqsQueue.Arn \ No newline at end of file diff --git a/examples/powertools-examples-serialization/README.md b/examples/powertools-examples-serialization/sam/README.md similarity index 97% rename from examples/powertools-examples-serialization/README.md rename to examples/powertools-examples-serialization/sam/README.md index 4e3f66eb0..247752f29 100644 --- a/examples/powertools-examples-serialization/README.md +++ b/examples/powertools-examples-serialization/sam/README.md @@ -21,7 +21,7 @@ in JSON looks like this: ## Deploy the sample application This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting -started with SAM in [the examples directory](../README.md) +started with SAM in [the examples directory](../../README.md) ## Test the application diff --git a/examples/powertools-examples-serialization/sam/events/APIGatewayEvent.json b/examples/powertools-examples-serialization/sam/events/APIGatewayEvent.json new file mode 100644 index 000000000..cb38a3429 --- /dev/null +++ b/examples/powertools-examples-serialization/sam/events/APIGatewayEvent.json @@ -0,0 +1,63 @@ +{ + "body": "{\"id\":1234, \"name\":\"product\", \"price\":42}", + "resource": "/{proxy+}", + "path": "/path/to/resource", + "httpMethod": "POST", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/path/to/resource", + "resourcePath": "/{proxy+}", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } + } + \ No newline at end of file diff --git a/examples/powertools-examples-serialization/sam/events/SQSEvent.json b/examples/powertools-examples-serialization/sam/events/SQSEvent.json new file mode 100644 index 000000000..9056d3ef2 --- /dev/null +++ b/examples/powertools-examples-serialization/sam/events/SQSEvent.json @@ -0,0 +1,39 @@ +{ + "Records": [ + { + "messageId": "d9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "13e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{ \"id\": 1234, \"name\": \"product\", \"price\": 42}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + }, + "md5OfBody": "13e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + }, + { + "messageId": "d9144555-9a4f-4ec3-99a0-34ce359b4b54", + "receiptHandle": "13e7f7851d2eaa5c01f208ebadbf1e72==", + "body": "{ \"id\": 12345, \"name\": \"product5\", \"price\": 45}", + "attributes": { + "ApproximateReceiveCount": "1", + "SentTimestamp": "1601975706495", + "SenderId": "AROAIFU437PVZ5L2J53F5", + "ApproximateFirstReceiveTimestamp": "1601975706499" + }, + "messageAttributes": { + + }, + "md5OfBody": "13e7f7851d2eaa5c01f208ebadbf1e72", + "eventSource": "aws:sqs", + "eventSourceARN": "arn:aws:sqs:eu-central-1:123456789012:TestLambda", + "awsRegion": "eu-central-1" + } + ] +} \ No newline at end of file diff --git a/examples/powertools-examples-serialization/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml similarity index 96% rename from examples/powertools-examples-serialization/pom.xml rename to examples/powertools-examples-serialization/sam/pom.xml index bd249bb25..8c17b2a86 100644 --- a/examples/powertools-examples-serialization/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <version>2.1.1</version> - <artifactId>powertools-examples-serialization</artifactId> + <artifactId>powertools-examples-serialization-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization</name> diff --git a/examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java b/examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java new file mode 100644 index 000000000..3ca75cf4a --- /dev/null +++ b/examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/APIGatewayRequestDeserializationFunction.java @@ -0,0 +1,53 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.demo.serialization; + +import static software.amazon.lambda.powertools.utilities.EventDeserializer.extractDataFrom; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import java.util.HashMap; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class APIGatewayRequestDeserializationFunction + implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(APIGatewayRequestDeserializationFunction.class); + private static final Map<String, String> HEADERS = new HashMap<String, String>() { + private static final long serialVersionUID = 7074189990115081999L; + { + put("Content-Type", "application/json"); + put("X-Custom-Header", "application/json"); + } + }; + + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) { + + Product product = extractDataFrom(event).as(Product.class); + LOGGER.info("\n=============== Deserialized request body: ==============="); + LOGGER.info("product={}\n", product); + + return new APIGatewayProxyResponseEvent() + .withHeaders(HEADERS) + .withStatusCode(200) + .withBody("Received request for productId: " + product.getId()); + } +} + diff --git a/examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/Product.java b/examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/Product.java new file mode 100644 index 000000000..25bae34f6 --- /dev/null +++ b/examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/Product.java @@ -0,0 +1,63 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.demo.serialization; + +public class Product { + private long id; + private String name; + private double price; + + public Product() { + } + + public Product(long id, String name, double price) { + this.id = id; + this.name = name; + this.price = price; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + @Override + public String toString() { + return "Product{" + + "id=" + id + + ", name='" + name + '\'' + + ", price=" + price + + '}'; + } +} diff --git a/examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java b/examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java new file mode 100644 index 000000000..79097e19c --- /dev/null +++ b/examples/powertools-examples-serialization/sam/src/main/java/org/demo/serialization/SQSEventDeserializationFunction.java @@ -0,0 +1,40 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.demo.serialization; + +import static software.amazon.lambda.powertools.utilities.EventDeserializer.extractDataFrom; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class SQSEventDeserializationFunction implements RequestHandler<SQSEvent, String> { + + private static final Logger LOGGER = LoggerFactory.getLogger(SQSEventDeserializationFunction.class); + + public String handleRequest(SQSEvent event, Context context) { + List<Product> products = extractDataFrom(event).asListOf(Product.class); + + LOGGER.info("\n=============== Deserialized messages: ==============="); + LOGGER.info("products={}\n", products); + + return "Number of received messages: " + products.size(); + } +} + diff --git a/examples/powertools-examples-serialization/sam/src/main/resources/log4j2.xml b/examples/powertools-examples-serialization/sam/src/main/resources/log4j2.xml new file mode 100644 index 000000000..fe943d707 --- /dev/null +++ b/examples/powertools-examples-serialization/sam/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration packages="com.amazonaws.services.lambda.runtime.log4j2"> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + </Appenders> + <Loggers> + <Logger name="JsonLogger" level="INFO" additivity="false"> + <AppenderRef ref="JsonAppender"/> + </Logger> + <Root level="info"> + <AppenderRef ref="JsonAppender"/> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/examples/powertools-examples-serialization/template.yaml b/examples/powertools-examples-serialization/sam/template.yaml similarity index 100% rename from examples/powertools-examples-serialization/template.yaml rename to examples/powertools-examples-serialization/sam/template.yaml diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 891a1582a..bb2f0fb34 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -70,6 +70,26 @@ <scope>test</scope> </dependency> </dependencies> + + <build> + <resources> + <!-- GraalVM Native Image Configuration Files --> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + <plugins> + <plugin> + <groupId>dev.aspectj</groupId> + <artifactId>aspectj-maven-plugin</artifactId> + <version>${aspectj-maven-plugin.version}</version> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> + <profiles> <profile> <id>generate-graalvm-files</id> @@ -159,23 +179,5 @@ </build> </profile> </profiles> - <build> - <resources> - <!-- GraalVM Native Image Configuration Files --> - <resource> - <directory>src/main/resources</directory> - </resource> - </resources> - <plugins> - <plugin> - <groupId>dev.aspectj</groupId> - <artifactId>aspectj-maven-plugin</artifactId> - <version>${aspectj-maven-plugin.version}</version> - <configuration> - <skip>true</skip> - </configuration> - </plugin> - </plugins> - </build> </project> diff --git a/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/jni-config.json b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/jni-config.json deleted file mode 100644 index 079c02a4d..000000000 --- a/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/jni-config.json +++ /dev/null @@ -1,18 +0,0 @@ -[ -{ - "name":"java.lang.String", - "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] -}, -{ - "name":"java.lang.System", - "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] -}, -{ - "name":"org.apache.maven.surefire.booter.ForkedBooter", - "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] -}, -{ - "name":"sun.management.VMManagementImpl", - "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] -} -] diff --git a/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json index 1a4f89735..e20bd748f 100644 --- a/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json +++ b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json @@ -309,7 +309,7 @@ "allDeclaredFields":true, "queryAllDeclaredMethods":true, "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"setAttributes","parameterTypes":["java.util.Map"] }, {"name":"setAwsRegion","parameterTypes":["java.lang.String"] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setEventSource","parameterTypes":["java.lang.String"] }, {"name":"setEventSourceArn","parameterTypes":["java.lang.String"] }, {"name":"setMd5OfBody","parameterTypes":["java.lang.String"] }, {"name":"setMessageAttributes","parameterTypes":["java.util.Map"] }, {"name":"setMessageId","parameterTypes":["java.lang.String"] }, {"name":"setReceiptHandle","parameterTypes":["java.lang.String"] }] + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"setAttributes","parameterTypes":["java.util.Map"] }, {"name":"setAwsRegion","parameterTypes":["java.lang.String"] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setEventSource","parameterTypes":["java.lang.String"] }, {"name":"setEventSourceArn","parameterTypes":["java.lang.String"] }, {"name":"setMd5OfBody","parameterTypes":["java.lang.String"] }, {"name":"setMd5OfMessageAttributes","parameterTypes":["java.lang.String"] },{"name":"setMessageAttributes","parameterTypes":["java.util.Map"] }, {"name":"setMessageId","parameterTypes":["java.lang.String"] }, {"name":"setReceiptHandle","parameterTypes":["java.lang.String"] }] }, { "name":"com.amazonaws.services.lambda.runtime.events.ScheduledEvent", @@ -423,48 +423,5 @@ { "name":"org.joda.time.DateTime", "methods":[{"name":"parse","parameterTypes":["java.lang.String"] }] -}, -{ - "name":"software.amazon.lambda.powertools.utilities.EventDeserializerTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"testDeserializeALBEventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent"] }, {"name":"testDeserializeAMQEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ActiveMQEvent"] }, {"name":"testDeserializeAPIGWEventBodyAsObject_shouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent"] }, {"name":"testDeserializeAPIGatewayEventAsList_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent"] }, {"name":"testDeserializeAPIGatewayMapEventAsList_shouldThrowException","parameterTypes":["java.util.Map"] }, {"name":"testDeserializeAPIGatewayNoBodyAsList_shouldThrowException","parameterTypes":[] }, {"name":"testDeserializeAPIGatewayNoBody_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent"] }, {"name":"testDeserializeApiGWV2EventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent"] }, {"name":"testDeserializeCWLEventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.CloudWatchLogsEvent"] }, {"name":"testDeserializeCfcrEventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent"] }, {"name":"testDeserializeEmptyEventAsList_shouldThrowException","parameterTypes":[] }, {"name":"testDeserializeKFEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent"] }, {"name":"testDeserializeKafipEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsFirehoseInputPreprocessingEvent"] }, {"name":"testDeserializeKafkaEventMessageAsList_shouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KafkaEvent"] }, {"name":"testDeserializeKasipEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsStreamsInputPreprocessingEvent"] }, {"name":"testDeserializeKinesisEventMessageAsList_shouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisEvent"] }, {"name":"testDeserializeMapAsObject_shouldReturnObject","parameterTypes":[] }, {"name":"testDeserializeProductAsProduct_shouldReturnProduct","parameterTypes":[] }, {"name":"testDeserializeRabbitMQEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.RabbitMQEvent"] }, {"name":"testDeserializeSNSEventMessageAsObject_shouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SNSEvent"] }, {"name":"testDeserializeSQSEventMessageAsList_shouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent"] }, {"name":"testDeserializeSQSEventMessageAsObject_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent"] }, {"name":"testDeserializeSQSEventNoBody_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent"] }, {"name":"testDeserializeScheduledEventMessageAsObject_shouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ScheduledEvent"] }, {"name":"testDeserializeStringArrayAsList_shouldReturnList","parameterTypes":[] }, {"name":"testDeserializeStringAsList_shouldThrowException","parameterTypes":[] }, {"name":"testDeserializeStringAsObject_shouldReturnObject","parameterTypes":[] }, {"name":"testDeserializeStringAsString_shouldReturnString","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.utilities.jmespath.Base64FunctionTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"testPowertoolsBase64","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunctionTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"testBase64GzipDecompressNull","parameterTypes":[] }, {"name":"testConstructor","parameterTypes":[] }, {"name":"testPowertoolsGzip","parameterTypes":[] }, {"name":"testPowertoolsGzipEmptyJsonAttribute","parameterTypes":[] }, {"name":"testPowertoolsGzipNotCompressedJsonAttribute","parameterTypes":[] }, {"name":"testPowertoolsGzipWrongArgumentType","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.utilities.jmespath.JsonFunctionTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"testJsonFunction","parameterTypes":[] }, {"name":"testJsonFunctionChild","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.utilities.model.Product", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"setId","parameterTypes":["long"] }, {"name":"setName","parameterTypes":["java.lang.String"] }, {"name":"setPrice","parameterTypes":["double"] }] } ] diff --git a/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json index d5bd7e14c..58b01cd07 100644 --- a/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json +++ b/powertools-serialization/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json @@ -6,36 +6,10 @@ "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" }, { "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" - }, { - "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" - }, { - "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.engine.TestEngine\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherDiscoveryListener\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherSessionListener\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.PostDiscoveryFilter\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.TestExecutionListener\\E" }, { "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" }, { - "pattern":"\\Qalb_event.json\\E" - }, { - "pattern":"\\Qamq_event.json\\E" - }, { - "pattern":"\\Qapigw_event.json\\E" - }, { - "pattern":"\\Qapigw_event_no_body.json\\E" - }, { - "pattern":"\\Qapigwv2_event.json\\E" - }, { - "pattern":"\\Qcfcr_event.json\\E" - }, { - "pattern":"\\Qcom/amazonaws/lambda/thirdparty/org/joda/time/tz/data/Europe/Berlin\\E" + "pattern":"\\Qcom/amazonaws/lambda/thirdparty/org/joda/time/tz/data/Europe/Amsterdam\\E" }, { "pattern":"\\Qcom/amazonaws/lambda/thirdparty/org/joda/time/tz/data/ZoneInfoMap\\E" }, { @@ -75,11 +49,9 @@ }, { "pattern":"\\Qcom/amazonaws/services/lambda/runtime/serialization/factories/sqs_event_no_body.json\\E" }, { - "pattern":"\\Qorg/joda/time/tz/data/Europe/Berlin\\E" + "pattern":"\\Qorg/joda/time/tz/data/Europe/Amsterdam\\E" }, { "pattern":"\\Qorg/joda/time/tz/data/ZoneInfoMap\\E" - }, { - "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" }]}, "bundles":[] } diff --git a/powertools-serialization/src/test/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json b/powertools-serialization/src/test/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json new file mode 100644 index 000000000..b781d2609 --- /dev/null +++ b/powertools-serialization/src/test/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/reflect-config.json @@ -0,0 +1,45 @@ +[ +{ + "name":"software.amazon.lambda.powertools.utilities.EventDeserializerTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"testDeserializeALBEventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent"] }, {"name":"testDeserializeAMQEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ActiveMQEvent"] }, {"name":"testDeserializeAPIGWEventBodyAsObject_shouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent"] }, {"name":"testDeserializeAPIGatewayEventAsList_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent"] }, {"name":"testDeserializeAPIGatewayMapEventAsList_shouldThrowException","parameterTypes":["java.util.Map"] }, {"name":"testDeserializeAPIGatewayNoBodyAsList_shouldThrowException","parameterTypes":[] }, {"name":"testDeserializeAPIGatewayNoBody_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent"] }, {"name":"testDeserializeApiGWV2EventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent"] }, {"name":"testDeserializeCWLEventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.CloudWatchLogsEvent"] }, {"name":"testDeserializeCfcrEventMessageAsObjectShouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent"] }, {"name":"testDeserializeEmptyEventAsList_shouldThrowException","parameterTypes":[] }, {"name":"testDeserializeKFEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent"] }, {"name":"testDeserializeKafipEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsFirehoseInputPreprocessingEvent"] }, {"name":"testDeserializeKafkaEventMessageAsList_shouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KafkaEvent"] }, {"name":"testDeserializeKasipEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsStreamsInputPreprocessingEvent"] }, {"name":"testDeserializeKinesisEventMessageAsList_shouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.KinesisEvent"] }, {"name":"testDeserializeMapAsObject_shouldReturnObject","parameterTypes":[] }, {"name":"testDeserializeProductAsProduct_shouldReturnProduct","parameterTypes":[] }, {"name":"testDeserializeRabbitMQEventMessageAsListShouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.RabbitMQEvent"] }, {"name":"testDeserializeSNSEventMessageAsObject_shouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SNSEvent"] }, {"name":"testDeserializeSQSEventMessageAsList_shouldReturnList","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent"] }, {"name":"testDeserializeSQSEventMessageAsObject_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent"] }, {"name":"testDeserializeSQSEventNoBody_shouldThrowException","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent"] }, {"name":"testDeserializeScheduledEventMessageAsObject_shouldReturnObject","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ScheduledEvent"] }, {"name":"testDeserializeStringArrayAsList_shouldReturnList","parameterTypes":[] }, {"name":"testDeserializeStringAsList_shouldThrowException","parameterTypes":[] }, {"name":"testDeserializeStringAsObject_shouldReturnObject","parameterTypes":[] }, {"name":"testDeserializeStringAsString_shouldReturnString","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.utilities.jmespath.Base64FunctionTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"testPowertoolsBase64","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunctionTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"testBase64GzipDecompressNull","parameterTypes":[] }, {"name":"testConstructor","parameterTypes":[] }, {"name":"testPowertoolsGzip","parameterTypes":[] }, {"name":"testPowertoolsGzipEmptyJsonAttribute","parameterTypes":[] }, {"name":"testPowertoolsGzipNotCompressedJsonAttribute","parameterTypes":[] }, {"name":"testPowertoolsGzipWrongArgumentType","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.utilities.jmespath.JsonFunctionTest", + "allDeclaredFields":true, + "allDeclaredClasses":true, + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"testJsonFunction","parameterTypes":[] }, {"name":"testJsonFunctionChild","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.utilities.model.Product", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"setId","parameterTypes":["long"] }, {"name":"setName","parameterTypes":["java.lang.String"] }, {"name":"setPrice","parameterTypes":["double"] }] +} +] diff --git a/powertools-serialization/src/test/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json b/powertools-serialization/src/test/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json new file mode 100644 index 000000000..986bf5b4a --- /dev/null +++ b/powertools-serialization/src/test/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization/resource-config.json @@ -0,0 +1,51 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qalb_event.json\\E" + }, { + "pattern":"\\Qamq_event.json\\E" + }, { + "pattern":"\\Qapigw_event.json\\E" + }, { + "pattern":"\\Qapigw_event_no_body.json\\E" + }, { + "pattern":"\\Qapigwv2_event.json\\E" + }, { + "pattern":"\\Qcfcr_event.json\\E" + }, { + "pattern":"\\Qcustom_event.json\\E" + }, { + "pattern":"\\Qcustom_event_gzip.json\\E" + }, { + "pattern":"\\Qcustom_event_json.json\\E" + }, { + "pattern":"\\Qcustom_event_map.json\\E" + }, { + "pattern":"\\Qcwl_event.json\\E" + }, { + "pattern":"\\Qjunit-platform.properties\\E" + }, { + "pattern":"\\Qkafip_event.json\\E" + }, { + "pattern":"\\Qkafka_event.json\\E" + }, { + "pattern":"\\Qkasip_event.json\\E" + }, { + "pattern":"\\Qkf_event.json\\E" + }, { + "pattern":"\\Qkinesis_event.json\\E" + }, { + "pattern":"\\Qrabbitmq_event.json\\E" + }, { + "pattern":"\\Qscheduled_event.json\\E" + }, { + "pattern":"\\Qsimplelogger.properties\\E" + }, { + "pattern":"\\Qsns_event.json\\E" + }, { + "pattern":"\\Qsqs_event.json\\E" + }, { + "pattern":"\\Qsqs_event_no_body.json\\E" + }]}, + "bundles":[] +} From f8a9ede9ef41dac2f5b8fb6f690bf9ad41e50366 Mon Sep 17 00:00:00 2001 From: Jeroen Reijn <j.reijn@gmail.com> Date: Fri, 11 Jul 2025 14:02:21 +0200 Subject: [PATCH 279/577] fix(examples): Fix GraalVM metadata after common runtime client changes (#1935) * fix(parameters): Update metadata to reflect new lambda-java-runtime-client changes * fix(core-utilties): Update metadata to reflect new lambda-java-runtime-client changes --- .../jni-config.json | 4 ++-- .../reflect-config.json | 4 ++-- .../resource-config.json | 8 ++++---- .../jni-config.json | 4 ++-- .../reflect-config.json | 4 ++-- .../resource-config.json | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json index d30696750..91be72f7a 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -4,8 +4,8 @@ "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] }, { - "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest", - "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}], + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], "allPublicMethods":true } ] \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index 106edef38..10152cc64 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -27,8 +27,8 @@ "fields":[{"name":"theUnsafe"}] }, { - "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest", - "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}], + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], "allPublicMethods":true } ] \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json index 7cc78a494..1062b4249 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -2,16 +2,16 @@ "resources": { "includes": [ { - "pattern": "\\Qaarch64/aws-lambda-runtime-interface-client.glibc.so\\E" + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" }, { - "pattern": "\\Qaarch64/aws-lambda-runtime-interface-client.musl.so\\E" + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" }, { - "pattern": "\\Qx86_64/aws-lambda-runtime-interface-client.glibc.so\\E" + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" }, { - "pattern": "\\Qx86_64/aws-lambda-runtime-interface-client.musl.so\\E" + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" } ] }, diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json index d30696750..91be72f7a 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -4,8 +4,8 @@ "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] }, { - "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest", - "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}], + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], "allPublicMethods":true } ] \ No newline at end of file diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index 106edef38..10152cc64 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -27,8 +27,8 @@ "fields":[{"name":"theUnsafe"}] }, { - "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest", - "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}], + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], "allPublicMethods":true } ] \ No newline at end of file diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json index 7cc78a494..1062b4249 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -2,16 +2,16 @@ "resources": { "includes": [ { - "pattern": "\\Qaarch64/aws-lambda-runtime-interface-client.glibc.so\\E" + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" }, { - "pattern": "\\Qaarch64/aws-lambda-runtime-interface-client.musl.so\\E" + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" }, { - "pattern": "\\Qx86_64/aws-lambda-runtime-interface-client.glibc.so\\E" + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" }, { - "pattern": "\\Qx86_64/aws-lambda-runtime-interface-client.musl.so\\E" + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" } ] }, From 3a7b67bb21e875135a2d52b12dcb5fab2d670888 Mon Sep 17 00:00:00 2001 From: Vishesh Ruparelia <visheshruparelia18@gmail.com> Date: Fri, 11 Jul 2025 20:22:20 +0530 Subject: [PATCH 280/577] feat(batch): add support for batch execution in parallel with custom Executor (#1900) * feat: add support for batch execution in parallel with custom Executor * pmd_analyse fix * add docs * Update docs/utilities/batch.md Co-authored-by: Philipp Page <philipp.page@yahoo.de> --------- Co-authored-by: Philipp Page <github@philipp.page> Co-authored-by: Philipp Page <philipp.page@yahoo.de> --- docs/utilities/batch.md | 25 +++++++ .../dynamo/DynamoDBStreamBatchHandler.java | 2 +- .../DynamoDBStreamBatchHandlerParallel.java | 37 ++++++++++ .../batch/kinesis/KinesisBatchHandler.java | 2 +- .../kinesis/KinesisBatchHandlerParallel.java | 39 +++++++++++ .../batch/sqs/AbstractSqsBatchHandler.java | 3 +- .../batch/sqs/SqsBatchHandlerParallel.java | 37 ++++++++++ .../batch/handler/BatchMessageHandler.java | 13 ++++ .../handler/DynamoDbBatchMessageHandler.java | 37 ++++++++-- .../KinesisStreamsBatchMessageHandler.java | 37 ++++++++-- .../batch/handler/SqsBatchMessageHandler.java | 48 ++++++++++--- .../batch/internal/MultiThreadMDC.java | 7 ++ .../batch/DdbBatchProcessorTest.java | 70 +++++++++++++++---- .../batch/KinesisBatchProcessorTest.java | 69 ++++++++++++++---- .../batch/SQSBatchProcessorTest.java | 68 ++++++++++++++---- 15 files changed, 425 insertions(+), 69 deletions(-) create mode 100644 examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandlerParallel.java create mode 100644 examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandlerParallel.java create mode 100644 examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandlerParallel.java diff --git a/docs/utilities/batch.md b/docs/utilities/batch.md index 7693ac98f..3f9b6e53d 100644 --- a/docs/utilities/batch.md +++ b/docs/utilities/batch.md @@ -510,6 +510,31 @@ used with SQS FIFO. In that case, an `UnsupportedOperationException` is thrown. } } ``` +=== "Example with SQS (using custom executor)" + + ```java hl_lines="4 10 15" + public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { + + private final BatchMessageHandler<SQSEvent, SQSBatchResponse> handler; + private final ExecutorService executor; + + public SqsBatchHandler() { + handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithMessageHandler(this::processMessage, Product.class); + executor = Executors.newFixedThreadPool(2); + } + + @Override + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + return handler.processBatchInParallel(sqsEvent, context, executor); + } + + private void processMessage(Product p, Context c) { + // Process the product + } + } + ``` ## Handling Messages diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandler.java index e3c27c093..4f27929f0 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandler.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandler.java @@ -25,7 +25,7 @@ public StreamsEventResponse handleRequest(DynamodbEvent ddbEvent, Context contex return handler.processBatch(ddbEvent, context); } - private void processMessage(DynamodbEvent.DynamodbStreamRecord dynamodbStreamRecord, Context context) { + private void processMessage(DynamodbEvent.DynamodbStreamRecord dynamodbStreamRecord) { LOGGER.info("Processing DynamoDB Stream Record" + dynamodbStreamRecord); } diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandlerParallel.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandlerParallel.java new file mode 100644 index 000000000..2e784b795 --- /dev/null +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/dynamo/DynamoDBStreamBatchHandlerParallel.java @@ -0,0 +1,37 @@ +package org.demo.batch.dynamo; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; +import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder; +import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class DynamoDBStreamBatchHandlerParallel implements RequestHandler<DynamodbEvent, StreamsEventResponse> { + + private static final Logger LOGGER = LoggerFactory.getLogger(DynamoDBStreamBatchHandlerParallel.class); + private final BatchMessageHandler<DynamodbEvent, StreamsEventResponse> handler; + private final ExecutorService executor; + + public DynamoDBStreamBatchHandlerParallel() { + handler = new BatchMessageHandlerBuilder() + .withDynamoDbBatchHandler() + .buildWithRawMessageHandler(this::processMessage); + executor = Executors.newFixedThreadPool(2); + } + + @Override + public StreamsEventResponse handleRequest(DynamodbEvent ddbEvent, Context context) { + return handler.processBatchInParallel(ddbEvent, context, executor); + } + + private void processMessage(DynamodbEvent.DynamodbStreamRecord dynamodbStreamRecord) { + LOGGER.info("Processing DynamoDB Stream Record" + dynamodbStreamRecord); + } + +} diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java index f5d7102b5..b7b4f462e 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandler.java @@ -26,7 +26,7 @@ public StreamsEventResponse handleRequest(KinesisEvent kinesisEvent, Context con return handler.processBatch(kinesisEvent, context); } - private void processMessage(Product p, Context c) { + private void processMessage(Product p) { LOGGER.info("Processing product " + p); } diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandlerParallel.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandlerParallel.java new file mode 100644 index 000000000..d7e99e85a --- /dev/null +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/kinesis/KinesisBatchHandlerParallel.java @@ -0,0 +1,39 @@ +package org.demo.batch.kinesis; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.KinesisEvent; +import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; +import org.demo.batch.model.Product; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder; +import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class KinesisBatchHandlerParallel implements RequestHandler<KinesisEvent, StreamsEventResponse> { + + private static final Logger LOGGER = LoggerFactory.getLogger(KinesisBatchHandlerParallel.class); + private final BatchMessageHandler<KinesisEvent, StreamsEventResponse> handler; + private final ExecutorService executor; + + + public KinesisBatchHandlerParallel() { + handler = new BatchMessageHandlerBuilder() + .withKinesisBatchHandler() + .buildWithMessageHandler(this::processMessage, Product.class); + executor = Executors.newFixedThreadPool(2); + } + + @Override + public StreamsEventResponse handleRequest(KinesisEvent kinesisEvent, Context context) { + return handler.processBatchInParallel(kinesisEvent, context, executor); + } + + private void processMessage(Product p) { + LOGGER.info("Processing product " + p); + } + +} diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java index 25dba47bb..ee33b50fd 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java @@ -42,11 +42,10 @@ public class AbstractSqsBatchHandler { /** * Simulate some processing (I/O + S3 put request) * @param p deserialized product - * @param context Lambda context */ @Logging @Tracing - protected void processMessage(Product p, Context context) { + protected void processMessage(Product p) { TracingUtils.putAnnotation("productId", p.getId()); TracingUtils.putAnnotation("Thread", Thread.currentThread().getName()); MDC.put("product", String.valueOf(p.getId())); diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandlerParallel.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandlerParallel.java new file mode 100644 index 000000000..21294dd55 --- /dev/null +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/SqsBatchHandlerParallel.java @@ -0,0 +1,37 @@ +package org.demo.batch.sqs; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import org.demo.batch.model.Product; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.lambda.powertools.batch.BatchMessageHandlerBuilder; +import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.tracing.Tracing; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class SqsBatchHandlerParallel extends AbstractSqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { + private static final Logger LOGGER = LoggerFactory.getLogger(SqsBatchHandlerParallel.class); + private final BatchMessageHandler<SQSEvent, SQSBatchResponse> handler; + private final ExecutorService executor; + + public SqsBatchHandlerParallel() { + handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithMessageHandler(this::processMessage, Product.class); + executor = Executors.newFixedThreadPool(2); + } + + @Logging + @Tracing + @Override + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + LOGGER.info("Processing batch of {} messages", sqsEvent.getRecords().size()); + return handler.processBatchInParallel(sqsEvent, context, executor); + } +} diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/BatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/BatchMessageHandler.java index 18d74bb25..c63409e35 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/BatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/BatchMessageHandler.java @@ -16,6 +16,9 @@ import com.amazonaws.services.lambda.runtime.Context; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; + /** * The basic interface a batch message handler must meet. * @@ -50,4 +53,14 @@ public interface BatchMessageHandler<E, R> { * @return A partial batch response */ R processBatchInParallel(E event, Context context); + + + /** + * Same as {@link #processBatchInParallel(Object, Context)} but with an option to provide custom {@link Executor} + * @param event The Lambda event containing the batch to process + * @param context The lambda context + * @param executor Custom executor to use for parallel processing + * @return A partial batch response + */ + R processBatchInParallel(E event, Context context, Executor executor); } diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java index 4b03d0947..df7179a88 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java @@ -17,8 +17,12 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; + +import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -66,7 +70,9 @@ public StreamsEventResponse processBatchInParallel(DynamodbEvent event, Context .parallelStream() // Parallel processing .map(eventRecord -> { multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); - return processBatchItem(eventRecord, context); + Optional<StreamsEventResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, context); + multiThreadMDC.removeThread(Thread.currentThread().getName()); + return failureOpt; }) .filter(Optional::isPresent) .map(Optional::get) @@ -75,6 +81,23 @@ public StreamsEventResponse processBatchInParallel(DynamodbEvent event, Context return StreamsEventResponse.builder().withBatchItemFailures(batchItemFailures).build(); } + @Override + public StreamsEventResponse processBatchInParallel(DynamodbEvent event, Context context, Executor executor) { + MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + + List<StreamsEventResponse.BatchItemFailure> batchItemFailures = new ArrayList<>(); + List<CompletableFuture<Void>> futures = event.getRecords().stream() + .map(eventRecord -> CompletableFuture.runAsync(() -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + Optional<StreamsEventResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, context); + failureOpt.ifPresent(batchItemFailures::add); + multiThreadMDC.removeThread(Thread.currentThread().getName()); + }, executor)) + .collect(Collectors.toList()); + futures.forEach(CompletableFuture::join); + return StreamsEventResponse.builder().withBatchItemFailures(batchItemFailures).build(); + } + private Optional<StreamsEventResponse.BatchItemFailure> processBatchItem(DynamodbEvent.DynamodbStreamRecord streamRecord, Context context) { try { LOGGER.debug("Processing item {}", streamRecord.getEventID()); @@ -86,19 +109,19 @@ private Optional<StreamsEventResponse.BatchItemFailure> processBatchItem(Dynamod this.successHandler.accept(streamRecord); } return Optional.empty(); - } catch (Throwable t) { + } catch (Exception e) { String sequenceNumber = streamRecord.getDynamodb().getSequenceNumber(); LOGGER.error("Error while processing record with id {}: {}, adding it to batch item failures", - sequenceNumber, t.getMessage()); - LOGGER.error("Error was", t); + sequenceNumber, e.getMessage()); + LOGGER.error("Error was", e); // Report failure if we have a handler if (this.failureHandler != null) { // A failing failure handler is no reason to fail the batch try { - this.failureHandler.accept(streamRecord, t); - } catch (Throwable t2) { - LOGGER.warn("failureHandler threw handling failure", t2); + this.failureHandler.accept(streamRecord, e); + } catch (Exception e2) { + LOGGER.warn("failureHandler threw handling failure", e2); } } return Optional.of(StreamsEventResponse.BatchItemFailure.builder().withItemIdentifier(sequenceNumber).build()); diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java index 7b4179de7..233830462 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java @@ -18,8 +18,12 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.KinesisEvent; import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; + +import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -77,7 +81,9 @@ public StreamsEventResponse processBatchInParallel(KinesisEvent event, Context c .parallelStream() // Parallel processing .map(eventRecord -> { multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); - return processBatchItem(eventRecord, context); + Optional<StreamsEventResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, context); + multiThreadMDC.removeThread(Thread.currentThread().getName()); + return failureOpt; }) .filter(Optional::isPresent) .map(Optional::get) @@ -86,6 +92,23 @@ public StreamsEventResponse processBatchInParallel(KinesisEvent event, Context c return StreamsEventResponse.builder().withBatchItemFailures(batchItemFailures).build(); } + @Override + public StreamsEventResponse processBatchInParallel(KinesisEvent event, Context context, Executor executor) { + MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + + List<StreamsEventResponse.BatchItemFailure> batchItemFailures = new ArrayList<>(); + List<CompletableFuture<Void>> futures = event.getRecords().stream() + .map(eventRecord -> CompletableFuture.runAsync(() -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + Optional<StreamsEventResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, context); + failureOpt.ifPresent(batchItemFailures::add); + multiThreadMDC.removeThread(Thread.currentThread().getName()); + }, executor)) + .collect(Collectors.toList()); + futures.forEach(CompletableFuture::join); + return StreamsEventResponse.builder().withBatchItemFailures(batchItemFailures).build(); + } + private Optional<StreamsEventResponse.BatchItemFailure> processBatchItem(KinesisEvent.KinesisEventRecord eventRecord, Context context) { try { LOGGER.debug("Processing item {}", eventRecord.getEventID()); @@ -102,19 +125,19 @@ private Optional<StreamsEventResponse.BatchItemFailure> processBatchItem(Kinesis this.successHandler.accept(eventRecord); } return Optional.empty(); - } catch (Throwable t) { + } catch (Exception e) { String sequenceNumber = eventRecord.getEventID(); LOGGER.error("Error while processing record with eventID {}: {}, adding it to batch item failures", - sequenceNumber, t.getMessage()); - LOGGER.error("Error was", t); + sequenceNumber, e.getMessage()); + LOGGER.error("Error was", e); // Report failure if we have a handler if (this.failureHandler != null) { // A failing failure handler is no reason to fail the batch try { - this.failureHandler.accept(eventRecord, t); - } catch (Throwable t2) { - LOGGER.warn("failureHandler threw handling failure", t2); + this.failureHandler.accept(eventRecord, e); + } catch (Exception e2) { + LOGGER.warn("failureHandler threw handling failure", e2); } } diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java index 2dfb0a28e..ccb6a6dd7 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java @@ -15,15 +15,20 @@ package software.amazon.lambda.powertools.batch.handler; import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.KinesisEvent; import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.stream.Collectors; + +import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.lambda.powertools.batch.internal.MultiThreadMDC; @@ -99,7 +104,7 @@ public SQSBatchResponse processBatch(SQSEvent event, Context context) { @Override public SQSBatchResponse processBatchInParallel(SQSEvent event, Context context) { - if (!event.getRecords().isEmpty() && event.getRecords().get(0).getAttributes().get(MESSAGE_GROUP_ID_KEY) != null) { + if (isFIFOEnabled(event)) { throw new UnsupportedOperationException("FIFO queues are not supported in parallel mode, use the processBatch method instead"); } @@ -109,7 +114,9 @@ public SQSBatchResponse processBatchInParallel(SQSEvent event, Context context) .map(sqsMessage -> { multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); - return processBatchItem(sqsMessage, context); + Optional<SQSBatchResponse.BatchItemFailure> failureOpt = processBatchItem(sqsMessage, context); + multiThreadMDC.removeThread(Thread.currentThread().getName()); + return failureOpt; }) .filter(Optional::isPresent) .map(Optional::get) @@ -118,6 +125,27 @@ public SQSBatchResponse processBatchInParallel(SQSEvent event, Context context) return SQSBatchResponse.builder().withBatchItemFailures(batchItemFailures).build(); } + @Override + public SQSBatchResponse processBatchInParallel(SQSEvent event, Context context, Executor executor) { + if (isFIFOEnabled(event)) { + throw new UnsupportedOperationException("FIFO queues are not supported in parallel mode, use the processBatch method instead"); + } + + MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + List<SQSBatchResponse.BatchItemFailure> batchItemFailures = new ArrayList<>(); + List<CompletableFuture<Void>> futures = event.getRecords().stream() + .map(eventRecord -> CompletableFuture.runAsync(() -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + Optional<SQSBatchResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, context); + failureOpt.ifPresent(batchItemFailures::add); + multiThreadMDC.removeThread(Thread.currentThread().getName()); + }, executor)) + .collect(Collectors.toList()); + futures.forEach(CompletableFuture::join); + + return SQSBatchResponse.builder().withBatchItemFailures(batchItemFailures).build(); + } + private Optional<SQSBatchResponse.BatchItemFailure> processBatchItem(SQSEvent.SQSMessage message, Context context) { try { LOGGER.debug("Processing message {}", message.getMessageId()); @@ -134,22 +162,26 @@ private Optional<SQSBatchResponse.BatchItemFailure> processBatchItem(SQSEvent.SQ this.successHandler.accept(message); } return Optional.empty(); - } catch (Throwable t) { + } catch (Exception e) { LOGGER.error("Error while processing message with messageId {}: {}, adding it to batch item failures", - message.getMessageId(), t.getMessage()); - LOGGER.error("Error was", t); + message.getMessageId(), e.getMessage()); + LOGGER.error("Error was", e); // Report failure if we have a handler if (this.failureHandler != null) { // A failing failure handler is no reason to fail the batch try { - this.failureHandler.accept(message, t); - } catch (Throwable t2) { - LOGGER.warn("failureHandler threw handling failure", t2); + this.failureHandler.accept(message, e); + } catch (Exception e2) { + LOGGER.warn("failureHandler threw handling failure", e2); } } return Optional.of(SQSBatchResponse.BatchItemFailure.builder().withItemIdentifier(message.getMessageId()) .build()); } } + + private boolean isFIFOEnabled(SQSEvent sqsEvent) { + return !sqsEvent.getRecords().isEmpty() && sqsEvent.getRecords().get(0).getAttributes().get(MESSAGE_GROUP_ID_KEY) != null; + } } diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/MultiThreadMDC.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/MultiThreadMDC.java index df1c2e7a0..b2b85044b 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/MultiThreadMDC.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/MultiThreadMDC.java @@ -44,4 +44,11 @@ public void copyMDCToThread(String thread) { mdcAwareThreads.add(thread); } } + + public void removeThread(String thread) { + if (mdcAwareThreads.contains(thread)) { + LOGGER.debug("Removing thread {}", thread); + mdcAwareThreads.remove(thread); + } + } } diff --git a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/DdbBatchProcessorTest.java b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/DdbBatchProcessorTest.java index 6bb247323..51131ae3f 100644 --- a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/DdbBatchProcessorTest.java +++ b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/DdbBatchProcessorTest.java @@ -23,7 +23,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.BiConsumer; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.params.ParameterizedTest; import org.mockito.Mock; @@ -43,6 +48,8 @@ public void clear() { private void processMessageSucceeds(DynamodbEvent.DynamodbStreamRecord record, Context context) { // Great success + // Printing to satisfy pmd_analyse + System.out.println("Great success, record: " + record + ", context: " + context); } private void processMessageFailsForFixedMessage(DynamodbEvent.DynamodbStreamRecord record, Context context) { @@ -78,6 +85,25 @@ private void processMessageInParallelFailsForFixedMessage(DynamodbEvent.Dynamodb } } + private StreamsEventResponse testParallelBatchExecution(DynamodbEvent event, + BiConsumer<DynamodbEvent.DynamodbStreamRecord, Context> messageHandler, + Executor executor) { + // Arrange + BatchMessageHandler<DynamodbEvent, StreamsEventResponse> handler = new BatchMessageHandlerBuilder() + .withDynamoDbBatchHandler() + .buildWithRawMessageHandler(messageHandler); + + // Act + StreamsEventResponse dynamodbBatchResponse; + if (executor == null) { + dynamodbBatchResponse = handler.processBatchInParallel(event, context); + } else { + dynamodbBatchResponse = handler.processBatchInParallel(event, context, executor); + } + + return dynamodbBatchResponse; + } + @ParameterizedTest @Event(value = "dynamo_event.json", type = DynamodbEvent.class) void batchProcessingSucceedsAndReturns(DynamodbEvent event) { @@ -96,13 +122,7 @@ void batchProcessingSucceedsAndReturns(DynamodbEvent event) { @ParameterizedTest @Event(value = "dynamo_event_big.json", type = DynamodbEvent.class) void parallelBatchProcessingSucceedsAndReturns(DynamodbEvent event) { - // Arrange - BatchMessageHandler<DynamodbEvent, StreamsEventResponse> handler = new BatchMessageHandlerBuilder() - .withDynamoDbBatchHandler() - .buildWithRawMessageHandler(this::processMessageInParallelSucceeds); - - // Act - StreamsEventResponse dynamodbBatchResponse = handler.processBatchInParallel(event, context); + StreamsEventResponse dynamodbBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelSucceeds, null); // Assert assertThat(dynamodbBatchResponse.getBatchItemFailures()).isEmpty(); @@ -129,13 +149,7 @@ void shouldAddMessageToBatchFailure_whenException_withMessage(DynamodbEvent even @ParameterizedTest @Event(value = "dynamo_event_big.json", type = DynamodbEvent.class) void parallelBatchProcessing_shouldAddMessageToBatchFailure_whenException_withMessage(DynamodbEvent event) { - // Arrange - BatchMessageHandler<DynamodbEvent, StreamsEventResponse> handler = new BatchMessageHandlerBuilder() - .withDynamoDbBatchHandler() - .buildWithRawMessageHandler(this::processMessageInParallelFailsForFixedMessage); - - // Act - StreamsEventResponse dynamodbBatchResponse = handler.processBatchInParallel(event, context); + StreamsEventResponse dynamodbBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelFailsForFixedMessage, null); // Assert assertThat(dynamodbBatchResponse.getBatchItemFailures()).hasSize(1); @@ -196,4 +210,32 @@ void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(DynamodbEvent ev assertThat(batchItemFailure.getItemIdentifier()).isEqualTo("4421584500000000017450439091"); } + @ParameterizedTest + @Event(value = "dynamo_event_big.json", type = DynamodbEvent.class) + void parallelBatchProcessingWithExecutorSucceedsAndReturns(DynamodbEvent event) { + ExecutorService executor = Executors.newFixedThreadPool(2); + + StreamsEventResponse dynamodbBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelSucceeds, executor); + executor.shutdown(); + + // Assert + assertThat(dynamodbBatchResponse.getBatchItemFailures()).isEmpty(); + assertThat(threadList).hasSizeGreaterThan(1); + } + + @ParameterizedTest + @Event(value = "dynamo_event_big.json", type = DynamodbEvent.class) + void parallelBatchProcessingWithExecutor_shouldAddMessageToBatchFailure_whenException_withMessage(DynamodbEvent event) { + ExecutorService executor = Executors.newFixedThreadPool(2); + + StreamsEventResponse dynamodbBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelFailsForFixedMessage, executor); + executor.shutdown(); + + // Assert + assertThat(dynamodbBatchResponse.getBatchItemFailures()).hasSize(1); + StreamsEventResponse.BatchItemFailure batchItemFailure = dynamodbBatchResponse.getBatchItemFailures().get(0); + assertThat(batchItemFailure.getItemIdentifier()).isEqualTo("4421584500000000017450439091"); + assertThat(threadList).hasSizeGreaterThan(1); + } + } diff --git a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/KinesisBatchProcessorTest.java b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/KinesisBatchProcessorTest.java index 059a4d2d0..32acde6f0 100644 --- a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/KinesisBatchProcessorTest.java +++ b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/KinesisBatchProcessorTest.java @@ -23,7 +23,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.BiConsumer; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.params.ParameterizedTest; import org.mockito.Mock; @@ -81,6 +86,25 @@ private void processMessageInParallelFailsForFixedMessage(KinesisEvent.KinesisEv } } + private StreamsEventResponse testParallelBatchExecution(KinesisEvent event, + BiConsumer<KinesisEvent.KinesisEventRecord, Context> messageHandler, + Executor executor) { + // Arrange + BatchMessageHandler<KinesisEvent, StreamsEventResponse> handler = new BatchMessageHandlerBuilder() + .withKinesisBatchHandler() + .buildWithRawMessageHandler(messageHandler); + + // Act + StreamsEventResponse kinesisBatchResponse; + if (executor == null) { + kinesisBatchResponse = handler.processBatchInParallel(event, context); + } else { + kinesisBatchResponse = handler.processBatchInParallel(event, context, executor); + } + + return kinesisBatchResponse; + } + // A handler that throws an exception for _one_ of the deserialized products in the same messages public void processMessageFailsForFixedProduct(Product product, Context context) { if (product.getId() == 1234) { @@ -106,13 +130,7 @@ void batchProcessingSucceedsAndReturns(KinesisEvent event) { @ParameterizedTest @Event(value = "kinesis_event_big.json", type = KinesisEvent.class) void batchProcessingInParallelSucceedsAndReturns(KinesisEvent event) { - // Arrange - BatchMessageHandler<KinesisEvent, StreamsEventResponse> handler = new BatchMessageHandlerBuilder() - .withKinesisBatchHandler() - .buildWithRawMessageHandler(this::processMessageInParallelSucceeds); - - // Act - StreamsEventResponse kinesisBatchResponse = handler.processBatchInParallel(event, context); + StreamsEventResponse kinesisBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelSucceeds, null); // Assert assertThat(kinesisBatchResponse.getBatchItemFailures()).isEmpty(); @@ -140,13 +158,7 @@ void shouldAddMessageToBatchFailure_whenException_withMessage(KinesisEvent event @ParameterizedTest @Event(value = "kinesis_event_big.json", type = KinesisEvent.class) void batchProcessingInParallel_shouldAddMessageToBatchFailure_whenException_withMessage(KinesisEvent event) { - // Arrange - BatchMessageHandler<KinesisEvent, StreamsEventResponse> handler = new BatchMessageHandlerBuilder() - .withKinesisBatchHandler() - .buildWithRawMessageHandler(this::processMessageInParallelFailsForFixedMessage); - - // Act - StreamsEventResponse kinesisBatchResponse = handler.processBatchInParallel(event, context); + StreamsEventResponse kinesisBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelFailsForFixedMessage, null); // Assert assertThat(kinesisBatchResponse.getBatchItemFailures()).hasSize(1); @@ -227,4 +239,33 @@ void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(KinesisEvent eve "49545115243490985018280067714973144582180062593244200961"); } + @ParameterizedTest + @Event(value = "kinesis_event_big.json", type = KinesisEvent.class) + void batchProcessingInParallelWithExecutorSucceedsAndReturns(KinesisEvent event) { + ExecutorService executor = Executors.newFixedThreadPool(2); + + StreamsEventResponse kinesisBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelSucceeds, executor); + executor.shutdown(); + + // Assert + assertThat(kinesisBatchResponse.getBatchItemFailures()).isEmpty(); + assertThat(threadList).hasSizeGreaterThan(1); + } + + @ParameterizedTest + @Event(value = "kinesis_event_big.json", type = KinesisEvent.class) + void batchProcessingInParallelWithExecutor_shouldAddMessageToBatchFailure_whenException_withMessage(KinesisEvent event) { + ExecutorService executor = Executors.newFixedThreadPool(2); + + StreamsEventResponse kinesisBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelFailsForFixedMessage, executor); + executor.shutdown(); + + // Assert + assertThat(kinesisBatchResponse.getBatchItemFailures()).hasSize(1); + StreamsEventResponse.BatchItemFailure batchItemFailure = kinesisBatchResponse.getBatchItemFailures().get(0); + assertThat(batchItemFailure.getItemIdentifier()).isEqualTo( + "49545115243490985018280067714973144582180062593244200961"); + assertThat(threadList).hasSizeGreaterThan(1); + } + } diff --git a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/SQSBatchProcessorTest.java b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/SQSBatchProcessorTest.java index 7dd51374e..f13196fc4 100644 --- a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/SQSBatchProcessorTest.java +++ b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/SQSBatchProcessorTest.java @@ -23,7 +23,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.BiConsumer; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.params.ParameterizedTest; import org.mockito.Mock; @@ -45,7 +50,7 @@ public void clear() { private void processMessageSucceeds(SQSEvent.SQSMessage sqsMessage) { } - private void processMessageInParallelSucceeds(SQSEvent.SQSMessage sqsMessage) { + private void processMessageInParallelSucceeds(SQSEvent.SQSMessage sqsMessage, Context context) { String thread = Thread.currentThread().getName(); if (!threadList.contains(thread)) { threadList.add(thread); @@ -86,6 +91,25 @@ private void processMessageFailsForFixedProduct(Product product, Context context } } + private SQSBatchResponse testParallelBatchExecution(SQSEvent event, + BiConsumer<SQSEvent.SQSMessage, Context> messageHandler, + Executor executor) { + // Arrange + BatchMessageHandler<SQSEvent, SQSBatchResponse> handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithRawMessageHandler(messageHandler); + + // Act + SQSBatchResponse sqsBatchResponse; + if (executor == null) { + sqsBatchResponse = handler.processBatchInParallel(event, context); + } else { + sqsBatchResponse = handler.processBatchInParallel(event, context, executor); + } + + return sqsBatchResponse; + } + @ParameterizedTest @Event(value = "sqs_event.json", type = SQSEvent.class) void batchProcessingSucceedsAndReturns(SQSEvent event) { @@ -104,13 +128,7 @@ void batchProcessingSucceedsAndReturns(SQSEvent event) { @ParameterizedTest @Event(value = "sqs_event_big.json", type = SQSEvent.class) void parallelBatchProcessingSucceedsAndReturns(SQSEvent event) { - // Arrange - BatchMessageHandler<SQSEvent, SQSBatchResponse> handler = new BatchMessageHandlerBuilder() - .withSqsBatchHandler() - .buildWithRawMessageHandler(this::processMessageInParallelSucceeds); - - // Act - SQSBatchResponse sqsBatchResponse = handler.processBatchInParallel(event, context); + SQSBatchResponse sqsBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelSucceeds, null); // Assert assertThat(sqsBatchResponse.getBatchItemFailures()).isEmpty(); @@ -137,13 +155,7 @@ void shouldAddMessageToBatchFailure_whenException_withMessage(SQSEvent event) { @ParameterizedTest @Event(value = "sqs_event_big.json", type = SQSEvent.class) void parallelBatchProcessing_shouldAddMessageToBatchFailure_whenException_withMessage(SQSEvent event) { - // Arrange - BatchMessageHandler<SQSEvent, SQSBatchResponse> handler = new BatchMessageHandlerBuilder() - .withSqsBatchHandler() - .buildWithRawMessageHandler(this::processMessageInParallelFailsForFixedMessage); - - // Act - SQSBatchResponse sqsBatchResponse = handler.processBatchInParallel(event, context); + SQSBatchResponse sqsBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelFailsForFixedMessage, null); // Assert assertThat(sqsBatchResponse.getBatchItemFailures()).hasSize(1); @@ -238,5 +250,31 @@ void failingSuccessHandlerShouldntFailBatchButShouldFailMessage(SQSEvent event) assertThat(batchItemFailure.getItemIdentifier()).isEqualTo("e9144555-9a4f-4ec3-99a0-34ce359b4b54"); } + @ParameterizedTest + @Event(value = "sqs_event_big.json", type = SQSEvent.class) + void parallelBatchProcessingWithExecutorSucceedsAndReturns(SQSEvent event) { + ExecutorService executor = Executors.newFixedThreadPool(2); + SQSBatchResponse sqsBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelSucceeds, executor); + executor.shutdown(); + + // Assert + assertThat(sqsBatchResponse.getBatchItemFailures()).isEmpty(); + assertThat(threadList).hasSizeGreaterThan(1); + } + + @ParameterizedTest + @Event(value = "sqs_event_big.json", type = SQSEvent.class) + void parallelBatchProcessingWithExecutor_shouldAddMessageToBatchFailure_whenException_withMessage(SQSEvent event) { + ExecutorService executor = Executors.newFixedThreadPool(2); + SQSBatchResponse sqsBatchResponse = testParallelBatchExecution(event, this::processMessageInParallelFailsForFixedMessage, executor); + executor.shutdown(); + + // Assert + assertThat(sqsBatchResponse.getBatchItemFailures()).hasSize(1); + SQSBatchResponse.BatchItemFailure batchItemFailure = sqsBatchResponse.getBatchItemFailures().get(0); + assertThat(batchItemFailure.getItemIdentifier()).isEqualTo("e9144555-9a4f-4ec3-99a0-34ce359b4b54"); + assertThat(threadList).hasSizeGreaterThan(1); + } + } From 9dcb9b64eaa15157b5356b48b39e632421a92736 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 10:44:11 +0200 Subject: [PATCH 281/577] build(deps): bump org.apache.commons:commons-lang3 from 3.15.0 to 3.18.0 (#1936) Bumps org.apache.commons:commons-lang3 from 3.15.0 to 3.18.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.18.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e86602f2f..108354d82 100644 --- a/pom.xml +++ b/pom.xml @@ -297,7 +297,7 @@ <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> - <version>3.15.0</version> + <version>3.18.0</version> </dependency> <!-- Test dependencies --> From 765f0ac698d1173582d1c63d8727841e19af9711 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 10:45:42 +0200 Subject: [PATCH 282/577] build(deps-dev): bump org.apache.commons:commons-lang3 (#1937) Bumps org.apache.commons:commons-lang3 from 3.15.0 to 3.18.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.18.0 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From 57c8cb207ae2f1fd237453cac278882efcd8eb4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 10:46:43 +0200 Subject: [PATCH 283/577] build(deps): bump aws.sdk.version from 2.30.31 to 2.31.78 (#1938) Bumps `aws.sdk.version` from 2.30.31 to 2.31.78. Updates `software.amazon.awssdk:url-connection-client` from 2.30.31 to 2.31.78 Updates `software.amazon.awssdk:sdk-core` from 2.30.31 to 2.31.78 Updates `software.amazon.awssdk:s3` from 2.30.31 to 2.31.78 Updates `software.amazon.awssdk:kinesis` from 2.30.31 to 2.31.78 Updates `software.amazon.awssdk:sqs` from 2.30.31 to 2.31.78 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.30.31 to 2.31.78 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.31.78 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.31.78 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.31.78 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 53db49e17..22a8835d3 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.30.31</sdk.version> + <sdk.version>2.31.78</sdk.version> </properties> <dependencies> From b277e65ca8f5993d1e2fa772e2424b88fbe47990 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 10:48:04 +0200 Subject: [PATCH 284/577] build(deps): bump log4j.version from 2.24.3 to 2.25.1 (#1939) Bumps `log4j.version` from 2.24.3 to 2.25.1. Updates `org.apache.logging.log4j:log4j-core` from 2.24.3 to 2.25.1 Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.24.3 to 2.25.1 Updates `org.apache.logging.log4j:log4j-slf4j2-impl` from 2.24.3 to 2.25.1 Updates `org.apache.logging.log4j:log4j-api` from 2.24.3 to 2.25.1 Updates `org.apache.logging.log4j:log4j-layout-template-json` from 2.24.3 to 2.25.1 Updates `org.apache.logging.log4j:log4j-jcl` from 2.24.3 to 2.25.1 --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-slf4j-impl dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-slf4j2-impl dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-api dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-layout-template-json dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-jcl dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 9e38e64e1..f9f851d8e 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -11,7 +11,7 @@ <packaging>jar</packaging> <properties> - <log4j.version>2.24.3</log4j.version> + <log4j.version>2.25.1</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index f5539567b..730ac8d21 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -9,7 +9,7 @@ <packaging>jar</packaging> <properties> - <log4j.version>2.24.3</log4j.version> + <log4j.version>2.25.1</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index c7aecd7e3..df5e39a3e 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -8,7 +8,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> <properties> - <log4j.version>2.24.3</log4j.version> + <log4j.version>2.25.1</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/pom.xml b/pom.xml index 108354d82..057ccf977 100644 --- a/pom.xml +++ b/pom.xml @@ -81,7 +81,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <maven.deploy.plugin.version>3.1.2</maven.deploy.plugin.version> - <log4j.version>2.24.3</log4j.version> + <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.7</slf4j.version> <jackson.version>2.19.1</jackson.version> <aws.sdk.version>2.31.78</aws.sdk.version> From 765ddf27bffb7eb3b15c7e645d6e2358c7aa464b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 10:48:25 +0200 Subject: [PATCH 285/577] build(deps): bump org.sonatype.central:central-publishing-maven-plugin (#1940) Bumps [org.sonatype.central:central-publishing-maven-plugin](https://github.com/sonatype/central-publishing-maven-plugin) from 0.7.0 to 0.8.0. - [Commits](https://github.com/sonatype/central-publishing-maven-plugin/commits) --- updated-dependencies: - dependency-name: org.sonatype.central:central-publishing-maven-plugin dependency-version: 0.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 057ccf977..c00e341a6 100644 --- a/pom.xml +++ b/pom.xml @@ -506,7 +506,7 @@ <plugin> <groupId>org.sonatype.central</groupId> <artifactId>central-publishing-maven-plugin</artifactId> - <version>0.7.0</version> + <version>0.8.0</version> <extensions>true</extensions> <configuration> <publishingServerId>central</publishingServerId> From ff87ecced7b067ea6a479229a94ff6236269dbc9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 10:48:46 +0200 Subject: [PATCH 286/577] build(deps): bump org.codehaus.mojo:build-helper-maven-plugin (#1941) Bumps [org.codehaus.mojo:build-helper-maven-plugin](https://github.com/mojohaus/build-helper-maven-plugin) from 3.6.0 to 3.6.1. - [Release notes](https://github.com/mojohaus/build-helper-maven-plugin/releases) - [Commits](https://github.com/mojohaus/build-helper-maven-plugin/compare/3.6.0...3.6.1) --- updated-dependencies: - dependency-name: org.codehaus.mojo:build-helper-maven-plugin dependency-version: 3.6.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-kafka/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 5eb79913b..02a52a2f4 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -203,7 +203,7 @@ <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <id>add-test-source</id> From 08c9db8632cd44453e52f5f5dc04c4ba0b456867 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 11:29:17 +0200 Subject: [PATCH 287/577] chore(ci): bump version to 2.2.0 (#1942) Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- .../powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 43 files changed, 49 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 7e33bf19e..3ea636922 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-metrics</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> </dependency> ... </dependencies> diff --git a/examples/pom.xml b/examples/pom.xml index 2487a4d14..4bea96700 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-examples</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Examples</name> diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 22a8835d3..abc4d660b 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-batch</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Batch</name> diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 7b0c9a21f..d6c2dbca0 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-cloudformation</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index f9f851d8e..1f0f9f4ef 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ <groupId>software.amazon.lambda.examples</groupId> <!-- TODO TODO TODO this should build from SNAPSHOT, but it doesn't, because the snapshots don't appear in the docker environment CDK builds it in in our CDK tests. How to procede? V2 blocker --> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-core-utilities-cdk</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 4af44d146..d6a4dc3cf 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <artifactId>cdk</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.162.1</cdk.version> diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 04368e29c..4cee5ecfa 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.1.1' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.1.1' - aspect 'software.amazon.lambda:powertools-metrics:2.1.1' + aspect 'software.amazon.lambda:powertools-tracing:2.2.0' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.2.0' + aspect 'software.amazon.lambda:powertools-metrics:2.2.0' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 2b3d184d7..e769c3c45 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.1.1") - aspect("software.amazon.lambda:powertools-logging-log4j:2.1.1") - aspect("software.amazon.lambda:powertools-metrics:2.1.1") + aspect("software.amazon.lambda:powertools-tracing:2.2.0") + aspect("software.amazon.lambda:powertools-logging-log4j:2.2.0") + aspect("software.amazon.lambda:powertools-metrics:2.2.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 730ac8d21..6fbe62ec2 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-core-utilities-sam-graalvm</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 62bff0cd4..ba436c650 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-core-utilities-sam</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index a042e098e..b62f193aa 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-core-utilities-serverless</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 418dc20af..a09b26ac6 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-core-utilities-terraform</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 932da03b4..a56eae46d 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-idempotency</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency</name> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 6921f2793..4ea02a649 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-kafka</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Kafka</name> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index df5e39a3e..3336f6bd1 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-parameters-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index a4f8d975b..c729ed83c 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-parameters-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters</name> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index 370a3ec60..2239515f3 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-serialization-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 8c17b2a86..ed70081a2 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-serialization-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization</name> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 272ff663f..6955fc4ea 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <artifactId>powertools-examples-validation</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Validation</name> diff --git a/mkdocs.yml b/mkdocs.yml index 0008ef9dd..9b70afcb3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -121,7 +121,7 @@ extra_javascript: extra: powertools: - version: 2.1.1 + version: 2.2.0 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index c00e341a6..c7e850e32 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Parent</name> diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index c5036e74a..09589595f 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <description>A suite of utilities that makes batch message processing using AWS Lambda easier.</description> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index c30b47884..a5888bf5d 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Cloudformation</name> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 20060bae7..27e2dbfb4 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Common Internal Utilities</name> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index dbeb8b1ca..4cf4afc3d 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <artifactId>powertools-e2e-tests</artifactId> diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 029fa4163..f40bc7ee6 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <artifactId>powertools-idempotency</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index c8ea35d4b..c8f1e58d6 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <artifactId>powertools-idempotency-core</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index 4dd59a476..701259da3 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <artifactId>powertools-idempotency-dynamodb</artifactId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 02a52a2f4..d0636baf2 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <artifactId>powertools-kafka</artifactId> diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 1b975739d..6b9b258ca 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <artifactId>powertools-large-messages</artifactId> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index af9f066b3..fe32aa534 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Logging</name> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 2cfcd967d..fd081b963 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index d729dba23..6dc6167ab 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 3501c7b0e..18b11f5c3 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Metrics</name> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index d4da33a8d..2429d374c 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <artifactId>powertools-parameters</artifactId> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 206d259e1..825e50d90 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 3959ff65b..b1bfaa5df 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 9885fcef1..34031ca42 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index e9f33a24b..faecdf157 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 21ce5639e..55a3b9509 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.1.1</version> + <version>2.2.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index bb2f0fb34..e0867b486 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <artifactId>powertools-serialization</artifactId> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 5239e7b6c..4d8326d6b 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Tracing</name> diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 3ab6e51fc..b51b531fa 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.1.1</version> + <version>2.2.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Validation</name> From 78fab5218a34d36ea2d1d6b5fd517ed556e7ea1a Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Mon, 21 Jul 2025 13:07:16 +0200 Subject: [PATCH 288/577] chore(ci): Add GraalVM E2E tests and GH workflows (#1945) * Add GraalVM support for E2E tests starting with metrics handler. * Add GraalVM E2E test support for Logging and Parameters. Refactor metrics configuration be in parent pom. * Add e2e-graal step to e2e test workflow. * Disable maven download progress logs to reduce amount of logs in GH runner. * Fix sonarlint issue. * Update osv-scanner to 2.1.0. * PIN docker image version. * Add fail-fast: false option to GH workflow. --- .github/workflows/check-e2e.yml | 36 +++- .github/workflows/security-osv.yml | 2 +- powertools-e2e-tests/handlers/logging/pom.xml | 24 ++- .../aws-lambda-java-core/reflect-config.json | 13 ++ .../reflect-config.json | 35 ++++ .../jni-config.json | 11 ++ .../native-image.properties | 1 + .../reflect-config.json | 61 ++++++ .../resource-config.json | 19 ++ .../reflect-config.json | 25 +++ .../reflect-config.json | 20 ++ .../resource-config.json | 7 + powertools-e2e-tests/handlers/metrics/pom.xml | 24 ++- .../aws-lambda-java-core/reflect-config.json | 13 ++ .../reflect-config.json | 35 ++++ .../jni-config.json | 11 ++ .../native-image.properties | 1 + .../reflect-config.json | 61 ++++++ .../resource-config.json | 19 ++ .../reflect-config.json | 25 +++ .../reflect-config.json | 20 ++ .../handlers/parameters/pom.xml | 24 ++- .../aws-lambda-java-core/reflect-config.json | 13 ++ .../reflect-config.json | 35 ++++ .../jni-config.json | 11 ++ .../native-image.properties | 1 + .../reflect-config.json | 61 ++++++ .../resource-config.json | 19 ++ .../reflect-config.json | 25 +++ .../reflect-config.json | 20 ++ .../resource-config.json | 7 + powertools-e2e-tests/handlers/pom.xml | 51 +++-- powertools-e2e-tests/pom.xml | 35 ++++ .../amazon/lambda/powertools/LoggingE2ET.java | 25 +-- .../amazon/lambda/powertools/MetricsE2ET.java | 38 ++-- .../lambda/powertools/ParametersE2ET.java | 20 +- .../testutils/DockerConfiguration.java | 180 ++++++++++++++++++ .../powertools/testutils/Infrastructure.java | 52 ++--- .../src/test/resources/docker/Dockerfile | 14 ++ 39 files changed, 1003 insertions(+), 91 deletions(-) create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json create mode 100644 powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java create mode 100644 powertools-e2e-tests/src/test/resources/docker/Dockerfile diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index d5c95f156..19500b2e5 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -47,6 +47,7 @@ jobs: id-token: write environment: E2E strategy: + fail-fast: false max-parallel: 3 matrix: java: @@ -70,4 +71,37 @@ jobs: - name: Run e2e test with Maven env: JAVA_VERSION: ${{ matrix.java }} - run: mvn -DskipTests install --file pom.xml && mvn -Pe2e -B verify --file powertools-e2e-tests/pom.xml + run: mvn -DskipTests -ntp install --file pom.xml && mvn -Pe2e -B -ntp verify --file powertools-e2e-tests/pom.xml + + e2e-graal: + name: End-to-end GraalVM Tests (Java ${{ matrix.java }}) + runs-on: ubuntu-latest + permissions: + id-token: write + environment: E2E + strategy: + fail-fast: false + max-parallel: 3 + matrix: + java: + - 11 + - 17 + - 21 + + steps: + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: Setup java + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + with: + distribution: 'corretto' + java-version: ${{ matrix.java }} + cache: maven + - name: Setup AWS credentials + uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 + with: + role-to-assume: ${{ secrets.AWS_IAM_ROLE }} + aws-region: us-east-1 + - name: Run e2e-graal test with Maven + env: + JAVA_VERSION: ${{ matrix.java }} + run: mvn -DskipTests -ntp install --file pom.xml && mvn -Pe2e-graal -B -ntp verify --file powertools-e2e-tests/pom.xml diff --git a/.github/workflows/security-osv.yml b/.github/workflows/security-osv.yml index 67e2e6e3f..73d6b1835 100644 --- a/.github/workflows/security-osv.yml +++ b/.github/workflows/security-osv.yml @@ -32,4 +32,4 @@ jobs: actions: read contents: read security-events: write - uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@764c91816374ff2d8fc2095dab36eecd42d61638 # v1.9.2 \ No newline at end of file + uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@b00f71e051ddddc6e46a193c31c8c0bf283bf9e6 # v2.1.0 diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml index 62f2f7530..f5eacf5c5 100644 --- a/powertools-e2e-tests/handlers/logging/pom.xml +++ b/powertools-e2e-tests/handlers/logging/pom.xml @@ -1,5 +1,5 @@ <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 http://maven.apache.org/maven-v4_0_0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -30,6 +30,14 @@ <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + </dependency> </dependencies> <build> @@ -62,4 +70,18 @@ </plugin> </plugins> </build> + + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index e543c2cd0..7bdc75591 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -1,5 +1,5 @@ <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 http://maven.apache.org/maven-v4_0_0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -21,6 +21,14 @@ <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> @@ -57,4 +65,18 @@ </plugin> </plugins> </build> + + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index 471e79d8f..46e6dc1e5 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -1,5 +1,5 @@ <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 http://maven.apache.org/maven-v4_0_0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -25,6 +25,14 @@ <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> @@ -61,4 +69,18 @@ </plugin> </plugins> </build> + + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 988ae3d55..1b3eaf3e0 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -1,5 +1,5 @@ <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 http://maven.apache.org/maven-v4_0_0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda</groupId> @@ -15,13 +15,13 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> - <lambda.java.core>1.2.2</lambda.java.core> - <lambda.java.serialization>1.1.2</lambda.java.serialization> - <lambda.java.events>3.11.2</lambda.java.events> + <lambda.java.core>1.3.0</lambda.java.core> + <lambda.java.serialization>1.1.6</lambda.java.serialization> + <lambda.java.events>3.16.1</lambda.java.events> <maven.shade.version>3.5.0</maven.shade.version> <aspectj.plugin.version>1.13.1</aspectj.plugin.version> <maven.compiler.version>3.11.0</maven.compiler.version> - <aws.sdk.version>2.20.108</aws.sdk.version> + <aws.sdk.version>2.32.2</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> @@ -112,6 +112,11 @@ <artifactId>aws-lambda-java-serialization</artifactId> <version>${lambda.java.serialization}</version> </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + <version>2.8.2</version> + </dependency> </dependencies> </dependencyManagement> @@ -134,17 +139,18 @@ </goals> <configuration> <transformers> - <transformer implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer"/> + <transformer + implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer" /> </transformers> </configuration> </execution> </executions> <dependencies> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> - </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> + <version>0.1.0</version> + </dependency> </dependencies> </plugin> <plugin> @@ -185,6 +191,29 @@ </dependency> </dependencies> </plugin> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + <version>0.10.6</version> + <extensions>true</extensions> + <executions> + <execution> + <id>build-native</id> + <goals> + <goal>build</goal> + </goals> + <phase>package</phase> + </execution> + </executions> + <configuration> + <imageName>handler</imageName> + <mainClass>com.amazonaws.services.lambda.runtime.api.client.AWSLambda</mainClass> + <buildArgs> + <arg>--enable-url-protocols=http</arg> + <arg>--add-opens java.base/java.util=ALL-UNNAMED</arg> + </buildArgs> + </configuration> + </plugin> </plugins> </pluginManagement> </build> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 4cf4afc3d..3bbaca3e2 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -234,6 +234,41 @@ </plugins> </build> </profile> + <profile> + <id>e2e-graal</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <version>3.5.3</version> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + <configuration> + <skipAfterFailureCount>1</skipAfterFailureCount> + <includes> + <!-- Add additional E2E tests here when adding new GraalVM support to utilities. --> + <include>**/MetricsE2ET.java</include> + <include>**/LoggingE2ET.java</include> + <include>**/ParametersE2ET.java</include> + </includes> + <excludes> + <exclude>**/TracingE2ET.java</exclude> + </excludes> + <systemPropertyVariables> + <graalvm.enabled>true</graalvm.enabled> + </systemPropertyVariables> + </configuration> + </plugin> + </plugins> + </build> + </profile> </profiles> </project> diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java index f78500c65..ad2c2564f 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java @@ -19,22 +19,25 @@ import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction; import static software.amazon.lambda.powertools.testutils.logging.InvocationLogs.Level.INFO; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + import software.amazon.lambda.powertools.testutils.Infrastructure; import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; -public class LoggingE2ET { +class LoggingE2ET { private static final ObjectMapper objectMapper = new ObjectMapper(); @@ -42,17 +45,17 @@ public class LoggingE2ET { private static String functionName; @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { + @Timeout(value = 10, unit = TimeUnit.MINUTES) + static void setup() { infrastructure = Infrastructure.builder() .testName(LoggingE2ET.class.getSimpleName()) .tracing(true) .pathToFunction("logging") .environmentVariables( Stream.of(new String[][] { - {"POWERTOOLS_LOG_LEVEL", "INFO"}, - {"POWERTOOLS_SERVICE_NAME", LoggingE2ET.class.getSimpleName()} - }) + { "POWERTOOLS_LOG_LEVEL", "INFO" }, + { "POWERTOOLS_SERVICE_NAME", LoggingE2ET.class.getSimpleName() } + }) .collect(Collectors.toMap(data -> data[0], data -> data[1]))) .build(); Map<String, String> outputs = infrastructure.deploy(); @@ -60,14 +63,14 @@ public static void setup() { } @AfterAll - public static void tearDown() { + static void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @Test - public void test_logInfoWithAdditionalKeys() throws JsonProcessingException { + void test_logInfoWithAdditionalKeys() throws JsonProcessingException { // GIVEN String orderId = UUID.randomUUID().toString(); String event = "{\"message\":\"New Order\", \"keys\":{\"orderId\":\"" + orderId + "\"}}"; diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java index 2765e0e70..feb9537d5 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java @@ -38,22 +38,22 @@ import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; import software.amazon.lambda.powertools.testutils.metrics.MetricsFetcher; -public class MetricsE2ET { - private static final String namespace = "MetricsE2ENamespace_" + UUID.randomUUID(); - private static final String service = "MetricsE2EService_" + UUID.randomUUID(); +class MetricsE2ET { + private static final String NAMESPACE = "MetricsE2ENamespace_" + UUID.randomUUID(); + private static final String SERVICE = "MetricsE2EService_" + UUID.randomUUID(); private static Infrastructure infrastructure; private static String functionName; @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { + @Timeout(value = 10, unit = TimeUnit.MINUTES) + static void setup() { infrastructure = Infrastructure.builder() .testName(MetricsE2ET.class.getSimpleName()) .pathToFunction("metrics") .environmentVariables( Stream.of(new String[][] { - { "POWERTOOLS_METRICS_NAMESPACE", namespace }, - { "POWERTOOLS_SERVICE_NAME", service } + { "POWERTOOLS_METRICS_NAMESPACE", NAMESPACE }, + { "POWERTOOLS_SERVICE_NAME", SERVICE } }) .collect(Collectors.toMap(data -> data[0], data -> data[1]))) .build(); @@ -62,14 +62,14 @@ public static void setup() { } @AfterAll - public static void tearDown() { + static void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @Test - public void test_recordMetrics() { + void test_recordMetrics() { // GIVEN Instant currentTimeTruncatedToMinutes = Instant.now(Clock.systemUTC()).truncatedTo(ChronoUnit.MINUTES); @@ -84,17 +84,17 @@ public void test_recordMetrics() { // THEN MetricsFetcher metricsFetcher = new MetricsFetcher(); List<Double> coldStart = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, - namespace, + NAMESPACE, "ColdStart", Stream.of(new String[][] { { "FunctionName", functionName }, - { "Service", service } }).collect(Collectors.toMap(data -> data[0], data -> data[1]))); + { "Service", SERVICE } }).collect(Collectors.toMap(data -> data[0], data -> data[1]))); assertThat(coldStart.get(0)).isEqualTo(1); List<Double> orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), - 60, namespace, + 60, NAMESPACE, "orders", Collections.singletonMap("Environment", "test")); assertThat(orderMetrics.get(0)).isEqualTo(2); List<Double> productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), - invocationResult.getEnd(), 60, namespace, + invocationResult.getEnd(), 60, NAMESPACE, "products", Collections.singletonMap("Environment", "test")); // When searching across a 1 minute time period with a period of 60 we find both metrics and the sum is 12 @@ -102,24 +102,22 @@ public void test_recordMetrics() { assertThat(productMetrics.get(0)).isEqualTo(12); orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, - namespace, - "orders", Collections.singletonMap("Service", service)); + NAMESPACE, + "orders", Collections.singletonMap("Service", SERVICE)); assertThat(orderMetrics.get(0)).isEqualTo(2); productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, - namespace, - "products", Collections.singletonMap("Service", service)); + NAMESPACE, + "products", Collections.singletonMap("Service", SERVICE)); assertThat(productMetrics.get(0)).isEqualTo(12); Instant searchStartTime = currentTimeTruncatedToMinutes.plusSeconds(15); Instant searchEndTime = currentTimeTruncatedToMinutes.plusSeconds(45); - List<Double> productMetricDataResult = metricsFetcher.fetchMetrics(searchStartTime, searchEndTime, 1, namespace, + List<Double> productMetricDataResult = metricsFetcher.fetchMetrics(searchStartTime, searchEndTime, 1, NAMESPACE, "products", Collections.singletonMap("Environment", "test")); // We are searching across the time period the metric was created but with a period of 1 second. Only the high // resolution metric will be available at this point - assertThat(productMetricDataResult.get(0)).isEqualTo(8); - } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java index 9582f9f23..39254a9e6 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ParametersE2ET.java @@ -24,22 +24,24 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.Timeout; + import software.amazon.lambda.powertools.testutils.AppConfig; import software.amazon.lambda.powertools.testutils.Infrastructure; import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; @TestInstance(TestInstance.Lifecycle.PER_CLASS) -public class ParametersE2ET { +class ParametersE2ET { private final AppConfig appConfig; private Infrastructure infrastructure; private String functionName; - public ParametersE2ET() { + ParametersE2ET() { String appName = UUID.randomUUID().toString(); Map<String, String> params = new HashMap<>(); params.put("key1", "value1"); @@ -48,17 +50,17 @@ public ParametersE2ET() { } @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) - public void setup() { + @Timeout(value = 15, unit = TimeUnit.MINUTES) + void setup() { infrastructure = Infrastructure.builder() .testName(ParametersE2ET.class.getSimpleName()) .pathToFunction("parameters") .appConfig(appConfig) .environmentVariables( Stream.of(new String[][] { - {"POWERTOOLS_LOG_LEVEL", "INFO"}, - {"POWERTOOLS_SERVICE_NAME", ParametersE2ET.class.getSimpleName()} - }) + { "POWERTOOLS_LOG_LEVEL", "INFO" }, + { "POWERTOOLS_SERVICE_NAME", ParametersE2ET.class.getSimpleName() } + }) .collect(Collectors.toMap(data -> data[0], data -> data[1]))) .build(); Map<String, String> outputs = infrastructure.deploy(); @@ -66,14 +68,14 @@ public void setup() { } @AfterAll - public void tearDown() { + void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @Test - public void test_getAppConfigValue() { + void test_getAppConfigValue() { for (Map.Entry<String, String> configKey : appConfig.getConfigurationValues().entrySet()) { // Arrange diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java new file mode 100644 index 000000000..204d5863a --- /dev/null +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java @@ -0,0 +1,180 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.testutils; + +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import software.amazon.awscdk.BundlingOptions; +import software.amazon.awscdk.BundlingOutput; +import software.amazon.awscdk.DockerImage; +import software.amazon.awscdk.DockerVolume; + +/** + * Configuration class for managing build environments and Docker settings + * used during Lambda function compilation. + */ +public class DockerConfiguration { + private final String baseImage; + private final List<String> buildArgs; + private final Map<String, String> environmentVariables; + private final List<DockerVolume> volumes; + + private DockerConfiguration(Builder builder) { + this.baseImage = builder.baseImage; + this.buildArgs = builder.buildArgs; + this.environmentVariables = builder.environmentVariables; + this.volumes = builder.volumes; + } + + public static Builder builder() { + return new Builder(); + } + + public String getBaseImage() { + return baseImage; + } + + public List<String> getBuildArgs() { + return buildArgs; + } + + public Map<String, String> getEnvironmentVariables() { + return environmentVariables; + } + + public List<DockerVolume> getVolumes() { + return volumes; + } + + /** + * Creates bundling options for GraalVM native image compilation. + */ + public BundlingOptions createGraalVMBundlingOptions(String pathToFunction, JavaRuntime runtime) { + List<String> packagingInstruction = Arrays.asList( + "/bin/sh", + "-c", + "cd " + pathToFunction + + " && timeout -s SIGKILL 10m mvn clean package -Pnative-image -ff" + + " -Dmaven.test.skip=true" + + " -Dmaven.compiler.source=" + runtime.getMvnProperty() + + " -Dmaven.compiler.target=" + runtime.getMvnProperty() + + " && mkdir -p /tmp/lambda-package" + + " && cp /asset-input/" + pathToFunction + "/target/handler /tmp/lambda-package/" + + " && chmod +x /tmp/lambda-package/handler" + + " && echo '#!/bin/bash\nset -e\n./handler $_HANDLER' > /tmp/lambda-package/bootstrap" + + " && chmod +x /tmp/lambda-package/bootstrap" + + " && cd /tmp/lambda-package" + + " && zip -r /asset-output/function.zip ."); + + return BundlingOptions.builder() + .command(packagingInstruction) + .image(DockerImage.fromRegistry(baseImage)) + .volumes(volumes) + .environment(environmentVariables) + .user("root") + .outputType(BundlingOutput.ARCHIVED) + .build(); + } + + /** + * Creates bundling options for standard JVM compilation. + */ + public BundlingOptions createJVMBundlingOptions(String pathToFunction, JavaRuntime runtime) { + List<String> packagingInstruction = Arrays.asList( + "/bin/sh", + "-c", + "cd " + pathToFunction + + " && timeout -s SIGKILL 5m mvn clean install -ff" + + " -Dmaven.test.skip=true" + + " -Dmaven.compiler.source=" + runtime.getMvnProperty() + + " -Dmaven.compiler.target=" + runtime.getMvnProperty() + + " && cp /asset-input/" + pathToFunction + "/target/function.jar /asset-output/"); + + return BundlingOptions.builder() + .command(packagingInstruction) + .image(DockerImage.fromRegistry(baseImage)) + .volumes(volumes) + .user("root") + .outputType(BundlingOutput.ARCHIVED) + .build(); + } + + /** + * Creates a default Docker configuration for GraalVM native image compilation. + */ + public static DockerConfiguration createGraalVMDefault(JavaRuntime runtime) { + // Use custom Dockerfile for GraalVM + String dockerDir = Paths.get(System.getProperty("user.dir"), "src", "test", "resources", "docker").toString(); + DockerImage customImage = DockerImage.fromBuild(dockerDir); + + return builder() + .baseImage(customImage.getImage()) + .environmentVariables(Map.of("JAVA_VERSION", runtime.getMvnProperty())) + .volumes(List.of( + DockerVolume.builder() + .hostPath(System.getProperty("user.home") + "/.m2/") + .containerPath("/root/.m2/") + .build())) + .build(); + } + + /** + * Creates a default Docker configuration for standard JVM compilation. + */ + public static DockerConfiguration createJVMDefault(JavaRuntime runtime) { + return builder() + .baseImage(runtime.getCdkRuntime().getBundlingImage().getImage()) + .volumes(List.of( + DockerVolume.builder() + .hostPath(System.getProperty("user.home") + "/.m2/") + .containerPath("/root/.m2/") + .build())) + .build(); + } + + public static class Builder { + private String baseImage; + private List<String> buildArgs; + private Map<String, String> environmentVariables; + private List<DockerVolume> volumes; + + public Builder baseImage(String baseImage) { + this.baseImage = baseImage; + return this; + } + + public Builder buildArgs(List<String> buildArgs) { + this.buildArgs = buildArgs; + return this; + } + + public Builder environmentVariables(Map<String, String> environmentVariables) { + this.environmentVariables = environmentVariables; + return this; + } + + public Builder volumes(List<DockerVolume> volumes) { + this.volumes = volumes; + return this; + } + + public DockerConfiguration build() { + return new DockerConfiguration(this); + } + } +} diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java index 07d816112..c65871a0a 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java @@ -19,13 +19,10 @@ import java.io.File; import java.io.IOException; import java.nio.file.Paths; -import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; -import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,10 +32,8 @@ import software.amazon.awscdk.App; import software.amazon.awscdk.BundlingOptions; -import software.amazon.awscdk.BundlingOutput; import software.amazon.awscdk.CfnOutput; import software.amazon.awscdk.DefaultStackSynthesizer; -import software.amazon.awscdk.DockerVolume; import software.amazon.awscdk.Duration; import software.amazon.awscdk.RemovalPolicy; import software.amazon.awscdk.Stack; @@ -59,6 +54,7 @@ import software.amazon.awscdk.services.kinesis.StreamMode; import software.amazon.awscdk.services.lambda.Code; import software.amazon.awscdk.services.lambda.Function; +import software.amazon.awscdk.services.lambda.Runtime; import software.amazon.awscdk.services.lambda.StartingPosition; import software.amazon.awscdk.services.lambda.Tracing; import software.amazon.awscdk.services.lambda.eventsources.DynamoEventSource; @@ -218,47 +214,31 @@ private Stack createStackWithLambda() { .build()) .build(); - List<String> packagingInstruction = Arrays.asList( - "/bin/sh", - "-c", - "cd " + pathToFunction + - " && timeout -s SIGKILL 5m mvn clean install -ff " + - " -Dmaven.test.skip=true " + - " -Dmaven.compiler.source=" + runtime.getMvnProperty() + - " -Dmaven.compiler.target=" + runtime.getMvnProperty() + - " && cp /asset-input/" + pathToFunction + "/target/function.jar /asset-output/"); - - BundlingOptions.Builder builderOptions = BundlingOptions.builder() - .command(packagingInstruction) - .image(runtime.getCdkRuntime().getBundlingImage()) - .volumes(singletonList( - // Mount local .m2 repo to avoid download all the dependencies again inside the container - DockerVolume.builder() - .hostPath(System.getProperty("user.home") + "/.m2/") - .containerPath("/root/.m2/") - .build())) - .user("root") - .outputType(BundlingOutput.ARCHIVED); + boolean isGraalVMEnabled = Boolean.parseBoolean(System.getProperty("graalvm.enabled", "false")); + DockerConfiguration dockerConfig = isGraalVMEnabled + ? DockerConfiguration.createGraalVMDefault(runtime) + : DockerConfiguration.createJVMDefault(runtime); + + BundlingOptions bundlingOptions = isGraalVMEnabled + ? dockerConfig.createGraalVMBundlingOptions(pathToFunction, runtime) + : dockerConfig.createJVMBundlingOptions(pathToFunction, runtime); functionName = stackName + "-function"; CfnOutput.Builder.create(e2eStack, FUNCTION_NAME_OUTPUT) .value(functionName) .build(); - LOG.debug("Building Lambda function with command " + - packagingInstruction.stream().collect(Collectors.joining(" ", "[", "]"))); + LOG.debug("Building Lambda function with {} configuration", isGraalVMEnabled ? "GraalVM" : "JVM"); Function function = Function.Builder .create(e2eStack, functionName) .code(Code.fromAsset("handlers/", AssetOptions.builder() - .bundling(builderOptions - .command(packagingInstruction) - .build()) + .bundling(bundlingOptions) .build())) .functionName(functionName) .handler("software.amazon.lambda.powertools.e2e.Function::handleRequest") .memorySize(1024) .timeout(Duration.seconds(timeout)) - .runtime(runtime.getCdkRuntime()) + .runtime(isGraalVMEnabled ? Runtime.PROVIDED_AL2023 : runtime.getCdkRuntime()) .environment(envVar) .tracing(tracing ? Tracing.ACTIVE : Tracing.DISABLED) .build(); @@ -457,17 +437,19 @@ private void synthesize() { private void uploadAssets() { Map<String, Asset> assets = findAssets(); assets.forEach((objectKey, asset) -> { - if (!asset.assetPath.endsWith(".jar")) { + // .zip will be used for GraalVM bundles. + if (!asset.assetPath.endsWith(".jar") && !asset.assetPath.endsWith(".zip")) { + LOG.info("Skipping upload of {}", asset); return; } + LOG.info("Uploading {}", asset); ListObjectsV2Response objects = s3 .listObjectsV2(ListObjectsV2Request.builder().bucket(asset.bucketName).build()); if (objects.contents().stream().anyMatch(o -> o.key().equals(objectKey))) { - LOG.debug("Asset already exists, skipping"); + LOG.debug("{} already exists, skipping", asset); return; } - LOG.info("Uploading asset " + objectKey + " to " + asset.bucketName); s3.putObject(PutObjectRequest.builder().bucket(asset.bucketName).key(objectKey).build(), Paths.get(cfnAssetDirectory, asset.assetPath)); }); diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile new file mode 100644 index 000000000..a244dd60d --- /dev/null +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -0,0 +1,14 @@ +# Use the official AWS SAM base image for Java 21 +FROM public.ecr.aws/sam/build-java21@sha256:a5554d68374e19450c6c88448516ac95a9acedc779f318040f5c230134b4e461 + +# Install GraalVM dependencies +RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz +RUN mv graalvm-jdk-21.* /usr/lib/graalvm + +# Make native image and mvn available on CLI +RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image +RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn + +# Set GraalVM as default +ENV JAVA_HOME=/usr/lib/graalvm +ENV PATH=/usr/lib/graalvm/bin:$PATH From 84e7ad0dafb2d9b55f6b1b6001845ae0f42e48bd Mon Sep 17 00:00:00 2001 From: Leandro Damascena <lcdama@amazon.pt> Date: Mon, 21 Jul 2025 17:08:40 +0100 Subject: [PATCH 289/577] chore(ci): add new dependabot package ecosystems (#1948) * Add new dependabot ecosystems * Addressing Philipp's comments --- .github/dependabot.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 73f454162..c2baff44e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,9 +1,24 @@ version: 2 updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + commit-message: + prefix: chore + + - package-ecosystem: docker + directories: + - "/powertools-e2e-tests" + - "/examples" + labels: [ ] + schedule: + interval: daily + - package-ecosystem: "maven" directory: "/" schedule: - interval: "weekly" + interval: "daily" labels: - "maven" - "dependencies" From f25af3c2c782a7117e8a571a0c858e88d873f89b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:50:05 +0200 Subject: [PATCH 290/577] chore: bump ossf/scorecard-action from 2.4.0 to 2.4.2 (#1950) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.0 to 2.4.2. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/62b2cac7ed8198b15735ed49ab1e5cf35480ba46...05b42c624433fc40578a4040d5cf5e36ddca8cde) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-version: 2.4.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 28c1ab261..2b0a9860b 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -39,7 +39,7 @@ jobs: with: persist-credentials: false - name: Run Analysis - uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 with: results_file: results.sarif results_format: sarif From b93dbaa79f356788b9e3326599ba128378f12023 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:50:36 +0200 Subject: [PATCH 291/577] build(deps): bump org.apache.maven.plugins:maven-gpg-plugin (#1951) Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.2.7 to 3.2.8. - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.2.7...maven-gpg-plugin-3.2.8) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-version: 3.2.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c7e850e32..3d9b01edd 100644 --- a/pom.xml +++ b/pom.xml @@ -107,7 +107,7 @@ <nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version> <maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version> <maven-source-plugin.version>3.3.0</maven-source-plugin.version> - <maven-gpg-plugin.version>3.2.7</maven-gpg-plugin.version> + <maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version> <junit.version>5.10.2</junit.version> <aws-embedded-metrics.version>4.1.2</aws-embedded-metrics.version> <jmespath.version>0.6.0</jmespath.version> From 552431692756384d084b1d6cebb14d92a9a28f83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:51:08 +0200 Subject: [PATCH 292/577] build(deps): bump com.amazonaws:aws-lambda-java-serialization (#1952) Bumps [com.amazonaws:aws-lambda-java-serialization](https://github.com/aws/aws-lambda-java-libs) from 1.1.5 to 1.1.6. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-serialization dependency-version: 1.1.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 3d9b01edd..92f133cc8 100644 --- a/pom.xml +++ b/pom.xml @@ -90,7 +90,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.0</lambda.events.version> - <lambda.serial.version>1.1.5</lambda.serial.version> + <lambda.serial.version>1.1.6</lambda.serial.version> <maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version> <aspectj.version>1.9.7</aspectj.version> <aspectj-maven-plugin.version>1.13.1</aspectj-maven-plugin.version> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index d0636baf2..8cdee8b5d 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -37,7 +37,7 @@ <kafka-clients.version>4.0.0</kafka-clients.version> <avro.version>1.12.0</avro.version> <protobuf.version>4.31.0</protobuf.version> - <lambda-serialization.version>1.1.5</lambda-serialization.version> + <lambda-serialization.version>1.1.6</lambda-serialization.version> </properties> <dependencies> From a12aadc97423291fbfb822a4e31c8a3625c68869 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:51:49 +0200 Subject: [PATCH 293/577] chore: bump actions/upload-artifact from 4.5.0 to 4.6.2 (#1953) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.5.0 to 4.6.2. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4.5.0...ea165f8d65b6e75b540449e92b4886f43607fa02) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 4.6.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- .github/workflows/security-scorecard.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dc462fbfc..ae2a90885 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -112,7 +112,7 @@ jobs: snapshot: ${{ inputs.snapshot}} - id: upload_source name: Upload artifacts - uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: if-no-files-found: error name: source diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 2b0a9860b..4f85a0322 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -46,7 +46,7 @@ jobs: publish_results: true repo_token: ${{ secrets.SCORECARD_TOKEN }} - name: Upload Results - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: SARIF file path: results.sarif From bc2d67971763a647c1188db436542ab514ec94be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:55:40 +0200 Subject: [PATCH 294/577] chore: bump dependabot/fetch-metadata from 2.3.0 to 2.4.0 (#1954) Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 2.3.0 to 2.4.0. - [Release notes](https://github.com/dependabot/fetch-metadata/releases) - [Commits](https://github.com/dependabot/fetch-metadata/compare/d7267f607e9d3fb96fc2fbe83e0af444713e90b7...08eff52bf64351f401fb50d4972fa95b9f2c2d1b) --- updated-dependencies: - dependency-name: dependabot/fetch-metadata dependency-version: 2.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-dependabot.yml b/.github/workflows/security-dependabot.yml index e1422fb2b..3baa20897 100644 --- a/.github/workflows/security-dependabot.yml +++ b/.github/workflows/security-dependabot.yml @@ -26,7 +26,7 @@ jobs: steps: - id: dependabot-metadata name: Fetch Dependabot metadata - uses: dependabot/fetch-metadata@d7267f607e9d3fb96fc2fbe83e0af444713e90b7 # v2.3.0 + uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b # v2.4.0 - name: Fail workflow if: ${{ steps.dependabot-metadata.outputs.update-type == 'version-update:semver-major' }} run: | From ad285d6b7e03d2a20ed15672a432f4f1cbd8729b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:58:08 +0200 Subject: [PATCH 295/577] build(deps): bump org.graalvm.buildtools:native-maven-plugin (#1956) Bumps [org.graalvm.buildtools:native-maven-plugin](https://github.com/graalvm/native-build-tools) from 0.10.1 to 0.11.0. - [Release notes](https://github.com/graalvm/native-build-tools/releases) - [Commits](https://github.com/graalvm/native-build-tools/compare/0.10.1...0.11.0) --- updated-dependencies: - dependency-name: org.graalvm.buildtools:native-maven-plugin dependency-version: 0.11.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- powertools-parameters/powertools-parameters-appconfig/pom.xml | 2 +- powertools-parameters/powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 6fbe62ec2..4c174fe06 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -158,7 +158,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.1</version> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 3336f6bd1..337e0101d 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -176,7 +176,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.1</version> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index 2239515f3..6320e8714 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -61,7 +61,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.1</version> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 27e2dbfb4..891a6380d 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -129,7 +129,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index fe32aa534..3f9748028 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -155,7 +155,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index fd081b963..50a569ea9 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -134,7 +134,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 6dc6167ab..1e8d6c1f4 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -124,7 +124,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 18b11f5c3..ba4084971 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -153,7 +153,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.6</version> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 2429d374c..ca4f1b46e 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -132,7 +132,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 825e50d90..554729e51 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -121,7 +121,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index b1bfaa5df..32f5d999a 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -122,7 +122,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 34031ca42..3aec19c87 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -122,7 +122,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index faecdf157..70d39a7ef 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -136,7 +136,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 55a3b9509..ec6190efa 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -132,7 +132,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index e0867b486..a496c5245 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -129,7 +129,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 4d8326d6b..13c6db97e 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -152,7 +152,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.2</version> <!-- or newer version --> + <version>0.11.0</version> <!-- or newer version --> <extensions>true</extensions> <executions> <execution> From 703e79fa447f413b731e5b9275072a003e547ac0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:59:29 +0200 Subject: [PATCH 296/577] chore: bump actions/setup-java from 3.11.0 to 4.7.1 (#1957) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 3.11.0 to 4.7.1. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v3.11.0...c5195efecf7bdfc987ee8bae7a71cb8b11521c00) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 4.7.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 2 +- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/check-pmd.yml | 2 +- .github/workflows/check-spotbugs.yml | 2 +- .github/workflows/release.yml | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index b5fe372dc..45fef40b9 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -96,7 +96,7 @@ jobs: name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Java - uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 with: distribution: corretto java-version: ${{ matrix.java }} diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 19500b2e5..345ea7548 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -58,7 +58,7 @@ jobs: steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: 'corretto' java-version: ${{ matrix.java }} @@ -91,7 +91,7 @@ jobs: steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup java - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: 'corretto' java-version: ${{ matrix.java }} diff --git a/.github/workflows/check-pmd.yml b/.github/workflows/check-pmd.yml index d97698af8..7ef10c1de 100644 --- a/.github/workflows/check-pmd.yml +++ b/.github/workflows/check-pmd.yml @@ -31,7 +31,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Java - uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: java-version: 21 distribution: corretto diff --git a/.github/workflows/check-spotbugs.yml b/.github/workflows/check-spotbugs.yml index fd76d9560..9f3333187 100644 --- a/.github/workflows/check-spotbugs.yml +++ b/.github/workflows/check-spotbugs.yml @@ -42,7 +42,7 @@ jobs: steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 - name: Setup Java - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: 'corretto' java-version: 21 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ae2a90885..9f3232bb6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -137,7 +137,7 @@ jobs: with: name: source - name: Setup Java - uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 with: distribution: corretto java-version: 21 @@ -172,7 +172,7 @@ jobs: with: name: source - name: Setup Java - uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 with: distribution: corretto java-version: ${{ matrix.java }} @@ -195,7 +195,7 @@ jobs: with: name: source - name: Setup Java - uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 with: distribution: corretto java-version: 21 From 79934fd49279c159f425404687bf67e9c4e8074e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 09:59:58 +0200 Subject: [PATCH 297/577] chore: bump github/codeql-action from 3.27.9 to 3.29.3 (#1958) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.9 to 3.29.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/df409f7d9260372bd5f19e5b04e83cb3c43714ae...d6bbdef45e766d081b84a2def353b0055f728d3e) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 4f85a0322..d800f9379 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 + uses: github/codeql-action/upload-sarif@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3 with: sarif_file: results.sarif From 1a09a7ddb4b2513364a3fc139bf84641c857a460 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:00:28 +0200 Subject: [PATCH 298/577] build(deps): bump com.google.protobuf:protobuf-java (#1959) Bumps [com.google.protobuf:protobuf-java](https://github.com/protocolbuffers/protobuf) from 4.31.0 to 4.31.1. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl) - [Commits](https://github.com/protocolbuffers/protobuf/compare/v4.31.0...v4.31.1) --- updated-dependencies: - dependency-name: com.google.protobuf:protobuf-java dependency-version: 4.31.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 4ea02a649..9e1034780 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -12,7 +12,7 @@ <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> <avro.version>1.12.0</avro.version> - <protobuf.version>4.31.0</protobuf.version> + <protobuf.version>4.31.1</protobuf.version> </properties> <dependencies> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 8cdee8b5d..454c07686 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -36,7 +36,7 @@ <properties> <kafka-clients.version>4.0.0</kafka-clients.version> <avro.version>1.12.0</avro.version> - <protobuf.version>4.31.0</protobuf.version> + <protobuf.version>4.31.1</protobuf.version> <lambda-serialization.version>1.1.6</lambda-serialization.version> </properties> From f8cc952b31e8b7a10a9010f9fcaad1caef5552d6 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 22 Jul 2025 10:48:08 +0200 Subject: [PATCH 299/577] chore(ci): Add Docker paths via globs to dependabot and update Dockerfiles to pin sha256 (#1960) * Add Docker paths to dependabot and update Dockerfiles to pin image version. * Remove dependabot auto-merging workflow. --- .github/dependabot.yml | 8 ++-- .github/workflows/security-dependabot.yml | 42 ------------------- .../sam-graalvm/Dockerfile | 2 +- .../sam-graalvm/Dockerfile | 2 +- .../sam-graalvm/Dockerfile | 2 +- 5 files changed, 8 insertions(+), 48 deletions(-) delete mode 100644 .github/workflows/security-dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c2baff44e..caa9934ca 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,11 +9,13 @@ updates: - package-ecosystem: docker directories: - - "/powertools-e2e-tests" - - "/examples" - labels: [ ] + - "/powertools-e2e-tests/src/test/resources/docker" + - "/docs" + - "/examples/**" schedule: interval: daily + commit-message: + prefix: chore - package-ecosystem: "maven" directory: "/" diff --git a/.github/workflows/security-dependabot.yml b/.github/workflows/security-dependabot.yml deleted file mode 100644 index 3baa20897..000000000 --- a/.github/workflows/security-dependabot.yml +++ /dev/null @@ -1,42 +0,0 @@ -# Auto merges dependabot PRs -# -# Description: -# Auto-merges dependabot PRs if all checks pass -# We verify all commits in the PR to ensure no one else has committed to the PR -# -# Triggers: -# - pull_request - -on: - pull_request: - branches: [ dependabot/* ] - -name: Dependabot updates -run-name: Dependabot - -permissions: - contents: read - -jobs: - dependabot: - runs-on: ubuntu-latest - if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'aws-powertools/powertools-lambda-java' }} - permissions: - pull-requests: write - steps: - - id: dependabot-metadata - name: Fetch Dependabot metadata - uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b # v2.4.0 - - name: Fail workflow - if: ${{ steps.dependabot-metadata.outputs.update-type == 'version-update:semver-major' }} - run: | - echo "::error::Major version upgrades are not wanted" - - name: Approve PR - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh pr review "${{ github.event.pull_request.html_url }}" --approve --body '🤖 Approved by another robot.' - - name: Enable auto-merge on PR - run: gh pr merge --auto --squash "${{ github.event.pull_request.html_url }}" - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/Dockerfile b/examples/powertools-examples-core-utilities/sam-graalvm/Dockerfile index a690606ad..8377d6dc7 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/Dockerfile +++ b/examples/powertools-examples-core-utilities/sam-graalvm/Dockerfile @@ -1,5 +1,5 @@ #Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21:latest +FROM public.ecr.aws/sam/build-java21@sha256:a5554d68374e19450c6c88448516ac95a9acedc779f318040f5c230134b4e461 #Install GraalVM dependencies RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz diff --git a/examples/powertools-examples-parameters/sam-graalvm/Dockerfile b/examples/powertools-examples-parameters/sam-graalvm/Dockerfile index a690606ad..8377d6dc7 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/Dockerfile +++ b/examples/powertools-examples-parameters/sam-graalvm/Dockerfile @@ -1,5 +1,5 @@ #Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21:latest +FROM public.ecr.aws/sam/build-java21@sha256:a5554d68374e19450c6c88448516ac95a9acedc779f318040f5c230134b4e461 #Install GraalVM dependencies RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz diff --git a/examples/powertools-examples-serialization/sam-graalvm/Dockerfile b/examples/powertools-examples-serialization/sam-graalvm/Dockerfile index a690606ad..8377d6dc7 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/Dockerfile +++ b/examples/powertools-examples-serialization/sam-graalvm/Dockerfile @@ -1,5 +1,5 @@ #Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21:latest +FROM public.ecr.aws/sam/build-java21@sha256:a5554d68374e19450c6c88448516ac95a9acedc779f318040f5c230134b4e461 #Install GraalVM dependencies RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From 429cc5b61c354382661b4b2f4be3d7e2750445c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 12:00:46 +0200 Subject: [PATCH 300/577] chore: bump squidfunk/mkdocs-material in /docs (#1961) Bumps squidfunk/mkdocs-material from `23b6978` to `0bfdba4`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: 0bfdba448e93984191246f7a28abeacc79f789e7e9cf0c639a48fe4365e880a7 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 8b5e5e275..d4f33c224 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -FROM squidfunk/mkdocs-material@sha256:23b69789b1dd836c53ea25b32f62ef8e1a23366037acd07c90959a219fd1f285 +FROM squidfunk/mkdocs-material@sha256:0bfdba448e93984191246f7a28abeacc79f789e7e9cf0c639a48fe4365e880a7 COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From 78237a1d9f8c6bc364c957530ef86d4dd7b0567c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 12:08:01 +0200 Subject: [PATCH 301/577] chore: bump sam/build-java21 (#1962) Bumps sam/build-java21 from `a5554d6` to `44e9166`. --- updated-dependencies: - dependency-name: sam/build-java21 dependency-version: 44e9166767b12df862da6f76b4622f89e3b97a31bab73bfbb3b1df13515bfd23 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index a244dd60d..927a221c4 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:a5554d68374e19450c6c88448516ac95a9acedc779f318040f5c230134b4e461 +FROM public.ecr.aws/sam/build-java21@sha256:44e9166767b12df862da6f76b4622f89e3b97a31bab73bfbb3b1df13515bfd23 # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From 47a41c71dadd74739663c5267ff41f5bb03927f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 12:08:26 +0200 Subject: [PATCH 302/577] chore: bump actions/checkout from 3.5.3 to 4.2.2 (#1963) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 4.2.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.5.3...11bd71901bbe5b1630ceea73d27597364c9af683) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 4.2.2 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/check-spotbugs.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 345ea7548..a50bc8838 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -56,7 +56,7 @@ jobs: - 21 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup java uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: @@ -89,7 +89,7 @@ jobs: - 21 steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup java uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: diff --git a/.github/workflows/check-spotbugs.yml b/.github/workflows/check-spotbugs.yml index 9f3333187..754672448 100644 --- a/.github/workflows/check-spotbugs.yml +++ b/.github/workflows/check-spotbugs.yml @@ -40,7 +40,7 @@ jobs: codecheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Java uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: From 79b21fcf9f13d97b1a8a3cc7cf553a8add131d40 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 12:08:51 +0200 Subject: [PATCH 303/577] build(deps): bump slf4j.version from 2.0.7 to 2.0.17 (#1964) Bumps `slf4j.version` from 2.0.7 to 2.0.17. Updates `org.slf4j:slf4j-api` from 2.0.7 to 2.0.17 Updates `org.slf4j:slf4j-simple` from 2.0.7 to 2.0.17 --- updated-dependencies: - dependency-name: org.slf4j:slf4j-api dependency-version: 2.0.17 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.slf4j:slf4j-simple dependency-version: 2.0.17 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 92f133cc8..a7a867339 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ <maven.compiler.target>11</maven.compiler.target> <maven.deploy.plugin.version>3.1.2</maven.deploy.plugin.version> <log4j.version>2.25.1</log4j.version> - <slf4j.version>2.0.7</slf4j.version> + <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.1</jackson.version> <aws.sdk.version>2.31.78</aws.sdk.version> <aws.xray.recorder.version>2.18.2</aws.xray.recorder.version> diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 09589595f..992f6d0e1 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -60,7 +60,7 @@ <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> - <version>2.0.7</version> + <version>2.0.17</version> <scope>test</scope> </dependency> <dependency> From 560bbaa98dc1ecf38e97148d4125c900736f924b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 12:21:28 +0200 Subject: [PATCH 304/577] chore: bump actions/dependency-review-action from 4.5.0 to 4.7.1 (#1968) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.5.0 to 4.7.1. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/3b139cfc5fae8b618d3eae3675e383bb1769c019...da24556b548a50705dd671f47852072ea4c105d9) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.7.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-dependencies-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml index 9c588d9be..108ba26fe 100644 --- a/.github/workflows/security-dependencies-check.yml +++ b/.github/workflows/security-dependencies-check.yml @@ -34,6 +34,6 @@ jobs: - name: Checkout Repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Verify Contents - uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 + uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 with: config-file: './.github/dependency-review-config.yml' \ No newline at end of file From 567dc6bce3dbfa02fdc0a766ac72106c29def735 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 13:27:33 +0200 Subject: [PATCH 305/577] chore: bump aws-actions/configure-aws-credentials from 2.2.0 to 4.2.1 (#1965) Bumps [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) from 2.2.0 to 4.2.1. - [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases) - [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/v2.2.0...b47578312673ae6fa5b5096b330d9fbac3d116df) --- updated-dependencies: - dependency-name: aws-actions/configure-aws-credentials dependency-version: 4.2.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 2 +- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/release.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 5d6870171..f9cbfe1ea 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -41,7 +41,7 @@ jobs: docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index a50bc8838..020b89b2a 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -64,7 +64,7 @@ jobs: java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -97,7 +97,7 @@ jobs: java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9f3232bb6..988f7fb79 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -278,7 +278,7 @@ jobs: docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@ececac1a45f3b08a01d2dd070d28d111c5fe6722 + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} From 07ecd3ce19ba6937f323b0d0e810f64858d877d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 13:37:17 +0200 Subject: [PATCH 306/577] build(deps): bump commons-io:commons-io from 2.19.0 to 2.20.0 (#1966) Bumps [commons-io:commons-io](https://github.com/apache/commons-io) from 2.19.0 to 2.20.0. - [Changelog](https://github.com/apache/commons-io/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-io/compare/rel/commons-io-2.19.0...rel/commons-io-2.20.0) --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-version: 2.20.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 3bbaca3e2..eed632ea0 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -103,7 +103,7 @@ <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> - <version>2.19.0</version> + <version>2.20.0</version> </dependency> <dependency> From f4421d81099aac8753198a254f863ba3455bcda8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 13:37:44 +0200 Subject: [PATCH 307/577] chore: bump actions/download-artifact from 4.2.1 to 4.3.0 (#1967) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.2.1 to 4.3.0. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/95815c38cf2ff2164869cbab79da8d1f422bc89e...d3f86a106a0bac45b974a628896c90dbdf5c8093) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 4.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 988f7fb79..a56301591 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -133,7 +133,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.6.1 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.6.1 with: name: source - name: Setup Java @@ -168,7 +168,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.6.1 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.6.1 with: name: source - name: Setup Java @@ -191,7 +191,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.6.1 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.6.1 with: name: source - name: Setup Java @@ -229,7 +229,7 @@ jobs: ref: ${{ env.RELEASE_COMMIT }} - id: download_source name: Download artifacts - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.6.1 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.6.1 with: name: source - id: setup-git From dc8692743fe9122040d39b8d8c4e2255c91a09c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 13:38:15 +0200 Subject: [PATCH 308/577] build(deps): bump jackson.version from 2.19.1 to 2.19.2 (#1969) Bumps `jackson.version` from 2.19.1 to 2.19.2. Updates `com.fasterxml.jackson.core:jackson-databind` from 2.19.1 to 2.19.2 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.core:jackson-core` from 2.19.1 to 2.19.2 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.19.1...jackson-core-2.19.2) Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.19.1 to 2.19.2 --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-version: 2.19.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-version: 2.19.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-version: 2.19.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Leandro Damascena <lcdama@amazon.pt> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a7a867339..d3e871b7e 100644 --- a/pom.xml +++ b/pom.xml @@ -83,7 +83,7 @@ <maven.deploy.plugin.version>3.1.2</maven.deploy.plugin.version> <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> - <jackson.version>2.19.1</jackson.version> + <jackson.version>2.19.2</jackson.version> <aws.sdk.version>2.31.78</aws.sdk.version> <aws.xray.recorder.version>2.18.2</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> From c4ac6619f05ac18c4247bd91265acee310ca8ff4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 13:39:33 +0200 Subject: [PATCH 309/577] build(deps): bump mockito.version from 4.11.0 to 5.18.0 (#1970) Bumps `mockito.version` from 4.11.0 to 5.18.0. Updates `org.mockito:mockito-core` from 4.11.0 to 5.18.0 - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v4.11.0...v5.18.0) Updates `org.mockito:mockito-subclass` from 5.6.0 to 5.18.0 - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.6.0...v5.18.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-version: 5.18.0 dependency-type: direct:production update-type: version-update:semver-major - dependency-name: org.mockito:mockito-subclass dependency-version: 5.18.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- powertools-common/pom.xml | 4 ++-- powertools-logging/pom.xml | 4 ++-- powertools-logging/powertools-logging-log4j/pom.xml | 4 ++-- powertools-logging/powertools-logging-logback/pom.xml | 4 ++-- powertools-parameters/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-appconfig/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-dynamodb/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-secrets/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-ssm/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-tests/pom.xml | 4 ++-- powertools-serialization/pom.xml | 4 ++-- powertools-tracing/pom.xml | 4 ++-- 16 files changed, 28 insertions(+), 28 deletions(-) diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index a56eae46d..010d313fa 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -63,7 +63,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> - <version>4.11.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> <dependency> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 337e0101d..95887d566 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -76,7 +76,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> - <version>5.1.1</version> + <version>5.18.0</version> <scope>test</scope> </dependency> <dependency> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index c729ed83c..45c71e3ed 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -50,7 +50,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> - <version>5.1.1</version> + <version>5.18.0</version> <scope>test</scope> </dependency> <dependency> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 6955fc4ea..153a2f77f 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -53,7 +53,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> - <version>4.11.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> <dependency> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 891a6380d..37039f51b 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -94,7 +94,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -120,7 +120,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 3f9748028..b86935998 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -120,7 +120,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -146,7 +146,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 50a569ea9..6b1212d45 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -99,7 +99,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -125,7 +125,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 1e8d6c1f4..6adbde9de 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -92,7 +92,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -115,7 +115,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index ca4f1b46e..c8ae5fe34 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -97,7 +97,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -123,7 +123,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 554729e51..823d99698 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -86,7 +86,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -112,7 +112,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 32f5d999a..1194418e9 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -87,7 +87,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -113,7 +113,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 3aec19c87..12d72b58b 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -87,7 +87,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -113,7 +113,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 70d39a7ef..1701140eb 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -101,7 +101,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -127,7 +127,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index ec6190efa..a4ff090ef 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -97,7 +97,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -123,7 +123,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.6.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index a496c5245..56e639ced 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -97,7 +97,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -120,7 +120,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 13c6db97e..7b430f869 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -117,7 +117,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -143,7 +143,7 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.17.0</version> + <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> From c08e1ef92e9c342bd247909a6b9a6bd158bb5a9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Jul 2025 13:41:53 +0200 Subject: [PATCH 310/577] chore: bump org.apache.maven.plugins:maven-compiler-plugin (#1972) Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.13.0 to 3.14.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.13.0...maven-compiler-plugin-3.14.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-version: 3.14.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index d6a4dc3cf..d15907cd3 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -16,7 +16,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> - <version>3.13.0</version> + <version>3.14.0</version> <configuration> <source>11</source> <target>11</target> diff --git a/pom.xml b/pom.xml index d3e871b7e..9c353dbc4 100644 --- a/pom.xml +++ b/pom.xml @@ -91,7 +91,7 @@ <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.0</lambda.events.version> <lambda.serial.version>1.1.6</lambda.serial.version> - <maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version> + <maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version> <aspectj.version>1.9.7</aspectj.version> <aspectj-maven-plugin.version>1.13.1</aspectj-maven-plugin.version> <maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index eed632ea0..7a65c04e5 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -194,7 +194,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> - <version>3.13.0</version> + <version>3.14.0</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> From 9f239f5a05521ed7dbf07d4cc729df3aa21732d1 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 24 Jul 2025 14:37:47 +0200 Subject: [PATCH 311/577] chore(ci): Remove osv workflow. (#1973) Co-authored-by: Leandro Damascena <lcdama@amazon.pt> --- .github/workflows/security-osv.yml | 35 ------------------------------ 1 file changed, 35 deletions(-) delete mode 100644 .github/workflows/security-osv.yml diff --git a/.github/workflows/security-osv.yml b/.github/workflows/security-osv.yml deleted file mode 100644 index 73d6b1835..000000000 --- a/.github/workflows/security-osv.yml +++ /dev/null @@ -1,35 +0,0 @@ -# Runs OSV scan -# -# Description: -# Checks dependencies already in the project for known issues -# -# Triggers: -# - pull_request -# - workflow_dispatch -# - cron -# - push - -on: - pull_request: - branches: - - main - workflow_dispatch: {} - schedule: - - cron: "30 12 * * 1" - push: - branches: - - main - -name: OpenSource Vulnerability Scanner -run-name: OpenSource Vulnerability Scanner - -permissions: - contents: read - -jobs: - scan-pr: - permissions: - actions: read - contents: read - security-events: write - uses: google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@b00f71e051ddddc6e46a193c31c8c0bf283bf9e6 # v2.1.0 From 2ebd14225047b8c4d7e8f8a374b9232219e3c05c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 14:39:13 +0200 Subject: [PATCH 312/577] chore: bump com.networknt:json-schema-validator from 1.5.1 to 1.5.8 (#1974) Bumps [com.networknt:json-schema-validator](https://github.com/networknt/json-schema-validator) from 1.5.1 to 1.5.8. - [Release notes](https://github.com/networknt/json-schema-validator/releases) - [Changelog](https://github.com/networknt/json-schema-validator/blob/master/CHANGELOG.md) - [Commits](https://github.com/networknt/json-schema-validator/compare/1.5.1...1.5.8) --- updated-dependencies: - dependency-name: com.networknt:json-schema-validator dependency-version: 1.5.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- powertools-validation/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index b51b531fa..73a150917 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -65,7 +65,7 @@ <dependency> <groupId>com.networknt</groupId> <artifactId>json-schema-validator</artifactId> - <version>1.5.1</version> + <version>1.5.8</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> From 3fa2b455e7c13ee166d35abc7405d6d2d0f0b379 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jul 2025 15:02:01 +0200 Subject: [PATCH 313/577] build(deps): bump aws.sdk.version from 2.31.78 to 2.32.5 (#1971) Bumps `aws.sdk.version` from 2.31.78 to 2.32.5. Updates `software.amazon.awssdk:bom` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:http-client-spi` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:url-connection-client` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:dynamodb` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:s3` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:lambda` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:kinesis` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:cloudwatch` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:xray` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:sqs` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:cloudformation` from 2.31.78 to 2.32.5 Updates `software.amazon.awssdk:sts` from 2.31.78 to 2.32.5 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.5 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.5 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.5 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index d6c2dbca0..1f0771eff 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.0</lambda.events.version> - <aws.sdk.version>2.31.78</aws.sdk.version> + <aws.sdk.version>2.32.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 9c353dbc4..45fdcdb29 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.31.78</aws.sdk.version> + <aws.sdk.version>2.32.5</aws.sdk.version> <aws.xray.recorder.version>2.18.2</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> From 2bb51d8064919ac4795c8ab8b6fb603fc2c65530 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 29 Jul 2025 09:59:19 +0200 Subject: [PATCH 314/577] fix(parameters): Correctly check for empty values in AppConfig Parameters Provider. (#1982) * fix(parameters): Correctly check for empty values in AppConfig Parameters Provider. * fix pmd findings. --- .../appconfig/AppConfigProvider.java | 44 +++++----- .../appconfig/AppConfigProviderTest.java | 84 ++++++++++--------- 2 files changed, 66 insertions(+), 62 deletions(-) diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java index 5fd272c9b..37f07ae7a 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java @@ -16,6 +16,8 @@ import java.util.HashMap; import java.util.Map; + +import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationRequest; import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationResponse; @@ -44,10 +46,10 @@ public class AppConfigProvider extends BaseProvider { private final AppConfigDataClient client; private final String application; private final String environment; - private final HashMap<String, EstablishedSession> establishedSessions = new HashMap<>(); + private final Map<String, EstablishedSession> establishedSessions = new HashMap<>(); AppConfigProvider(CacheManager cacheManager, TransformationManager transformationManager, - AppConfigDataClient client, String environment, String application) { + AppConfigDataClient client, String environment, String application) { super(cacheManager, transformationManager); this.client = client; this.application = application; @@ -63,7 +65,6 @@ public static AppConfigProviderBuilder builder() { return new AppConfigProviderBuilder(); } - /** * Retrieve the parameter value from the AppConfig parameter store.<br /> * @@ -76,13 +77,12 @@ protected String getValue(String key) { // so that we can the initial token. If we already have a session, we can take // the next request token from there. EstablishedSession establishedSession = establishedSessions.getOrDefault(key, null); - String sessionToken = establishedSession != null ? - establishedSession.nextSessionToken : - client.startConfigurationSession(StartConfigurationSessionRequest.builder() - .applicationIdentifier(this.application) - .environmentIdentifier(this.environment) - .configurationProfileIdentifier(key) - .build()) + String sessionToken = establishedSession != null ? establishedSession.nextSessionToken + : client.startConfigurationSession(StartConfigurationSessionRequest.builder() + .applicationIdentifier(this.application) + .environmentIdentifier(this.environment) + .configurationProfileIdentifier(key) + .build()) .initialConfigurationToken(); // Get the configuration using the token @@ -93,16 +93,18 @@ protected String getValue(String key) { // Get the next session token we'll use next time we are asked for this key String nextSessionToken = response.nextPollConfigurationToken(); - // Get the value of the key. Note that AppConfig will return null if the value - // has not changed since we last asked for it in this session - in this case - // we return the value we stashed at last request. - String value = response.configuration() != null ? - response.configuration().asUtf8String() : // if we have a new value, use it - establishedSession != null ? - establishedSession.lastConfigurationValue : - // if we don't but we have a previous value, use that - null; // otherwise we've got no value - + // Get the value of the key. Note that AppConfig will return an empty value if the configuration has not changed + // since we last asked for it in this session - in this case we return the value we stashed at last request. + // https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-code-samples-using-API-read-configuration.html + SdkBytes configFromApi = response.configuration(); + String value; + if (configFromApi != null && configFromApi.asByteArray().length != 0) { + value = configFromApi.asUtf8String(); + } else if (establishedSession != null) { + value = establishedSession.lastConfigurationValue; + } else { + value = null; + } // Update the cache so we can get the next value later establishedSessions.put(key, new EstablishedSession(nextSessionToken, value)); @@ -116,7 +118,7 @@ protected Map<String, String> getMultipleValues(String path) { "Retrieving multiple parameter values is not supported with the AWS App Config Provider"); } - private static class EstablishedSession { + private static final class EstablishedSession { private final String nextSessionToken; private final String lastConfigurationValue; diff --git a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java index 039611875..da01d7d9a 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java @@ -14,9 +14,9 @@ package software.amazon.lambda.powertools.parameters.appconfig; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatRuntimeException; -import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.MockitoAnnotations.openMocks; import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; @@ -27,6 +27,7 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; + import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; import software.amazon.awssdk.services.appconfigdata.model.GetLatestConfigurationRequest; @@ -36,11 +37,11 @@ import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; -public class AppConfigProviderTest { +class AppConfigProviderTest { - private final String environmentName = "test"; - private final String applicationName = "fakeApp"; - private final String defaultTestKey = "key1"; + private static final String ENVIRONMENT_NAME = "test"; + private static final String DEFAULT_TEST_KEY = "key1"; + private static final String APPLICATION_NAME = "fakeApp"; @Mock AppConfigDataClient client; @@ -53,19 +54,18 @@ public class AppConfigProviderTest { private AppConfigProvider provider; @BeforeEach - public void init() { + void init() { openMocks(this); provider = AppConfigProvider.builder() .withClient(client) - .withApplication(applicationName) - .withEnvironment(environmentName) + .withApplication(APPLICATION_NAME) + .withEnvironment(ENVIRONMENT_NAME) .withCacheManager(new CacheManager()) .withTransformationManager(new TransformationManager()) .build(); } - /** * Tests repeated calls to the AppConfigProvider for the same key behave correctly. This is more complicated than * it seems, as the service itself will return no-data if the value of a property remains unchanged since the @@ -73,7 +73,7 @@ public void init() { * subsequent calls should once again return the new data. */ @Test - public void getValueRetrievesValue() { + void getValueRetrievesValue() { // Arrange StartConfigurationSessionResponse firstSession = StartConfigurationSessionResponse.builder() .initialConfigurationToken("token1") @@ -92,24 +92,32 @@ public void getValueRetrievesValue() { GetLatestConfigurationResponse thirdResponse = GetLatestConfigurationResponse.builder() .nextPollConfigurationToken("token4") .build(); + // Forth response returns empty, which means the provider should yield the previous value again + GetLatestConfigurationResponse forthResponse = GetLatestConfigurationResponse.builder() + .nextPollConfigurationToken("token5") + .configuration(SdkBytes.fromUtf8String("")) + .build(); Mockito.when(client.startConfigurationSession(startSessionRequestCaptor.capture())) .thenReturn(firstSession); Mockito.when(client.getLatestConfiguration(getLatestConfigurationRequestCaptor.capture())) - .thenReturn(firstResponse, secondResponse, thirdResponse); + .thenReturn(firstResponse, secondResponse, thirdResponse, forthResponse); // Act - String returnedValue1 = provider.getValue(defaultTestKey); - String returnedValue2 = provider.getValue(defaultTestKey); - String returnedValue3 = provider.getValue(defaultTestKey); + String returnedValue1 = provider.getValue(DEFAULT_TEST_KEY); + String returnedValue2 = provider.getValue(DEFAULT_TEST_KEY); + String returnedValue3 = provider.getValue(DEFAULT_TEST_KEY); + String returnedValue4 = provider.getValue(DEFAULT_TEST_KEY); // Assert assertThat(returnedValue1).isEqualTo(firstResponse.configuration().asUtf8String()); assertThat(returnedValue2).isEqualTo(secondResponse.configuration().asUtf8String()); assertThat(returnedValue3).isEqualTo(secondResponse.configuration() .asUtf8String()); // Third response is mocked to return null and should re-use previous value - assertThat(startSessionRequestCaptor.getValue().applicationIdentifier()).isEqualTo(applicationName); - assertThat(startSessionRequestCaptor.getValue().environmentIdentifier()).isEqualTo(environmentName); - assertThat(startSessionRequestCaptor.getValue().configurationProfileIdentifier()).isEqualTo(defaultTestKey); + assertThat(returnedValue4).isEqualTo(secondResponse.configuration() + .asUtf8String()); // Forth response is mocked to return empty and should re-use previous value + assertThat(startSessionRequestCaptor.getValue().applicationIdentifier()).isEqualTo(APPLICATION_NAME); + assertThat(startSessionRequestCaptor.getValue().environmentIdentifier()).isEqualTo(ENVIRONMENT_NAME); + assertThat(startSessionRequestCaptor.getValue().configurationProfileIdentifier()).isEqualTo(DEFAULT_TEST_KEY); assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(0).configurationToken()).isEqualTo( firstSession.initialConfigurationToken()); assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo( @@ -119,8 +127,7 @@ public void getValueRetrievesValue() { } @Test - public void getValueNoValueExists() { - + void getValueNoValueExists() { // Arrange StartConfigurationSessionResponse session = StartConfigurationSessionResponse.builder() .initialConfigurationToken("token1") @@ -134,11 +141,10 @@ public void getValueNoValueExists() { .thenReturn(response); // Act - String returnedValue = provider.getValue(defaultTestKey); - + String returnedValue = provider.getValue(DEFAULT_TEST_KEY); // Assert - assertThat(returnedValue).isEqualTo(null); + assertThat(returnedValue).isNull(); } /** @@ -146,7 +152,7 @@ public void getValueNoValueExists() { * work as expected. This means two separate configuration sessions should be established with AppConfig. */ @Test - public void multipleKeysRetrievalWorks() { + void multipleKeysRetrievalWorks() { // Arrange String param1Key = "key1"; StartConfigurationSessionResponse param1Session = StartConfigurationSessionResponse.builder() @@ -184,49 +190,45 @@ public void multipleKeysRetrievalWorks() { param1Session.initialConfigurationToken()); assertThat(getLatestConfigurationRequestCaptor.getAllValues().get(1).configurationToken()).isEqualTo( param2Session.initialConfigurationToken()); - } @Test - public void getMultipleValuesThrowsException() { - + void getMultipleValuesThrowsException() { // Act & Assert assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path")) .withMessage("Retrieving multiple parameter values is not supported with the AWS App Config Provider"); } @Test - public void testAppConfigProviderBuilderMissingEnvironment_throwsException() { - + void testAppConfigProviderBuilderMissingEnvironment_throwsException() { // Act & Assert assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder() - .withCacheManager(new CacheManager()) - .withApplication(applicationName) - .withClient(client) - .build()) + .withCacheManager(new CacheManager()) + .withApplication(APPLICATION_NAME) + .withClient(client) + .build()) .withMessage("No environment provided; please provide one"); } @Test - public void testAppConfigProviderBuilderMissingApplication_throwsException() { - + void testAppConfigProviderBuilderMissingApplication_throwsException() { // Act & Assert assertThatIllegalStateException().isThrownBy(() -> AppConfigProvider.builder() - .withCacheManager(new CacheManager()) - .withEnvironment(environmentName) - .withClient(client) - .build()) + .withCacheManager(new CacheManager()) + .withEnvironment(ENVIRONMENT_NAME) + .withClient(client) + .build()) .withMessage("No application provided; please provide one"); } - @Test - public void testAppConfigProvider_withoutParameter_shouldHaveDefaultTransformationManager() { + @Test + void testAppConfigProvider_withoutParameter_shouldHaveDefaultTransformationManager() { // Act AppConfigProvider appConfigProvider = AppConfigProvider.builder() .withEnvironment("test") .withApplication("app") .build(); // Assert - assertDoesNotThrow(()->appConfigProvider.withTransformation(json)); + assertDoesNotThrow(() -> appConfigProvider.withTransformation(json)); } } From 9728cf47b74076e7fef0da459c8c95b61e6b2518 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 10:16:03 +0200 Subject: [PATCH 315/577] chore: bump com.amazonaws:aws-lambda-java-events from 3.16.0 to 3.16.1 (#1975) Bumps [com.amazonaws:aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs) from 3.16.0 to 3.16.1. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-events dependency-version: 3.16.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- examples/powertools-examples-core-utilities/serverless/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- examples/powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- pom.xml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 1f0771eff..d8b01aa41 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -13,7 +13,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> - <lambda.events.version>3.16.0</lambda.events.version> + <lambda.events.version>3.16.1</lambda.events.version> <aws.sdk.version>2.32.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 1f0f9f4ef..1d40289d9 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -41,7 +41,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> - <version>3.16.0</version> + <version>3.16.1</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 4c174fe06..468b9ac3b 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -39,7 +39,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> - <version>3.16.0</version> + <version>3.16.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index ba436c650..dd675ae65 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -38,7 +38,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> - <version>3.16.0</version> + <version>3.16.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index b62f193aa..6f92663c4 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -38,7 +38,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> - <version>3.16.0</version> + <version>3.16.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index a09b26ac6..74d2cd78b 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -38,7 +38,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> - <version>3.16.0</version> + <version>3.16.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 010d313fa..2eb307f8b 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -52,7 +52,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> - <version>3.16.0</version> + <version>3.16.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 95887d566..cd689787f 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -39,7 +39,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> - <version>3.16.0</version> + <version>3.16.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 45c71e3ed..978e0313e 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -38,7 +38,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> - <version>3.16.0</version> + <version>3.16.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index 6320e8714..d34d168c9 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -31,7 +31,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> - <version>3.16.0</version> + <version>3.16.1</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index ed70081a2..39673f15f 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -31,7 +31,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> - <version>3.16.0</version> + <version>3.16.1</version> </dependency> </dependencies> diff --git a/pom.xml b/pom.xml index 45fdcdb29..bc72893ad 100644 --- a/pom.xml +++ b/pom.xml @@ -89,7 +89,7 @@ <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <lambda.core.version>1.3.0</lambda.core.version> - <lambda.events.version>3.16.0</lambda.events.version> + <lambda.events.version>3.16.1</lambda.events.version> <lambda.serial.version>1.1.6</lambda.serial.version> <maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version> <aspectj.version>1.9.7</aspectj.version> From 100c146ad8a9ad66ffeabd6ad3ab4fba46a2b7c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 10:16:41 +0200 Subject: [PATCH 316/577] chore: bump aws.sdk.version from 2.31.78 to 2.32.6 (#1976) Bumps `aws.sdk.version` from 2.31.78 to 2.32.6. Updates `software.amazon.awssdk:url-connection-client` from 2.31.78 to 2.32.6 Updates `software.amazon.awssdk:sdk-core` from 2.31.78 to 2.32.6 Updates `software.amazon.awssdk:s3` from 2.31.78 to 2.32.6 Updates `software.amazon.awssdk:kinesis` from 2.31.78 to 2.32.6 Updates `software.amazon.awssdk:sqs` from 2.31.78 to 2.32.6 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.31.78 to 2.32.6 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.32.6 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.32.6 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index abc4d660b..7db5a9688 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.31.78</sdk.version> + <sdk.version>2.32.6</sdk.version> </properties> <dependencies> From 0f2420c5de272b6a33634a835ef64ffac747a904 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 10:17:12 +0200 Subject: [PATCH 317/577] chore: bump org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions (#1977) Bumps org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions from 0.1.0 to 0.2.0. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions dependency-version: 0.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 468b9ac3b..acc8b55e4 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -135,7 +135,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> </dependencies> </plugin> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index cd689787f..98dfb6d82 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -153,7 +153,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> </dependencies> </plugin> From f050d35b15069cb7756402ff646cc639108960ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 10:17:34 +0200 Subject: [PATCH 318/577] chore: bump github/codeql-action from 3.29.3 to 3.29.4 (#1978) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.3 to 3.29.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/d6bbdef45e766d081b84a2def353b0055f728d3e...4e828ff8d448a8a6e532957b1811f387a63867e8) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index d800f9379..1d88a8b9f 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@d6bbdef45e766d081b84a2def353b0055f728d3e # v3.29.3 + uses: github/codeql-action/upload-sarif@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4 with: sarif_file: results.sarif From ad36ab3f0fd1deb5da9af008494f1771401da7cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 10:17:53 +0200 Subject: [PATCH 319/577] build(deps): bump com.amazonaws:aws-lambda-java-tests (#1979) Bumps [com.amazonaws:aws-lambda-java-tests](https://github.com/aws/aws-lambda-java-libs) from 1.1.1 to 1.1.2. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-tests dependency-version: 1.1.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index bc72893ad..1a1d2ea58 100644 --- a/pom.xml +++ b/pom.xml @@ -370,7 +370,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-tests</artifactId> - <version>1.1.1</version> + <version>1.1.2</version> <scope>test</scope> </dependency> <dependency> From aa864c90db62aaaea83538002275cbf76dd50480 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 10:18:22 +0200 Subject: [PATCH 320/577] build(deps): bump io.github.ascopes:protobuf-maven-plugin (#1980) Bumps [io.github.ascopes:protobuf-maven-plugin](https://github.com/ascopes/protobuf-maven-plugin) from 3.3.0 to 3.6.1. - [Release notes](https://github.com/ascopes/protobuf-maven-plugin/releases) - [Commits](https://github.com/ascopes/protobuf-maven-plugin/compare/v3.3.0...v3.6.1) --- updated-dependencies: - dependency-name: io.github.ascopes:protobuf-maven-plugin dependency-version: 3.6.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 9e1034780..b962c0136 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -141,7 +141,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.3.0</version> + <version>3.6.1</version> <executions> <execution> <goals> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 454c07686..3056cc33d 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -181,7 +181,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.3.0</version> + <version>3.6.1</version> <executions> <execution> <id>generate-test-sources</id> From c70a9dd0c256e101e2d8492555607bc493037581 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:54:24 +0200 Subject: [PATCH 321/577] chore(ci): bump version to 2.2.1 (#1983) Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/README.md | 4 ++-- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- .../powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 44 files changed, 51 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 3ea636922..d5f240b6e 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-metrics</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> </dependency> ... </dependencies> diff --git a/examples/pom.xml b/examples/pom.xml index 4bea96700..bbf2f991e 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-examples</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Examples</name> diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 7db5a9688..0d288f8ba 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-batch</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Batch</name> diff --git a/examples/powertools-examples-cloudformation/README.md b/examples/powertools-examples-cloudformation/README.md index f0a15f1cd..98302aab9 100644 --- a/examples/powertools-examples-cloudformation/README.md +++ b/examples/powertools-examples-cloudformation/README.md @@ -15,7 +15,7 @@ Run the following in your shell: ```bash cd infra/sam sam build -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-20230718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.2.1718 ``` ### Deploy with CDK @@ -32,5 +32,5 @@ To build and deploy this application for the first time, run the following in yo cd infra/cdk mvn package cdk synth -cdk deploy -c BucketNameParam=my-unique-bucket-20230718 +cdk deploy -c BucketNameParam=my-unique-bucket-2.2.1718 ``` \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index d8b01aa41..96f9c0337 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-cloudformation</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 1d40289d9..67705c89e 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ <groupId>software.amazon.lambda.examples</groupId> <!-- TODO TODO TODO this should build from SNAPSHOT, but it doesn't, because the snapshots don't appear in the docker environment CDK builds it in in our CDK tests. How to procede? V2 blocker --> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-core-utilities-cdk</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index d15907cd3..0a2949658 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <artifactId>cdk</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.162.1</cdk.version> diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 4cee5ecfa..124c7b60b 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.2.0' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.2.0' - aspect 'software.amazon.lambda:powertools-metrics:2.2.0' + aspect 'software.amazon.lambda:powertools-tracing:2.2.1' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.2.1' + aspect 'software.amazon.lambda:powertools-metrics:2.2.1' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index e769c3c45..25ff24fac 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.2.0") - aspect("software.amazon.lambda:powertools-logging-log4j:2.2.0") - aspect("software.amazon.lambda:powertools-metrics:2.2.0") + aspect("software.amazon.lambda:powertools-tracing:2.2.1") + aspect("software.amazon.lambda:powertools-logging-log4j:2.2.1") + aspect("software.amazon.lambda:powertools-metrics:2.2.1") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index acc8b55e4..d0fb3b8ea 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-core-utilities-sam-graalvm</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index dd675ae65..0208798fc 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-core-utilities-sam</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 6f92663c4..a715553fb 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-core-utilities-serverless</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 74d2cd78b..c80a9566d 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-core-utilities-terraform</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 2eb307f8b..96f5002fe 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-idempotency</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency</name> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index b962c0136..7c87a964b 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-kafka</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Kafka</name> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 98dfb6d82..fcdf1ffef 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-parameters-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 978e0313e..129095534 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-parameters-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters</name> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index d34d168c9..a67433a08 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-serialization-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 39673f15f..78bb6caad 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-serialization-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization</name> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 153a2f77f..1227acc42 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <artifactId>powertools-examples-validation</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Validation</name> diff --git a/mkdocs.yml b/mkdocs.yml index 9b70afcb3..e258d8c5a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -121,7 +121,7 @@ extra_javascript: extra: powertools: - version: 2.2.0 + version: 2.2.1 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index 1a1d2ea58..4a8dcf0b9 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Parent</name> diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 992f6d0e1..74eae5726 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <description>A suite of utilities that makes batch message processing using AWS Lambda easier.</description> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index a5888bf5d..b4d247178 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <name>Powertools for AWS Lambda (Java) - Cloudformation</name> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 37039f51b..adc86547d 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <name>Powertools for AWS Lambda (Java) - Common Internal Utilities</name> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 7a65c04e5..38cd6a135 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <artifactId>powertools-e2e-tests</artifactId> diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index f40bc7ee6..08eefc473 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <artifactId>powertools-idempotency</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index c8f1e58d6..0f2c2dec1 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <artifactId>powertools-idempotency-core</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index 701259da3..3c3304bf9 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <artifactId>powertools-idempotency-dynamodb</artifactId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 3056cc33d..0e1a85b6d 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <artifactId>powertools-kafka</artifactId> diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 6b9b258ca..c9bfb2476 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <artifactId>powertools-large-messages</artifactId> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index b86935998..e6b9d6603 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <name>Powertools for AWS Lambda (Java) - Logging</name> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 6b1212d45..836ded5ed 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 6adbde9de..1ad566809 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index ba4084971..b91789b4b 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <name>Powertools for AWS Lambda (Java) - Metrics</name> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index c8ae5fe34..1bc7efb52 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <artifactId>powertools-parameters</artifactId> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 823d99698..06567c284 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 1194418e9..39b1bf083 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 12d72b58b..6d156e13c 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 1701140eb..3b7916e3e 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index a4ff090ef..b83793200 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.0</version> + <version>2.2.1</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 56e639ced..9905d0f82 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <artifactId>powertools-serialization</artifactId> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 7b430f869..2fa82e708 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <name>Powertools for AWS Lambda (Java) - Tracing</name> diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 73a150917..b845bdb20 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.0</version> + <version>2.2.1</version> </parent> <name>Powertools for AWS Lambda (Java) - Validation</name> From b84c531e5247688d540772b37d63c3a3a1142ccf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jul 2025 13:50:54 +0200 Subject: [PATCH 322/577] chore: bump squidfunk/mkdocs-material in /docs (#1984) Bumps squidfunk/mkdocs-material from `0bfdba4` to `bb7b015`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: bb7b015690d9fb5ef0dbc98ca3520f153aa43129fb96aec5ca54c9154dc3b729 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index d4f33c224..858c60705 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -FROM squidfunk/mkdocs-material@sha256:0bfdba448e93984191246f7a28abeacc79f789e7e9cf0c639a48fe4365e880a7 +FROM squidfunk/mkdocs-material@sha256:bb7b015690d9fb5ef0dbc98ca3520f153aa43129fb96aec5ca54c9154dc3b729 COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From adc0a31acbed0215e257b12ab68484f2ca1f04ec Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Wed, 30 Jul 2025 18:26:50 +0200 Subject: [PATCH 323/577] docs(examples): Enable end to end tracing for SQS batch example. (#1995) --- .../deploy/sqs/template.yml | 2 +- .../demo/batch/sqs/AbstractSqsBatchHandler.java | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/examples/powertools-examples-batch/deploy/sqs/template.yml b/examples/powertools-examples-batch/deploy/sqs/template.yml index 2f1d6c363..1232e4d51 100644 --- a/examples/powertools-examples-batch/deploy/sqs/template.yml +++ b/examples/powertools-examples-batch/deploy/sqs/template.yml @@ -65,6 +65,7 @@ Resources: DemoSQSSenderFunction: Type: AWS::Serverless::Function Properties: + Tracing: Active CodeUri: ../.. Handler: org.demo.batch.sqs.SqsBatchSender::handleRequest Environment: @@ -173,7 +174,6 @@ Resources: Action: - s3:PutObject Resource: !Sub ${Bucket.Arn}/* - Events: MySQSEvent: Type: SQS diff --git a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java index ee33b50fd..1b3029d40 100644 --- a/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java +++ b/examples/powertools-examples-batch/src/main/java/org/demo/batch/sqs/AbstractSqsBatchHandler.java @@ -14,21 +14,22 @@ package org.demo.batch.sqs; -import com.amazonaws.services.lambda.runtime.Context; -import com.fasterxml.jackson.databind.ObjectMapper; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Random; + import org.demo.batch.model.Product; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; + +import com.fasterxml.jackson.databind.ObjectMapper; + import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.PutObjectRequest; -import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.tracing.Tracing; import software.amazon.lambda.powertools.tracing.TracingUtils; @@ -43,7 +44,6 @@ public class AbstractSqsBatchHandler { * Simulate some processing (I/O + S3 put request) * @param p deserialized product */ - @Logging @Tracing protected void processMessage(Product p) { TracingUtils.putAnnotation("productId", p.getId()); @@ -51,15 +51,16 @@ protected void processMessage(Product p) { MDC.put("product", String.valueOf(p.getId())); LOGGER.info("Processing product {}", p); - char c = (char)(r.nextInt(26) + 'a'); + char c = (char) (r.nextInt(26) + 'a'); char[] chars = new char[1024 * 1000]; Arrays.fill(chars, c); p.setName(new String(chars)); try { - File file = new File("/tmp/"+p.getId()+".json"); + File file = new File("/tmp/" + p.getId() + ".json"); mapper.writeValue(file, p); s3.putObject( - PutObjectRequest.builder().bucket(bucket).key(p.getId()+".json").build(), RequestBody.fromFile(file)); + PutObjectRequest.builder().bucket(bucket).key(p.getId() + ".json").build(), + RequestBody.fromFile(file)); } catch (IOException e) { throw new RuntimeException(e); } finally { From 030564242729527e0c0ed2fd12750684aae75612 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Wed, 30 Jul 2025 18:27:02 +0200 Subject: [PATCH 324/577] docs(examples): Add Logging and Tracing to idempotency example with correct configuration. (#1993) --- .../kotlin/.gitignore | 1 + .../src/main/java/helloworld/App.java | 3 +++ .../src/main/resources/log4j2.xml | 16 ++++++++++++++++ .../org/demo/kafka/protobuf/ProtobufProduct.java | 4 ++-- .../kafka/protobuf/ProtobufProductOrBuilder.java | 2 +- .../protobuf/ProtobufProductOuterClass.java | 4 ++-- 6 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 examples/powertools-examples-core-utilities/kotlin/.gitignore create mode 100644 examples/powertools-examples-idempotency/src/main/resources/log4j2.xml diff --git a/examples/powertools-examples-core-utilities/kotlin/.gitignore b/examples/powertools-examples-core-utilities/kotlin/.gitignore new file mode 100644 index 000000000..e660fd93d --- /dev/null +++ b/examples/powertools-examples-core-utilities/kotlin/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java index 029877c73..ebe9fac22 100644 --- a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java @@ -34,6 +34,7 @@ import software.amazon.lambda.powertools.idempotency.Idempotent; import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.tracing.Tracing; import software.amazon.lambda.powertools.utilities.JsonConfig; public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @@ -91,6 +92,7 @@ public App(DynamoDbClient client) { */ @Idempotent // The magic is here! @Logging(logEvent = true) + @Tracing public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { Map<String, String> headers = new HashMap<>(); @@ -130,6 +132,7 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv * @return The contents of the given URL * @throws IOException */ + @Tracing private String getPageContents(String address) throws IOException { URL url = new URL(address); try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) { diff --git a/examples/powertools-examples-idempotency/src/main/resources/log4j2.xml b/examples/powertools-examples-idempotency/src/main/resources/log4j2.xml new file mode 100644 index 000000000..5dede7b58 --- /dev/null +++ b/examples/powertools-examples-idempotency/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + </Appenders> + <Loggers> + <Logger name="JsonLogger" level="INFO" additivity="false"> + <AppenderRef ref="JsonAppender" /> + </Logger> + <Root level="info"> + <AppenderRef ref="JsonAppender" /> + </Root> + </Loggers> +</Configuration> diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java index 6da9113fc..250f37090 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.31.0 +// Protobuf Java Version: 4.31.1 package org.demo.kafka.protobuf; @@ -19,7 +19,7 @@ public final class ProtobufProduct extends com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 31, - /* patch= */ 0, + /* patch= */ 1, /* suffix= */ "", ProtobufProduct.class.getName()); } diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java index 9c1518db3..b2d185f6d 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.31.0 +// Protobuf Java Version: 4.31.1 package org.demo.kafka.protobuf; diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java index 6a99f35ec..adbfdd73a 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.31.0 +// Protobuf Java Version: 4.31.1 package org.demo.kafka.protobuf; @@ -13,7 +13,7 @@ private ProtobufProductOuterClass() {} com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 31, - /* patch= */ 0, + /* patch= */ 1, /* suffix= */ "", ProtobufProductOuterClass.class.getName()); } From 094c3d9e17e19b0003b1fa6719a59afc93f89f44 Mon Sep 17 00:00:00 2001 From: Subhash Kovela <46015546+subhash686@users.noreply.github.com> Date: Thu, 31 Jul 2025 11:02:51 -0400 Subject: [PATCH 325/577] feat: Support CRaC priming of powertools metrics and idempotency-dynamodb (#1861) * Automatic priming of powertools-metrics * Fixed resource name and added unit tests and javadoc comments * Invoke prime Dynamo persistent store * Fixed Sonar issues * Update classesloaded.txt replaced build time class list with run time class list * Moved priming to MetricsFactory and DynamoDBPersistenceStore, added Priming.md * Update classesloaded.txt classesloaded file generated using the new method * Update LambdaMetricsAspect.java Removed unused import * Update DynamoDBPersistenceStore.java Fixed variable naming Sonar issue * Improved priming.md documentation and static initialization of classes using for priming. Also fixed an unrelated flaky unit test * Fixed a Sonarqube finding and added more unit tests to ensure all available classes are loaded --------- Co-authored-by: Philipp Page <github@philipp.page> --- Priming.md | 59 + pom.xml | 6 + .../common/internal/ClassPreLoader.java | 91 + .../common/internal/ClassPreLoaderTest.java | 34 + .../src/test/resources/classesloaded.txt | 2 + .../powertools-idempotency-dynamodb/pom.xml | 4 + .../dynamodb/DynamoDBPersistenceStore.java | 38 +- .../internal/LambdaJsonEncoderTest.java | 2 +- powertools-metrics/pom.xml | 21 + .../powertools/metrics/MetricsFactory.java | 23 +- .../src/main/resources/classesloaded.txt | 3651 +++++++++++++++++ 11 files changed, 3927 insertions(+), 4 deletions(-) create mode 100644 Priming.md create mode 100644 powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/ClassPreLoader.java create mode 100644 powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/ClassPreLoaderTest.java create mode 100644 powertools-common/src/test/resources/classesloaded.txt create mode 100644 powertools-metrics/src/main/resources/classesloaded.txt diff --git a/Priming.md b/Priming.md new file mode 100644 index 000000000..d7597ad8c --- /dev/null +++ b/Priming.md @@ -0,0 +1,59 @@ +# Automatic Priming for AWS Lambda Powertools Java + +## Table of Contents +- [Overview](#overview) +- [Implementation Steps](#general-implementation-steps) +- [Known Issues](#known-issues-and-solutions) +- [Reference Implementation](#reference-implementation) + +## Overview +Priming is the process of preloading dependencies and initializing resources during the INIT phase, rather than during the INVOKE phase to further optimize startup performance with SnapStart. +This is required because Java frameworks that use dependency injection load classes into memory when these classes are explicitly invoked, which typically happens during Lambda’s INVOKE phase. + +This documentation provides guidance for automatic class priming in Powertools for AWS Lambda Java modules. + + +## Implementation Steps +Classes are proactively loaded using Java runtime hooks which are part of the open source [CRaC (Coordinated Restore at Checkpoint) project](https://openjdk.org/projects/crac/). +Implementations across the project use the `beforeCheckpoint()` hook, to prime Snapstart-enabled Java functions via Class Priming. +In order to generate the `classloaded.txt` file for a Java module in this project, follow these general steps. + +1. **Add Maven Profile** + - Add maven test profile with the following VM argument for generating classes loaded files. + ```shell + -Xlog:class+load=info:classesloaded.txt + ``` + - You can find an example of this in `generate-classesloaded-file` profile in this [pom.xml](powertools-metrics/pom.xml). + +2. **Generate classes loaded file** + - Run tests with `-Pgenerate-classesloaded-file` profile. + ```shell + mvn -Pgenerate-classesloaded-file clean test + ``` + - This will generate a file named `classesloaded.txt` in the target directory of the module. + +3. **Cleanup the file** + - The classes loaded file generated in Step 2 has the format + `[0.054s][info][class,load] java.lang.Object source: shared objects file` + but we are only interested in `java.lang.Object` - the fully qualified class name. + - To strip the lines to include only the fully qualified class name, + Use the following regex to replace with empty string. + - `^\[[\[\]0-9.a-z,]+ ` (to replace the left part) + - `( source: )[0-9a-z :/._$-]+` (to replace the right part) + +4. **Add file to resources** + - Move the cleaned-up file to the corresponding `src/main/resources` directory of the module. See [example](powertools-metrics/src/main/resources/classesloaded.txt). + +5. **Register and checkpoint** + - A class, usually the entry point of the module, should register the CRaC resource in the constructor. [Example](powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java) + - Note that AspectJ aspect is not suitable for this purpose, as it does not work with CRaC. + - Add the `beforeCheckpoint()` hook in the same class to invoke `ClassPreLoader.preloadClasses()`. The `ClassPreLoader` class is implemented in `powertools-common` module. + - This will ensure that the classes are already pre-loaded by the Snapstart RESTORE operation leading to a shorter INIT duration. + + +## Known Issues +- This is a manual process at the moment, but it can be automated in the future. +- `classesloaded.txt` file includes test classes as well because the file is generated while running tests. This is not a problem because all the classes that are not found are ignored by `ClassPreLoader.preloadClasses()`. Also `beforeCheckpoint()` hook is not time-sensitive, it only runs once when a new Lambda version gets published. + +## Reference Implementation +Working example is available in the [powertools-metrics](powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java). diff --git a/pom.xml b/pom.xml index 4a8dcf0b9..db78120d1 100644 --- a/pom.xml +++ b/pom.xml @@ -117,6 +117,7 @@ <mockito.version>5.18.0</mockito.version> <mockito-junit-jupiter.version>5.18.0</mockito-junit-jupiter.version> <junit-pioneer.version>2.3.0</junit-pioneer.version> + <crac.version>1.4.0</crac.version> <!-- As we have a .mvn directory at the root of the project, this will evaluate to the root directory regardless of where maven is run - sub-module, or root. --> @@ -264,6 +265,11 @@ <artifactId>logback-ecs-encoder</artifactId> <version>${elastic.version}</version> </dependency> + <dependency> + <groupId>org.crac</groupId> + <artifactId>crac</artifactId> + <version>${crac.version}</version> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/ClassPreLoader.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/ClassPreLoader.java new file mode 100644 index 000000000..ca599429e --- /dev/null +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/ClassPreLoader.java @@ -0,0 +1,91 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.common.internal; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.net.URL; +import java.net.URLConnection; +import java.util.Enumeration; + +/** + * Used to preload classes to support automatic priming for SnapStart + */ +public final class ClassPreLoader { + public static final String CLASSES_FILE = "classesloaded.txt"; + + private ClassPreLoader() { + // Hide default constructor + } + + /** + * Initializes the classes listed in the classesloaded resource + */ + public static void preloadClasses() { + try { + Enumeration<URL> files = ClassPreLoader.class.getClassLoader().getResources(CLASSES_FILE); + // If there are multiple files, preload classes from all of them + while (files.hasMoreElements()) { + URL url = files.nextElement(); + URLConnection conn = url.openConnection(); + conn.setUseCaches(false); + InputStream is = conn.getInputStream(); + preloadClassesFromStream(is); + } + } catch (IOException ignored) { + // No action is required if preloading fails for any reason + } + } + + /** + * Loads the list of classes passed as a stream + * + * @param is + */ + private static void preloadClassesFromStream(InputStream is) { + try (is; + InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8); + BufferedReader reader = new BufferedReader(isr)) { + String line; + while ((line = reader.readLine()) != null) { + int idx = line.indexOf('#'); + if (idx != -1) { + line = line.substring(0, idx); + } + final String className = line.stripTrailing(); + if (!className.isBlank()) { + loadClassIfFound(className); + } + } + } catch (Exception ignored) { + // No action is required if preloading fails for any reason + } + } + + /** + * Initializes the class with given name if found, ignores otherwise + * + * @param className + */ + private static void loadClassIfFound(String className) { + try { + Class.forName(className, true, ClassPreLoader.class.getClassLoader()); + } catch (ClassNotFoundException e) { + // No action is required if the class with given name cannot be found + } + } +} \ No newline at end of file diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/ClassPreLoaderTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/ClassPreLoaderTest.java new file mode 100644 index 000000000..03991688e --- /dev/null +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/ClassPreLoaderTest.java @@ -0,0 +1,34 @@ +package software.amazon.lambda.powertools.common.internal; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +class ClassPreLoaderTest { + + // Making this volatile so the Thread Context doesn't need any special handling + static volatile boolean dummyClassLoaded = false; + + /** + * Dummy class to be loaded by ClassPreLoader in test. + * <b>The class name is referenced in <i>powertools-common/src/test/resources/classesloaded.txt</i></b> + * This class is used to verify that the ClassPreLoader can load valid classes. + * The static block sets a flag to indicate that the class has been loaded. + */ + static class DummyClass { + static { + dummyClassLoaded = true; + } + } + @Test + void preloadClasses_shouldIgnoreInvalidClassesAndLoadValidClasses() { + + dummyClassLoaded = false; + // powertools-common/src/test/resources/classesloaded.txt has a class that does not exist + // Verify that the missing class did not throw any exception + assertDoesNotThrow(ClassPreLoader::preloadClasses); + + // When the classloaded.txt is a mixed bag of valid and invalid classes, Valid class must load + assertTrue(dummyClassLoaded, "DummyClass should be loaded"); + } +} \ No newline at end of file diff --git a/powertools-common/src/test/resources/classesloaded.txt b/powertools-common/src/test/resources/classesloaded.txt new file mode 100644 index 000000000..498ffdf69 --- /dev/null +++ b/powertools-common/src/test/resources/classesloaded.txt @@ -0,0 +1,2 @@ +software.amazon.lambda.powertools.common.internal.NonExistingClass +software.amazon.lambda.powertools.common.internal.ClassPreLoaderTest$DummyClass \ No newline at end of file diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index 3c3304bf9..d63719bbe 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -57,6 +57,10 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>org.crac</groupId> + <artifactId>crac</artifactId> + </dependency> <!-- Test dependencies --> <dependency> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java index 9c96541f6..c128fa5bd 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStore.java @@ -14,6 +14,8 @@ package software.amazon.lambda.powertools.idempotency.persistence.dynamodb; +import org.crac.Core; +import org.crac.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; @@ -37,6 +39,7 @@ import software.amazon.lambda.powertools.idempotency.persistence.PersistenceStore; import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.AbstractMap; import java.util.HashMap; import java.util.Map; @@ -52,7 +55,7 @@ * DynamoDB version of the {@link PersistenceStore}. Will store idempotency data in DynamoDB.<br> * Use the {@link Builder} to create a new instance. */ -public class DynamoDBPersistenceStore extends BasePersistenceStore implements PersistenceStore { +public final class DynamoDBPersistenceStore extends BasePersistenceStore implements PersistenceStore, Resource { public static final String IDEMPOTENCY = "idempotency"; private static final Logger LOG = LoggerFactory.getLogger(DynamoDBPersistenceStore.class); @@ -109,6 +112,39 @@ private DynamoDBPersistenceStore(String tableName, this.dynamoDbClient = null; } } + Core.getGlobalContext().register(this); + } + + /** + * Primes the persistent store by invoking the get record method with a key that doesn't exist. + * + * @param context + * @throws Exception + */ + @Override + public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception { + try { + String primingRecordKey = "__invoke_prime__"; + Instant now = Instant.now(); + long expiry = now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(); + DataRecord primingDataRecord = new DataRecord( + primingRecordKey, + DataRecord.Status.COMPLETED, + expiry, + null, // no data + null // no validation + ); + putRecord(primingDataRecord, Instant.now()); + getRecord(primingRecordKey); + deleteRecord(primingRecordKey); + } catch (Exception unknown) { + // This is unexpected but we must continue without any interruption + } + } + + @Override + public void afterRestore(org.crac.Context<? extends Resource> context) throws Exception { + // This is a no-op, as we don't need to do anything after restore } public static Builder builder() { diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 81e830045..c0eecf6f3 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -368,7 +368,7 @@ void shouldLogThreadInfo() { String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("\"thread\":\"main\",\"thread_id\":1,\"thread_priority\":5"); + assertThat(result).contains("\"thread\":\"main\",\"thread_id\":"+ Thread.currentThread().getId() +",\"thread_priority\":5"); } @Test diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index b91789b4b..7e59bdbf9 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -39,6 +39,10 @@ <artifactId>aspectjrt</artifactId> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.crac</groupId> + <artifactId>crac</artifactId> + </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-common</artifactId> @@ -114,6 +118,23 @@ </dependencies> <profiles> + <profile> + <id>generate-classesloaded-file</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine>-Xlog:class+load=info:classesloaded.txt + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + </argLine> + </configuration> + </plugin> + </plugins> + </build> + </profile> <profile> <id>generate-graalvm-files</id> <dependencies> diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java index 1fd5f88ca..67ab17b7b 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java @@ -14,6 +14,9 @@ package software.amazon.lambda.powertools.metrics; +import org.crac.Core; +import org.crac.Resource; +import software.amazon.lambda.powertools.common.internal.ClassPreLoader; import software.amazon.lambda.powertools.common.internal.LambdaConstants; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.metrics.model.DimensionSet; @@ -23,11 +26,16 @@ /** * Factory for accessing the singleton Metrics instance */ -public final class MetricsFactory { +public final class MetricsFactory implements Resource { private static MetricsProvider provider = new EmfMetricsProvider(); private static Metrics metrics; - private MetricsFactory() { + // Dummy instance to register MetricsFactory with CRaC + private static final MetricsFactory INSTANCE = new MetricsFactory(); + + // Static block to ensure CRaC registration happens at class loading time + static { + Core.getGlobalContext().register(INSTANCE); } /** @@ -68,4 +76,15 @@ public static synchronized void setMetricsProvider(MetricsProvider metricsProvid // Reset the metrics instance so it will be recreated with the new provider metrics = null; } + + @Override + public void beforeCheckpoint(org.crac.Context<? extends Resource> context) throws Exception { + MetricsFactory.getMetricsInstance(); + ClassPreLoader.preloadClasses(); + } + + @Override + public void afterRestore(org.crac.Context<? extends Resource> context) throws Exception { + // No action needed after restore + } } diff --git a/powertools-metrics/src/main/resources/classesloaded.txt b/powertools-metrics/src/main/resources/classesloaded.txt new file mode 100644 index 000000000..f56d6af78 --- /dev/null +++ b/powertools-metrics/src/main/resources/classesloaded.txt @@ -0,0 +1,3651 @@ +java.lang.Object +java.io.Serializable +java.lang.Comparable +java.lang.CharSequence +java.lang.constant.Constable +java.lang.constant.ConstantDesc +java.lang.String +java.lang.reflect.AnnotatedElement +java.lang.reflect.GenericDeclaration +java.lang.reflect.Type +java.lang.invoke.TypeDescriptor +java.lang.invoke.TypeDescriptor$OfField +java.lang.Class +java.lang.Cloneable +java.lang.ClassLoader +java.lang.System +java.lang.Throwable +java.lang.Error +java.lang.ThreadDeath +java.lang.Exception +java.lang.RuntimeException +java.lang.SecurityManager +java.security.ProtectionDomain +java.security.AccessControlContext +java.security.AccessController +java.security.SecureClassLoader +java.lang.ReflectiveOperationException +java.lang.ClassNotFoundException +java.lang.Record +java.lang.LinkageError +java.lang.NoClassDefFoundError +java.lang.ClassCastException +java.lang.ArrayStoreException +java.lang.VirtualMachineError +java.lang.InternalError +java.lang.OutOfMemoryError +java.lang.StackOverflowError +java.lang.IllegalMonitorStateException +java.lang.ref.Reference +java.lang.ref.SoftReference +java.lang.ref.WeakReference +java.lang.ref.FinalReference +java.lang.ref.PhantomReference +java.lang.ref.Finalizer +java.lang.Runnable +java.lang.Thread +java.lang.Thread$UncaughtExceptionHandler +java.lang.ThreadGroup +java.util.Dictionary +java.util.Map +java.util.Hashtable +java.util.Properties +java.lang.Module +java.lang.reflect.AccessibleObject +java.lang.reflect.Member +java.lang.reflect.Field +java.lang.reflect.Parameter +java.lang.reflect.Executable +java.lang.reflect.Method +java.lang.reflect.Constructor +jdk.internal.reflect.MagicAccessorImpl +jdk.internal.reflect.MethodAccessor +jdk.internal.reflect.MethodAccessorImpl +jdk.internal.reflect.ConstructorAccessor +jdk.internal.reflect.ConstructorAccessorImpl +jdk.internal.reflect.DelegatingClassLoader +jdk.internal.reflect.ConstantPool +jdk.internal.reflect.FieldAccessor +jdk.internal.reflect.FieldAccessorImpl +jdk.internal.reflect.UnsafeFieldAccessorImpl +jdk.internal.reflect.UnsafeStaticFieldAccessorImpl +java.lang.annotation.Annotation +jdk.internal.reflect.CallerSensitive +jdk.internal.reflect.NativeConstructorAccessorImpl +java.lang.invoke.MethodHandle +java.lang.invoke.DirectMethodHandle +java.lang.invoke.VarHandle +java.lang.invoke.MemberName +java.lang.invoke.ResolvedMethodName +java.lang.invoke.MethodHandleNatives +java.lang.invoke.LambdaForm +java.lang.invoke.TypeDescriptor$OfMethod +java.lang.invoke.MethodType +java.lang.BootstrapMethodError +java.lang.invoke.CallSite +jdk.internal.invoke.NativeEntryPoint +java.lang.invoke.MethodHandleNatives$CallSiteContext +java.lang.invoke.ConstantCallSite +java.lang.invoke.MutableCallSite +java.lang.invoke.VolatileCallSite +java.lang.AssertionStatusDirectives +java.lang.Appendable +java.lang.AbstractStringBuilder +java.lang.StringBuffer +java.lang.StringBuilder +jdk.internal.misc.UnsafeConstants +jdk.internal.misc.Unsafe +jdk.internal.module.Modules +java.lang.AutoCloseable +java.io.Closeable +java.io.InputStream +java.io.ByteArrayInputStream +java.net.URL +java.util.jar.Manifest +jdk.internal.loader.BuiltinClassLoader +jdk.internal.loader.ClassLoaders +jdk.internal.loader.ClassLoaders$AppClassLoader +jdk.internal.loader.ClassLoaders$PlatformClassLoader +java.security.CodeSource +java.util.AbstractMap +java.util.concurrent.ConcurrentMap +java.util.concurrent.ConcurrentHashMap +java.lang.Iterable +java.util.Collection +java.util.AbstractCollection +java.util.List +java.util.AbstractList +java.util.RandomAccess +java.util.ArrayList +java.lang.StackTraceElement +java.nio.Buffer +java.lang.StackWalker +java.lang.StackStreamFactory$AbstractStackWalker +java.lang.StackWalker$StackFrame +java.lang.StackFrameInfo +java.lang.LiveStackFrame +java.lang.LiveStackFrameInfo +java.util.concurrent.locks.AbstractOwnableSynchronizer +java.lang.Boolean +java.lang.Character +java.lang.Number +java.lang.Float +java.lang.Double +java.lang.Byte +java.lang.Short +java.lang.Integer +java.lang.Long +java.util.Iterator +java.lang.reflect.RecordComponent +jdk.internal.vm.vector.VectorSupport +jdk.internal.vm.vector.VectorSupport$VectorPayload +jdk.internal.vm.vector.VectorSupport$Vector +jdk.internal.vm.vector.VectorSupport$VectorMask +jdk.internal.vm.vector.VectorSupport$VectorShuffle +java.lang.Integer$IntegerCache +java.lang.Long$LongCache +java.lang.Byte$ByteCache +java.lang.Short$ShortCache +java.lang.Character$CharacterCache +java.util.jar.Attributes$Name +java.util.ImmutableCollections$AbstractImmutableMap +java.util.ImmutableCollections$MapN +sun.util.locale.BaseLocale +jdk.internal.module.ArchivedModuleGraph +java.lang.module.ModuleFinder +jdk.internal.module.SystemModuleFinders$SystemModuleFinder +java.util.ImmutableCollections$AbstractImmutableCollection +java.util.Set +java.util.ImmutableCollections$AbstractImmutableSet +java.util.ImmutableCollections$SetN +java.lang.module.ModuleReference +jdk.internal.module.ModuleReferenceImpl +java.lang.module.ModuleDescriptor +java.lang.module.ModuleDescriptor$Version +java.util.ImmutableCollections$Set12 +java.lang.module.ModuleDescriptor$Requires +java.lang.Enum +java.lang.module.ModuleDescriptor$Requires$Modifier +java.lang.module.ModuleDescriptor$Exports +java.net.URI +java.util.function.Supplier +jdk.internal.module.SystemModuleFinders$2 +jdk.internal.module.ModuleHashes$HashSupplier +jdk.internal.module.SystemModuleFinders$3 +java.lang.module.ModuleDescriptor$Provides +java.util.ImmutableCollections$AbstractImmutableList +java.util.ImmutableCollections$List12 +java.util.ImmutableCollections$ListN +java.lang.module.ModuleDescriptor$Opens +jdk.internal.module.ModuleTarget +jdk.internal.module.ModuleHashes +java.util.Collections$UnmodifiableMap +java.util.HashMap +java.util.Map$Entry +java.util.HashMap$Node +java.lang.module.Configuration +java.lang.module.ResolvedModule +java.util.function.Function +jdk.internal.module.ModuleLoaderMap$Mapper +java.util.ImmutableCollections +java.lang.ModuleLayer +jdk.internal.math.FDBigInteger +java.lang.NullPointerException +java.lang.ArithmeticException +java.io.ObjectStreamField +java.util.Comparator +java.lang.String$CaseInsensitiveComparator +java.lang.Module$ArchivedData +jdk.internal.misc.CDS +java.util.Objects +jdk.internal.access.JavaLangReflectAccess +java.lang.reflect.ReflectAccess +jdk.internal.access.SharedSecrets +java.lang.invoke.MethodHandles +java.lang.invoke.MemberName$Factory +java.security.Guard +java.security.Permission +java.security.BasicPermission +java.lang.reflect.ReflectPermission +java.lang.StringLatin1 +java.lang.invoke.MethodHandles$Lookup +jdk.internal.reflect.Reflection +java.lang.Math +java.util.AbstractSet +java.util.ImmutableCollections$MapN$1 +java.util.ImmutableCollections$MapN$MapNIterator +java.util.KeyValueHolder +java.util.LinkedHashMap$Entry +java.util.HashMap$TreeNode +java.lang.Runtime +java.util.concurrent.locks.Lock +java.util.concurrent.locks.ReentrantLock +java.util.concurrent.ConcurrentHashMap$Segment +java.util.concurrent.ConcurrentHashMap$CounterCell +java.util.concurrent.ConcurrentHashMap$Node +java.util.concurrent.locks.LockSupport +java.util.concurrent.ConcurrentHashMap$ReservationNode +java.security.PrivilegedAction +jdk.internal.reflect.ReflectionFactory$GetReflectionFactoryAction +jdk.internal.reflect.ReflectionFactory +java.lang.ref.Reference$ReferenceHandler +jdk.internal.ref.Cleaner +java.lang.ref.ReferenceQueue +java.lang.ref.ReferenceQueue$Null +java.lang.ref.ReferenceQueue$Lock +jdk.internal.access.JavaLangRefAccess +java.lang.ref.Reference$1 +java.lang.ref.Finalizer$FinalizerThread +jdk.internal.access.JavaLangAccess +java.lang.System$2 +jdk.internal.misc.VM +jdk.internal.util.SystemProps +jdk.internal.util.SystemProps$Raw +java.lang.StringConcatHelper +java.lang.VersionProps +java.util.Arrays +java.lang.CharacterData +java.lang.CharacterDataLatin1 +java.util.HashMap$EntrySet +java.util.HashMap$HashIterator +java.util.HashMap$EntryIterator +jdk.internal.util.StaticProperty +java.io.FileInputStream +java.io.FileDescriptor +jdk.internal.access.JavaIOFileDescriptorAccess +java.io.FileDescriptor$1 +java.io.Flushable +java.io.OutputStream +java.io.FileOutputStream +java.io.FilterInputStream +java.io.BufferedInputStream +java.io.FilterOutputStream +java.io.PrintStream +java.io.BufferedOutputStream +java.io.Writer +java.io.OutputStreamWriter +java.nio.charset.Charset +java.nio.charset.spi.CharsetProvider +sun.nio.cs.StandardCharsets +java.lang.ThreadLocal +java.util.concurrent.atomic.AtomicInteger +sun.security.action.GetPropertyAction +sun.nio.cs.HistoricallyNamedCharset +sun.nio.cs.Unicode +sun.nio.cs.UTF_8 +sun.nio.cs.StreamEncoder +java.nio.charset.CharsetEncoder +sun.nio.cs.UTF_8$Encoder +java.nio.charset.CodingErrorAction +java.nio.ByteBuffer +jdk.internal.misc.ScopedMemoryAccess +jdk.internal.access.JavaNioAccess +java.nio.Buffer$1 +java.nio.HeapByteBuffer +java.nio.ByteOrder +java.io.BufferedWriter +java.lang.Terminator +jdk.internal.misc.Signal$Handler +java.lang.Terminator$1 +jdk.internal.misc.Signal +java.util.Hashtable$Entry +jdk.internal.misc.Signal$NativeHandler +jdk.internal.misc.OSEnvironment +java.util.Collections +java.util.Collections$EmptySet +java.util.Collections$EmptyList +java.util.Collections$EmptyMap +java.lang.IllegalArgumentException +java.lang.invoke.MethodHandleStatics +jdk.internal.module.ModuleBootstrap +sun.invoke.util.VerifyAccess +java.lang.reflect.Modifier +jdk.internal.access.JavaLangModuleAccess +java.lang.module.ModuleDescriptor$1 +java.io.File +java.io.DefaultFileSystem +java.io.FileSystem +java.io.UnixFileSystem +jdk.internal.util.ArraysSupport +jdk.internal.module.ModulePatcher +jdk.internal.module.ModuleBootstrap$Counters +jdk.internal.module.ArchivedBootLayer +jdk.internal.access.JavaNetUriAccess +java.net.URI$1 +jdk.internal.loader.ArchivedClassLoaders +jdk.internal.loader.ClassLoaders$BootClassLoader +java.security.cert.Certificate +java.lang.ClassLoader$ParallelLoaders +java.util.WeakHashMap +java.util.WeakHashMap$Entry +java.util.Collections$SetFromMap +java.util.WeakHashMap$KeySet +jdk.internal.access.JavaSecurityAccess +java.security.ProtectionDomain$JavaSecurityAccessImpl +java.security.ProtectionDomain$Key +java.security.Principal +jdk.internal.loader.NativeLibraries +jdk.internal.loader.ClassLoaderHelper +java.util.HashSet +java.util.Queue +java.util.Deque +java.util.ArrayDeque +jdk.internal.loader.URLClassPath +java.net.URLStreamHandlerFactory +java.net.URL$DefaultFactory +jdk.internal.access.JavaNetURLAccess +java.net.URL$3 +java.io.File$PathStatus +sun.net.www.ParseUtil +java.util.HexFormat +java.net.URLStreamHandler +sun.net.www.protocol.file.Handler +sun.net.util.IPAddressUtil +jdk.internal.util.Preconditions +sun.net.www.protocol.jar.Handler +jdk.internal.module.ServicesCatalog +jdk.internal.loader.AbstractClassLoaderValue +jdk.internal.loader.ClassLoaderValue +java.util.Optional +jdk.internal.loader.BootLoader +jdk.internal.loader.BuiltinClassLoader$LoadedModule +java.util.ImmutableCollections$SetN$SetNIterator +java.util.ImmutableCollections$Set12$1 +java.util.ListIterator +java.util.ImmutableCollections$ListItr +jdk.internal.module.ModuleLoaderMap +jdk.internal.loader.AbstractClassLoaderValue$Memoizer +jdk.internal.module.ServicesCatalog$ServiceProvider +java.util.concurrent.CopyOnWriteArrayList +java.util.HashMap$KeySet +java.util.HashMap$KeyIterator +java.lang.ModuleLayer$Controller +java.lang.invoke.LambdaMetafactory +java.lang.invoke.MethodType$ConcurrentWeakInternSet +java.lang.Void +java.lang.invoke.MethodTypeForm +java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry +sun.invoke.util.Wrapper +sun.invoke.util.Wrapper$Format +java.lang.invoke.LambdaForm$NamedFunction +java.lang.invoke.DirectMethodHandle$Holder +sun.invoke.util.ValueConversions +java.lang.invoke.MethodHandleImpl +java.lang.invoke.Invokers +java.lang.invoke.LambdaForm$Kind +java.lang.NoSuchMethodException +java.lang.invoke.LambdaForm$BasicType +java.lang.reflect.Array +java.lang.invoke.LambdaForm$Name +java.lang.invoke.LambdaForm$Holder +java.lang.invoke.InvokerBytecodeGenerator +java.lang.invoke.InvokerBytecodeGenerator$2 +java.lang.invoke.MethodHandleImpl$Intrinsic +java.lang.invoke.BootstrapMethodInvoker +java.lang.invoke.VarHandle$AccessMode +java.lang.invoke.VarHandle$AccessType +java.lang.invoke.Invokers$Holder +jdk.internal.access.JavaLangInvokeAccess +java.lang.invoke.MethodHandleImpl$1 +java.lang.invoke.AbstractValidatingLambdaMetafactory +java.lang.invoke.InnerClassLambdaMetafactory +jdk.internal.org.objectweb.asm.Type +sun.security.action.GetBooleanAction +jdk.internal.org.objectweb.asm.Handle +sun.invoke.util.BytecodeDescriptor +jdk.internal.org.objectweb.asm.ConstantDynamic +java.lang.invoke.MethodHandleInfo +java.lang.invoke.InfoFromMemberName +jdk.internal.org.objectweb.asm.ClassVisitor +jdk.internal.org.objectweb.asm.ClassWriter +jdk.internal.org.objectweb.asm.SymbolTable +jdk.internal.org.objectweb.asm.Symbol +jdk.internal.org.objectweb.asm.SymbolTable$Entry +jdk.internal.org.objectweb.asm.ByteVector +java.lang.invoke.LambdaProxyClassArchive +jdk.internal.org.objectweb.asm.MethodVisitor +jdk.internal.org.objectweb.asm.MethodWriter +jdk.internal.org.objectweb.asm.Label +java.lang.invoke.TypeConvertingMethodAdapter +java.lang.invoke.InnerClassLambdaMetafactory$ForwardingMethodGenerator +jdk.internal.org.objectweb.asm.Handler +jdk.internal.org.objectweb.asm.Attribute +jdk.internal.org.objectweb.asm.AnnotationVisitor +jdk.internal.org.objectweb.asm.AnnotationWriter +java.lang.invoke.MethodHandles$Lookup$ClassOption +java.lang.invoke.MethodHandles$Lookup$ClassFile +jdk.internal.org.objectweb.asm.ClassReader +java.lang.StringUTF16 +java.lang.invoke.MethodHandles$Lookup$ClassDefiner +jdk.internal.module.ModuleBootstrap$$Lambda$1/0x0000007001040850 +java.lang.invoke.InnerClassLambdaMetafactory$1 +java.lang.Class$ReflectionData +java.lang.Class$Atomic +jdk.internal.reflect.DelegatingConstructorAccessorImpl +java.lang.invoke.BoundMethodHandle +java.lang.invoke.ClassSpecializer +java.lang.invoke.BoundMethodHandle$Specializer +java.lang.invoke.ClassSpecializer$1 +java.lang.invoke.ClassSpecializer$SpeciesData +java.lang.invoke.BoundMethodHandle$SpeciesData +java.lang.invoke.ClassSpecializer$Factory +java.lang.invoke.BoundMethodHandle$Specializer$Factory +java.lang.invoke.SimpleMethodHandle +java.lang.NoSuchFieldException +java.lang.invoke.BoundMethodHandle$Species_L +sun.invoke.util.VerifyType +sun.invoke.empty.Empty +java.lang.invoke.DirectMethodHandle$2 +java.lang.invoke.DirectMethodHandle$Accessor +java.lang.invoke.DelegatingMethodHandle +java.lang.invoke.MethodHandleImpl$IntrinsicMethodHandle +java.lang.invoke.DelegatingMethodHandle$Holder +sun.invoke.util.Wrapper$1 +java.lang.invoke.LambdaFormEditor +java.lang.invoke.LambdaFormEditor$TransformKey +java.lang.invoke.LambdaFormBuffer +java.lang.invoke.LambdaFormEditor$Transform +jdk.internal.org.objectweb.asm.Frame +java.lang.invoke.InvokerBytecodeGenerator$ClassData +java.util.ArrayList$Itr +jdk.internal.org.objectweb.asm.FieldVisitor +jdk.internal.org.objectweb.asm.FieldWriter +java.lang.invoke.LambdaForm$MH/0x0000007001000400 +jdk.internal.ref.CleanerFactory +java.util.concurrent.ThreadFactory +jdk.internal.ref.CleanerFactory$1 +java.lang.ref.Cleaner +java.lang.ref.Cleaner$1 +jdk.internal.ref.CleanerImpl +java.lang.ref.Cleaner$Cleanable +jdk.internal.ref.PhantomCleanable +jdk.internal.ref.CleanerImpl$PhantomCleanableRef +jdk.internal.ref.CleanerImpl$CleanerCleanable +jdk.internal.misc.InnocuousThread +java.util.ArrayList$SubList +java.lang.Module$ReflectionData +java.lang.WeakPairMap +java.lang.WeakPairMap$Pair +java.lang.WeakPairMap$Pair$Lookup +java.util.function.BiFunction +java.lang.Module$$Lambda$2/0x0000007001040a90 +java.lang.WeakPairMap$WeakRefPeer +java.lang.WeakPairMap$Pair$Weak +java.lang.WeakPairMap$Pair$Weak$1 +java.lang.WeakPairMap$$Lambda$3/0x00000070010413e8 +java.lang.invoke.DirectMethodHandle$Constructor +java.lang.invoke.StringConcatFactory +java.lang.invoke.StringConcatFactory$1 +java.lang.invoke.StringConcatFactory$2 +java.lang.invoke.StringConcatFactory$3 +sun.launcher.LauncherHelper +java.lang.StringCoding +java.util.zip.ZipConstants +java.util.zip.ZipFile +java.util.jar.JarFile +jdk.internal.access.JavaUtilZipFileAccess +java.util.zip.ZipFile$1 +jdk.internal.access.JavaUtilJarAccess +java.util.jar.JavaUtilJarAccessImpl +java.lang.Runtime$Version +java.util.zip.ZipFile$CleanableResource +java.util.zip.ZipCoder +java.util.zip.ZipCoder$UTF8ZipCoder +java.util.zip.ZipFile$Source +sun.nio.fs.DefaultFileSystemProvider +java.nio.file.spi.FileSystemProvider +sun.nio.fs.AbstractFileSystemProvider +sun.nio.fs.UnixFileSystemProvider +sun.nio.fs.BsdFileSystemProvider +sun.nio.fs.MacOSXFileSystemProvider +java.nio.file.OpenOption +java.nio.file.StandardOpenOption +java.nio.file.FileSystem +sun.nio.fs.UnixFileSystem +sun.nio.fs.BsdFileSystem +sun.nio.fs.MacOSXFileSystem +java.nio.file.Watchable +java.nio.file.Path +sun.nio.fs.UnixPath +sun.nio.fs.Util +sun.nio.fs.UnixNativeDispatcher +jdk.internal.loader.NativeLibraries$LibraryPaths +jdk.internal.loader.NativeLibraries$1 +java.util.ArrayDeque$DeqIterator +jdk.internal.loader.NativeLibrary +jdk.internal.loader.NativeLibraries$NativeLibraryImpl +jdk.internal.loader.NativeLibraries$NativeLibraryImpl$1 +java.util.concurrent.ConcurrentHashMap$CollectionView +java.util.concurrent.ConcurrentHashMap$ValuesView +java.util.concurrent.ConcurrentHashMap$Traverser +java.util.concurrent.ConcurrentHashMap$BaseIterator +java.util.Enumeration +java.util.concurrent.ConcurrentHashMap$ValueIterator +java.nio.file.attribute.BasicFileAttributes +java.nio.file.attribute.PosixFileAttributes +sun.nio.fs.UnixFileAttributes +sun.nio.fs.UnixFileStoreAttributes +sun.nio.fs.UnixMountEntry +java.util.zip.ZipFile$Source$Key +java.nio.file.CopyOption +java.nio.file.LinkOption +java.nio.file.Files +java.nio.file.attribute.AttributeView +java.nio.file.attribute.FileAttributeView +java.nio.file.attribute.BasicFileAttributeView +java.nio.file.attribute.UserDefinedFileAttributeView +sun.nio.fs.UnixFileAttributeViews +sun.nio.fs.DynamicFileAttributeView +sun.nio.fs.AbstractBasicFileAttributeView +sun.nio.fs.UnixFileAttributeViews$Basic +sun.nio.fs.NativeBuffers +jdk.internal.misc.TerminatingThreadLocal +sun.nio.fs.NativeBuffers$1 +jdk.internal.misc.TerminatingThreadLocal$1 +java.lang.ThreadLocal$ThreadLocalMap +java.lang.ThreadLocal$ThreadLocalMap$Entry +java.util.IdentityHashMap +java.util.IdentityHashMap$KeySet +sun.nio.fs.NativeBuffer +sun.nio.fs.NativeBuffer$Deallocator +sun.nio.fs.UnixFileAttributes$UnixAsBasicFileAttributes +java.io.DataOutput +java.io.DataInput +java.io.RandomAccessFile +jdk.internal.access.JavaIORandomAccessFileAccess +java.io.RandomAccessFile$2 +java.io.FileCleanable +java.util.zip.ZipFile$Source$End +java.util.zip.ZipUtils +java.util.concurrent.TimeUnit +java.nio.file.attribute.FileTime +jdk.internal.perf.PerfCounter +jdk.internal.perf.Perf$GetPerfAction +jdk.internal.perf.Perf +jdk.internal.perf.PerfCounter$CoreCounters +sun.nio.ch.DirectBuffer +java.nio.MappedByteBuffer +java.nio.DirectByteBuffer +java.nio.Bits +java.util.concurrent.atomic.AtomicLong +jdk.internal.misc.VM$BufferPool +java.nio.Bits$1 +java.nio.LongBuffer +java.nio.DirectLongBufferU +java.util.zip.ZipEntry +java.util.jar.JarEntry +java.util.jar.JarFile$JarFileEntry +java.util.zip.ZipFile$ZipFileInputStream +java.util.zip.InflaterInputStream +java.util.zip.ZipFile$ZipFileInflaterInputStream +java.util.zip.Inflater +java.util.zip.Inflater$InflaterZStreamRef +java.util.zip.ZipFile$InflaterCleanupAction +sun.security.util.SignatureFileVerifier +sun.security.util.Debug +java.util.Locale +sun.util.locale.LocaleUtils +sun.security.action.GetIntegerAction +java.util.jar.JarVerifier +java.security.CodeSigner +java.io.ByteArrayOutputStream +java.util.jar.Attributes +java.util.LinkedHashMap +java.util.jar.Manifest$FastInputStream +java.io.RandomAccessFile$1 +sun.net.util.URLUtil +java.security.PrivilegedExceptionAction +jdk.internal.loader.URLClassPath$3 +jdk.internal.loader.URLClassPath$Loader +jdk.internal.loader.URLClassPath$JarLoader +jdk.internal.loader.URLClassPath$JarLoader$1 +jdk.internal.loader.FileURLMapper +jdk.internal.util.jar.JarIndex +java.util.StringTokenizer +jdk.internal.loader.Resource +jdk.internal.loader.URLClassPath$JarLoader$2 +java.lang.NamedPackage +java.lang.Package +java.lang.Package$VersionInfo +sun.nio.ByteBuffered +java.util.zip.Checksum +java.util.zip.CRC32 +java.util.zip.Checksum$1 +java.security.SecureClassLoader$CodeSourceKey +java.security.SecureClassLoader$1 +java.security.PermissionCollection +sun.security.util.LazyCodeSourcePermissionCollection +java.security.Permissions +java.lang.RuntimePermission +java.security.BasicPermissionCollection +java.security.AllPermission +java.security.UnresolvedPermission +java.security.SecureClassLoader$DebugHolder +org.apache.maven.surefire.booter.ForkedBooter +org.apache.maven.surefire.api.fork.ForkNodeArguments +org.apache.maven.plugin.surefire.log.api.ConsoleLogger +java.lang.SecurityException +java.security.AccessControlException +java.io.IOException +org.apache.maven.surefire.api.provider.CommandListener +java.lang.InterruptedException +java.util.concurrent.ConcurrentHashMap$ForwardingNode +java.util.concurrent.Executor +java.util.concurrent.ExecutorService +java.util.concurrent.ScheduledExecutorService +org.apache.maven.surefire.api.report.ReporterFactory +org.apache.maven.surefire.api.provider.CommandChainReader +java.lang.PublicMethods$MethodList +java.lang.PublicMethods$Key +java.util.concurrent.Semaphore +java.util.concurrent.locks.AbstractQueuedSynchronizer +java.util.concurrent.Semaphore$Sync +java.util.concurrent.Semaphore$NonfairSync +org.apache.maven.surefire.booter.BooterDeserializer +org.apache.maven.surefire.booter.SystemPropertyManager +java.util.Properties$LineReader +java.util.Properties$EntrySet +java.util.concurrent.ConcurrentHashMap$EntrySetView +java.util.Collections$SynchronizedCollection +java.util.Collections$SynchronizedSet +java.util.concurrent.ConcurrentHashMap$EntryIterator +java.util.concurrent.ConcurrentHashMap$MapEntry +java.util.Collections$UnmodifiableCollection +java.util.Collections$UnmodifiableSet +java.util.Collections$UnmodifiableCollection$1 +org.apache.maven.surefire.booter.KeyValueSource +org.apache.maven.surefire.booter.PropertiesWrapper +java.lang.IllegalStateException +java.io.FileInputStream$1 +org.apache.maven.surefire.booter.TypeEncodedValue +org.apache.maven.surefire.api.testset.DirectoryScannerParameters +org.apache.maven.surefire.api.util.RunOrder +org.apache.maven.surefire.api.testset.RunOrderParameters +org.apache.maven.surefire.api.testset.TestArtifactInfo +org.apache.maven.surefire.api.testset.TestRequest +org.apache.maven.surefire.api.testset.TestFilter +org.apache.maven.surefire.api.testset.GenericTestPattern +org.apache.maven.surefire.api.testset.TestListResolver +java.util.Collections$SingletonSet +org.apache.maven.surefire.api.testset.IncludedExcludedPatterns +java.util.LinkedHashSet +java.util.Collections$1 +org.apache.maven.surefire.shared.utils.StringUtils +java.lang.IndexOutOfBoundsException +java.lang.StringIndexOutOfBoundsException +org.apache.maven.surefire.api.testset.ResolvedTest +org.apache.maven.surefire.api.testset.ResolvedTest$Type +org.apache.maven.surefire.api.testset.ResolvedTest$ClassMatcher +org.apache.maven.surefire.api.testset.ResolvedTest$MethodMatcher +org.apache.maven.surefire.api.report.ReporterConfiguration +org.apache.maven.surefire.api.booter.Shutdown +java.lang.Class$3 +jdk.internal.reflect.NativeMethodAccessorImpl +jdk.internal.reflect.DelegatingMethodAccessorImpl +org.apache.maven.surefire.booter.ProviderConfiguration +org.apache.maven.surefire.api.cli.CommandLineOption +org.apache.maven.surefire.api.booter.DumpErrorSingleton +org.apache.maven.surefire.api.util.internal.DumpFileUtils +java.lang.management.ManagementFactory +java.lang.IncompatibleClassChangeError +java.lang.NoSuchMethodError +java.lang.invoke.LambdaForm$DMH/0x0000007001006000 +java.lang.management.ManagementFactory$$Lambda$4/0x00000070010443a0 +java.lang.management.PlatformManagedObject +java.lang.management.RuntimeMXBean +java.lang.management.ManagementFactory$PlatformMBeanFinder +java.lang.management.ManagementFactory$PlatformMBeanFinder$1 +java.io.FilePermission +jdk.internal.access.JavaIOFilePermissionAccess +java.io.FilePermission$1 +sun.security.util.FilePermCompat +sun.security.util.SecurityProperties +java.security.Security +java.security.Security$1 +jdk.internal.access.JavaSecurityPropertiesAccess +java.security.Security$2 +sun.management.spi.PlatformMBeanProvider +java.util.ServiceLoader +java.util.ServiceLoader$ModuleServicesLookupIterator +java.util.ServiceLoader$LazyClassPathLookupIterator +java.util.ServiceLoader$2 +java.util.ServiceLoader$3 +java.util.concurrent.CopyOnWriteArrayList$COWIterator +com.sun.management.internal.PlatformMBeanProviderImpl +java.util.ServiceLoader$1 +java.util.ServiceLoader$Provider +java.util.ServiceLoader$ProviderImpl +com.sun.management.internal.PlatformMBeanProviderImpl$$Lambda$5/0x0000007001045a48 +sun.management.spi.PlatformMBeanProvider$PlatformComponent +com.sun.management.internal.PlatformMBeanProviderImpl$1 +java.util.stream.BaseStream +java.util.stream.Stream +java.util.Spliterators +java.util.Spliterators$EmptySpliterator +java.util.Spliterator +java.util.Spliterators$EmptySpliterator$OfRef +java.util.Spliterator$OfPrimitive +java.util.Spliterator$OfInt +java.util.Spliterators$EmptySpliterator$OfInt +java.util.Spliterator$OfLong +java.util.Spliterators$EmptySpliterator$OfLong +java.util.Spliterator$OfDouble +java.util.Spliterators$EmptySpliterator$OfDouble +java.util.Spliterators$ArraySpliterator +java.util.stream.StreamSupport +java.util.stream.PipelineHelper +java.util.stream.AbstractPipeline +java.util.stream.ReferencePipeline +java.util.stream.ReferencePipeline$Head +java.util.stream.StreamOpFlag +java.util.stream.StreamOpFlag$Type +java.util.stream.StreamOpFlag$MaskBuilder +java.util.EnumMap +java.util.EnumMap$1 +sun.reflect.annotation.AnnotationParser +java.util.stream.Collectors +java.util.stream.Collector$Characteristics +java.util.EnumSet +java.util.RegularEnumSet +java.util.stream.Collector +java.util.stream.Collectors$CollectorImpl +java.util.stream.Collectors$$Lambda$31/0x800000046 +java.util.function.BiConsumer +java.lang.invoke.DirectMethodHandle$Interface +java.util.stream.Collectors$$Lambda$23/0x80000003a +java.util.function.BinaryOperator +java.util.stream.Collectors$$Lambda$26/0x800000041 +java.util.stream.Collectors$$Lambda$28/0x800000043 +java.util.stream.ReduceOps +java.util.stream.TerminalOp +java.util.stream.ReduceOps$ReduceOp +java.util.stream.ReduceOps$3 +java.util.stream.StreamShape +java.util.stream.ReduceOps$Box +java.util.function.Consumer +java.util.stream.Sink +java.util.stream.TerminalSink +java.util.stream.ReduceOps$AccumulatingSink +java.util.stream.ReduceOps$3ReducingSink +com.sun.management.internal.PlatformMBeanProviderImpl$2 +com.sun.management.internal.PlatformMBeanProviderImpl$3 +com.sun.management.internal.PlatformMBeanProviderImpl$4 +javax.management.DynamicMBean +com.sun.management.DiagnosticCommandMBean +javax.management.NotificationBroadcaster +javax.management.NotificationEmitter +sun.management.NotificationEmitterSupport +com.sun.management.internal.DiagnosticCommandImpl +sun.management.ManagementFactoryHelper +sun.management.VMManagement +sun.management.VMManagementImpl +com.sun.management.internal.PlatformMBeanProviderImpl$5 +java.util.Collections$UnmodifiableList +java.util.Collections$UnmodifiableRandomAccessList +jdk.management.jfr.internal.FlightRecorderMXBeanProvider +java.util.concurrent.Callable +java.util.Collections$EmptyEnumeration +java.lang.management.DefaultPlatformMBeanProvider +java.lang.management.DefaultPlatformMBeanProvider$1 +java.lang.management.DefaultPlatformMBeanProvider$2 +java.lang.management.DefaultPlatformMBeanProvider$3 +java.lang.management.DefaultPlatformMBeanProvider$4 +java.lang.management.DefaultPlatformMBeanProvider$5 +java.lang.management.DefaultPlatformMBeanProvider$6 +java.lang.management.DefaultPlatformMBeanProvider$7 +java.lang.management.DefaultPlatformMBeanProvider$8 +sun.management.ManagementFactoryHelper$LoggingMXBeanAccess +sun.management.ManagementFactoryHelper$LoggingMXBeanAccess$1 +java.util.logging.LogManager +java.lang.management.DefaultPlatformMBeanProvider$9 +java.lang.management.DefaultPlatformMBeanProvider$10 +java.lang.management.DefaultPlatformMBeanProvider$11 +jdk.management.jfr.FlightRecorderMXBean +jdk.management.jfr.internal.FlightRecorderMXBeanProvider$SingleMBeanComponent +java.util.Collections$SingletonList +java.util.HashMap$Values +java.util.HashMap$HashMapSpliterator +java.util.HashMap$ValueSpliterator +java.util.function.Predicate +java.lang.management.ManagementFactory$PlatformMBeanFinder$$Lambda$10/0x000000700104b430 +java.util.stream.ReferencePipeline$StatelessOp +java.util.stream.ReferencePipeline$2 +java.lang.management.ManagementFactory$PlatformMBeanFinder$$Lambda$11/0x000000700104b688 +java.util.stream.ReduceOps$2 +java.util.stream.ReduceOps$2ReducingSink +java.util.stream.Sink$ChainedReference +java.util.stream.ReferencePipeline$2$1 +sun.management.RuntimeImpl +java.util.Collections$SingletonMap +java.util.Collections$2 +java.lang.invoke.LambdaForm$DMH/0x0000007001006400 +sun.management.spi.PlatformMBeanProvider$PlatformComponent$$Lambda$12/0x000000700104c478 +sun.management.spi.PlatformMBeanProvider$PlatformComponent$$Lambda$13/0x000000700104c6d0 +java.util.stream.ReferencePipeline$3 +java.util.stream.Collectors$$Lambda$14/0x000000700104c918 +java.util.stream.Collectors$$Lambda$15/0x000000700104cb38 +java.util.stream.Collectors$$Lambda$16/0x000000700104cd68 +java.util.stream.ReferencePipeline$3$1 +sun.management.Util +java.lang.management.ManagementPermission +java.util.Arrays$ArrayList +java.util.Arrays$ArrayItr +org.apache.maven.surefire.booter.ClassLoaderConfiguration +org.apache.maven.surefire.booter.AbstractPathConfiguration +org.apache.maven.surefire.booter.ClasspathConfiguration +org.apache.maven.surefire.booter.Classpath +java.net.MalformedURLException +java.net.URLClassLoader +org.apache.maven.surefire.booter.IsolatedClassLoader +org.apache.maven.surefire.booter.SurefireExecutionException +org.apache.maven.surefire.booter.ProcessCheckerType +org.apache.maven.surefire.booter.StartupConfiguration +org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory +java.util.Spliterators$1Adapter +java.util.HashMap$ValueIterator +jdk.internal.module.Resources +jdk.internal.loader.BuiltinClassLoader$2 +jdk.internal.loader.BuiltinClassLoader$5 +java.lang.module.ModuleReader +jdk.internal.module.SystemModuleFinders$SystemModuleReader +jdk.internal.module.SystemModuleFinders$SystemImage +jdk.internal.jimage.ImageReaderFactory +java.nio.file.Paths +java.nio.file.FileSystems +java.nio.file.FileSystems$DefaultFileSystemHolder +java.nio.file.FileSystems$DefaultFileSystemHolder$1 +java.net.URI$Parser +jdk.internal.jimage.ImageReaderFactory$1 +jdk.internal.jimage.ImageReader +jdk.internal.jimage.BasicImageReader +jdk.internal.jimage.ImageReader$SharedImageReader +jdk.internal.jimage.BasicImageReader$1 +jdk.internal.jimage.NativeImageBuffer +jdk.internal.jimage.NativeImageBuffer$1 +jdk.internal.jimage.ImageHeader +java.nio.IntBuffer +java.nio.DirectIntBufferU +java.nio.DirectByteBufferR +java.nio.DirectIntBufferRU +jdk.internal.jimage.ImageStrings +jdk.internal.jimage.ImageStringsReader +jdk.internal.jimage.decompressor.Decompressor +jdk.internal.jimage.ImageLocation +java.util.Collections$EmptyIterator +jdk.internal.loader.BuiltinClassLoader$1 +java.lang.CompoundEnumeration +jdk.internal.loader.URLClassPath$1 +jdk.internal.loader.URLClassPath$FileLoader +java.util.SortedSet +java.util.NavigableSet +java.util.TreeSet +java.util.SortedMap +java.util.NavigableMap +java.util.TreeMap +java.util.TreeMap$Entry +java.util.TreeMap$KeySet +java.util.TreeMap$PrivateEntryIterator +java.util.TreeMap$KeyIterator +java.lang.Readable +java.io.Reader +java.io.BufferedReader +java.io.InputStreamReader +sun.nio.cs.StreamDecoder +java.nio.charset.CharsetDecoder +sun.nio.cs.UTF_8$Decoder +java.util.Vector +java.nio.CharBuffer +java.nio.HeapCharBuffer +java.nio.charset.CoderResult +java.util.AbstractSequentialList +java.util.LinkedList +java.util.LinkedList$Node +java.net.URLConnection +java.net.JarURLConnection +sun.net.www.protocol.jar.JarURLConnection +sun.net.www.protocol.jar.URLJarFile$URLJarFileCloseController +sun.net.www.protocol.jar.JarFileFactory +sun.net.www.URLConnection +sun.net.www.protocol.file.FileURLConnection +sun.net.www.MessageHeader +sun.net.www.protocol.jar.URLJarFile +sun.nio.fs.UnixFileKey +sun.net.www.protocol.jar.URLJarFile$URLJarFileEntry +sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream +java.util.LinkedHashMap$LinkedKeySet +java.util.LinkedHashMap$LinkedHashIterator +java.util.LinkedHashMap$LinkedKeyIterator +org.apache.maven.surefire.booter.spi.AbstractMasterProcessChannelProcessorFactory +org.apache.maven.surefire.booter.spi.LegacyMasterProcessChannelProcessorFactory +org.apache.maven.surefire.api.booter.MasterProcessChannelEncoder +org.apache.maven.surefire.api.booter.MasterProcessChannelDecoder +org.apache.maven.surefire.api.util.internal.DaemonThreadFactory +java.util.concurrent.Executors +java.util.concurrent.Executors$DefaultThreadFactory +org.apache.maven.surefire.api.util.internal.DaemonThreadFactory$NamedThreadFactory +java.util.concurrent.AbstractExecutorService +java.util.concurrent.ThreadPoolExecutor +java.util.concurrent.ScheduledThreadPoolExecutor +java.util.concurrent.RejectedExecutionHandler +java.util.concurrent.ThreadPoolExecutor$AbortPolicy +java.util.concurrent.BlockingQueue +java.util.AbstractQueue +java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue +java.util.concurrent.Future +java.util.concurrent.RunnableFuture +java.util.concurrent.Delayed +java.util.concurrent.ScheduledFuture +java.util.concurrent.RunnableScheduledFuture +java.util.concurrent.locks.ReentrantLock$Sync +java.util.concurrent.locks.ReentrantLock$NonfairSync +java.util.concurrent.locks.Condition +java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject +org.apache.maven.surefire.booter.spi.SurefireMasterProcessChannelProcessorFactory +java.net.URISyntaxException +java.util.concurrent.ExecutionException +java.net.SocketAddress +java.net.InetSocketAddress +java.nio.channels.Channel +java.nio.channels.AsynchronousChannel +java.nio.channels.AsynchronousByteChannel +org.apache.maven.surefire.booter.ForkedNodeArg +java.lang.UnsupportedOperationException +org.apache.maven.plugin.surefire.log.api.NullConsoleLogger +org.apache.maven.surefire.api.util.internal.Channels +org.apache.maven.surefire.api.util.internal.Channels$2 +org.apache.maven.surefire.api.util.internal.Channels$1 +java.nio.channels.ReadableByteChannel +java.nio.channels.WritableByteChannel +org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel +org.apache.maven.surefire.api.util.internal.AbstractNoninterruptibleWritableChannel +org.apache.maven.surefire.api.util.internal.Channels$4 +java.nio.channels.ClosedChannelException +java.nio.channels.NonWritableChannelException +org.apache.maven.surefire.booter.spi.AbstractMasterProcessChannelProcessorFactory$1 +java.util.concurrent.FutureTask +java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask +java.lang.invoke.VarHandles +java.lang.invoke.VarHandleInts$FieldInstanceReadOnly +java.lang.invoke.VarHandleInts$FieldInstanceReadWrite +java.lang.invoke.VarHandle$1 +jdk.internal.util.Preconditions$1 +java.lang.invoke.VarHandleGuards +java.lang.invoke.VarForm +java.lang.invoke.VarHandleReferences$FieldInstanceReadOnly +java.lang.invoke.VarHandleReferences$FieldInstanceReadWrite +java.util.concurrent.FutureTask$WaitNode +java.util.concurrent.Executors$RunnableAdapter +java.util.concurrent.ThreadPoolExecutor$Worker +java.lang.Thread$State +java.util.concurrent.TimeUnit$1 +java.time.temporal.TemporalUnit +java.time.temporal.ChronoUnit +java.time.temporal.TemporalAmount +java.time.Duration +java.math.BigInteger +java.lang.invoke.VarHandle$AccessDescriptor +org.apache.maven.surefire.api.stream.AbstractStreamEncoder +org.apache.maven.surefire.booter.stream.EventEncoder +org.apache.maven.surefire.booter.spi.EventChannelEncoder +java.lang.AssertionError +java.util.concurrent.ForkJoinPool$ManagedBlocker +java.util.concurrent.locks.AbstractQueuedSynchronizer$Node +java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode +org.apache.maven.surefire.api.booter.ForkedProcessEventType +org.apache.maven.surefire.api.report.ReportEntry +java.util.concurrent.atomic.AtomicBoolean +org.apache.maven.surefire.booter.spi.CommandChannelDecoder +org.apache.maven.surefire.api.stream.MalformedChannelException +org.apache.maven.surefire.api.stream.AbstractStreamDecoder +org.apache.maven.surefire.booter.stream.CommandDecoder +org.apache.maven.surefire.api.util.internal.AbstractNoninterruptibleReadableChannel +org.apache.maven.surefire.api.util.internal.Channels$3 +java.nio.channels.NonReadableChannelException +java.io.EOFException +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$MalformedFrameException +org.apache.maven.surefire.api.stream.SegmentType +java.io.FileNotFoundException +org.apache.maven.surefire.api.booter.Constants +java.nio.charset.StandardCharsets +sun.nio.cs.US_ASCII +sun.nio.cs.ISO_8859_1 +sun.nio.cs.UTF_16BE +sun.nio.cs.UTF_16LE +sun.nio.cs.UTF_16 +org.apache.maven.surefire.api.booter.MasterProcessCommand +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$Segment +org.apache.maven.surefire.booter.ForkedBooter$8 +org.apache.maven.surefire.shared.utils.cli.ShutdownHookUtils +java.lang.ApplicationShutdownHooks +java.lang.ApplicationShutdownHooks$1 +java.lang.Shutdown +java.lang.Shutdown$Lock +org.apache.maven.surefire.api.booter.ForkingReporterFactory +org.apache.maven.surefire.api.report.RunListener +org.apache.maven.surefire.api.report.TestOutputReceiver +org.apache.maven.surefire.api.report.TestReportListener +org.apache.maven.surefire.api.booter.ForkingRunListener +org.apache.maven.surefire.booter.CommandReader +org.apache.maven.surefire.api.testset.TestSetFailedException +java.util.concurrent.ConcurrentLinkedQueue +java.util.concurrent.ConcurrentLinkedQueue$Node +org.apache.maven.surefire.booter.CommandReader$CommandRunnable +java.util.concurrent.atomic.AtomicReference +java.util.concurrent.CountDownLatch +java.util.concurrent.CountDownLatch$Sync +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$Memento +org.apache.maven.surefire.booter.PpidChecker +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$BufferedStream +org.apache.maven.surefire.booter.PpidChecker$ProcessInfoConsumer +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$StreamReadStatus +org.apache.maven.surefire.booter.PpidChecker$1 +org.apache.maven.surefire.booter.stream.CommandDecoder$1 +org.apache.maven.surefire.booter.PpidChecker$2 +java.lang.NoSuchFieldError +org.apache.maven.surefire.api.booter.Command +org.apache.maven.surefire.booter.CommandReader$1 +java.util.concurrent.ConcurrentLinkedQueue$Itr +org.apache.maven.surefire.shared.lang3.SystemUtils +org.apache.maven.surefire.shared.lang3.JavaVersion +org.apache.maven.surefire.shared.lang3.math.NumberUtils +java.lang.NumberFormatException +java.math.BigDecimal +jdk.internal.math.FloatingDecimal +jdk.internal.math.FloatingDecimal$BinaryToASCIIConverter +jdk.internal.math.FloatingDecimal$ExceptionalBinaryToASCIIBuffer +jdk.internal.math.FloatingDecimal$BinaryToASCIIBuffer +jdk.internal.math.FloatingDecimal$1 +jdk.internal.math.FloatingDecimal$ASCIIToBinaryConverter +jdk.internal.math.FloatingDecimal$PreparedASCIIToBinaryBuffer +jdk.internal.math.FloatingDecimal$ASCIIToBinaryBuffer +org.apache.maven.surefire.shared.lang3.StringUtils +java.util.regex.Pattern +java.util.regex.Pattern$Node +java.util.regex.Pattern$LastNode +java.util.regex.Pattern$GroupHead +java.util.regex.CharPredicates +java.lang.Character$Subset +java.lang.Character$UnicodeBlock +java.util.regex.Pattern$CharPredicate +java.util.regex.CharPredicates$$Lambda$17/0x000000700105cff8 +java.util.regex.Pattern$BmpCharPredicate +java.util.regex.Pattern$CharProperty +java.util.regex.Pattern$Qtype +java.util.regex.Pattern$BmpCharProperty +java.util.regex.Pattern$CharPropertyGreedy +java.util.regex.Pattern$SliceNode +java.util.regex.Pattern$Slice +java.util.regex.Pattern$Begin +java.util.regex.Pattern$First +java.util.regex.Pattern$Start +java.util.regex.Pattern$StartS +java.util.regex.Pattern$TreeInfo +java.util.regex.Pattern$GroupTail +java.util.regex.CharPredicates$$Lambda$17/0x800000025 +java.util.regex.Pattern$BmpCharPropertyGreedy +java.util.regex.Pattern$$Lambda$19/0x800000029 +java.util.regex.Pattern$Ques +java.util.regex.Pattern$BranchConn +java.util.regex.Pattern$Branch +java.util.regex.ASCII +java.util.regex.Pattern$Curly +java.util.regex.CharPredicates$$Lambda$18/0x800000026 +java.util.regex.Pattern$Dollar +java.util.regex.Pattern$BitClass +org.apache.maven.surefire.booter.ForkedBooter$4 +org.apache.maven.surefire.api.booter.BiProperty +org.apache.maven.surefire.booter.ForkedBooter$3 +org.apache.maven.surefire.booter.ForkedBooter$PingScheduler +org.apache.maven.surefire.api.provider.ProviderParameters +org.apache.maven.surefire.api.booter.BaseProviderFactory +org.apache.maven.surefire.api.util.DirectoryScanner +org.apache.maven.surefire.api.util.ScanResult +org.apache.maven.surefire.api.util.RunOrderCalculator +org.apache.maven.surefire.api.util.ReflectionUtils +org.apache.maven.surefire.api.util.SurefireReflectionException +java.lang.reflect.InvocationTargetException +java.lang.IllegalAccessException +org.apache.maven.surefire.api.provider.SurefireProvider +org.apache.maven.surefire.api.provider.AbstractProvider +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider +org.junit.platform.launcher.Launcher +org.apache.maven.surefire.api.util.ScannerFilter +java.io.StringReader +java.io.UncheckedIOException +org.apache.maven.surefire.junitplatform.LazyLauncher +org.junit.platform.launcher.TagFilter +org.junit.platform.commons.JUnitException +org.junit.platform.commons.util.PreconditionViolationException +org.junit.platform.commons.PreconditionViolationException +org.junit.platform.engine.Filter +org.junit.platform.launcher.PostDiscoveryFilter +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$21/0x00000070010136c8 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$22/0x0000007001013908 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$23/0x0000007001013b40 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$24/0x0000007001013d80 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$25/0x0000007001013fb8 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$26/0x0000007001014208 +org.apache.maven.surefire.junitplatform.TestMethodFilter +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$27/0x00000070010146b8 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$28/0x00000070010148f8 +org.junit.platform.launcher.EngineFilter +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$29/0x0000007001014d88 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$30/0x0000007001014fc8 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$31/0x0000007001015200 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$32/0x0000007001015440 +org.junit.platform.launcher.TestExecutionListener +org.apache.maven.surefire.report.RunModeSetter +org.apache.maven.surefire.junitplatform.RunListenerAdapter +org.apache.maven.surefire.api.report.OutputReportEntry +org.apache.maven.surefire.api.report.TestSetReportEntry +org.apache.maven.surefire.api.report.StackTraceWriter +org.apache.maven.surefire.report.ClassMethodIndexer +org.apache.maven.surefire.api.report.RunMode +org.apache.maven.surefire.api.report.ConsoleOutputCapture +org.apache.maven.surefire.api.report.ConsoleOutputCapture$ForwardingPrintStream +org.apache.maven.surefire.api.report.ConsoleOutputCapture$NullOutputStream +java.util.logging.Logger +java.util.logging.Handler +java.util.logging.Level +java.util.logging.Level$KnownLevel +java.util.logging.Level$KnownLevel$$Lambda$14/0x800000022 +java.util.logging.Level$KnownLevel$$Lambda$15/0x800000023 +java.util.logging.Logger$LoggerBundle +java.util.logging.Logger$ConfigurationData +java.util.logging.LogManager$1 +java.util.logging.LogManager$LoggerContext +java.util.logging.LogManager$SystemLoggerContext +java.util.logging.LogManager$LogNode +java.util.Collections$SynchronizedMap +java.util.logging.LogManager$Cleaner +java.util.logging.LoggingPermission +sun.util.logging.internal.LoggingProviderImpl$LogManagerAccess +java.util.logging.LogManager$LoggingProviderAccess +java.lang.System$LoggerFinder +jdk.internal.logger.DefaultLoggerFinder +sun.util.logging.internal.LoggingProviderImpl +java.util.logging.LogManager$2 +java.util.logging.LogManager$RootLogger +java.util.logging.LogManager$LoggerWeakRef +java.lang.invoke.MethodHandleImpl$AsVarargsCollector +java.lang.invoke.BoundMethodHandle$Species_LL +java.lang.invoke.LambdaForm$MH/0x0000007001018000 +java.util.logging.LogManager$VisitedLoggers +java.util.logging.LogManager$LoggerContext$1 +java.util.concurrent.ConcurrentHashMap$KeySetView +java.util.Collections$3 +java.util.concurrent.ConcurrentHashMap$KeyIterator +java.util.Hashtable$Enumerator +java.util.logging.Level$$Lambda$13/0x800000011 +java.util.ArrayList$ArrayListSpliterator +java.util.logging.Level$KnownLevel$$Lambda$16/0x800000024 +java.util.stream.ReferencePipeline$7 +java.util.stream.FindOps +java.util.stream.FindOps$FindSink +java.util.stream.FindOps$FindSink$OfRef +java.util.stream.FindOps$FindOp +java.util.stream.FindOps$FindSink$OfRef$$Lambda$41/0x800000050 +java.util.stream.FindOps$FindSink$OfRef$$Lambda$39/0x80000004e +java.util.stream.FindOps$FindSink$OfRef$$Lambda$40/0x80000004f +java.util.stream.FindOps$FindSink$OfRef$$Lambda$38/0x80000004d +java.util.stream.ReferencePipeline$7$1 +java.util.stream.Streams$AbstractStreamBuilderImpl +java.util.stream.Stream$Builder +java.util.stream.Streams$StreamBuilderImpl +java.util.stream.Streams +java.util.IdentityHashMap$Values +java.lang.System$Logger +sun.util.logging.PlatformLogger$Bridge +sun.util.logging.PlatformLogger$ConfigurableBridge +jdk.internal.logger.BootstrapLogger +jdk.internal.logger.BootstrapLogger$DetectBackend +jdk.internal.logger.BootstrapLogger$DetectBackend$1 +jdk.internal.logger.BootstrapLogger$LoggingBackend +jdk.internal.logger.BootstrapLogger$RedirectedLoggers +jdk.internal.logger.BootstrapLogger$BootstrapExecutors +java.util.logging.LogManager$4 +java.util.logging.Logger$SystemLoggerHelper +java.util.logging.Logger$SystemLoggerHelper$1 +jdk.internal.logger.DefaultLoggerFinder$1 +org.apache.maven.surefire.junitplatform.TestPlanScannerFilter +org.apache.maven.surefire.api.util.DefaultScanResult +jdk.internal.loader.URLClassPath$FileLoader$1 +software.amazon.lambda.powertools.metrics.MetricsBuilderTest +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder +org.junit.platform.engine.ConfigurationParameters +org.junit.platform.engine.EngineDiscoveryRequest +org.junit.platform.launcher.LauncherDiscoveryRequest +org.junit.platform.engine.DiscoverySelector +org.junit.platform.engine.discovery.DiscoverySelectors +org.junit.platform.commons.util.Preconditions +org.junit.platform.commons.util.StringUtils +java.util.regex.CharPredicates$$Lambda$41/0x000000700105e690 +org.junit.platform.engine.discovery.ClassSelector +java.lang.invoke.LambdaForm$DMH/0x0000007001018400 +org.junit.platform.commons.util.Preconditions$$Lambda$42/0x000000700101d038 +org.junit.platform.commons.util.Preconditions$$Lambda$43/0x000000700101d270 +java.lang.invoke.LambdaForm$DMH/0x0000007001018800 +java.lang.invoke.DirectMethodHandle$Special +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder$$Lambda$44/0x000000700101d4a8 +org.junit.platform.launcher.core.LauncherConfigurationParameters +org.junit.platform.commons.logging.LoggerFactory +org.junit.platform.commons.logging.Logger +org.junit.platform.commons.logging.LoggerFactory$DelegatingLogger +org.junit.platform.launcher.core.LauncherConfigurationParameters$Builder +org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider +org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider$2 +org.junit.platform.commons.util.ClassLoaderUtils +org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider$3 +org.junit.platform.launcher.core.LauncherConfigurationParameters$$Lambda$45/0x000000700101ea88 +org.junit.platform.launcher.core.LauncherConfigurationParameters$$Lambda$46/0x000000700101ecd0 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners +org.junit.platform.engine.EngineDiscoveryListener +org.junit.platform.launcher.LauncherDiscoveryListener +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$LauncherDiscoveryListenerType +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$LauncherDiscoveryListenerType$$Lambda$47/0x000000700101f770 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$LauncherDiscoveryListenerType$$Lambda$48/0x000000700101f990 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$$Lambda$49/0x000000700101fda8 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$$Lambda$50/0x000000700101a000 +org.junit.platform.launcher.listeners.discovery.AbortOnFailureLauncherDiscoveryListener +org.junit.platform.engine.EngineDiscoveryListener$1 +org.junit.platform.launcher.LauncherDiscoveryListener$1 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$$Lambda$51/0x000000700101a958 +org.junit.platform.launcher.core.DefaultDiscoveryRequest +org.junit.platform.launcher.LauncherSession +org.junit.platform.launcher.core.LauncherFactory +org.junit.platform.launcher.core.LauncherConfig +org.junit.platform.launcher.core.LauncherConfig$Builder +org.junit.platform.launcher.core.DefaultLauncherConfig +org.junit.platform.launcher.core.DefaultLauncherSession +org.junit.platform.launcher.LauncherInterceptor +org.junit.platform.launcher.core.DefaultLauncherSession$1 +org.junit.platform.launcher.core.LauncherConfigurationParameters$$Lambda$52/0x0000007001019000 +org.junit.platform.launcher.LauncherSessionListener +org.junit.platform.launcher.core.LauncherFactory$$Lambda$53/0x0000007001019440 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$54/0x0000007001019668 +org.junit.platform.launcher.core.ListenerRegistry +org.junit.platform.launcher.listeners.session.LauncherSessionListeners +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$55/0x0000007001019cc8 +org.junit.platform.launcher.core.ServiceLoaderRegistry +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$56/0x0000007001020000 +java.lang.invoke.LambdaForm$DMH/0x0000007001024000 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$57/0x0000007001020228 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$58/0x0000007001020460 +org.junit.platform.launcher.LauncherSessionListener$1 +org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry +org.junit.platform.engine.TestEngine +org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry$$Lambda$59/0x0000007001020cd8 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$60/0x0000007001020f00 +org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine +org.junit.jupiter.engine.JupiterTestEngine +org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutorService +org.junit.jupiter.engine.config.JupiterConfiguration +org.junit.platform.engine.TestDescriptor +org.junit.platform.engine.support.hierarchical.EngineExecutionContext +org.junit.platform.launcher.core.LauncherFactory$$Lambda$61/0x0000007001021e48 +org.junit.platform.launcher.core.DefaultLauncher +org.junit.platform.launcher.TestPlan +org.junit.platform.launcher.core.InternalTestPlan +org.junit.platform.launcher.core.LauncherListenerRegistry +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$62/0x0000007001022a18 +org.junit.platform.launcher.core.CompositeTestExecutionListener +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$63/0x0000007001022ee8 +org.junit.platform.launcher.core.EngineExecutionOrchestrator +org.junit.platform.engine.EngineExecutionListener +org.junit.platform.launcher.TestPlan$Visitor +org.junit.platform.launcher.core.DefaultLauncher$$Lambda$64/0x0000007001023750 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator +org.junit.platform.launcher.core.EngineDiscoveryResultValidator +org.junit.platform.launcher.core.EngineIdValidator +org.junit.platform.launcher.core.LauncherFactory$$Lambda$65/0x0000007001026000 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$66/0x0000007001026238 +java.util.Spliterators$IteratorSpliterator +org.junit.platform.commons.util.ClassNamePatternFilterUtils +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$67/0x0000007001026678 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$68/0x00000070010268b8 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$69/0x0000007001026b08 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$70/0x0000007001026d48 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$71/0x0000007001026f90 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$72/0x00000070010271e0 +java.util.stream.ForEachOps +java.util.stream.ForEachOps$ForEachOp +java.util.stream.ForEachOps$ForEachOp$OfRef +org.junitpioneer.jupiter.issue.IssueExtensionExecutionListener +org.junitpioneer.jupiter.IssueProcessor +org.junit.platform.launcher.listeners.UniqueIdTrackingListener +org.junit.platform.launcher.core.LauncherFactory$$Lambda$73/0x0000007001027b40 +org.junit.platform.launcher.core.DelegatingLauncher +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$Phase +org.junit.platform.engine.UniqueId +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$74/0x0000007001025670 +org.junit.platform.launcher.core.EngineFilterer +org.junit.platform.engine.FilterResult +org.junit.platform.launcher.core.EngineFilterer$$Lambda$75/0x0000007001025cf8 +java.lang.invoke.LambdaForm$DMH/0x0000007001024400 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$76/0x0000007001024800 +java.util.stream.MatchOps$MatchKind +java.util.stream.MatchOps +java.util.stream.MatchOps$MatchOp +java.util.stream.MatchOps$BooleanTerminalSink +java.util.stream.MatchOps$$Lambda$77/0x000000700105f7f0 +java.util.stream.MatchOps$1MatchSink +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$78/0x0000007001024a50 +org.junit.platform.engine.UniqueIdFormat +java.io.UnsupportedEncodingException +java.util.Formatter +java.util.regex.Pattern$$Lambda$20/0x80000002a +java.util.regex.Pattern$$Lambda$22/0x800000032 +java.util.Locale$Category +java.util.Formatter$Conversion +java.util.Formatter$FormatString +java.util.Formatter$FormatSpecifier +java.util.Formatter$Flags +java.util.Formatter$FixedString +java.util.Formattable +java.util.regex.Pattern$$Lambda$81/0x0000007001060378 +java.lang.invoke.LambdaForm$DMH/0x0000007001028000 +org.junit.platform.engine.UniqueIdFormat$$Lambda$82/0x000000700102c000 +java.net.URLEncoder +java.util.BitSet +java.io.CharArrayWriter +org.junit.platform.engine.UniqueIdFormat$$Lambda$83/0x000000700102c240 +org.junit.platform.engine.UniqueIdFormat$$Lambda$84/0x000000700102c480 +org.junit.platform.engine.UniqueIdFormat$$Lambda$85/0x000000700102c6c0 +org.junit.platform.engine.UniqueIdFormat$$Lambda$86/0x000000700102c900 +org.junit.platform.engine.UniqueIdFormat$$Lambda$87/0x000000700102cb40 +org.junit.platform.engine.UniqueId$Segment +org.junit.jupiter.engine.config.CachingJupiterConfiguration +org.junit.jupiter.engine.config.DefaultJupiterConfiguration +org.junit.jupiter.api.parallel.ExecutionMode +org.junit.jupiter.api.TestInstance$Lifecycle +org.junit.jupiter.api.io.CleanupMode +org.junit.jupiter.engine.config.EnumConfigurationParameterConverter +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter +org.junit.jupiter.api.DisplayNameGenerator +org.junit.jupiter.api.MethodOrderer +org.junit.jupiter.api.ClassOrderer +org.junit.jupiter.api.io.TempDirFactory +org.junit.platform.engine.support.hierarchical.Node +org.junit.platform.engine.support.descriptor.AbstractTestDescriptor +org.junit.platform.engine.support.descriptor.EngineDescriptor +org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor +org.junit.jupiter.api.extension.ExecutableInvoker +org.junit.jupiter.api.extension.ExtensionContext +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver +org.junit.platform.engine.support.discovery.SelectorResolver +org.junit.platform.engine.TestDescriptor$Visitor +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$InitializationContext +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$Builder +org.junit.jupiter.engine.discovery.predicates.IsTestClassWithTests +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod +org.junit.jupiter.engine.discovery.predicates.IsTestMethod +org.junit.jupiter.api.Test +org.junit.jupiter.engine.discovery.predicates.IsTestFactoryMethod +org.junit.jupiter.api.TestFactory +org.junit.jupiter.engine.discovery.predicates.IsTestTemplateMethod +org.junit.jupiter.api.TestTemplate +java.lang.invoke.LambdaForm$DMH/0x0000007001028400 +java.util.function.Predicate$$Lambda$88/0x0000007001060df0 +org.junit.jupiter.engine.discovery.predicates.IsPotentialTestContainer +org.junit.jupiter.engine.discovery.predicates.IsNestedTestClass +org.junit.jupiter.engine.discovery.predicates.IsInnerClass +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$Builder$$Lambda$89/0x0000007001029000 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$90/0x0000007001029248 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$91/0x0000007001029488 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$92/0x00000070010296c8 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$93/0x0000007001029908 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$94/0x0000007001029b48 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$DefaultInitializationContext +org.junit.platform.engine.DiscoveryFilter +org.junit.platform.engine.discovery.ClassNameFilter +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$95/0x0000007001028c00 +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$96/0x0000007001030000 +org.junit.platform.engine.discovery.PackageNameFilter +org.junit.platform.engine.CompositeFilter +org.junit.platform.engine.CompositeFilter$1 +org.junit.platform.engine.CompositeFilter$1$$Lambda$97/0x00000070010308c0 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$$Lambda$98/0x0000007001030b10 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$$Lambda$99/0x0000007001030d58 +java.util.stream.Collectors$$Lambda$100/0x0000007001061048 +java.util.stream.Collectors$$Lambda$101/0x0000007001061278 +org.junit.platform.engine.support.discovery.ClassContainerSelectorResolver +org.junit.jupiter.engine.discovery.ClassSelectorResolver +org.junit.jupiter.engine.discovery.MethodSelectorResolver +org.junit.jupiter.engine.discovery.MethodFinder +java.util.regex.Pattern$$Lambda$102/0x00000070010614c0 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor +org.junit.jupiter.engine.discovery.ClassOrderingVisitor +org.junit.jupiter.api.ClassOrdererContext +org.junit.jupiter.engine.discovery.MethodOrderingVisitor +org.junit.jupiter.api.MethodOrdererContext +java.lang.invoke.LambdaForm$DMH/0x0000007001034000 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$103/0x0000007001032558 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution +org.junit.platform.engine.support.discovery.SelectorResolver$Context +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$DefaultContext +org.junit.platform.engine.support.discovery.SelectorResolver$Match +org.junit.platform.engine.support.discovery.SelectorResolver$Match$$Lambda$104/0x0000007001033008 +org.junit.platform.engine.support.discovery.SelectorResolver$Match$Type +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$105/0x0000007001033668 +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$106/0x00000070010338c0 +java.util.ArrayDeque$$Lambda$107/0x0000007001061720 +org.junit.platform.engine.discovery.UniqueIdSelector +org.junit.platform.engine.support.discovery.SelectorResolver$Resolution +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$108/0x0000007001036000 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$109/0x0000007001036248 +org.junit.platform.engine.discovery.ClasspathResourceSelector +org.junit.platform.engine.discovery.ClasspathRootSelector +org.junit.platform.commons.util.ReflectionUtils +java.util.regex.Pattern$$Lambda$21/0x800000031 +org.junit.platform.commons.util.ClasspathScanner +java.nio.file.FileVisitor +org.junit.platform.commons.util.ReflectionUtils$$Lambda$111/0x0000007001036cf8 +org.junit.platform.commons.function.Try +java.lang.invoke.LambdaForm$DMH/0x0000007001034400 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$112/0x0000007001037168 +java.lang.invoke.LambdaForm$DMH/0x0000007001034800 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$113/0x0000007001037398 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$114/0x00000070010375d0 +org.junit.platform.commons.function.Try$Failure +org.junit.platform.commons.function.Try$Success +org.junit.platform.commons.function.Try$$Lambda$115/0x0000007001037ca8 +java.util.regex.MatchResult +java.util.regex.Matcher +java.util.regex.IntHashSet +java.util.regex.Pattern$1 +org.junit.platform.engine.discovery.ClassSelector$$Lambda$116/0x0000007001035000 +org.junit.platform.commons.util.ReflectionUtils$HierarchyTraversalMode +java.lang.PublicMethods +software.amazon.lambda.powertools.metrics.provider.MetricsProvider +java.util.LinkedHashMap$LinkedValues +java.util.LinkedHashMap$LinkedValueIterator +org.junit.platform.commons.util.ReflectionUtils$$Lambda$117/0x0000007001035888 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$118/0x0000007001035ad8 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$119/0x0000007001035cf8 +java.util.stream.SortedOps +java.util.stream.ReferencePipeline$StatefulOp +java.util.stream.SortedOps$OfRef +org.junit.platform.commons.util.ReflectionUtils$$Lambda$120/0x0000007001034c00 +java.util.stream.SortedOps$AbstractRefSortingSink +java.util.stream.SortedOps$SizedRefSortingSink +java.util.Arrays$LegacyMergeSort +java.util.TimSort +org.junit.platform.commons.util.AnnotationUtils +java.lang.annotation.Inherited +sun.reflect.generics.parser.SignatureParser +sun.reflect.generics.tree.Tree +sun.reflect.generics.tree.TypeTree +sun.reflect.generics.tree.TypeArgument +sun.reflect.generics.tree.ReturnType +sun.reflect.generics.tree.TypeSignature +sun.reflect.generics.tree.BaseType +sun.reflect.generics.tree.FieldTypeSignature +sun.reflect.generics.tree.SimpleClassTypeSignature +sun.reflect.generics.tree.ClassTypeSignature +sun.reflect.generics.scope.Scope +sun.reflect.generics.scope.AbstractScope +sun.reflect.generics.scope.ClassScope +sun.reflect.generics.factory.GenericsFactory +sun.reflect.generics.factory.CoreReflectionFactory +sun.reflect.generics.visitor.TypeTreeVisitor +sun.reflect.generics.visitor.Reifier +java.lang.annotation.Target +java.lang.reflect.GenericArrayType +sun.reflect.annotation.AnnotationType +sun.reflect.annotation.AnnotationType$1 +java.lang.annotation.ElementType +java.lang.annotation.Retention +java.lang.annotation.Documented +java.lang.annotation.RetentionPolicy +sun.reflect.annotation.ExceptionProxy +sun.reflect.annotation.AnnotationTypeMismatchExceptionProxy +sun.reflect.annotation.AnnotationParser$1 +java.lang.reflect.InvocationHandler +sun.reflect.annotation.AnnotationInvocationHandler +java.lang.reflect.Proxy +java.lang.ClassValue +java.lang.reflect.Proxy$1 +java.lang.ClassValue$Entry +java.lang.ClassValue$Identity +java.lang.ClassValue$Version +jdk.internal.loader.AbstractClassLoaderValue$Sub +java.lang.reflect.Proxy$$Lambda$121/0x000000700106b350 +java.lang.reflect.Proxy$ProxyBuilder +java.lang.reflect.Proxy$ProxyBuilder$$Lambda$122/0x000000700106b790 +java.lang.module.ModuleDescriptor$Modifier +java.lang.module.ModuleDescriptor$Builder +jdk.internal.module.Checks +java.lang.module.ModuleDescriptor$Builder$$Lambda$1/0x800000002 +java.lang.reflect.Proxy$$Lambda$124/0x000000700106b9c0 +java.lang.reflect.ProxyGenerator +java.lang.reflect.ProxyGenerator$ProxyMethod +java.util.StringJoiner +java.lang.reflect.ProxyGenerator$$Lambda$125/0x000000700106c110 +java.lang.reflect.ProxyGenerator$$Lambda$126/0x000000700106c350 +java.lang.reflect.ProxyGenerator$PrimitiveTypeInfo +jdk.internal.org.objectweb.asm.Edge +jdk.proxy1.$Proxy0 +java.lang.reflect.Proxy$ProxyBuilder$1 +sun.reflect.annotation.AnnotationParser$$Lambda$127/0x000000700106ce40 +java.lang.invoke.LambdaForm$DMH/0x000000700103c000 +jdk.proxy1.$Proxy1 +jdk.proxy1.$Proxy2 +org.apiguardian.api.API +org.apiguardian.api.API$Status +jdk.proxy2.$Proxy3 +java.lang.reflect.UndeclaredThrowableException +org.junit.platform.commons.annotation.Testable +jdk.proxy1.$Proxy4 +jdk.proxy2.$Proxy5 +java.lang.Class$AnnotationData +org.junit.jupiter.api.AfterEach +jdk.proxy2.$Proxy6 +java.util.LinkedHashMap$LinkedEntrySet +java.util.LinkedHashMap$LinkedEntryIterator +jdk.internal.misc.ScopedMemoryAccess$Scope +jdk.proxy2.$Proxy7 +java.lang.invoke.MethodHandle$1 +java.lang.invoke.LambdaForm$DMH/0x000000700103c400 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$128/0x00000070010395a0 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor +org.junit.jupiter.engine.descriptor.ClassTestDescriptor +org.junit.jupiter.engine.extension.ExtensionRegistry +org.junit.platform.engine.TestSource +org.junit.jupiter.engine.extension.ExtensionRegistrar +org.junit.jupiter.api.extension.TestInstanceFactoryContext +org.junit.jupiter.api.extension.ExtensionConfigurationException +org.junit.jupiter.api.extension.TestInstantiationException +org.junit.jupiter.engine.execution.ConditionEvaluator +org.junit.jupiter.engine.execution.ConditionEvaluationException +org.junit.jupiter.api.extension.ConditionEvaluationResult +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker +org.junit.jupiter.api.extension.ReflectiveInvocationContext +org.junit.jupiter.api.extension.InvocationInterceptor$Invocation +org.junit.jupiter.engine.execution.InvocationInterceptorChain +org.junit.jupiter.engine.descriptor.DisplayNameUtils +org.junit.jupiter.api.DisplayNameGenerator$Standard +org.junit.jupiter.api.DisplayNameGenerator$Simple +org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores +org.junit.jupiter.api.DisplayNameGenerator$IndicativeSentences +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$129/0x000000700103ed38 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$130/0x000000700103ef80 +org.junit.platform.engine.support.descriptor.ClassSource +org.junit.jupiter.api.DisplayName +org.junit.jupiter.api.DisplayNameGeneration +java.lang.invoke.LambdaForm$DMH/0x000000700103c800 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$131/0x000000700103f7c8 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$132/0x000000700103fa08 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$133/0x000000700103fc48 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$134/0x000000700103d000 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$135/0x000000700103d248 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$136/0x000000700103d488 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$137/0x000000700103d6d8 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$138/0x000000700103d920 +org.junit.jupiter.engine.config.DefaultJupiterConfiguration$$Lambda$139/0x000000700103db40 +org.junit.jupiter.api.Tag +java.lang.annotation.Repeatable +org.junit.jupiter.api.Tags +jdk.proxy1.$Proxy8 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$140/0x0000007001080000 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$141/0x0000007001080228 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$142/0x0000007001080468 +org.junit.platform.engine.TestTag +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$143/0x00000070010808d0 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$144/0x0000007001080b10 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$145/0x0000007001080d30 +java.lang.invoke.LambdaForm$DMH/0x0000007001084000 +java.util.function.Function$$Lambda$146/0x000000700106e488 +org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils +org.junit.jupiter.api.TestInstance +jdk.internal.reflect.ClassFileConstants +jdk.internal.reflect.AccessorGenerator +jdk.internal.reflect.MethodAccessorGenerator +jdk.internal.reflect.ByteVectorFactory +jdk.internal.reflect.ByteVector +jdk.internal.reflect.ByteVectorImpl +jdk.internal.reflect.ClassFileAssembler +jdk.internal.reflect.UTF8 +jdk.internal.reflect.Label +jdk.internal.reflect.Label$PatchInfo +jdk.internal.reflect.MethodAccessorGenerator$1 +jdk.internal.reflect.ClassDefiner +jdk.internal.reflect.ClassDefiner$1 +jdk.internal.reflect.GeneratedConstructorAccessor1 +java.lang.Class$1 +jdk.internal.reflect.BootstrapConstructorAccessorImpl +org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils$$Lambda$147/0x0000007001081178 +org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils$$Lambda$148/0x00000070010813b8 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$149/0x00000070010815e0 +java.lang.invoke.LambdaForm$DMH/0x0000007001084800 +org.junit.jupiter.engine.config.EnumConfigurationParameterConverter$$Lambda$150/0x0000007001081a20 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$151/0x0000007001081c68 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$152/0x0000007001081eb0 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$153/0x00000070010820d8 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$154/0x0000007001082320 +org.junit.platform.engine.SelectorResolutionResult +org.junit.platform.engine.SelectorResolutionResult$Status +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$155/0x0000007001082bb8 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$156/0x0000007001082e08 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$157/0x0000007001083040 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$158/0x0000007001083290 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$159/0x00000070010834e8 +java.util.stream.DistinctOps +java.util.stream.DistinctOps$1 +org.junit.platform.commons.util.CollectionUtils +org.junit.platform.commons.util.CollectionUtils$$Lambda$160/0x0000007001083948 +java.util.stream.DistinctOps$1$2 +org.junit.jupiter.api.BeforeEach +jdk.proxy2.$Proxy9 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$161/0x0000007001086000 +org.junit.platform.commons.support.ReflectionSupport +org.junit.platform.engine.discovery.NestedClassSelector +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$162/0x0000007001086688 +java.util.stream.Streams$ConcatSpliterator +java.util.stream.Streams$ConcatSpliterator$OfRef +java.util.stream.AbstractPipeline$$Lambda$163/0x0000007001070f38 +java.util.stream.StreamSpliterators$AbstractWrappingSpliterator +java.util.stream.StreamSpliterators$WrappingSpliterator +java.util.stream.Streams$2 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$164/0x00000070010868d0 +java.lang.invoke.LambdaForm$DMH/0x0000007001084c00 +java.util.stream.StreamSpliterators +java.util.stream.StreamSpliterators$WrappingSpliterator$$Lambda$165/0x0000007001071ac8 +org.junit.platform.engine.discovery.MethodSelector +org.junit.platform.engine.discovery.MethodSelector$$Lambda$166/0x0000007001086d40 +org.junit.platform.commons.util.ClassUtils +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$167/0x0000007001087188 +org.junit.platform.engine.discovery.IterationSelector +org.junit.platform.engine.discovery.DirectorySelector +org.junit.platform.engine.discovery.FileSelector +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$168/0x0000007001087a38 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$169/0x0000007001087c60 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$1 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$2 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$3 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$170/0x0000007001085b38 +java.lang.invoke.LambdaForm$DMH/0x0000007001088000 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$171/0x0000007001085d80 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$172/0x000000700108c000 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$173/0x000000700108c240 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$174/0x000000700108c488 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$175/0x000000700108c6b0 +org.junit.platform.commons.util.ClassUtils$$Lambda$176/0x000000700108c8f8 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall$VoidMethodInterceptorCall +org.junit.jupiter.api.extension.Extension +org.junit.jupiter.api.extension.InvocationInterceptor +java.lang.invoke.LambdaForm$DMH/0x0000007001088400 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$177/0x000000700108da08 +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall$$Lambda$178/0x000000700108de28 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$179/0x000000700108e050 +org.junit.jupiter.api.DisplayNameGenerator$$Lambda$180/0x000000700108e298 +org.junit.platform.engine.support.descriptor.MethodSource +org.junit.platform.commons.util.AnnotationUtils$$Lambda$181/0x000000700108e700 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$182/0x000000700108e940 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$183/0x000000700108eb90 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$184/0x000000700108edd0 +java.util.HashMap$KeySpliterator +org.junit.jupiter.engine.descriptor.Filterable +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$185/0x000000700108f1f8 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$186/0x000000700108f430 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$187/0x000000700108f678 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$188/0x000000700108f8b0 +org.junit.jupiter.api.ClassDescriptor +org.junit.jupiter.engine.discovery.AbstractAnnotatedDescriptorWrapper +org.junit.jupiter.engine.discovery.DefaultClassDescriptor +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$189/0x000000700108a258 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$MessageGenerator +java.lang.invoke.LambdaForm$DMH/0x0000007001088800 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$190/0x000000700108a698 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$191/0x000000700108a8c0 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$DescriptorWrapperOrderer +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$$Lambda$192/0x000000700108acf8 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$$Lambda$193/0x000000700108af50 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$$Lambda$194/0x000000700108b198 +java.lang.invoke.LambdaForm$DMH/0x0000007001088c00 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$$Lambda$195/0x000000700108b3b8 +org.junit.jupiter.api.TestClassOrder +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$196/0x000000700108b7f0 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$197/0x000000700108ba30 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$198/0x000000700108bc70 +org.junit.platform.engine.TestDescriptor$$Lambda$199/0x0000007001089000 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$200/0x0000007001089238 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$201/0x0000007001089470 +org.junit.jupiter.api.TestMethodOrder +org.junit.platform.commons.support.AnnotationSupport +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$202/0x0000007001089ab8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$203/0x0000007001089cf8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$204/0x0000007001090000 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$205/0x0000007001090240 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$206/0x0000007001090468 +java.lang.invoke.LambdaForm$DMH/0x0000007001094000 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$207/0x00000070010906b0 +org.junit.platform.engine.TestDescriptor$Type +org.junit.platform.engine.TestDescriptor$$Lambda$208/0x0000007001090d28 +org.junit.platform.launcher.core.EngineDiscoveryResultValidator$$Lambda$209/0x0000007001090f78 +org.junit.platform.launcher.core.EngineDiscoveryResultValidator$$Lambda$210/0x00000070010911a0 +org.junit.platform.launcher.EngineDiscoveryResult +org.junit.platform.launcher.EngineDiscoveryResult$Status +org.junit.platform.commons.util.ExceptionUtils +java.io.StringWriter +org.junit.platform.launcher.listeners.discovery.AbortOnFailureLauncherDiscoveryListener$$Lambda$211/0x0000007001091c30 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$212/0x0000007001091e60 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$213/0x00000070010920b0 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$214/0x0000007001092308 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$215/0x0000007001092548 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$216/0x0000007001092768 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$217/0x00000070010929b8 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$218/0x0000007001092be0 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$219/0x0000007001092e18 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$220/0x0000007001093048 +org.junit.platform.launcher.core.LauncherDiscoveryResult +org.junit.platform.launcher.TestPlan$$Lambda$221/0x00000070010934a0 +org.junit.platform.launcher.TestPlan$$Lambda$222/0x00000070010936f0 +org.junit.platform.launcher.TestPlan$$Lambda$223/0x0000007001093918 +org.junit.platform.launcher.TestIdentifier +org.junit.platform.launcher.TestIdentifier$SerializedForm +java.io.ObjectStreamClass +java.io.ObjectStreamClass$Caches +java.io.ClassCache +java.io.ObjectStreamClass$Caches$1 +java.io.ClassCache$1 +java.io.ObjectStreamClass$Caches$2 +java.lang.ClassValue$ClassValueMap +java.io.Externalizable +java.io.ObjectStreamClass$2 +jdk.internal.reflect.UnsafeFieldAccessorFactory +jdk.internal.reflect.UnsafeQualifiedStaticFieldAccessorImpl +jdk.internal.reflect.UnsafeQualifiedStaticLongFieldAccessorImpl +java.util.ComparableTimSort +jdk.internal.reflect.SerializationConstructorAccessorImpl +jdk.internal.reflect.GeneratedSerializationConstructorAccessor1 +java.io.ObjectOutput +java.io.ObjectStreamConstants +java.io.ObjectOutputStream +java.io.ObjectInput +java.io.ObjectInputStream +java.lang.Class$$Lambda$224/0x0000007001075608 +java.util.stream.Collectors$$Lambda$32/0x800000047 +java.util.stream.Collectors$$Lambda$24/0x80000003f +java.util.stream.Collectors$$Lambda$27/0x800000042 +java.util.stream.Collectors$$Lambda$29/0x800000044 +java.lang.CloneNotSupportedException +java.io.ClassCache$CacheRef +java.io.ObjectStreamClass$FieldReflectorKey +java.io.ObjectStreamClass$FieldReflector +org.junit.platform.launcher.TestIdentifier$$Lambda$229/0x0000007001096000 +org.junit.platform.launcher.TestPlan$$Lambda$230/0x0000007001096240 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$231/0x0000007001096480 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$232/0x00000070010966b8 +software.amazon.lambda.powertools.metrics.ConfigurationPrecedenceTest +com.amazonaws.services.lambda.runtime.Context +com.amazonaws.services.lambda.runtime.RequestHandler +org.junitpioneer.jupiter.SetEnvironmentVariable$SetEnvironmentVariables +org.junitpioneer.jupiter.SetEnvironmentVariable +org.junitpioneer.jupiter.WritesEnvironmentVariable +org.junit.jupiter.api.extension.ExtendWith +sun.reflect.annotation.AnnotationParser$$Lambda$233/0x0000007001076168 +jdk.proxy2.$Proxy10 +jdk.proxy2.$Proxy11 +software.amazon.lambda.powertools.metrics.ConfigurationPrecedenceTest$HandlerWithDefaultMetricsAnnotation +software.amazon.lambda.powertools.metrics.ConfigurationPrecedenceTest$HandlerWithMetricsAnnotation +org.junit.jupiter.api.parallel.ResourceLock +jdk.proxy2.$Proxy12 +sun.reflect.annotation.AnnotationParser$$Lambda$234/0x0000007001076390 +org.junit.jupiter.api.extension.BeforeEachCallback +org.junit.jupiter.api.extension.AfterEachCallback +org.junit.jupiter.api.extension.BeforeAllCallback +org.junit.jupiter.api.extension.AfterAllCallback +org.junitpioneer.jupiter.AbstractEntryBasedExtension +org.junitpioneer.jupiter.EnvironmentVariableExtension +jdk.proxy2.$Proxy13 +org.junit.jupiter.api.parallel.ResourceAccessMode +jdk.proxy2.$Proxy14 +jdk.internal.reflect.GeneratedConstructorAccessor2 +org.junit.jupiter.api.parallel.ResourceLocks +jdk.internal.reflect.GeneratedConstructorAccessor3 +org.junit.jupiter.api.extension.Extensions +sun.reflect.annotation.AnnotationInvocationHandler$1 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$235/0x0000007001098aa0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$236/0x0000007001098cc8 +software.amazon.lambda.powertools.metrics.MetricsFactoryTest +jdk.internal.reflect.GeneratedConstructorAccessor4 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest +java.time.temporal.TemporalAccessor +java.time.temporal.Temporal +java.time.temporal.TemporalAdjuster +java.time.Instant +software.amazon.lambda.powertools.metrics.internal.EmfMetricsLoggerTest +software.amazon.lambda.powertools.metrics.model.MetricUnit +software.amazon.cloudwatchlogs.emf.model.Unit +org.junit.jupiter.params.ParameterizedTest +jdk.proxy2.$Proxy15 +org.junit.jupiter.params.provider.MethodSource +org.junit.jupiter.params.provider.ArgumentsSource +jdk.proxy2.$Proxy16 +jdk.proxy2.$Proxy17 +org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider +org.junit.jupiter.params.ParameterizedTestExtension +jdk.internal.reflect.GeneratedConstructorAccessor5 +jdk.internal.reflect.GeneratedConstructorAccessor6 +org.junit.jupiter.params.provider.ArgumentsProvider +org.junit.jupiter.params.support.AnnotationConsumer +org.junit.jupiter.params.provider.AnnotationBasedArgumentsProvider +org.junit.jupiter.params.provider.MethodArgumentsProvider +jdk.proxy2.$Proxy18 +org.junit.jupiter.params.provider.ArgumentsSources +org.junit.platform.commons.util.ClassUtils$$Lambda$237/0x000000700109ba00 +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor +java.util.function.BiPredicate +org.junit.jupiter.engine.descriptor.DynamicDescendantFilter +org.junit.jupiter.engine.descriptor.DynamicDescendantFilter$WithoutIndexFiltering +org.junit.jupiter.engine.descriptor.DynamicDescendantFilter$Mode +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest +jdk.internal.reflect.GeneratedConstructorAccessor7 +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithAnnotationOnWrongMethod +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithColdStartMetricsAnnotation +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithCustomFunctionName +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithDefaultMetricsAnnotation +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithMetricsAnnotation +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithServiceNameAndColdStart +software.amazon.lambda.powertools.metrics.provider.EmfMetricsProviderTest +software.amazon.lambda.powertools.metrics.model.DimensionSetTest +software.amazon.lambda.powertools.metrics.model.DimensionSet +software.amazon.lambda.powertools.metrics.Metrics +software.amazon.lambda.powertools.metrics.testutils.TestMetrics +software.amazon.lambda.powertools.metrics.model.MetricResolution +org.junit.platform.commons.util.ReflectionUtils$$Lambda$238/0x00000070010a0248 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$239/0x00000070010a0488 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$240/0x00000070010a06c8 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$241/0x00000070010a0920 +java.lang.reflect.Executable$$Lambda$242/0x00000070010767f0 +software.amazon.lambda.powertools.metrics.testutils.TestContext +com.amazonaws.services.lambda.runtime.LambdaLogger +com.amazonaws.services.lambda.runtime.CognitoIdentity +com.amazonaws.services.lambda.runtime.ClientContext +software.amazon.lambda.powertools.metrics.testutils.TestMetricsProvider +org.apache.maven.surefire.api.util.TestsToRun +org.apache.maven.surefire.api.util.DefaultRunOrderCalculator +java.util.random.RandomGenerator +java.util.Random +org.apache.maven.surefire.api.util.CloseableIterator +org.apache.maven.surefire.api.util.TestsToRun$ClassesIterator +java.util.NoSuchElementException +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$243/0x00000070010a1ff8 +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder$$Lambda$244/0x00000070010a2230 +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$245/0x00000070010a2468 +org.junit.platform.launcher.core.CompositeTestExecutionListener$EagerTestExecutionListener +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$246/0x00000070010a28a0 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$247/0x00000070010a2af8 +org.junit.platform.engine.reporting.ReportEntry +java.lang.invoke.LambdaForm$DMH/0x00000070010a4000 +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$248/0x00000070010a2f50 +org.junit.platform.launcher.core.StreamInterceptingTestExecutionListener +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$249/0x00000070010a3450 +org.junit.platform.engine.EngineExecutionListener$1 +org.junit.platform.launcher.core.IterationOrder +org.junit.platform.launcher.core.IterationOrder$1 +org.junit.platform.launcher.core.IterationOrder$2 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$250/0x00000070010a61f8 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$251/0x00000070010a6430 +java.lang.invoke.LambdaForm$DMH/0x00000070010a4400 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$252/0x00000070010a6658 +org.junit.platform.launcher.core.CompositeEngineExecutionListener +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$253/0x00000070010a6b00 +org.junit.platform.launcher.core.ExecutionListenerAdapter +org.junit.platform.launcher.core.DelegatingEngineExecutionListener +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener +org.junit.platform.launcher.core.EngineDiscoveryErrorDescriptor +org.junit.platform.launcher.core.OutcomeDelayingEngineExecutionListener +org.junit.platform.engine.ExecutionRequest +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$254/0x00000070010a7c90 +org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService +org.junit.jupiter.engine.execution.JupiterEngineExecutionContext +org.junit.jupiter.engine.execution.JupiterEngineExecutionContext$State +org.junit.platform.engine.support.hierarchical.ThrowableCollector$Factory +org.junit.platform.engine.support.hierarchical.ThrowableCollector +org.junit.jupiter.engine.support.JupiterThrowableCollectorFactory +org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector +org.junit.jupiter.engine.JupiterTestEngine$$Lambda$255/0x00000070010a4800 +org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor +org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutorService$TestTask +org.junit.platform.engine.support.hierarchical.NodeTreeWalker +org.junit.platform.engine.support.hierarchical.LockManager +org.junit.platform.engine.support.hierarchical.ResourceLock +java.util.concurrent.locks.ReadWriteLock +org.junit.platform.engine.support.hierarchical.ExclusiveResource +org.junit.platform.engine.support.hierarchical.LockManager$$Lambda$256/0x00000070010a8858 +org.junit.platform.engine.support.hierarchical.LockManager$$Lambda$257/0x00000070010a8a98 +java.lang.invoke.LambdaForm$DMH/0x00000070010ac000 +java.lang.invoke.LambdaForm$MH/0x00000070010ac400 +java.util.Comparator$$Lambda$258/0x0000007001076e90 +java.util.Comparators$NaturalOrderComparator +java.lang.invoke.LambdaForm$DMH/0x00000070010ac800 +java.util.Comparator$$Lambda$259/0x00000070010777f0 +java.lang.invoke.LambdaForm$DMH/0x00000070010acc00 +java.util.Comparator$$Lambda$260/0x0000007001077a90 +org.junit.platform.engine.support.hierarchical.ExclusiveResource$LockMode +org.junit.platform.engine.support.hierarchical.LockManager$$Lambda$261/0x00000070010a8f20 +org.junit.platform.engine.support.hierarchical.SingleLock +org.junit.platform.engine.support.hierarchical.LockManager$$Lambda$262/0x00000070010a95c8 +java.util.concurrent.locks.ReentrantReadWriteLock +java.util.concurrent.locks.ReentrantReadWriteLock$Sync +java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync +java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter +java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock +java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock +org.junit.platform.engine.support.hierarchical.NodeUtils +org.junit.platform.engine.support.hierarchical.NodeUtils$1 +org.junit.platform.engine.support.hierarchical.NodeExecutionAdvisor +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$263/0x00000070010a9f08 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$264/0x00000070010aa140 +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$265/0x00000070010aa380 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$1 +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$266/0x00000070010aa9b8 +org.junit.platform.engine.support.hierarchical.Node$ExecutionMode +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$267/0x00000070010ab048 +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$268/0x00000070010ab280 +org.junit.platform.commons.util.CollectionUtils$$Lambda$269/0x00000070010ab4b8 +org.junit.platform.engine.support.hierarchical.NodeTestTaskContext +org.junit.platform.engine.support.hierarchical.NodeTestTask +org.junit.platform.engine.support.hierarchical.Node$DynamicTestExecutor +java.lang.invoke.LambdaForm$DMH/0x00000070010ad000 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$270/0x00000070010abd70 +org.opentest4j.IncompleteExecutionException +org.opentest4j.TestAbortedException +org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector$$Lambda$271/0x00000070010ae4c0 +org.junit.platform.commons.util.UnrecoverableExceptions +org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector$$Lambda$272/0x00000070010ae920 +org.junit.platform.engine.support.hierarchical.ThrowableCollector$Executable +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$273/0x00000070010aed40 +org.junit.jupiter.engine.extension.MutableExtensionRegistry +org.junit.jupiter.api.extension.ExecutionCondition +org.junit.jupiter.engine.extension.DisabledCondition +org.junit.jupiter.engine.extension.TimeoutExtension +org.junit.jupiter.api.Timeout +org.junit.jupiter.api.extension.ExtensionContext$Namespace +org.junit.jupiter.engine.extension.RepeatedTestExtension +org.junit.jupiter.api.extension.TestTemplateInvocationContext +org.junit.jupiter.api.extension.ParameterResolver +org.junit.jupiter.engine.extension.TestInfoParameterResolver +org.junit.jupiter.api.TestInfo +org.junit.jupiter.engine.extension.TestReporterParameterResolver +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$274/0x00000070010b0440 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$275/0x00000070010b0678 +org.junit.jupiter.engine.extension.TempDirectory +org.junit.jupiter.engine.extension.TempDirectory$Scope +org.junit.jupiter.api.extension.AnnotatedElementContext +org.junit.jupiter.api.extension.ParameterResolutionException +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$276/0x00000070010b11c8 +org.junit.jupiter.engine.execution.DefaultExecutableInvoker +org.junit.jupiter.engine.descriptor.AbstractExtensionContext +org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext +org.junit.jupiter.api.extension.ExtensionContext$Store +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$CloseAction +java.lang.invoke.LambdaForm$DMH/0x00000070010b4000 +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$277/0x00000070010b2210 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore +org.junit.platform.engine.support.store.NamespacedHierarchicalStoreException +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$278/0x00000070010b28b8 +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$279/0x00000070010b2af8 +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$280/0x00000070010b2d18 +org.junit.jupiter.engine.execution.JupiterEngineExecutionContext$Builder +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$281/0x00000070010b3190 +org.junit.platform.engine.support.hierarchical.Node$SkipResult +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$282/0x00000070010b35d8 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$283/0x00000070010b3810 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$284/0x00000070010b3a38 +org.junit.platform.launcher.TestPlan$$Lambda$285/0x00000070010b3c70 +org.junit.platform.launcher.TestPlan$$Lambda$286/0x00000070010b6000 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$287/0x00000070010b6228 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$288/0x00000070010b6460 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$289/0x00000070010b6688 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$290/0x00000070010b68c0 +org.junit.platform.engine.UniqueIdFormat$$Lambda$291/0x00000070010b6ae8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$292/0x00000070010b6d30 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$293/0x00000070010b6f88 +org.junit.platform.engine.support.hierarchical.Node$Invocation +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$294/0x00000070010b73b0 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$295/0x00000070010b75d8 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$296/0x00000070010b7800 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$297/0x00000070010b7a48 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor +java.util.concurrent.CancellationException +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$298/0x00000070010b5000 +org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService$$Lambda$299/0x00000070010b5238 +org.junit.jupiter.engine.descriptor.ExtensionUtils +java.util.function.ToIntFunction +java.lang.invoke.LambdaForm$DMH/0x00000070010b4400 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$300/0x00000070010b5670 +java.util.Comparator$$Lambda$301/0x0000007001078e48 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$302/0x00000070010b5890 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$303/0x00000070010b5ad0 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$304/0x00000070010b5d10 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$305/0x00000070010b4800 +com.fasterxml.jackson.core.Versioned +com.fasterxml.jackson.core.TreeCodec +com.fasterxml.jackson.core.ObjectCodec +com.fasterxml.jackson.databind.ObjectMapper +org.junit.platform.commons.util.ReflectionUtils$$Lambda$306/0x00000070010b8d00 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$307/0x00000070010b8f98 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$308/0x00000070010b91b8 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$309/0x00000070010b9408 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$310/0x00000070010b9660 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$311/0x00000070010b98b8 +java.util.stream.SortedOps$RefSortingSink +java.util.stream.SortedOps$RefSortingSink$$Lambda$312/0x00000070010793a8 +org.junit.jupiter.api.extension.TestInstanceFactory +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$313/0x00000070010b9cf0 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$314/0x00000070010b9f48 +org.junit.jupiter.engine.extension.ExtensionRegistry$$Lambda$315/0x00000070010ba190 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$316/0x00000070010ba3b0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$317/0x00000070010ba600 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$318/0x00000070010ba828 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$319/0x00000070010baa70 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$320/0x00000070010bacb0 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils +org.junit.jupiter.api.BeforeAll +org.junit.platform.commons.util.AnnotationUtils$$Lambda$321/0x00000070010bb2f0 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$322/0x00000070010bb548 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$323/0x00000070010bb780 +org.junit.jupiter.api.AfterAll +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$324/0x00000070010bbbb8 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$325/0x00000070010bbdf0 +org.junit.jupiter.engine.execution.BeforeEachMethodAdapter +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$326/0x00000070010bc228 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$327/0x00000070010bc470 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$328/0x00000070010bc6a8 +org.junit.jupiter.engine.execution.AfterEachMethodAdapter +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$329/0x00000070010bcad0 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$330/0x00000070010bcd18 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$331/0x00000070010bcf40 +org.junit.jupiter.engine.descriptor.ClassExtensionContext +org.junit.jupiter.engine.execution.TestInstancesProvider +org.junit.jupiter.api.extension.TestInstances +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$332/0x00000070010bd948 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$333/0x00000070010bdb80 +org.junit.jupiter.engine.execution.ConditionEvaluator$$Lambda$334/0x00000070010bddc8 +org.junit.jupiter.engine.execution.ConditionEvaluator$$Lambda$335/0x00000070010be010 +java.util.stream.AbstractSpinedBuffer +java.util.stream.SpinedBuffer +java.util.stream.StreamSpliterators$WrappingSpliterator$$Lambda$336/0x0000007001079cd0 +java.util.function.BooleanSupplier +java.util.stream.StreamSpliterators$WrappingSpliterator$$Lambda$337/0x000000700107a180 +org.junit.jupiter.api.Disabled +org.junit.jupiter.engine.extension.DisabledCondition$$Lambda$338/0x00000070010be460 +org.junit.jupiter.engine.execution.ConditionEvaluator$$Lambda$339/0x00000070010be6a8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$340/0x00000070010be8d0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$341/0x00000070010beb28 +org.junit.platform.launcher.TestIdentifier$$Lambda$342/0x00000070010bed80 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$343/0x00000070010befc0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$344/0x00000070010bf208 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$345/0x00000070010bf450 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$346/0x00000070010bf670 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$347/0x00000070010bf8c0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$348/0x00000070010bfb00 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$349/0x00000070010bfd58 +org.apache.maven.surefire.api.report.SimpleReportEntry +org.apache.maven.surefire.api.util.internal.ClassMethod +org.apache.maven.surefire.report.ClassMethodIndexer$$Lambda$350/0x00000070010c0510 +org.apache.maven.surefire.api.util.internal.ImmutableMap +org.apache.maven.surefire.booter.spi.EventChannelEncoder$StackTrace +java.lang.StrictMath +java.nio.StringCharBuffer +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$351/0x00000070010c0f00 +org.junit.jupiter.engine.extension.TimeoutDuration +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$352/0x00000070010c1350 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$353/0x00000070010c1590 +org.junit.jupiter.api.Timeout$ThreadMode +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$354/0x00000070010c1a10 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$355/0x00000070010c1c50 +org.junit.jupiter.engine.execution.NamespaceAwareStore +org.junit.jupiter.api.extension.ExtensionContextException +org.junit.jupiter.api.extension.ExtensionContext$Store$CloseableResource +java.lang.invoke.LambdaForm$DMH/0x00000070010c4000 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$356/0x00000070010c2598 +org.junit.jupiter.engine.execution.NamespaceAwareStore$$Lambda$357/0x00000070010c27c0 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$CompositeKey +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$358/0x00000070010c2bf8 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$StoredValue +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$359/0x00000070010c3030 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$360/0x00000070010c3280 +org.junit.jupiter.engine.execution.NamespaceAwareStore$$Lambda$361/0x00000070010c34c8 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$362/0x00000070010c36f0 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$MemoizingSupplier +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$363/0x00000070010c3b68 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$364/0x00000070010c3d90 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$MemoizingSupplier$Failure +org.junit.jupiter.api.io.TempDir +org.junit.platform.commons.util.AnnotationUtils$$Lambda$365/0x00000070010c6608 +java.util.function.Predicate$$Lambda$366/0x000000700107aa40 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$367/0x00000070010c6860 +org.junit.jupiter.engine.descriptor.ClassExtensionContext$$Lambda$368/0x00000070010c6a98 +org.junit.jupiter.engine.descriptor.MethodExtensionContext +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$369/0x00000070010c70a8 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$370/0x00000070010c72d0 +java.lang.invoke.LambdaForm$DMH/0x00000070010c4400 +java.lang.invoke.LambdaForm$MH/0x00000070010c4800 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$371/0x00000070010c74f8 +org.junit.jupiter.engine.descriptor.DefaultTestInstanceFactoryContext +org.junit.jupiter.api.extension.TestInstancePreConstructCallback +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$372/0x00000070010c7b78 +java.lang.invoke.LambdaForm$DMH/0x00000070010c4c00 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$373/0x00000070010c7db0 +org.junit.jupiter.engine.execution.ParameterResolutionUtils +org.junit.jupiter.api.extension.ParameterContext +org.junit.jupiter.engine.execution.ConstructorInvocation +org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptorCall +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$$Lambda$374/0x00000070010c58a0 +org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation +java.util.ArrayList$ListItr +org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation +com.fasterxml.jackson.core.JacksonException +com.fasterxml.jackson.core.JsonProcessingException +com.fasterxml.jackson.databind.DatabindException +com.fasterxml.jackson.databind.JsonMappingException +com.fasterxml.jackson.core.TokenStreamFactory +com.fasterxml.jackson.core.JsonFactory +com.fasterxml.jackson.databind.MappingJsonFactory +com.fasterxml.jackson.databind.jsontype.SubtypeResolver +com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver +com.fasterxml.jackson.databind.DatabindContext +com.fasterxml.jackson.databind.SerializerProvider +com.fasterxml.jackson.databind.ser.DefaultSerializerProvider +com.fasterxml.jackson.databind.ser.DefaultSerializerProvider$Impl +com.fasterxml.jackson.databind.deser.DeserializerFactory +com.fasterxml.jackson.databind.deser.BasicDeserializerFactory +com.fasterxml.jackson.databind.deser.BeanDeserializerFactory +com.fasterxml.jackson.databind.DeserializationContext +com.fasterxml.jackson.databind.deser.DefaultDeserializationContext +com.fasterxml.jackson.databind.deser.DefaultDeserializationContext$Impl +com.fasterxml.jackson.databind.ser.SerializerFactory +com.fasterxml.jackson.databind.ser.BasicSerializerFactory +com.fasterxml.jackson.databind.ser.BeanSerializerFactory +com.fasterxml.jackson.databind.AnnotationIntrospector +com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector +com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy$Provider +com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy$Provider +com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator +com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator$Base +com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator +java.text.Format +java.text.DateFormat +com.fasterxml.jackson.databind.util.StdDateFormat +com.fasterxml.jackson.core.TreeNode +com.fasterxml.jackson.databind.JsonSerializable +com.fasterxml.jackson.databind.JsonSerializable$Base +com.fasterxml.jackson.databind.JsonNode +com.fasterxml.jackson.databind.node.BaseJsonNode +com.fasterxml.jackson.databind.node.ValueNode +com.fasterxml.jackson.databind.node.NullNode +com.fasterxml.jackson.core.JsonGenerator +com.fasterxml.jackson.databind.util.TokenBuffer +com.fasterxml.jackson.databind.introspect.ClassIntrospector +com.fasterxml.jackson.databind.introspect.BasicClassIntrospector +com.fasterxml.jackson.databind.Module$SetupContext +com.fasterxml.jackson.databind.introspect.VisibilityChecker +com.fasterxml.jackson.core.JsonParser +com.fasterxml.jackson.core.base.ParserMinimalBase +com.fasterxml.jackson.databind.node.TreeTraversingParser +com.fasterxml.jackson.core.util.BufferRecycler$Gettable +com.fasterxml.jackson.core.io.SegmentedStringWriter +com.fasterxml.jackson.core.util.ByteArrayBuilder +com.fasterxml.jackson.core.type.ResolvedType +com.fasterxml.jackson.databind.JavaType +com.fasterxml.jackson.databind.type.TypeBase +com.fasterxml.jackson.databind.type.ArrayType +com.fasterxml.jackson.databind.type.CollectionLikeType +com.fasterxml.jackson.databind.type.CollectionType +com.fasterxml.jackson.databind.type.MapLikeType +com.fasterxml.jackson.databind.type.MapType +com.fasterxml.jackson.databind.exc.MismatchedInputException +com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder +com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair +com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector +com.fasterxml.jackson.databind.introspect.Annotated +com.fasterxml.jackson.databind.introspect.AnnotatedMember +com.fasterxml.jackson.databind.introspect.TypeResolutionContext +com.fasterxml.jackson.databind.introspect.AnnotatedClass +com.fasterxml.jackson.databind.introspect.AnnotatedWithParams +com.fasterxml.jackson.databind.introspect.AnnotatedMethod +com.fasterxml.jackson.databind.introspect.VirtualAnnotatedMember +com.fasterxml.jackson.databind.util.Named +com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition +com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition +com.fasterxml.jackson.databind.BeanProperty +com.fasterxml.jackson.databind.introspect.ConcreteBeanPropertyBase +com.fasterxml.jackson.databind.ser.PropertyWriter +com.fasterxml.jackson.databind.ser.BeanPropertyWriter +com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter +com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter +com.fasterxml.jackson.databind.annotation.JsonSerialize +com.fasterxml.jackson.annotation.JsonView +com.fasterxml.jackson.annotation.JsonFormat +com.fasterxml.jackson.annotation.JsonTypeInfo +com.fasterxml.jackson.annotation.JsonRawValue +com.fasterxml.jackson.annotation.JsonUnwrapped +com.fasterxml.jackson.annotation.JsonBackReference +com.fasterxml.jackson.annotation.JsonManagedReference +com.fasterxml.jackson.databind.annotation.JsonDeserialize +com.fasterxml.jackson.annotation.JsonMerge +com.fasterxml.jackson.databind.ext.Java7Support +java.lang.IllegalAccessError +com.fasterxml.jackson.databind.ext.Java7SupportImpl +com.fasterxml.jackson.databind.util.ClassUtil +com.fasterxml.jackson.databind.util.ClassUtil$Ctor +java.beans.Transient +java.beans.ConstructorProperties +com.fasterxml.jackson.databind.util.LookupCache +com.fasterxml.jackson.databind.util.LRUMap +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$Builder +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap +java.io.ObjectStreamException +java.io.InvalidObjectException +com.fasterxml.jackson.databind.util.internal.Linked +com.fasterxml.jackson.databind.util.internal.LinkedDeque +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$1 +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$2 +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$3 +java.util.concurrent.atomic.AtomicLongArray +java.lang.invoke.VarHandleLongs$Array +java.util.concurrent.atomic.AtomicReferenceArray +java.lang.invoke.VarHandleReferences$Array +com.fasterxml.jackson.databind.cfg.BaseSettings +java.util.TimeZone +sun.util.calendar.ZoneInfo +sun.util.calendar.ZoneInfoFile +sun.util.calendar.ZoneInfoFile$1 +java.io.DataInputStream +sun.util.calendar.ZoneInfoFile$ZoneOffsetTransitionRule +com.fasterxml.jackson.databind.type.TypeFactory +com.fasterxml.jackson.databind.type.SimpleType +com.fasterxml.jackson.databind.type.IdentityEqualityType +com.fasterxml.jackson.databind.type.ResolvedRecursiveType +com.fasterxml.jackson.databind.type.ReferenceType +com.fasterxml.jackson.databind.type.IterationType +com.fasterxml.jackson.databind.type.PlaceholderForType +com.fasterxml.jackson.databind.type.TypeParser +com.fasterxml.jackson.databind.type.TypeBindings +java.text.SimpleDateFormat +java.util.Calendar +java.util.GregorianCalendar +java.text.ParseException +java.text.AttributedCharacterIterator$Attribute +java.text.Format$Field +java.text.DateFormat$Field +sun.util.calendar.ZoneInfoFile$Checksum +java.util.spi.LocaleServiceProvider +sun.util.spi.CalendarProvider +sun.util.locale.provider.LocaleProviderAdapter +sun.util.locale.provider.LocaleProviderAdapter$Type +sun.util.locale.provider.LocaleProviderAdapter$1 +sun.util.locale.provider.ResourceBundleBasedAdapter +sun.util.locale.provider.JRELocaleProviderAdapter +sun.util.cldr.CLDRLocaleProviderAdapter +sun.util.locale.provider.LocaleDataMetaInfo +sun.util.cldr.CLDRBaseLocaleDataMetaInfo +sun.util.locale.LanguageTag +sun.util.locale.ParseStatus +sun.util.locale.StringTokenIterator +sun.util.locale.InternalLocaleBuilder +sun.util.locale.InternalLocaleBuilder$CaseInsensitiveChar +sun.util.locale.BaseLocale$Key +sun.util.locale.LocaleObjectCache +sun.util.locale.BaseLocale$Cache +sun.util.locale.LocaleObjectCache$CacheEntry +java.util.Locale$Cache +sun.util.cldr.CLDRLocaleProviderAdapter$$Lambda$58/0x800000063 +jdk.internal.module.ModulePatcher$PatchedModuleReader +sun.net.www.protocol.jrt.Handler +sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$60/0x800000065 +sun.util.locale.provider.AvailableLanguageTags +sun.util.locale.provider.CalendarProviderImpl +java.util.Calendar$Builder +sun.util.calendar.CalendarSystem +sun.util.calendar.CalendarSystem$GregorianHolder +sun.util.calendar.AbstractCalendar +sun.util.calendar.BaseCalendar +sun.util.calendar.Gregorian +sun.util.locale.provider.CalendarDataUtility +java.util.Locale$Builder +java.util.spi.CalendarDataProvider +sun.util.locale.provider.LocaleServiceProviderPool +java.text.spi.BreakIteratorProvider +java.text.spi.CollatorProvider +java.text.spi.DateFormatProvider +java.text.spi.DateFormatSymbolsProvider +java.text.spi.DecimalFormatSymbolsProvider +java.text.spi.NumberFormatProvider +java.util.spi.CurrencyNameProvider +java.util.spi.LocaleNameProvider +java.util.spi.TimeZoneNameProvider +sun.util.locale.provider.LocaleServiceProviderPool$LocalizedObjectGetter +sun.util.locale.provider.CalendarDataUtility$CalendarWeekParameterGetter +java.util.ResourceBundle$Control +java.util.ResourceBundle +java.util.ResourceBundle$Control$CandidateListCache +java.util.ResourceBundle$SingleFormatControl +java.util.ResourceBundle$NoFallbackControl +sun.util.cldr.CLDRLocaleProviderAdapter$$Lambda$59/0x800000064 +sun.util.locale.provider.CalendarDataProviderImpl +sun.util.cldr.CLDRCalendarDataProviderImpl +sun.util.locale.provider.LocaleResources +sun.util.resources.LocaleData +sun.util.resources.LocaleData$1 +sun.util.resources.Bundles$Strategy +sun.util.resources.LocaleData$LocaleDataStrategy +sun.util.resources.Bundles +sun.util.resources.Bundles$1 +jdk.internal.access.JavaUtilResourceBundleAccess +java.util.ResourceBundle$1 +java.util.ResourceBundle$2 +sun.util.resources.Bundles$CacheKey +java.util.ListResourceBundle +sun.util.resources.cldr.CalendarData +java.util.ResourceBundle$ResourceBundleProviderHelper +java.util.ResourceBundle$ResourceBundleProviderHelper$$Lambda$12/0x800000010 +sun.util.resources.Bundles$CacheKeyReference +sun.util.resources.Bundles$BundleReference +sun.util.locale.provider.LocaleResources$ResourceReference +sun.util.calendar.CalendarDate +sun.util.calendar.BaseCalendar$Date +sun.util.calendar.Gregorian$Date +sun.util.calendar.CalendarUtils +java.text.DateFormatSymbols +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$62/0x800000067 +sun.util.locale.provider.DateFormatSymbolsProviderImpl +sun.text.resources.cldr.FormatData +sun.text.resources.cldr.FormatData_en +java.text.NumberFormat +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$64/0x800000069 +sun.util.locale.provider.NumberFormatProviderImpl +java.text.DecimalFormatSymbols +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$63/0x800000068 +sun.util.locale.provider.DecimalFormatSymbolsProviderImpl +java.lang.StringLatin1$CharsSpliterator +java.util.stream.IntStream +java.util.stream.IntPipeline +java.util.stream.IntPipeline$Head +java.util.function.IntPredicate +java.text.DecimalFormatSymbols$$Lambda$8/0x80000000c +java.util.stream.IntPipeline$StatelessOp +java.util.stream.IntPipeline$10 +java.util.function.IntConsumer +java.util.stream.Sink$OfInt +java.util.stream.FindOps$FindSink$OfInt +java.util.OptionalInt +java.util.stream.FindOps$FindSink$OfInt$$Lambda$37/0x80000004c +java.util.stream.FindOps$FindSink$OfInt$$Lambda$35/0x80000004a +java.util.stream.FindOps$FindSink$OfInt$$Lambda$36/0x80000004b +java.util.stream.FindOps$FindSink$OfInt$$Lambda$34/0x800000049 +java.util.stream.Sink$ChainedInt +java.util.stream.IntPipeline$10$1 +java.lang.StringUTF16$CharsSpliterator +java.lang.CharacterData00 +java.text.DecimalFormat +java.text.FieldPosition +java.text.DigitList +java.math.RoundingMode +java.util.Date +com.fasterxml.jackson.core.Base64Variants +com.fasterxml.jackson.core.Base64Variant +com.fasterxml.jackson.core.Base64Variant$PaddingReadBehaviour +com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy +com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy +com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy$RecordNaming +com.fasterxml.jackson.databind.cfg.CacheProvider +com.fasterxml.jackson.databind.cfg.DefaultCacheProvider +com.fasterxml.jackson.core.io.DataOutputAsStream +com.fasterxml.jackson.core.SerializableString +com.fasterxml.jackson.core.TSFBuilder +com.fasterxml.jackson.core.JsonFactoryBuilder +java.io.CharArrayReader +com.fasterxml.jackson.core.base.GeneratorBase +com.fasterxml.jackson.core.json.JsonGeneratorImpl +com.fasterxml.jackson.core.json.WriterBasedJsonGenerator +com.fasterxml.jackson.core.base.ParserBase +com.fasterxml.jackson.core.json.JsonParserBase +com.fasterxml.jackson.core.json.ReaderBasedJsonParser +com.fasterxml.jackson.core.json.UTF8DataInputJsonParser +com.fasterxml.jackson.core.json.UTF8JsonGenerator +com.fasterxml.jackson.core.io.UTF8Writer +com.fasterxml.jackson.core.async.NonBlockingInputFeeder +com.fasterxml.jackson.core.async.ByteArrayFeeder +com.fasterxml.jackson.core.json.async.NonBlockingJsonParserBase +com.fasterxml.jackson.core.json.async.NonBlockingUtf8JsonParserBase +com.fasterxml.jackson.core.json.async.NonBlockingJsonParser +com.fasterxml.jackson.core.async.ByteBufferFeeder +com.fasterxml.jackson.core.json.async.NonBlockingByteBufferJsonParser +com.fasterxml.jackson.core.util.JacksonFeature +com.fasterxml.jackson.core.JsonFactory$Feature +com.fasterxml.jackson.core.JsonParser$Feature +com.fasterxml.jackson.core.JsonGenerator$Feature +com.fasterxml.jackson.core.io.SerializedString +com.fasterxml.jackson.core.io.JsonStringEncoder +com.fasterxml.jackson.core.io.CharTypes +com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer +com.fasterxml.jackson.core.exc.StreamConstraintsException +com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer$TableInfo +com.fasterxml.jackson.core.util.JsonRecyclerPools +com.fasterxml.jackson.core.util.RecyclerPool +com.fasterxml.jackson.core.util.RecyclerPool$ThreadLocalPoolBase +com.fasterxml.jackson.core.util.JsonRecyclerPools$ThreadLocalPool +com.fasterxml.jackson.core.util.RecyclerPool$WithPool +com.fasterxml.jackson.core.StreamReadConstraints +com.fasterxml.jackson.core.StreamWriteConstraints +com.fasterxml.jackson.core.ErrorReportConfiguration +com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer +com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer$TableInfo +com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer$Bucket +com.fasterxml.jackson.databind.util.RootNameLookup +com.fasterxml.jackson.databind.introspect.ClassIntrospector$MixInResolver +com.fasterxml.jackson.databind.introspect.SimpleMixInResolver +com.fasterxml.jackson.databind.cfg.MapperConfig +com.fasterxml.jackson.databind.cfg.MapperConfigBase +com.fasterxml.jackson.databind.SerializationConfig +com.fasterxml.jackson.databind.BeanDescription +com.fasterxml.jackson.databind.introspect.BasicBeanDescription +com.fasterxml.jackson.databind.DeserializationConfig +com.fasterxml.jackson.databind.introspect.AnnotatedClassResolver +com.fasterxml.jackson.databind.introspect.AnnotationCollector +com.fasterxml.jackson.databind.util.Annotations +com.fasterxml.jackson.databind.introspect.AnnotationCollector$EmptyCollector +com.fasterxml.jackson.databind.introspect.AnnotationCollector$NoAnnotations +com.fasterxml.jackson.databind.introspect.AnnotatedClass$Creators +com.fasterxml.jackson.databind.introspect.AnnotatedConstructor +com.fasterxml.jackson.databind.introspect.AnnotatedParameter +com.fasterxml.jackson.databind.cfg.ConfigOverrides +com.fasterxml.jackson.annotation.JacksonAnnotationValue +com.fasterxml.jackson.annotation.JsonInclude$Value +com.fasterxml.jackson.annotation.JsonInclude$Include +com.fasterxml.jackson.annotation.JsonSetter$Value +com.fasterxml.jackson.annotation.Nulls +com.fasterxml.jackson.databind.introspect.VisibilityChecker$Std +com.fasterxml.jackson.annotation.JsonAutoDetect$Visibility +com.fasterxml.jackson.databind.cfg.CoercionConfigs +com.fasterxml.jackson.databind.type.LogicalType +com.fasterxml.jackson.databind.cfg.CoercionAction +com.fasterxml.jackson.databind.cfg.CoercionConfig +com.fasterxml.jackson.databind.cfg.MutableCoercionConfig +com.fasterxml.jackson.databind.cfg.CoercionInputShape +com.fasterxml.jackson.databind.jsontype.DefaultBaseTypeLimitingValidator +com.fasterxml.jackson.core.PrettyPrinter +com.fasterxml.jackson.annotation.JsonFormat$Value +com.fasterxml.jackson.annotation.JsonFormat$Shape +com.fasterxml.jackson.annotation.JsonFormat$Features +com.fasterxml.jackson.databind.cfg.ConfigOverride +com.fasterxml.jackson.databind.cfg.ConfigOverride$Empty +com.fasterxml.jackson.databind.cfg.ConfigFeature +com.fasterxml.jackson.databind.MapperFeature +com.fasterxml.jackson.core.util.Instantiatable +com.fasterxml.jackson.core.util.DefaultPrettyPrinter +com.fasterxml.jackson.core.util.DefaultPrettyPrinter$Indenter +com.fasterxml.jackson.core.util.Separators +com.fasterxml.jackson.core.util.Separators$Spacing +com.fasterxml.jackson.core.util.DefaultPrettyPrinter$NopIndenter +com.fasterxml.jackson.core.util.DefaultPrettyPrinter$FixedSpaceIndenter +com.fasterxml.jackson.core.util.DefaultIndenter +com.fasterxml.jackson.databind.SerializationFeature +com.fasterxml.jackson.databind.cfg.DatatypeFeatures +com.fasterxml.jackson.databind.cfg.DatatypeFeatures$DefaultHolder +com.fasterxml.jackson.databind.cfg.DatatypeFeature +com.fasterxml.jackson.databind.cfg.EnumFeature +com.fasterxml.jackson.databind.cfg.JsonNodeFeature +com.fasterxml.jackson.databind.cfg.ContextAttributes +com.fasterxml.jackson.databind.cfg.ContextAttributes$Impl +com.fasterxml.jackson.databind.DeserializationFeature +com.fasterxml.jackson.databind.node.JsonNodeCreator +com.fasterxml.jackson.databind.node.JsonNodeFactory +com.fasterxml.jackson.databind.node.NumericNode +com.fasterxml.jackson.databind.node.FloatNode +com.fasterxml.jackson.databind.node.DoubleNode +com.fasterxml.jackson.databind.node.BigIntegerNode +com.fasterxml.jackson.databind.node.ShortNode +com.fasterxml.jackson.databind.node.IntNode +com.fasterxml.jackson.databind.node.DecimalNode +com.fasterxml.jackson.databind.node.LongNode +com.fasterxml.jackson.databind.node.TextNode +com.fasterxml.jackson.databind.node.BinaryNode +com.fasterxml.jackson.databind.node.POJONode +com.fasterxml.jackson.databind.node.MissingNode +com.fasterxml.jackson.databind.node.BooleanNode +com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable +com.fasterxml.jackson.databind.JsonSerializer +com.fasterxml.jackson.databind.jsonschema.SchemaAware +com.fasterxml.jackson.databind.ser.std.StdSerializer +com.fasterxml.jackson.databind.ser.std.NullSerializer +com.fasterxml.jackson.databind.ser.impl.FailingSerializer +com.fasterxml.jackson.databind.ser.std.ToEmptyObjectSerializer +com.fasterxml.jackson.databind.ser.impl.UnknownSerializer +com.fasterxml.jackson.databind.exc.InvalidDefinitionException +com.fasterxml.jackson.databind.exc.InvalidTypeIdException +com.fasterxml.jackson.databind.ser.ContextualSerializer +com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer +com.fasterxml.jackson.databind.node.ContainerNode +com.fasterxml.jackson.databind.node.ObjectNode +com.fasterxml.jackson.databind.ser.ResolvableSerializer +com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer +com.fasterxml.jackson.databind.ser.SerializerCache +com.fasterxml.jackson.databind.deser.NullValueProvider +com.fasterxml.jackson.databind.JsonDeserializer +com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer +com.fasterxml.jackson.databind.exc.PropertyBindingException +com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException +com.fasterxml.jackson.databind.exc.InvalidFormatException +com.fasterxml.jackson.databind.exc.ValueInstantiationException +com.fasterxml.jackson.databind.deser.UnresolvedForwardReference +com.fasterxml.jackson.databind.deser.ContextualDeserializer +com.fasterxml.jackson.databind.deser.AbstractDeserializer +com.fasterxml.jackson.databind.deser.ValueInstantiator$Gettable +com.fasterxml.jackson.databind.deser.std.StdDeserializer +com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer +com.fasterxml.jackson.databind.deser.std.EnumDeserializer +com.fasterxml.jackson.databind.deser.std.StringArrayDeserializer +com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase +com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer +com.fasterxml.jackson.databind.deser.ResolvableDeserializer +com.fasterxml.jackson.databind.deser.std.EnumMapDeserializer +com.fasterxml.jackson.databind.deser.std.MapDeserializer +com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer +com.fasterxml.jackson.databind.deser.std.StringDeserializer +com.fasterxml.jackson.databind.deser.std.MapEntryDeserializer +com.fasterxml.jackson.databind.deser.std.TokenBufferDeserializer +com.fasterxml.jackson.databind.deser.SettableBeanProperty +com.fasterxml.jackson.databind.deser.CreatorProperty +com.fasterxml.jackson.databind.deser.std.ReferenceTypeDeserializer +com.fasterxml.jackson.databind.deser.std.AtomicReferenceDeserializer +com.fasterxml.jackson.databind.deser.std.EnumSetDeserializer +com.fasterxml.jackson.databind.deser.std.CollectionDeserializer +com.fasterxml.jackson.databind.deser.std.ArrayBlockingQueueDeserializer +com.fasterxml.jackson.databind.deser.std.StringCollectionDeserializer +com.fasterxml.jackson.databind.deser.impl.ErrorThrowingDeserializer +com.fasterxml.jackson.annotation.ObjectIdGenerator +com.fasterxml.jackson.annotation.ObjectIdGenerators$Base +com.fasterxml.jackson.annotation.ObjectIdGenerators$PropertyGenerator +com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator +com.fasterxml.jackson.databind.deser.BeanDeserializerBase +com.fasterxml.jackson.databind.deser.BeanDeserializer +com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer +com.fasterxml.jackson.databind.deser.impl.MethodProperty +com.fasterxml.jackson.databind.deser.impl.FieldProperty +com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer +com.fasterxml.jackson.databind.deser.impl.SetterlessProperty +com.fasterxml.jackson.databind.deser.Deserializers +com.fasterxml.jackson.databind.PropertyName +com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig +com.fasterxml.jackson.databind.deser.BeanDeserializerModifier +com.fasterxml.jackson.databind.AbstractTypeResolver +com.fasterxml.jackson.databind.deser.ValueInstantiators +com.fasterxml.jackson.databind.deser.KeyDeserializers +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializers +com.fasterxml.jackson.databind.KeyDeserializer +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringCtorKeyDeserializer +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringFactoryKeyDeserializer +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$DelegatingKD +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$EnumKD +com.fasterxml.jackson.databind.deser.DeserializerCache +com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer +com.fasterxml.jackson.databind.ser.ContainerSerializer +com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase +com.fasterxml.jackson.databind.ser.std.CollectionSerializer +com.fasterxml.jackson.databind.ser.std.StaticListSerializerBase +com.fasterxml.jackson.databind.ser.impl.IndexedStringListSerializer +com.fasterxml.jackson.databind.ser.impl.StringCollectionSerializer +com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer +com.fasterxml.jackson.databind.ser.std.EnumSetSerializer +com.fasterxml.jackson.databind.ser.std.MapSerializer +com.fasterxml.jackson.databind.ser.impl.MapEntrySerializer +com.fasterxml.jackson.databind.ser.std.ArraySerializerBase +com.fasterxml.jackson.databind.ser.impl.StringArraySerializer +com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer +com.fasterxml.jackson.databind.ser.impl.IteratorSerializer +com.fasterxml.jackson.databind.ser.std.IterableSerializer +com.fasterxml.jackson.databind.ser.std.StdScalarSerializer +com.fasterxml.jackson.databind.ser.std.EnumSerializer +com.fasterxml.jackson.databind.ser.std.JsonValueSerializer +com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase +com.fasterxml.jackson.databind.ser.std.ToStringSerializer +com.fasterxml.jackson.databind.ser.std.SerializableSerializer +com.fasterxml.jackson.databind.ser.std.DateTimeSerializerBase +com.fasterxml.jackson.databind.ser.std.CalendarSerializer +com.fasterxml.jackson.databind.ser.std.DateSerializer +com.fasterxml.jackson.databind.ser.std.ByteBufferSerializer +com.fasterxml.jackson.databind.ser.std.InetAddressSerializer +com.fasterxml.jackson.databind.ser.std.InetSocketAddressSerializer +com.fasterxml.jackson.databind.ser.std.TimeZoneSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializer +com.fasterxml.jackson.databind.ser.std.ReferenceTypeSerializer +com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator +com.fasterxml.jackson.databind.introspect.AnnotatedField +com.fasterxml.jackson.databind.ser.std.BeanSerializerBase +com.fasterxml.jackson.databind.ser.BeanSerializer +com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer +com.fasterxml.jackson.databind.ser.std.StringSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers +com.fasterxml.jackson.databind.ser.std.NumberSerializers$Base +com.fasterxml.jackson.databind.ser.std.NumberSerializers$IntegerSerializer +com.fasterxml.jackson.core.JsonParser$NumberType +com.fasterxml.jackson.databind.ser.std.NumberSerializers$LongSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$IntLikeSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$ShortSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$DoubleSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$FloatSerializer +com.fasterxml.jackson.databind.ser.std.BooleanSerializer +com.fasterxml.jackson.databind.ser.std.BooleanSerializer$AsNumber +com.fasterxml.jackson.databind.ser.std.NumberSerializer$BigDecimalAsStringSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers +java.util.Currency +java.util.UUID +com.fasterxml.jackson.databind.ser.std.UUIDSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicBooleanSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicIntegerSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicLongSerializer +com.fasterxml.jackson.databind.ser.std.FileSerializer +com.fasterxml.jackson.databind.ser.std.ClassSerializer +com.fasterxml.jackson.databind.ser.std.TokenBufferSerializer +com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig +com.fasterxml.jackson.databind.ser.Serializers +com.fasterxml.jackson.databind.ser.BeanSerializerModifier +org.junit.jupiter.engine.execution.DefaultTestInstances +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$387/0x000000700111c2d0 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$388/0x000000700111c518 +org.junit.jupiter.api.extension.TestInstancePostProcessor +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$389/0x000000700111c940 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$390/0x000000700111cb78 +org.junit.jupiter.api.Order +java.lang.invoke.LambdaForm$DMH/0x0000007001120000 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$391/0x000000700111cfc8 +org.junit.jupiter.api.extension.RegisterExtension +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$392/0x000000700111d408 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$393/0x000000700111d650 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$394/0x000000700111d8a0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$395/0x000000700111dae8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$396/0x000000700111dd30 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$397/0x000000700111df70 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$398/0x000000700111e1c0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$399/0x000000700111e400 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$400/0x000000700111e658 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$401/0x000000700111e8a8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$402/0x000000700111eae8 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$CallbackInvoker +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$403/0x000000700111ef38 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$404/0x000000700111f158 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$405/0x000000700111f380 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$406/0x000000700111f5b8 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$407/0x000000700111f808 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$408/0x000000700111fa30 +java.util.AbstractList$Itr +java.util.AbstractList$ListItr +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$409/0x000000700111fc50 +org.junit.jupiter.engine.execution.MethodInvocation +org.junit.jupiter.engine.extension.TimeoutExtension$TimeoutProvider +org.junit.jupiter.engine.extension.TimeoutConfiguration +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$410/0x00000070011246e8 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$411/0x0000007001124940 +org.junit.jupiter.engine.extension.TimeoutDurationParser +java.time.DateTimeException +java.time.format.DateTimeParseException +java.util.regex.Pattern$$Lambda$412/0x000000700107f270 +java.util.regex.Pattern$$Lambda$413/0x000000700107f4d0 +java.util.regex.Pattern$$Lambda$414/0x000000700107f730 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$415/0x0000007001124d98 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$416/0x0000007001124fc0 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$417/0x0000007001125208 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$418/0x0000007001125450 +org.junit.jupiter.api.extension.BeforeTestExecutionCallback +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$419/0x0000007001125878 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$420/0x0000007001125a98 +org.junit.jupiter.engine.descriptor.MethodExtensionContext$$Lambda$421/0x0000007001125cc0 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$422/0x0000007001125f00 +org.junit.jupiter.engine.execution.NamespaceAwareStore$$Lambda$423/0x0000007001126158 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$424/0x0000007001126380 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$425/0x00000070011265a8 +software.amazon.lambda.powertools.metrics.MetricsBuilder +org.crac.Resource +software.amazon.lambda.powertools.metrics.MetricsFactory +software.amazon.lambda.powertools.metrics.provider.EmfMetricsProvider +software.amazon.lambda.powertools.metrics.internal.EmfMetricsLogger +org.slf4j.LoggerFactory +org.slf4j.spi.SLF4JServiceProvider +java.util.ServiceConfigurationError +org.slf4j.event.LoggingEvent +org.slf4j.helpers.SubstituteServiceProvider +org.slf4j.IMarkerFactory +org.slf4j.spi.MDCAdapter +org.slf4j.ILoggerFactory +org.slf4j.helpers.SubstituteLoggerFactory +org.slf4j.Logger +java.util.concurrent.LinkedBlockingQueue +java.util.concurrent.LinkedBlockingQueue$Node +org.slf4j.helpers.BasicMarkerFactory +org.slf4j.Marker +org.slf4j.helpers.BasicMDCAdapter +java.lang.InheritableThreadLocal +org.slf4j.helpers.BasicMDCAdapter$1 +org.slf4j.helpers.ThreadLocalMapOfStacks +org.slf4j.helpers.NOP_FallbackServiceProvider +org.slf4j.helpers.NOPLoggerFactory +org.slf4j.helpers.NOPMDCAdapter +org.slf4j.helpers.Util +org.slf4j.simple.SimpleServiceProvider +org.slf4j.simple.SimpleLoggerFactory +org.slf4j.helpers.AbstractLogger +org.slf4j.helpers.LegacyAbstractLogger +org.slf4j.simple.SimpleLogger +org.slf4j.spi.LoggingEventBuilder +org.slf4j.simple.SimpleLoggerConfiguration +org.slf4j.simple.SimpleLoggerConfiguration$$Lambda$426/0x0000007001128230 +sun.net.ProgressMonitor +sun.net.ProgressMeteringPolicy +sun.net.DefaultProgressMeteringPolicy +org.slf4j.simple.OutputChoice +org.slf4j.simple.OutputChoice$OutputChoiceType +software.amazon.cloudwatchlogs.emf.environment.EnvironmentProvider +software.amazon.cloudwatchlogs.emf.environment.Environment +software.amazon.cloudwatchlogs.emf.config.EnvironmentConfigurationProvider +software.amazon.cloudwatchlogs.emf.config.Configuration +software.amazon.cloudwatchlogs.emf.config.SystemWrapper +java.lang.ProcessEnvironment +java.lang.ProcessEnvironment$ExternalData +java.lang.ProcessEnvironment$Variable +java.lang.ProcessEnvironment$Value +java.lang.ProcessEnvironment$StringEnvironment +software.amazon.cloudwatchlogs.emf.util.StringUtils +software.amazon.cloudwatchlogs.emf.environment.Environments +software.amazon.cloudwatchlogs.emf.environment.LambdaEnvironment +software.amazon.cloudwatchlogs.emf.sinks.ISink +software.amazon.cloudwatchlogs.emf.environment.AgentBasedEnvironment +software.amazon.cloudwatchlogs.emf.environment.DefaultEnvironment +software.amazon.cloudwatchlogs.emf.sinks.retry.RetryStrategy +software.amazon.cloudwatchlogs.emf.environment.EC2Environment +software.amazon.cloudwatchlogs.emf.exception.EMFClientException +software.amazon.cloudwatchlogs.emf.environment.ResourceFetcher +software.amazon.cloudwatchlogs.emf.environment.ECSEnvironment +java.net.UnknownHostException +software.amazon.cloudwatchlogs.emf.model.MetricsContext +software.amazon.cloudwatchlogs.emf.model.RootNode +com.fasterxml.jackson.databind.ser.FilterProvider +com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider +com.fasterxml.jackson.databind.ser.BeanPropertyFilter +com.fasterxml.jackson.databind.ser.PropertyFilter +com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter +software.amazon.cloudwatchlogs.emf.model.EmptyMetricsFilter +com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter$FilterExceptFilter +com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter$SerializeExceptFilter +software.amazon.cloudwatchlogs.emf.model.Metadata +java.time.InstantSource +java.time.Clock +software.amazon.cloudwatchlogs.emf.model.MetricDirective +java.util.Collections$SynchronizedList +java.util.Collections$SynchronizedRandomAccessList +software.amazon.cloudwatchlogs.emf.model.DimensionSet +software.amazon.cloudwatchlogs.emf.exception.DimensionSetExceededException +software.amazon.cloudwatchlogs.emf.logger.MetricsLogger +software.amazon.cloudwatchlogs.emf.exception.InvalidDimensionException +software.amazon.cloudwatchlogs.emf.environment.EnvironmentProvider$1 +java.util.concurrent.CompletionStage +java.util.concurrent.CompletableFuture +java.util.concurrent.CompletableFuture$AltResult +java.util.concurrent.ForkJoinPool +java.lang.invoke.VarHandleLongs$FieldInstanceReadOnly +java.lang.invoke.VarHandleLongs$FieldInstanceReadWrite +java.lang.invoke.VarHandleInts$FieldStaticReadOnly +java.lang.invoke.VarHandleInts$FieldStaticReadWrite +java.util.concurrent.ForkJoinPool$ForkJoinWorkerThreadFactory +java.util.concurrent.ForkJoinPool$DefaultForkJoinWorkerThreadFactory +java.util.concurrent.ForkJoinPool$1 +java.util.concurrent.ForkJoinPool$DefaultCommonPoolForkJoinWorkerThreadFactory +java.util.concurrent.ForkJoinPool$WorkQueue +java.util.concurrent.CompletableFuture$AsynchronousCompletionTask +java.util.concurrent.ForkJoinTask +java.util.concurrent.CompletableFuture$Completion +software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor +software.amazon.lambda.powertools.common.internal.SystemWrapper +software.amazon.lambda.powertools.metrics.internal.Validator +software.amazon.cloudwatchlogs.emf.util.Validator +software.amazon.cloudwatchlogs.emf.exception.InvalidNamespaceException +software.amazon.cloudwatchlogs.emf.exception.InvalidTimestampException +software.amazon.cloudwatchlogs.emf.exception.InvalidMetricException +org.assertj.core.api.InstanceOfAssertFactories +org.assertj.core.api.Assertions +org.assertj.core.api.NumberAssert +org.assertj.core.api.ComparableAssert +org.assertj.core.api.Descriptable +org.assertj.core.api.ExtensionPoints +org.assertj.core.api.Assert +org.assertj.core.api.AbstractAssert +org.assertj.core.api.AbstractObjectAssert +org.assertj.core.api.AbstractComparableAssert +org.assertj.core.api.AbstractBigIntegerAssert +org.assertj.core.api.BigIntegerAssert +org.assertj.core.data.TemporalOffset +org.assertj.core.data.TemporalUnitOffset +org.assertj.core.data.TemporalUnitWithinOffset +org.assertj.core.data.TemporalUnitLessThanOffset +org.assertj.core.configuration.ConfigurationProvider +org.assertj.core.api.AssertionsForClassTypes +org.assertj.core.api.EnumerableAssert +org.assertj.core.api.AbstractCharSequenceAssert +org.assertj.core.api.CharSequenceAssert +org.assertj.core.api.AbstractStringAssert +org.assertj.core.api.StringAssert +org.assertj.core.api.AbstractDateAssert +org.assertj.core.api.DateAssert +org.assertj.core.api.AbstractTemporalAssert +org.assertj.core.api.AbstractZonedDateTimeAssert +org.assertj.core.api.ZonedDateTimeAssert +org.assertj.core.api.AbstractShortAssert +org.assertj.core.api.ShortAssert +org.assertj.core.api.ArraySortedAssert +org.assertj.core.api.AbstractEnumerableAssert +org.assertj.core.api.AbstractArrayAssert +org.assertj.core.api.AbstractShortArrayAssert +org.assertj.core.api.ShortArrayAssert +org.assertj.core.api.AbstractYearMonthAssert +org.assertj.core.api.YearMonthAssert +org.assertj.core.api.AbstractInstantAssert +org.assertj.core.api.InstantAssert +org.assertj.core.api.AbstractDurationAssert +org.assertj.core.api.DurationAssert +org.assertj.core.api.AbstractPeriodAssert +org.assertj.core.api.PeriodAssert +org.assertj.core.api.AbstractThrowableAssert +org.assertj.core.api.ThrowableAssert +org.assertj.core.api.AbstractLocalDateTimeAssert +org.assertj.core.api.LocalDateTimeAssert +org.assertj.core.api.AbstractOffsetDateTimeAssert +org.assertj.core.api.OffsetDateTimeAssert +org.assertj.core.api.AbstractOffsetTimeAssert +org.assertj.core.api.OffsetTimeAssert +org.assertj.core.api.AbstractLocalTimeAssert +org.assertj.core.api.LocalTimeAssert +org.assertj.core.api.AbstractLocalDateAssert +org.assertj.core.api.LocalDateAssert +org.assertj.core.api.AbstractCharacterAssert +org.assertj.core.api.CharacterAssert +org.assertj.core.api.AbstractBigDecimalAssert +org.assertj.core.api.BigDecimalAssert +org.assertj.core.api.AbstractCharArrayAssert +org.assertj.core.api.CharArrayAssert +org.assertj.core.api.AbstractByteAssert +org.assertj.core.api.ByteAssert +org.assertj.core.api.AbstractBooleanAssert +org.assertj.core.api.BooleanAssert +org.assertj.core.api.AbstractBooleanArrayAssert +org.assertj.core.api.BooleanArrayAssert +org.assertj.core.api.AbstractUriAssert +org.assertj.core.api.UriAssert +org.assertj.core.api.AbstractUrlAssert +org.assertj.core.api.UrlAssert +org.assertj.core.api.AbstractByteArrayAssert +org.assertj.core.api.ByteArrayAssert +org.assertj.core.api.AbstractIntArrayAssert +org.assertj.core.api.IntArrayAssert +org.assertj.core.api.AbstractIntegerAssert +org.assertj.core.api.IntegerAssert +org.assertj.core.api.AbstractFloatArrayAssert +org.assertj.core.api.FloatArrayAssert +org.assertj.core.api.AbstractLongArrayAssert +org.assertj.core.api.LongArrayAssert +org.assertj.core.api.AbstractLongAssert +org.assertj.core.api.LongAssert +org.assertj.core.api.AbstractDoubleArrayAssert +org.assertj.core.api.DoubleArrayAssert +org.assertj.core.api.FloatingPointNumberAssert +org.assertj.core.api.AbstractDoubleAssert +org.assertj.core.api.DoubleAssert +org.assertj.core.api.AbstractFloatAssert +org.assertj.core.api.FloatAssert +org.assertj.core.api.AbstractInputStreamAssert +org.assertj.core.api.InputStreamAssert +org.assertj.core.api.AbstractFileAssert +org.assertj.core.api.FileAssert +org.assertj.core.api.ObjectAssert +org.assertj.core.description.Description +org.assertj.core.description.LazyTextDescription +org.assertj.core.description.TextDescription +org.assertj.core.api.AssertionInfo +org.assertj.core.internal.ComparisonStrategy +org.assertj.core.api.ObjectEnumerableAssert +org.assertj.core.api.IndexedObjectEnumerableAssert +org.assertj.core.api.AbstractIterableAssert +org.assertj.core.api.AbstractCollectionAssert +org.assertj.core.api.AbstractListAssert +org.assertj.core.api.FactoryBasedNavigableListAssert +org.assertj.core.api.ListAssert +org.assertj.core.internal.Objects +org.assertj.core.util.introspection.IntrospectionError +org.assertj.core.error.ErrorMessageFactory +org.assertj.core.internal.AbstractComparisonStrategy +org.assertj.core.internal.StandardComparisonStrategy +org.assertj.core.util.introspection.PropertySupport +org.assertj.core.internal.Failures +org.assertj.core.error.AssertionErrorCreator +org.assertj.core.util.Arrays +org.assertj.core.error.ConstructorInvoker +org.assertj.core.util.introspection.FieldSupport +org.assertj.core.error.GroupTypeDescription +org.assertj.core.internal.Conditions +org.assertj.core.api.WritableAssertionInfo +org.assertj.core.presentation.Representation +org.assertj.core.configuration.Configuration +org.assertj.core.configuration.PreferredAssumptionException +org.assertj.core.configuration.PreferredAssumptionException$1 +org.assertj.core.configuration.Services +org.assertj.core.util.Lists +org.assertj.core.util.Streams +org.assertj.core.util.Lists$$Lambda$427/0x00000070011aa8d0 +org.assertj.core.presentation.CompositeRepresentation +org.assertj.core.presentation.CompositeRepresentation$$Lambda$428/0x00000070011aad48 +java.util.Collections$ReverseComparator +java.util.Collections$ReverseComparator2 +org.assertj.core.presentation.StandardRepresentation +java.time.chrono.ChronoLocalDateTime +java.time.LocalDateTime +java.time.chrono.ChronoZonedDateTime +java.time.ZonedDateTime +java.time.OffsetDateTime +java.nio.file.DirectoryStream +org.assertj.core.api.ThrowableAssert$ThrowingCallable +software.amazon.lambda.powertools.metrics.MetricsBuilderTest$$Lambda$429/0x00000070011ab530 +org.assertj.core.internal.Throwables +org.assertj.core.internal.CommonValidations +org.junit.jupiter.api.extension.AfterTestExecutionCallback +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$430/0x00000070011abe30 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$431/0x00000070011ac050 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$432/0x00000070011ac288 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$433/0x00000070011ac4b0 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$434/0x00000070011ac6d8 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$435/0x00000070011ac8f8 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$436/0x00000070011acb50 +jdk.internal.reflect.UnsafeStaticObjectFieldAccessorImpl +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$437/0x00000070011acd78 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$438/0x00000070011acf98 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$439/0x00000070011ad1c0 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$440/0x00000070011ad3e8 +org.junit.jupiter.engine.descriptor.MethodExtensionContext$$Lambda$441/0x00000070011ad610 +org.junit.jupiter.api.extension.TestInstancePreDestroyCallback +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$442/0x00000070011ada50 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$443/0x00000070011adc70 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$444/0x00000070011ade98 +java.util.concurrent.ConcurrentHashMap$EntrySpliterator +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$EvaluatedValue +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$445/0x00000070011ae2f8 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$446/0x00000070011ae538 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$EvaluatedValue$$Lambda$447/0x00000070011ae788 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$448/0x00000070011ae9c8 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$449/0x00000070011aec00 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$450/0x00000070011aee28 +org.junit.platform.engine.TestExecutionResult +org.junit.platform.engine.TestExecutionResult$Status +org.junit.jupiter.api.extension.TestWatcher +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$451/0x00000070011af8c0 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$452/0x00000070011afaf8 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$453/0x00000070011afd30 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$454/0x00000070011b0000 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$455/0x00000070011b0250 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$456/0x00000070011b0490 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$457/0x00000070011b06d0 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$458/0x00000070011b0920 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$459/0x00000070011b0b58 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$460/0x00000070011b0d80 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$461/0x00000070011b0fb8 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$462/0x00000070011b11e0 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$463/0x00000070011b1418 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$464/0x00000070011b1640 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$1 +java.lang.invoke.LambdaForm$DMH/0x00000070011b4000 +software.amazon.lambda.powertools.metrics.model.DimensionSet$$Lambda$465/0x00000070011b1aa0 +org.apache.commons.lang3.StringUtils +org.apache.commons.lang3.CharUtils +java.util.function.IntFunction +org.apache.commons.lang3.CharUtils$$Lambda$466/0x00000070011b20e8 +org.apache.commons.lang3.ArrayUtils +java.util.concurrent.ThreadLocalRandom +software.amazon.lambda.powertools.metrics.internal.EmfMetricsLogger$$Lambda$467/0x00000070011b2510 +software.amazon.cloudwatchlogs.emf.logger.MetricsLogger$$Lambda$468/0x00000070011b2940 +software.amazon.cloudwatchlogs.emf.model.StorageResolution +software.amazon.cloudwatchlogs.emf.model.MetricDefinition +java.lang.invoke.LambdaForm$DMH/0x00000070011b4400 +software.amazon.cloudwatchlogs.emf.model.MetricDirective$$Lambda$469/0x00000070011b37d0 +java.lang.invoke.LambdaForm$DMH/0x00000070011b4800 +java.lang.invoke.LambdaForm$DMH/0x00000070011b4c00 +java.lang.invoke.LambdaForm$MH/0x00000070011b5000 +software.amazon.cloudwatchlogs.emf.sinks.ConsoleSink +software.amazon.cloudwatchlogs.emf.environment.LambdaEnvironment$$Lambda$470/0x00000070011b3c48 +java.util.concurrent.ConcurrentHashMap$ValueSpliterator +software.amazon.cloudwatchlogs.emf.model.MetricsContext$$Lambda$471/0x00000070011b6000 +com.fasterxml.jackson.core.util.BufferRecyclers +com.fasterxml.jackson.core.util.BufferRecycler +com.fasterxml.jackson.core.util.TextBuffer +com.fasterxml.jackson.core.io.ContentReference +com.fasterxml.jackson.core.io.IOContext +com.fasterxml.jackson.core.util.ReadConstrainedTextBuffer +com.fasterxml.jackson.core.exc.StreamWriteException +com.fasterxml.jackson.core.JsonGenerationException +com.fasterxml.jackson.core.JsonStreamContext +com.fasterxml.jackson.core.json.JsonWriteContext +com.fasterxml.jackson.core.StreamWriteCapability +com.fasterxml.jackson.core.util.JacksonFeatureSet +com.fasterxml.jackson.core.FormatFeature +com.fasterxml.jackson.core.json.JsonWriteFeature +com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap +com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap$Bucket +com.fasterxml.jackson.databind.util.TypeKey +com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap$$Lambda$472/0x00000070011b8a38 +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$EntrySet +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$EntryIterator +com.fasterxml.jackson.databind.type.ClassStack +sun.reflect.generics.repository.AbstractRepository +sun.reflect.generics.repository.GenericDeclRepository +sun.reflect.generics.repository.ClassRepository +java.lang.reflect.TypeVariable +sun.reflect.generics.tree.FormalTypeParameter +sun.reflect.generics.tree.Signature +sun.reflect.generics.tree.ClassSignature +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$WeightedValue +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$Node +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$AddTask +com.fasterxml.jackson.databind.introspect.AnnotationCollector$OneCollector +com.fasterxml.jackson.annotation.JsonFilter +com.fasterxml.jackson.annotation.JacksonAnnotation +jdk.proxy2.$Proxy19 +com.fasterxml.jackson.databind.introspect.AnnotationCollector$NCollector +com.fasterxml.jackson.annotation.JacksonAnnotationsInside +jdk.proxy2.$Proxy20 +com.fasterxml.jackson.databind.introspect.AnnotationCollector$OneAnnotation +com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector +com.fasterxml.jackson.annotation.JsonAutoDetect +com.fasterxml.jackson.annotation.JsonIdentityInfo +com.fasterxml.jackson.databind.util.ArrayIterator +com.fasterxml.jackson.databind.introspect.CollectorBase +com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector +com.fasterxml.jackson.databind.introspect.AnnotationMap +com.fasterxml.jackson.databind.introspect.TypeResolutionContext$Basic +com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector$FieldBuilder +com.fasterxml.jackson.annotation.JsonProperty +com.fasterxml.jackson.annotation.JsonProperty$Access +jdk.proxy2.$Proxy21 +com.fasterxml.jackson.annotation.JsonKey +com.fasterxml.jackson.annotation.JsonValue +com.fasterxml.jackson.annotation.JsonAnyGetter +com.fasterxml.jackson.annotation.JsonAnySetter +com.fasterxml.jackson.core.util.InternCache +com.fasterxml.jackson.annotation.JsonGetter +com.fasterxml.jackson.annotation.JsonIgnore +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$WithMember +com.fasterxml.jackson.databind.AnnotationIntrospector$ReferenceProperty +com.fasterxml.jackson.databind.AnnotationIntrospector$ReferenceProperty$Type +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$Linked +com.fasterxml.jackson.annotation.JsonAutoDetect$1 +com.fasterxml.jackson.annotation.PropertyAccessor +com.fasterxml.jackson.databind.introspect.AnnotatedMethodCollector +com.fasterxml.jackson.databind.introspect.MemberKey +com.fasterxml.jackson.databind.introspect.AnnotatedMethodCollector$MethodBuilder +jdk.proxy2.$Proxy22 +com.fasterxml.jackson.databind.introspect.AnnotatedMethodMap +sun.reflect.generics.scope.MethodScope +sun.reflect.generics.repository.ConstructorRepository +sun.reflect.generics.repository.MethodRepository +sun.reflect.generics.tree.MethodTypeSignature +java.lang.reflect.ParameterizedType +sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl +sun.reflect.generics.reflectiveObjects.LazyReflectiveObjectGenerator +sun.reflect.generics.reflectiveObjects.TypeVariableImpl +com.fasterxml.jackson.databind.type.TypeBindings$TypeParamStash +sun.reflect.generics.tree.TypeVariableSignature +com.fasterxml.jackson.databind.type.TypeBindings$AsKey +com.fasterxml.jackson.annotation.JsonSetter +com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector +sun.reflect.generics.scope.ConstructorScope +sun.reflect.generics.tree.VoidDescriptor +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$5 +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$6 +java.util.LinkedList$ListItr +com.fasterxml.jackson.annotation.JacksonInject +com.fasterxml.jackson.databind.annotation.JsonNaming +com.fasterxml.jackson.annotation.JsonPropertyOrder +com.fasterxml.jackson.annotation.JsonPropertyDescription +com.fasterxml.jackson.databind.PropertyMetadata +com.fasterxml.jackson.databind.ext.OptionalHandlerFactory +org.w3c.dom.Node +org.w3c.dom.Document +com.fasterxml.jackson.databind.ext.Java7Handlers +com.fasterxml.jackson.databind.ext.Java7HandlersImpl +com.fasterxml.jackson.databind.ext.NioPathSerializer +com.fasterxml.jackson.databind.ext.NioPathDeserializer +java.net.InetAddress +com.fasterxml.jackson.databind.util.BeanUtil +com.fasterxml.jackson.databind.ObjectReader +com.fasterxml.jackson.databind.ObjectWriter +com.fasterxml.jackson.databind.ser.BeanSerializerBuilder +com.fasterxml.jackson.annotation.JsonIgnoreType +com.fasterxml.jackson.databind.ser.PropertyBuilder +com.fasterxml.jackson.annotation.JsonInclude +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$3 +com.fasterxml.jackson.annotation.JsonTypeId +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$2 +com.fasterxml.jackson.databind.BeanProperty$Std +com.fasterxml.jackson.databind.annotation.JsonTypeResolver +com.fasterxml.jackson.databind.ser.PropertyBuilder$1 +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$1 +com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Empty +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Single +com.fasterxml.jackson.databind.annotation.JsonAppend +com.fasterxml.jackson.annotation.JsonIgnoreProperties +com.fasterxml.jackson.annotation.JsonIgnoreProperties$Value +com.fasterxml.jackson.annotation.JsonIncludeProperties +com.fasterxml.jackson.annotation.JsonIncludeProperties$Value +com.fasterxml.jackson.databind.ser.std.MapProperty +com.fasterxml.jackson.databind.util.IgnorePropertiesUtil +com.fasterxml.jackson.databind.ser.AnyGetterWriter +com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer +com.fasterxml.jackson.databind.ser.impl.BeanAsArraySerializer +com.fasterxml.jackson.databind.ser.std.StdKeySerializers +com.fasterxml.jackson.databind.ser.std.StdKeySerializer +com.fasterxml.jackson.databind.ser.std.StdKeySerializers$StringKeySerializer +com.fasterxml.jackson.databind.ser.std.StdKeySerializers$Dynamic +com.fasterxml.jackson.databind.ser.std.StdKeySerializers$Default +com.fasterxml.jackson.databind.ser.std.StdKeySerializers$EnumKeySerializer +com.fasterxml.jackson.annotation.JsonFormat$Feature +software.amazon.cloudwatchlogs.emf.model.Metadata$$Lambda$473/0x00000070011c9930 +com.fasterxml.jackson.annotation.OptBoolean +jdk.proxy2.$Proxy23 +com.fasterxml.jackson.databind.annotation.JsonSerialize$Inclusion +com.fasterxml.jackson.databind.annotation.JsonSerialize$Typing +com.fasterxml.jackson.databind.util.Converter +com.fasterxml.jackson.databind.util.Converter$None +com.fasterxml.jackson.databind.JsonSerializer$None +software.amazon.cloudwatchlogs.emf.serializers.InstantSerializer +jdk.proxy2.$Proxy24 +com.fasterxml.jackson.databind.JsonDeserializer$None +com.fasterxml.jackson.databind.KeyDeserializer$None +software.amazon.cloudwatchlogs.emf.serializers.InstantDeserializer +jdk.proxy2.$Proxy25 +jdk.internal.ValueBased +com.sun.proxy.jdk.proxy1.$Proxy26 +java.lang.FunctionalInterface +jdk.proxy1.$Proxy27 +com.fasterxml.jackson.databind.introspect.AnnotationCollector$TwoAnnotations +com.fasterxml.jackson.databind.annotation.NoClass +com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector$1 +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$SerializerAndMapResult +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Double +com.fasterxml.jackson.core.io.NumberOutput +jdk.proxy2.$Proxy28 +sun.reflect.generics.tree.BooleanSignature +software.amazon.cloudwatchlogs.emf.serializers.UnitSerializer +software.amazon.cloudwatchlogs.emf.serializers.UnitDeserializer +software.amazon.cloudwatchlogs.emf.serializers.StorageResolutionFilter +jdk.proxy2.$Proxy29 +software.amazon.cloudwatchlogs.emf.serializers.StorageResolutionSerializer +software.amazon.cloudwatchlogs.emf.model.MetricDirective$$Lambda$474/0x00000070011ceac8 +com.fasterxml.jackson.databind.BeanProperty$Bogus +jdk.internal.vm.annotation.IntrinsicCandidate +com.sun.proxy.jdk.proxy1.$Proxy30 +java.lang.Deprecated +jdk.proxy1.$Proxy31 +com.fasterxml.jackson.databind.introspect.MethodGenericTypeResolver +com.fasterxml.jackson.databind.ser.std.NumberSerializers$1 +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Multi +software.amazon.cloudwatchlogs.emf.model.MetricDirective$$Lambda$475/0x00000070011cf658 +software.amazon.cloudwatchlogs.emf.model.MetricDirective$$Lambda$476/0x00000070011cf890 +com.fasterxml.jackson.core.exc.StreamReadException +com.fasterxml.jackson.core.exc.InputCoercionException +com.fasterxml.jackson.core.JsonParseException +com.fasterxml.jackson.core.io.JsonEOFException +com.fasterxml.jackson.core.json.JsonReadContext +com.fasterxml.jackson.core.StreamReadCapability +com.fasterxml.jackson.core.JsonToken +com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer +com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer +com.fasterxml.jackson.databind.node.ArrayNode +com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer$ObjectDeserializer +com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer$ArrayDeserializer +com.fasterxml.jackson.databind.util.LinkedNode +com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer$ContainerStack +com.fasterxml.jackson.core.io.NumberInput +com.fasterxml.jackson.core.JsonParser$NumberTypeFP +com.fasterxml.jackson.core.StreamReadFeature +org.assertj.core.internal.Strings +org.assertj.core.internal.InputStreamsException +org.assertj.core.internal.Comparables +java.util.AbstractMap$SimpleEntry +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$WriteThroughEntry +java.lang.invoke.LambdaForm$DMH/0x00000070011d8000 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$477/0x00000070011d54d0 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$478/0x00000070011d5708 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$479/0x00000070011d5940 +org.apache.maven.surefire.api.util.internal.ObjectUtils +org.apache.maven.surefire.api.util.internal.ImmutableMap$Node +jdk.internal.reflect.GeneratedMethodAccessor1 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$480/0x00000070011d5fe8 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$481/0x00000070011d6228 +java.util.stream.Nodes +java.util.stream.Node +java.util.stream.Nodes$EmptyNode +java.util.stream.Nodes$EmptyNode$OfRef +java.util.stream.Node$OfPrimitive +java.util.stream.Node$OfInt +java.util.stream.Nodes$EmptyNode$OfInt +java.util.stream.Node$OfLong +java.util.stream.Nodes$EmptyNode$OfLong +java.util.stream.Node$OfDouble +java.util.stream.Nodes$EmptyNode$OfDouble +java.util.stream.Node$Builder +java.util.stream.Nodes$ArrayNode +java.util.stream.Nodes$FixedNodeBuilder +org.junitpioneer.internal.PioneerUtils +org.junitpioneer.internal.PioneerUtils$$Lambda$482/0x00000070011d6650 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$483/0x00000070011d6890 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$484/0x00000070011d6ac8 +org.junitpioneer.jupiter.ClearEnvironmentVariable +org.junitpioneer.jupiter.ClearEnvironmentVariable$ClearEnvironmentVariables +org.junitpioneer.jupiter.EnvironmentVariableExtension$$Lambda$485/0x00000070011d7100 +org.junitpioneer.internal.PioneerUtils$$Lambda$486/0x00000070011d7340 +org.junitpioneer.internal.PioneerUtils$$Lambda$487/0x00000070011d7560 +org.junitpioneer.internal.PioneerUtils$$Lambda$488/0x00000070011d7790 +org.junitpioneer.jupiter.EnvironmentVariableExtension$$Lambda$489/0x00000070011d79d8 +org.junitpioneer.jupiter.EnvironmentVariableExtension$$Lambda$490/0x00000070011d7c18 +java.util.stream.Collectors$$Lambda$491/0x000000700114cf38 +java.util.stream.Collectors$$Lambda$492/0x000000700114d158 +java.util.stream.Collectors$$Lambda$493/0x000000700114d390 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$494/0x00000070011dc000 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$495/0x00000070011dc258 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$496/0x00000070011dc498 +java.time.chrono.ChronoLocalDate +java.time.LocalDate +java.time.temporal.TemporalField +java.time.temporal.ChronoField +java.time.temporal.ValueRange +java.time.LocalTime +java.time.Clock$SystemClock +java.time.ZoneId +java.time.ZoneOffset +java.time.ZoneRegion +java.time.zone.ZoneRulesProvider +java.time.zone.ZoneRulesProvider$1 +java.time.zone.TzdbZoneRulesProvider +java.time.zone.Ser +java.time.zone.ZoneRules +java.time.zone.ZoneOffsetTransitionRule +java.time.Month +java.time.DayOfWeek +java.time.zone.ZoneOffsetTransitionRule$TimeDefinition +java.time.zone.ZoneOffsetTransition +java.time.temporal.TemporalAdjusters +java.lang.invoke.LambdaForm$DMH/0x00000070011d8800 +java.time.temporal.TemporalAdjusters$$Lambda$497/0x00000070011507c8 +java.time.LocalDate$1 +java.time.chrono.Chronology +java.time.chrono.AbstractChronology +java.time.chrono.IsoChronology +java.time.zone.ZoneOffsetTransitionRule$1 +org.junit.platform.engine.reporting.ReportEntry$$Lambda$498/0x00000070011dc6e0 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$499/0x00000070011dc918 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$500/0x00000070011dcb50 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$501/0x00000070011dcd78 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$502/0x00000070011dcfb0 +org.apache.maven.surefire.api.report.TestOutputReportEntry +org.junitpioneer.jupiter.AbstractEntryBasedExtension$EntriesBackup +org.junitpioneer.jupiter.AbstractEntryBasedExtension$EntriesBackup$$Lambda$503/0x00000070011dd628 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$504/0x00000070011dd860 +java.lang.invoke.LambdaForm$DMH/0x00000070011d8c00 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$505/0x00000070011dda98 +org.junitpioneer.jupiter.EnvironmentVariableUtils +org.junitpioneer.jupiter.EnvironmentVariableUtils$$Lambda$506/0x00000070011dded8 +jdk.internal.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl +jdk.internal.reflect.UnsafeQualifiedFieldAccessorImpl +jdk.internal.reflect.UnsafeQualifiedObjectFieldAccessorImpl +org.aspectj.lang.JoinPoint +org.aspectj.lang.ProceedingJoinPoint +org.aspectj.lang.Signature +org.aspectj.runtime.internal.AroundClosure +software.amazon.lambda.powertools.metrics.ConfigurationPrecedenceTest$HandlerWithMetricsAnnotation$AjcClosure1 +org.aspectj.runtime.reflect.Factory +org.aspectj.lang.JoinPoint$StaticPart +org.aspectj.lang.JoinPoint$EnclosingStaticPart +org.aspectj.lang.reflect.MemberSignature +org.aspectj.lang.reflect.CodeSignature +org.aspectj.lang.reflect.MethodSignature +org.aspectj.lang.reflect.SourceLocation +org.aspectj.lang.reflect.ConstructorSignature +org.aspectj.lang.reflect.FieldSignature +org.aspectj.lang.reflect.AdviceSignature +org.aspectj.lang.reflect.InitializerSignature +org.aspectj.lang.reflect.CatchClauseSignature +org.aspectj.lang.reflect.LockSignature +org.aspectj.lang.reflect.UnlockSignature +org.aspectj.runtime.reflect.SignatureImpl +org.aspectj.runtime.reflect.MemberSignatureImpl +org.aspectj.runtime.reflect.CodeSignatureImpl +org.aspectj.runtime.reflect.MethodSignatureImpl +org.aspectj.runtime.reflect.SignatureImpl$Cache +org.aspectj.runtime.reflect.JoinPointImpl$StaticPartImpl +org.aspectj.runtime.reflect.SourceLocationImpl +org.aspectj.runtime.reflect.JoinPointImpl +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect +org.aspectj.lang.NoAspectBoundException +software.amazon.lambda.powertools.metrics.FlushMetrics +jdk.proxy2.$Proxy32 +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspect$$Lambda$507/0x00000070011d98f0 +software.amazon.cloudwatchlogs.emf.logger.MetricsLogger$$Lambda$508/0x00000070011d9b28 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$509/0x00000070011d9d50 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$EntriesBackup$$Lambda$510/0x00000070011e0000 +org.junitpioneer.jupiter.EnvironmentVariableUtils$$Lambda$511/0x00000070011e0238 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$EntriesBackup$$Lambda$512/0x00000070011e0470 +software.amazon.lambda.powertools.metrics.ConfigurationPrecedenceTest$HandlerWithDefaultMetricsAnnotation$AjcClosure1 +software.amazon.lambda.powertools.metrics.MetricsFactoryTest$$Lambda$513/0x00000070011e08f8 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$514/0x00000070011e0b18 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$515/0x00000070011e0d40 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$516/0x00000070011e0f68 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$517/0x00000070011e1188 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$518/0x00000070011e13b0 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$519/0x00000070011e15d8 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$520/0x00000070011e1800 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$521/0x00000070011e1a20 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$522/0x00000070011e1c40 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$523/0x00000070011e1e60 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$524/0x00000070011e2080 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$525/0x00000070011e22a0 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$526/0x00000070011e24c0 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$527/0x00000070011e26e0 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$528/0x00000070011e2900 +jdk.internal.reflect.GeneratedConstructorAccessor8 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$529/0x00000070011e2b28 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$530/0x00000070011e2d48 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$531/0x00000070011e2f68 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$532/0x00000070011e3188 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$533/0x00000070011e33a8 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$534/0x00000070011e35d0 +software.amazon.lambda.powertools.metrics.internal.ValidatorTest$$Lambda$535/0x00000070011e37f0 +software.amazon.lambda.powertools.metrics.internal.EmfMetricsLogger$$Lambda$536/0x00000070011e3a18 +software.amazon.cloudwatchlogs.emf.logger.MetricsLogger$$Lambda$537/0x00000070011e3c50 +software.amazon.lambda.powertools.metrics.internal.EmfMetricsLogger$$Lambda$538/0x00000070011e6000 +org.assertj.core.internal.Numbers +org.assertj.core.internal.RealNumbers +org.assertj.core.internal.Doubles +org.assertj.core.internal.ComparatorBasedComparisonStrategy +software.amazon.lambda.powertools.metrics.internal.EmfMetricsLoggerTest$$Lambda$539/0x00000070011e7018 +software.amazon.cloudwatchlogs.emf.Constants +org.assertj.core.internal.WholeNumbers +org.assertj.core.internal.Longs +jdk.internal.reflect.GeneratedMethodAccessor2 +jdk.internal.reflect.GeneratedMethodAccessor3 +jdk.internal.reflect.GeneratedMethodAccessor4 +jdk.internal.reflect.GeneratedMethodAccessor5 +jdk.internal.reflect.GeneratedMethodAccessor6 +jdk.internal.reflect.GeneratedMethodAccessor7 +jdk.internal.reflect.GeneratedMethodAccessor8 +jdk.internal.reflect.GeneratedMethodAccessor9 +jdk.internal.reflect.GeneratedMethodAccessor10 +jdk.internal.reflect.GeneratedMethodAccessor11 +jdk.internal.reflect.GeneratedMethodAccessor12 +jdk.internal.reflect.GeneratedMethodAccessor13 +org.assertj.core.internal.Integers +software.amazon.lambda.powertools.metrics.internal.EmfMetricsLoggerTest$$Lambda$540/0x00000070011ec3a8 +software.amazon.cloudwatchlogs.emf.logger.MetricsLogger$$Lambda$541/0x00000070011ec5d0 +java.lang.invoke.LambdaForm$DMH/0x00000070011e9400 +software.amazon.lambda.powertools.metrics.internal.EmfMetricsLogger$$Lambda$542/0x00000070011ec7f8 +software.amazon.cloudwatchlogs.emf.logger.MetricsLogger$$Lambda$543/0x00000070011eca30 +org.slf4j.event.Level +java.text.DontCareFieldPosition +java.text.Format$FieldDelegate +java.text.DontCareFieldPosition$1 +java.text.NumberFormat$Field +org.slf4j.helpers.MessageFormatter +org.slf4j.helpers.FormattingTuple +org.slf4j.simple.OutputChoice$1 +java.nio.file.attribute.FileAttribute +sun.nio.fs.UnixFileModeAttribute +sun.nio.fs.UnixChannelFactory +sun.nio.fs.UnixChannelFactory$Flags +java.nio.channels.ByteChannel +java.nio.channels.SeekableByteChannel +java.nio.channels.GatheringByteChannel +java.nio.channels.ScatteringByteChannel +java.nio.channels.InterruptibleChannel +java.nio.channels.spi.AbstractInterruptibleChannel +java.nio.channels.FileChannel +sun.nio.ch.FileChannelImpl +sun.nio.ch.IOUtil +sun.nio.ch.NativeThreadSet +sun.nio.ch.NativeDispatcher +sun.nio.ch.FileDispatcher +sun.nio.ch.FileDispatcherImpl +sun.nio.ch.FileChannelImpl$Closer +java.nio.channels.Channels +sun.nio.ch.ChannelInputStream +sun.nio.ch.NativeThread +sun.nio.ch.IOStatus +java.nio.channels.SelectableChannel +sun.nio.ch.Util +sun.nio.ch.Util$1 +sun.nio.ch.Util$BufferCache +java.nio.DirectByteBuffer$Deallocator +java.lang.invoke.LambdaForm$DMH/0x00000070011e9800 +org.assertj.core.internal.Strings$$Lambda$544/0x00000070011ed6d8 +org.assertj.core.internal.Strings$$Lambda$545/0x00000070011ed930 +software.amazon.lambda.powertools.metrics.internal.EmfMetricsLogger$$Lambda$546/0x00000070011edb50 +org.assertj.core.api.AssertionsForInterfaceTypes +org.assertj.core.api.GenericComparableAssert +org.assertj.core.api.AbstractUniversalComparableAssert +org.assertj.core.api.UniversalComparableAssert +org.assertj.core.api.AbstractMapAssert +org.assertj.core.api.MapAssert +org.assertj.core.api.AbstractMapSizeAssert +org.assertj.core.api.MapSizeAssert +org.assertj.core.internal.Maps +java.lang.InstantiationException +org.assertj.core.data.MapEntry +org.assertj.core.internal.ErrorMessages +org.junit.jupiter.engine.descriptor.TestTemplateExtensionContext +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor$$Lambda$547/0x00000070011f1640 +org.junit.jupiter.api.RepeatedTest +org.junit.jupiter.params.ParameterizedTestMethodContext +org.junit.jupiter.params.ParameterizedTestMethodContext$Resolver +org.junit.jupiter.params.aggregator.ArgumentsAccessor +org.junit.jupiter.params.aggregator.AggregateWith +org.junit.jupiter.params.ParameterizedTestMethodContext$ResolverType +org.junit.jupiter.params.ParameterizedTestMethodContext$ResolverType$1 +org.junit.jupiter.params.ParameterizedTestMethodContext$ResolverType$2 +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$548/0x00000070011f2dc0 +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor$$Lambda$549/0x00000070011f2fe8 +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor$$Lambda$550/0x00000070011f3210 +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor$$Lambda$551/0x00000070011f3458 +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor$$Lambda$552/0x00000070011f36a0 +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor$$Lambda$553/0x00000070011f38f0 +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor$$Lambda$554/0x00000070011f3b30 +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$555/0x00000070011f3d68 +org.junit.platform.engine.ConfigurationParameters$$Lambda$556/0x00000070011f3fa8 +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$557/0x00000070011f41f0 +org.junit.jupiter.params.ParameterizedTestNameFormatter +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$558/0x00000070011f4630 +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$559/0x00000070011f4870 +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$560/0x00000070011f4ab8 +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$561/0x00000070011f4d00 +org.junit.jupiter.params.provider.Arguments +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$562/0x00000070011f5148 +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$563/0x00000070011f5388 +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$564/0x00000070011f55d0 +org.junit.jupiter.params.ParameterizedTestExtension$$Lambda$565/0x00000070011f5818 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$566/0x00000070011f5a40 +org.junit.jupiter.params.support.AnnotationConsumerInitializer +org.junit.jupiter.params.support.AnnotationConsumerInitializer$AnnotationConsumingMethodSignature +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$567/0x00000070011f62b0 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$568/0x00000070011f64f0 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$569/0x00000070011f6740 +java.util.stream.ReduceOps$1 +java.util.stream.ReduceOps$1ReducingSink +java.lang.invoke.LambdaForm$DMH/0x00000070011e9c00 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$570/0x00000070011f6988 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$571/0x00000070011f6be0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$572/0x00000070011f6e30 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$573/0x00000070011f7088 +sun.reflect.generics.tree.BottomSignature +sun.reflect.generics.tree.Wildcard +java.lang.reflect.WildcardType +sun.reflect.generics.reflectiveObjects.WildcardTypeImpl +org.junit.platform.commons.util.ReflectionUtils$$Lambda$574/0x00000070011f72e0 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$575/0x00000070011f7530 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$576/0x00000070011f7788 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$577/0x00000070011f79c8 +org.junit.jupiter.engine.descriptor.TestTemplateExtensionContext$$Lambda$578/0x00000070011f7bf0 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$579/0x00000070011f8000 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$580/0x00000070011f8248 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$581/0x00000070011f8490 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$582/0x00000070011f86d8 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$583/0x00000070011f8918 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$584/0x00000070011f8b58 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$585/0x00000070011f8d80 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$586/0x00000070011f8fc8 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$587/0x00000070011f9220 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$588/0x00000070011f9448 +org.junit.jupiter.params.provider.Arguments$$Lambda$589/0x00000070011f9868 +org.junit.jupiter.params.ParameterizedTestInvocationContext +org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor +org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor$$Lambda$590/0x00000070011fa158 +org.junit.jupiter.params.ParameterizedTestNameFormatter$$Lambda$591/0x00000070011fa378 +java.util.stream.ReferencePipeline$$Lambda$592/0x0000007001156f20 +org.junit.jupiter.api.Named +java.util.stream.Streams$RangeIntSpliterator +org.junit.jupiter.params.ParameterizedTestNameFormatter$$Lambda$593/0x00000070011fa7b8 +java.util.stream.IntPipeline$1 +java.util.stream.IntPipeline$1$1 +org.junit.jupiter.params.ParameterizedTestNameFormatter$$Lambda$594/0x00000070011fa9e0 +java.text.MessageFormat +java.text.MessageFormat$Field +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$595/0x00000070011fac20 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$596/0x00000070011fae58 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$597/0x00000070011fb080 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$598/0x00000070011fb2b8 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor$$Lambda$599/0x00000070011fb4e0 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DynamicTaskState +org.junit.platform.engine.support.hierarchical.NodeTestTask$DynamicTaskState$$Lambda$600/0x00000070011fb908 +org.junit.jupiter.params.ParameterizedTestParameterResolver +org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor$$Lambda$601/0x00000070011fbd88 +org.junit.jupiter.engine.execution.DefaultParameterContext +org.junit.jupiter.engine.execution.ParameterResolutionUtils$$Lambda$602/0x00000070011fc290 +org.junit.jupiter.api.TestReporter +org.junit.jupiter.params.ParameterizedTestParameterResolver$$Lambda$603/0x00000070011fc6e8 +org.junit.jupiter.params.converter.ConvertWith +org.junit.jupiter.params.ParameterizedTestMethodContext$ResolverType$1$$Lambda$604/0x00000070011fcb28 +org.junit.jupiter.params.converter.ArgumentConverter +org.junit.jupiter.params.ParameterizedTestMethodContext$ResolverType$1$$Lambda$605/0x00000070011fcf68 +org.junit.jupiter.params.ParameterizedTestMethodContext$ResolverType$1$$Lambda$606/0x00000070011fd1a8 +org.junit.jupiter.params.ParameterizedTestMethodContext$Converter +org.junit.jupiter.params.ParameterizedTestMethodContext$ResolverType$1$$Lambda$607/0x00000070011fd620 +org.junit.jupiter.params.converter.DefaultArgumentConverter +org.junit.jupiter.params.converter.ArgumentConversionException +org.junit.jupiter.params.converter.StringToObjectConverter +org.junit.jupiter.params.converter.StringToBooleanConverter +org.junit.jupiter.params.converter.StringToCharacterConverter +org.junit.jupiter.params.converter.StringToNumberConverter +org.junit.jupiter.params.converter.StringToNumberConverter$$Lambda$608/0x00000070011fe7b0 +org.junit.jupiter.params.converter.StringToNumberConverter$$Lambda$609/0x00000070011fe9f0 +org.junit.jupiter.params.converter.StringToNumberConverter$$Lambda$610/0x00000070011fec30 +org.junit.jupiter.params.converter.StringToNumberConverter$$Lambda$611/0x00000070011fee70 +org.junit.jupiter.params.converter.StringToNumberConverter$$Lambda$612/0x00000070011ff0b0 +org.junit.jupiter.params.converter.StringToNumberConverter$$Lambda$613/0x00000070011ff2f0 +org.junit.jupiter.params.converter.StringToNumberConverter$$Lambda$614/0x00000070011ff530 +org.junit.jupiter.params.converter.StringToNumberConverter$$Lambda$615/0x00000070011ff770 +org.junit.jupiter.params.converter.StringToClassConverter +org.junit.jupiter.params.converter.StringToEnumConverter +org.junit.jupiter.params.converter.StringToJavaTimeConverter +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$616/0x0000007001200248 +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$617/0x0000007001200488 +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$618/0x00000070012006c8 +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$619/0x0000007001200908 +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$620/0x0000007001200b48 +java.time.MonthDay +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$621/0x0000007001200d88 +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$622/0x0000007001200fc8 +java.time.OffsetTime +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$623/0x0000007001201208 +java.time.chrono.ChronoPeriod +java.time.Period +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$624/0x0000007001201448 +java.time.Year +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$625/0x0000007001201688 +java.time.YearMonth +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$626/0x00000070012018c8 +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$627/0x0000007001201b08 +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$628/0x0000007001201d48 +org.junit.jupiter.params.converter.StringToJavaTimeConverter$$Lambda$629/0x0000007001201f88 +org.junit.jupiter.params.converter.StringToCommonJavaTypesConverter +org.junit.jupiter.params.converter.StringToCommonJavaTypesConverter$$Lambda$630/0x0000007001202410 +org.junit.jupiter.params.converter.StringToCommonJavaTypesConverter$$Lambda$631/0x0000007001202650 +org.junit.jupiter.params.converter.StringToCommonJavaTypesConverter$$Lambda$632/0x0000007001202890 +org.junit.jupiter.params.converter.StringToCommonJavaTypesConverter$$Lambda$633/0x0000007001202ad0 +org.junit.jupiter.params.converter.StringToCommonJavaTypesConverter$$Lambda$634/0x0000007001202d10 +org.junit.jupiter.params.converter.StringToCommonJavaTypesConverter$$Lambda$635/0x0000007001202f50 +org.junit.jupiter.params.converter.StringToCommonJavaTypesConverter$$Lambda$636/0x0000007001203190 +org.junit.jupiter.params.converter.StringToCommonJavaTypesConverter$$Lambda$637/0x00000070012033d0 +org.junit.jupiter.params.converter.FallbackStringToObjectConverter +org.junit.jupiter.params.converter.FallbackStringToObjectConverter$$Lambda$638/0x0000007001203858 +org.junit.jupiter.engine.execution.ParameterResolutionUtils$$Lambda$639/0x0000007001203a98 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$640/0x0000007001203cc0 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$641/0x0000007001203f18 +org.junit.jupiter.params.ParameterizedTestParameterResolver$$Lambda$642/0x0000007001204140 +org.junit.jupiter.params.ParameterizedTestParameterResolver$$Lambda$643/0x0000007001204398 +org.junit.jupiter.params.ParameterizedTestParameterResolver$CloseableArgument +org.junit.jupiter.params.ParameterizedTestParameterResolver$$Lambda$644/0x0000007001204810 +org.junit.jupiter.params.ParameterizedTestParameterResolver$$Lambda$645/0x0000007001204a50 +org.junit.jupiter.engine.descriptor.TestTemplateExtensionContext$$Lambda$646/0x0000007001204c88 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor$$Lambda$647/0x0000007001204ec8 +jdk.internal.reflect.GeneratedConstructorAccessor9 +jdk.internal.reflect.GeneratedMethodAccessor14 +jdk.internal.reflect.GeneratedMethodAccessor15 +jdk.internal.reflect.GeneratedMethodAccessor16 +jdk.internal.reflect.GeneratedMethodAccessor17 +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor$$Lambda$648/0x0000007001205100 +software.amazon.lambda.powertools.metrics.internal.EmfMetricsLoggerTest$$Lambda$649/0x0000007001205328 +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithAnnotationOnWrongMethod$AjcClosure1 +com.amazonaws.services.lambda.runtime.RequestStreamHandler +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithMetricsAnnotation$AjcClosure1 +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithDefaultMetricsAnnotation$AjcClosure1 +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithColdStartMetricsAnnotation$AjcClosure1 +org.assertj.core.api.AbstractObjectArrayAssert +org.assertj.core.api.ObjectArrayAssert +org.assertj.core.internal.ObjectArrays +org.assertj.core.internal.Arrays +org.assertj.core.internal.Iterables +org.assertj.core.internal.Predicates +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithCustomFunctionName$AjcClosure1 +software.amazon.lambda.powertools.metrics.internal.LambdaMetricsAspectTest$HandlerWithServiceNameAndColdStart$AjcClosure1 +org.assertj.core.api.CollectionAssert +org.assertj.core.api.AbstractIterableSizeAssert +org.assertj.core.api.IterableSizeAssert +org.assertj.core.util.Lists$$Lambda$650/0x000000700120fda0 +org.assertj.core.internal.StandardComparisonStrategy$$Lambda$651/0x000000700120a000 +org.assertj.core.util.Preconditions +org.assertj.core.internal.IterableDiff +org.assertj.core.internal.IterableDiff$$Lambda$652/0x000000700120a678 +org.assertj.core.util.IterableUtil +software.amazon.lambda.powertools.metrics.model.DimensionSetTest$$Lambda$653/0x000000700120aad8 +org.junit.platform.launcher.core.OutcomeDelayingEngineExecutionListener$Outcome +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$654/0x000000700120b140 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$655/0x000000700120b378 +java.lang.invoke.LambdaForm$DMH/0x0000007001209400 +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$656/0x000000700120b5a0 +org.junit.platform.launcher.core.DefaultLauncherSession$ClosedLauncher +org.apache.maven.surefire.api.suite.RunResult +org.apache.maven.surefire.booter.ForkedBooter$6 +org.apache.maven.surefire.booter.ForkedBooter$7 +java.util.concurrent.locks.AbstractQueuedSynchronizer$SharedNode +java.util.concurrent.locks.AbstractQueuedSynchronizer$ExclusiveNode +org.apache.maven.surefire.booter.ForkedBooter$1 +org.apache.maven.surefire.booter.spi.AbstractMasterProcessChannelProcessorFactory$2 +java.util.IdentityHashMap$IdentityHashMapIterator +java.util.IdentityHashMap$KeyIterator From 07ff3b265bc1359b9195ed7845f46c890d2073f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 10:46:32 +0200 Subject: [PATCH 326/577] build(deps): bump aws.sdk.version from 2.32.5 to 2.32.10 (#1985) Bumps `aws.sdk.version` from 2.32.5 to 2.32.10. Updates `software.amazon.awssdk:bom` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:http-client-spi` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:url-connection-client` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:dynamodb` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:s3` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:lambda` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:kinesis` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:cloudwatch` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:xray` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:sqs` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:cloudformation` from 2.32.5 to 2.32.10 Updates `software.amazon.awssdk:sts` from 2.32.5 to 2.32.10 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.10 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.10 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.10 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 96f9c0337..619ccfcba 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.5</aws.sdk.version> + <aws.sdk.version>2.32.10</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index db78120d1..506df4232 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.32.5</aws.sdk.version> + <aws.sdk.version>2.32.10</aws.sdk.version> <aws.xray.recorder.version>2.18.2</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> From 22c35eddce945dd041e32daa32f0dd9dff9ca7d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 10:48:33 +0200 Subject: [PATCH 327/577] build(deps): bump org.apache.maven.plugins:maven-source-plugin (#1987) Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.3.0 to 3.3.1. - [Release notes](https://github.com/apache/maven-source-plugin/releases) - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.3.0...maven-source-plugin-3.3.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-version: 3.3.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 506df4232..47db4dea9 100644 --- a/pom.xml +++ b/pom.xml @@ -106,7 +106,7 @@ <jacoco-maven-plugin.version>0.8.13</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version> <maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version> - <maven-source-plugin.version>3.3.0</maven-source-plugin.version> + <maven-source-plugin.version>3.3.1</maven-source-plugin.version> <maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version> <junit.version>5.10.2</junit.version> <aws-embedded-metrics.version>4.1.2</aws-embedded-metrics.version> From f0b6eed1099fee66514e5a5a3370255e332cdc3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 10:52:54 +0200 Subject: [PATCH 328/577] build(deps): bump org.junit:junit-bom from 5.10.2 to 5.13.4 (#1988) Bumps [org.junit:junit-bom](https://github.com/junit-team/junit-framework) from 5.10.2 to 5.13.4. - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](https://github.com/junit-team/junit-framework/compare/r5.10.2...r5.13.4) --- updated-dependencies: - dependency-name: org.junit:junit-bom dependency-version: 5.13.4 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 47db4dea9..a1b714540 100644 --- a/pom.xml +++ b/pom.xml @@ -108,7 +108,7 @@ <maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version> <maven-source-plugin.version>3.3.1</maven-source-plugin.version> <maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version> - <junit.version>5.10.2</junit.version> + <junit.version>5.13.4</junit.version> <aws-embedded-metrics.version>4.1.2</aws-embedded-metrics.version> <jmespath.version>0.6.0</jmespath.version> <aws.sdk.v1.version>1.12.781</aws.sdk.v1.version> From 3798e63d62018179e608dd080dd292d36ca34acd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 10:53:36 +0200 Subject: [PATCH 329/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.162.1 to 2.208.0 (#1990) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.162.1 to 2.208.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/v2.208.0/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.162.1...v2.208.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.208.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 0a2949658..317277af9 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.2.1</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.162.1</cdk.version> + <cdk.version>2.208.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.11.1</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 38cd6a135..1b36d4701 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.2</constructs.version> - <cdk.version>2.186.0</cdk.version> + <cdk.version>2.208.0</cdk.version> </properties> <dependencies> From e6c1676dceb21a4baf1130754aae731ffd41c6c6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 10:53:58 +0200 Subject: [PATCH 330/577] chore: bump github/codeql-action from 3.29.4 to 3.29.5 (#1992) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.4 to 3.29.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4e828ff8d448a8a6e532957b1811f387a63867e8...51f77329afa6477de8c49fc9c7046c15b9a4e79d) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 1d88a8b9f..6367d2452 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4 + uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 with: sarif_file: results.sarif From a691a3bde77b6b0a06884a577bc139290dc56256 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Wed, 6 Aug 2025 10:44:11 +0200 Subject: [PATCH 331/577] chore(ci): Make E2E tests compatible with latest CDK lib version. Improve retry implementation. (#2008) * chore(ci): Make E2E asset deployment compatible with updated CDK lib version. Refactor retry4j to resilience4j. * Add Retry logic to tests instead of Thread.sleep where appropriate. * Avoid request building code duplication in BatchE2ET.java. * Include TracingE2ET again after updating retry logic. * Address Sonarlint issues. * Downgrade resilience4j to Java11 compatible version 1.x * Fix pmd_analyze issues. * Fix more pmd_analyze issues. * Fix more pmd_analyze issues. * Fix more pmd_analyze issues. * Fix more pmd_analyze issues. * Fix more pmd_analyze issues. * Add GraalVM support for TracingE2ET. * Increase TracingE2ET timeout to 15 minutes. --- .../lambda/powertools/e2e/Function.java | 2 +- powertools-e2e-tests/handlers/tracing/pom.xml | 24 +++- .../aws-lambda-java-core/reflect-config.json | 13 ++ .../reflect-config.json | 35 +++++ .../jni-config.json | 11 ++ .../native-image.properties | 1 + .../reflect-config.json | 61 ++++++++ .../resource-config.json | 19 +++ .../reflect-config.json | 25 ++++ .../reflect-config.json | 20 +++ .../resource-config.json | 7 + powertools-e2e-tests/pom.xml | 27 +--- .../amazon/lambda/powertools/BatchE2ET.java | 96 +++++++------ .../lambda/powertools/IdempotencyE2ET.java | 11 +- .../lambda/powertools/LargeMessageE2ET.java | 59 +++++--- .../LargeMessageIdempotentE2ET.java | 64 ++++++--- .../amazon/lambda/powertools/TracingE2ET.java | 36 ++--- .../lambda/powertools/ValidationALBE2ET.java | 129 +++++++++-------- .../powertools/ValidationApiGWE2ET.java | 135 +++++++++--------- .../testutils/DataNotReadyException.java | 25 ++++ .../powertools/testutils/Infrastructure.java | 24 ++-- .../powertools/testutils/RetryUtils.java | 75 ++++++++++ .../metrics/MetricDataNotFoundException.java | 27 ++++ .../testutils/metrics/MetricsFetcher.java | 34 ++--- .../testutils/tracing/TraceFetcher.java | 79 ++++------ .../tracing/TraceNotFoundException.java | 27 ++++ 26 files changed, 724 insertions(+), 342 deletions(-) create mode 100644 powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json create mode 100644 powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DataNotReadyException.java create mode 100644 powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/RetryUtils.java create mode 100644 powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricDataNotFoundException.java create mode 100644 powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceNotFoundException.java diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index 16109778d..038704931 100644 --- a/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/idempotency/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -60,4 +60,4 @@ public String handleRequest(Input input, Context context) { DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME.withZone(TimeZone.getTimeZone("UTC").toZoneId()); return dtf.format(Instant.now()); } -} \ No newline at end of file +} diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index b1bc14c05..67bcee662 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -1,5 +1,5 @@ <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 http://maven.apache.org/maven-v4_0_0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -21,6 +21,14 @@ <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> @@ -57,4 +65,18 @@ </plugin> </plugins> </build> + + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> diff --git a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 1b36d4701..ccd87e95e 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -40,14 +40,12 @@ <artifactId>log4j-slf4j2-impl</artifactId> <scope>test</scope> </dependency> - <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>lambda</artifactId> <version>${aws.sdk.version}</version> <scope>test</scope> </dependency> - <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>dynamodb</artifactId> @@ -66,72 +64,62 @@ <version>${aws.sdk.version}</version> <scope>test</scope> </dependency> - <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>xray</artifactId> <version>${aws.sdk.version}</version> <scope>test</scope> </dependency> - <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>sqs</artifactId> <version>${aws.sdk.version}</version> <scope>test</scope> </dependency> - <dependency> <groupId>com.amazonaws</groupId> <artifactId>amazon-sqs-java-extended-client-lib</artifactId> <version>2.1.2</version> <scope>test</scope> </dependency> - <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>url-connection-client</artifactId> <scope>test</scope> </dependency> - <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> - <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.20.0</version> </dependency> - <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> - <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <scope>test</scope> </dependency> - <dependency> - <groupId>com.evanlennick</groupId> - <artifactId>retry4j</artifactId> - <version>0.15.0</version> + <groupId>io.github.resilience4j</groupId> + <artifactId>resilience4j-retry</artifactId> + <!-- 2.x. not compatible with Java 11 anymore --> + <version>1.7.1</version> <scope>test</scope> </dependency> - <dependency> <groupId>software.amazon.awscdk</groupId> <artifactId>aws-cdk-lib</artifactId> <version>${cdk.version}</version> <scope>test</scope> </dependency> - <dependency> <groupId>software.constructs</groupId> <artifactId>constructs</artifactId> @@ -226,9 +214,6 @@ <includes> <include>**/*E2ET.java</include> </includes> - <excludes> - <exclude>**/TracingE2ET.java</exclude> - </excludes> </configuration> </plugin> </plugins> @@ -257,10 +242,8 @@ <include>**/MetricsE2ET.java</include> <include>**/LoggingE2ET.java</include> <include>**/ParametersE2ET.java</include> + <include>**/TracingE2ET.java</include> </includes> - <excludes> - <exclude>**/TracingE2ET.java</exclude> - </excludes> <systemPropertyVariables> <graalvm.enabled>true</graalvm.enabled> </systemPropertyVariables> diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/BatchE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/BatchE2ET.java index c5f74594d..181d5e583 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/BatchE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/BatchE2ET.java @@ -15,10 +15,7 @@ package software.amazon.lambda.powertools; import static org.assertj.core.api.Assertions.assertThat; -import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -26,11 +23,16 @@ import java.util.UUID; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; + import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; @@ -44,18 +46,18 @@ import software.amazon.awssdk.services.kinesis.KinesisClient; import software.amazon.awssdk.services.kinesis.model.PutRecordsRequest; import software.amazon.awssdk.services.kinesis.model.PutRecordsRequestEntry; -import software.amazon.awssdk.services.kinesis.model.PutRecordsResponse; import software.amazon.awssdk.services.sqs.SqsClient; import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest; import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry; +import software.amazon.lambda.powertools.testutils.DataNotReadyException; import software.amazon.lambda.powertools.testutils.Infrastructure; +import software.amazon.lambda.powertools.testutils.RetryUtils; import software.amazon.lambda.powertools.utilities.JsonConfig; -public class BatchE2ET { +class BatchE2ET { private static final SdkHttpClient httpClient = UrlConnectionHttpClient.builder().build(); private static final Region region = Region.of(System.getProperty("AWS_DEFAULT_REGION", "eu-west-1")); private static Infrastructure infrastructure; - private static String functionName; private static String queueUrl; private static String kinesisStreamName; @@ -71,13 +73,12 @@ public BatchE2ET() { testProducts = Arrays.asList( new Product(1, "product1", 1.23), new Product(2, "product2", 4.56), - new Product(3, "product3", 6.78) - ); + new Product(3, "product3", 6.78)); } @BeforeAll @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { + static void setup() { String random = UUID.randomUUID().toString().substring(0, 6); String queueName = "batchqueue" + random; kinesisStreamName = "batchstream" + random; @@ -94,7 +95,6 @@ public static void setup() { .build(); Map<String, String> outputs = infrastructure.deploy(); - functionName = outputs.get(FUNCTION_NAME_OUTPUT); queueUrl = outputs.get("QueueURL"); kinesisStreamName = outputs.get("KinesisStreamName"); outputTable = outputs.get("TableNameForAsyncTests"); @@ -117,21 +117,21 @@ public static void setup() { } @AfterAll - public static void tearDown() { + static void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @AfterEach - public void cleanUpTest() { + void cleanUpTest() { // Delete everything in the output table ScanResponse items = ddbClient.scan(ScanRequest.builder() .tableName(outputTable) .build()); for (Map<String, AttributeValue> item : items.items()) { - HashMap<String, AttributeValue> key = new HashMap<String, AttributeValue>() { + Map<String, AttributeValue> key = new HashMap<>() { { put("functionName", AttributeValue.builder() .s(item.get("functionName").s()) @@ -150,7 +150,7 @@ public void cleanUpTest() { } @Test - public void sqsBatchProcessingSucceeds() throws InterruptedException { + void sqsBatchProcessingSucceeds() { List<SendMessageBatchRequestEntry> entries = testProducts.stream() .map(p -> { try { @@ -169,17 +169,23 @@ public void sqsBatchProcessingSucceeds() throws InterruptedException { .entries(entries) .queueUrl(queueUrl) .build()); - Thread.sleep(30000); // wait for function to be executed // THEN - ScanResponse items = ddbClient.scan(ScanRequest.builder() - .tableName(outputTable) - .build()); - validateAllItemsHandled(items); + ScanRequest scanRequest = ScanRequest.builder().tableName(outputTable).build(); + RetryUtils.withRetry(() -> { + ScanResponse items = ddbClient.scan(scanRequest); + if (!areAllTestProductsPresent(items)) { + throw new DataNotReadyException("sqs-batch-processing not complete yet"); + } + return null; + }, "sqs-batch-processing", DataNotReadyException.class).get(); + + ScanResponse finalItems = ddbClient.scan(scanRequest); + assertThat(areAllTestProductsPresent(finalItems)).isTrue(); } @Test - public void kinesisBatchProcessingSucceeds() throws InterruptedException { + void kinesisBatchProcessingSucceeds() { List<PutRecordsRequestEntry> entries = testProducts.stream() .map(p -> { try { @@ -194,21 +200,27 @@ public void kinesisBatchProcessingSucceeds() throws InterruptedException { .collect(Collectors.toList()); // WHEN - PutRecordsResponse result = kinesisClient.putRecords(PutRecordsRequest.builder() + kinesisClient.putRecords(PutRecordsRequest.builder() .streamName(kinesisStreamName) .records(entries) .build()); - Thread.sleep(30000); // wait for function to be executed // THEN - ScanResponse items = ddbClient.scan(ScanRequest.builder() - .tableName(outputTable) - .build()); - validateAllItemsHandled(items); + ScanRequest scanRequest = ScanRequest.builder().tableName(outputTable).build(); + RetryUtils.withRetry(() -> { + ScanResponse items = ddbClient.scan(scanRequest); + if (!areAllTestProductsPresent(items)) { + throw new DataNotReadyException("kinesis-batch-processing not complete yet"); + } + return null; + }, "kinesis-batch-processing", DataNotReadyException.class).get(); + + ScanResponse finalItems = ddbClient.scan(scanRequest); + assertThat(areAllTestProductsPresent(finalItems)).isTrue(); } @Test - public void ddbStreamsBatchProcessingSucceeds() throws InterruptedException { + void ddbStreamsBatchProcessingSucceeds() { // GIVEN String theId = "my-test-id"; @@ -223,39 +235,43 @@ public void ddbStreamsBatchProcessingSucceeds() throws InterruptedException { } }) .build()); - Thread.sleep(90000); // wait for function to be executed // THEN - ScanResponse items = ddbClient.scan(ScanRequest.builder() - .tableName(outputTable) - .build()); + ScanRequest scanRequest = ScanRequest.builder().tableName(outputTable).build(); + RetryUtils.withRetry(() -> { + ScanResponse items = ddbClient.scan(scanRequest); + if (items.count() != 1) { + throw new DataNotReadyException("DDB streams processing not complete yet"); + } + return null; + }, "ddb-streams-batch-processing", DataNotReadyException.class).get(); - assertThat(items.count()).isEqualTo(1); - assertThat(items.items().get(0).get("id").s()).isEqualTo(theId); + ScanResponse finalItems = ddbClient.scan(scanRequest); + assertThat(finalItems.count()).isEqualTo(1); + assertThat(finalItems.items().get(0).get("id").s()).isEqualTo(theId); } - private void validateAllItemsHandled(ScanResponse items) { + private boolean areAllTestProductsPresent(ScanResponse items) { for (Product p : testProducts) { boolean foundIt = false; for (Map<String, AttributeValue> a : items.items()) { if (a.get("id").s().equals(Long.toString(p.id))) { foundIt = true; + break; } } - assertThat(foundIt).isTrue(); + if (!foundIt) { + return false; + } } + return true; } class Product { private long id; - private String name; - private double price; - public Product() { - } - public Product(long id, String name, double price) { this.id = id; this.name = name; diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java index 242d1a2db..292f46bfa 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java @@ -21,21 +21,23 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; + import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; + import software.amazon.lambda.powertools.testutils.Infrastructure; import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; -public class IdempotencyE2ET { +class IdempotencyE2ET { private static Infrastructure infrastructure; private static String functionName; @BeforeAll @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { + static void setup() { String random = UUID.randomUUID().toString().substring(0, 6); infrastructure = Infrastructure.builder() .testName(IdempotencyE2ET.class.getSimpleName()) @@ -47,14 +49,14 @@ public static void setup() { } @AfterAll - public static void tearDown() { + static void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @Test - public void test_ttlNotExpired_sameResult_ttlExpired_differentResult() throws InterruptedException { + void test_ttlNotExpired_sameResult_ttlExpired_differentResult() throws InterruptedException { // GIVEN String event = "{\"message\":\"TTL 10sec\"}"; @@ -65,6 +67,7 @@ public void test_ttlNotExpired_sameResult_ttlExpired_differentResult() throws In // Second invocation (should get same result) InvocationResult result2 = invokeFunction(functionName, event); + // Function idempotency record expiration is set to 10 seconds Thread.sleep(12000); // Third invocation (should get different result) diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java index d9c3ef749..74247ca2e 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java @@ -36,9 +36,11 @@ import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.sqs.SqsClient; import software.amazon.awssdk.services.sqs.model.SendMessageRequest; +import software.amazon.lambda.powertools.testutils.DataNotReadyException; import software.amazon.lambda.powertools.testutils.Infrastructure; +import software.amazon.lambda.powertools.testutils.RetryUtils; -public class LargeMessageE2ET { +class LargeMessageE2ET { private static final Logger LOG = LoggerFactory.getLogger(LargeMessageE2ET.class); private static final SdkHttpClient httpClient = UrlConnectionHttpClient.builder().build(); @@ -62,7 +64,7 @@ public class LargeMessageE2ET { @BeforeAll @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { + static void setup() { String random = UUID.randomUUID().toString().substring(0, 6); bucketName = "largemessagebucket" + random; String queueName = "largemessagequeue" + random; @@ -84,14 +86,14 @@ public static void setup() { } @AfterAll - public static void tearDown() { + static void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @AfterEach - public void reset() { + void reset() { if (messageId != null) { Map<String, AttributeValue> itemToDelete = new HashMap<>(); itemToDelete.put("functionName", AttributeValue.builder().s(functionName).build()); @@ -102,25 +104,24 @@ public void reset() { } @Test - public void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException, InterruptedException { - // given + void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException { + // GIVEN final ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration() .withPayloadSupportEnabled(s3Client, bucketName); try (AmazonSQSExtendedClient client = new AmazonSQSExtendedClient( - SqsClient.builder().region(region).httpClient(httpClient).build(), extendedClientConfig)) { - InputStream inputStream = this.getClass().getResourceAsStream("/large_sqs_message.txt"); + SqsClient.builder().region(region).httpClient(httpClient).build(), extendedClientConfig); + InputStream inputStream = this.getClass().getResourceAsStream("/large_sqs_message.txt");) { String bigMessage = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - // when + // WHEN client.sendMessage(SendMessageRequest .builder() .queueUrl(queueUrl) .messageBody(bigMessage) .build()); } - Thread.sleep(30000); // wait for function to be executed - // then + // THEN QueryRequest request = QueryRequest .builder() .tableName(tableName) @@ -128,8 +129,17 @@ public void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException, In .expressionAttributeValues( Collections.singletonMap(":func", AttributeValue.builder().s(functionName).build())) .build(); - QueryResponse response = dynamoDbClient.query(request); - List<Map<String, AttributeValue>> items = response.items(); + + RetryUtils.withRetry(() -> { + QueryResponse response = dynamoDbClient.query(request); + if (response.items().size() != 1) { + throw new DataNotReadyException("Large message processing not complete yet"); + } + return null; + }, "large-message-processing", DataNotReadyException.class).get(); + + QueryResponse finalResponse = dynamoDbClient.query(request); + List<Map<String, AttributeValue>> items = finalResponse.items(); assertThat(items).hasSize(1); messageId = items.get(0).get("id").s(); assertThat(Integer.valueOf(items.get(0).get("bodySize").n())).isEqualTo(300977); @@ -137,8 +147,8 @@ public void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException, In } @Test - public void smallSQSMessage_shouldNotReadFromS3() throws IOException, InterruptedException { - // given + void smallSQSMessage_shouldNotReadFromS3() { + // GIVEN final ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration() .withPayloadSupportEnabled(s3Client, bucketName); try (AmazonSQSExtendedClient client = new AmazonSQSExtendedClient( @@ -146,16 +156,14 @@ public void smallSQSMessage_shouldNotReadFromS3() throws IOException, Interrupte extendedClientConfig)) { String message = "Hello World"; - // when + // WHEN client.sendMessage(SendMessageRequest .builder() .queueUrl(queueUrl) .messageBody(message) .build()); - Thread.sleep(30000); // wait for function to be executed - - // then + // THEN QueryRequest request = QueryRequest .builder() .tableName(tableName) @@ -163,8 +171,17 @@ public void smallSQSMessage_shouldNotReadFromS3() throws IOException, Interrupte .expressionAttributeValues( Collections.singletonMap(":func", AttributeValue.builder().s(functionName).build())) .build(); - QueryResponse response = dynamoDbClient.query(request); - List<Map<String, AttributeValue>> items = response.items(); + + RetryUtils.withRetry(() -> { + QueryResponse response = dynamoDbClient.query(request); + if (response.items().size() != 1) { + throw new DataNotReadyException("Small message processing not complete yet"); + } + return null; + }, "small-message-processing", DataNotReadyException.class).get(); + + QueryResponse finalResponse = dynamoDbClient.query(request); + List<Map<String, AttributeValue>> items = finalResponse.items(); assertThat(items).hasSize(1); messageId = items.get(0).get("id").s(); assertThat(Integer.valueOf(items.get(0).get("bodySize").n())).isEqualTo( diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageIdempotentE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageIdempotentE2ET.java index ef342ea13..cd787b60a 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageIdempotentE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageIdempotentE2ET.java @@ -24,6 +24,7 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; + import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -31,6 +32,7 @@ import org.junit.jupiter.api.Timeout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; @@ -44,9 +46,11 @@ import software.amazon.awssdk.services.sqs.SqsClient; import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; import software.amazon.awssdk.services.sqs.model.SendMessageRequest; +import software.amazon.lambda.powertools.testutils.DataNotReadyException; import software.amazon.lambda.powertools.testutils.Infrastructure; +import software.amazon.lambda.powertools.testutils.RetryUtils; -public class LargeMessageIdempotentE2ET { +class LargeMessageIdempotentE2ET { private static final Logger LOG = LoggerFactory.getLogger(LargeMessageIdempotentE2ET.class); private static final SdkHttpClient httpClient = UrlConnectionHttpClient.builder().build(); @@ -72,10 +76,9 @@ public class LargeMessageIdempotentE2ET { private static String queueUrl; private static String tableName; - @BeforeAll @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { + static void setup() { String random = UUID.randomUUID().toString().substring(0, 6); bucketName = "largemessagebucket" + random; String queueName = "largemessagequeue" + random; @@ -98,34 +101,33 @@ public static void setup() { } @AfterAll - public static void tearDown() { + static void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @Test - public void test_ttlNotExpired_doesNotInsertInDDB_ttlExpired_insertInDDB() throws InterruptedException, + void test_ttlNotExpired_doesNotInsertInDDB_ttlExpired_insertInDDB() throws InterruptedException, IOException { - int waitMs = 15000; - // GIVEN - InputStream inputStream = this.getClass().getResourceAsStream("/large_sqs_message.txt"); - String bigMessage = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - // upload manually to S3 - String key = UUID.randomUUID().toString(); - s3Client.putObject(PutObjectRequest.builder() - .bucket(bucketName) - .key(key) - .build(), RequestBody.fromString(bigMessage)); + String s3Key = UUID.randomUUID().toString(); + try (InputStream inputStream = this.getClass().getResourceAsStream("/large_sqs_message.txt")) { + String bigMessage = IOUtils.toString(inputStream, StandardCharsets.UTF_8); + + // upload manually to S3 + s3Client.putObject(PutObjectRequest.builder() + .bucket(bucketName) + .key(s3Key) + .build(), RequestBody.fromString(bigMessage)); + } // WHEN SendMessageRequest messageRequest = SendMessageRequest.builder() .queueUrl(queueUrl) .messageBody(String.format( "[\"software.amazon.payloadoffloading.PayloadS3Pointer\",{\"s3BucketName\":\"%s\",\"s3Key\":\"%s\"}]", - bucketName, key)) + bucketName, s3Key)) .messageAttributes(Collections.singletonMap("SQSLargePayloadSize", MessageAttributeValue.builder() .stringValue("300977") .dataType("Number") @@ -135,7 +137,6 @@ public void test_ttlNotExpired_doesNotInsertInDDB_ttlExpired_insertInDDB() throw // First invocation // send message to SQS with the good pointer and metadata sqsClient.sendMessage(messageRequest); - Thread.sleep(waitMs); // wait for the function to be invoked & executed // THEN QueryRequest request = QueryRequest @@ -145,6 +146,15 @@ public void test_ttlNotExpired_doesNotInsertInDDB_ttlExpired_insertInDDB() throw .expressionAttributeValues( Collections.singletonMap(":func", AttributeValue.builder().s(functionName).build())) .build(); + + RetryUtils.withRetry(() -> { + QueryResponse response = dynamoDbClient.query(request); + if (response.items().size() != 1) { + throw new DataNotReadyException("First invocation processing not complete yet"); + } + return null; + }, "first-invocation-processing", DataNotReadyException.class).get(); + QueryResponse response = dynamoDbClient.query(request); List<Map<String, AttributeValue>> items = response.items(); assertThat(items).hasSize(1); @@ -156,7 +166,14 @@ public void test_ttlNotExpired_doesNotInsertInDDB_ttlExpired_insertInDDB() throw // Second invocation // send the same message before ttl expires sqsClient.sendMessage(messageRequest); - Thread.sleep(waitMs); // wait for the function to be invoked & executed + + RetryUtils.withRetry(() -> { + QueryResponse resp = dynamoDbClient.query(request); + if (resp.items().size() != 1) { + throw new DataNotReadyException("Second invocation processing not complete yet"); + } + return null; + }, "second-invocation-processing", DataNotReadyException.class).get(); // THEN response = dynamoDbClient.query(request); @@ -174,7 +191,14 @@ public void test_ttlNotExpired_doesNotInsertInDDB_ttlExpired_insertInDDB() throw // Third invocation // send the same message again sqsClient.sendMessage(messageRequest); - Thread.sleep(waitMs); // wait for the function to be invoked + + RetryUtils.withRetry(() -> { + QueryResponse resp = dynamoDbClient.query(request); + if (resp.items().size() != 2) { + throw new DataNotReadyException("Third invocation processing not complete yet"); + } + return null; + }, "third-invocation-processing", DataNotReadyException.class).get(); // THEN response = dynamoDbClient.query(request); diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java index d2a5ceed1..13d8adb9b 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/TracingE2ET.java @@ -15,6 +15,7 @@ package software.amazon.lambda.powertools; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static software.amazon.lambda.powertools.testutils.Infrastructure.FUNCTION_NAME_OUTPUT; import static software.amazon.lambda.powertools.testutils.lambda.LambdaInvoker.invokeFunction; @@ -33,21 +34,21 @@ import software.amazon.lambda.powertools.testutils.tracing.Trace; import software.amazon.lambda.powertools.testutils.tracing.TraceFetcher; -public class TracingE2ET { - private static final String service = "TracingE2EService_" + UUID.randomUUID(); +class TracingE2ET { + private static final String SERVICE = "TracingE2EService_" + UUID.randomUUID(); private static Infrastructure infrastructure; private static String functionName; @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { + @Timeout(value = 15, unit = TimeUnit.MINUTES) + static void setup() { infrastructure = Infrastructure.builder() .testName(TracingE2ET.class.getSimpleName()) .pathToFunction("tracing") .tracing(true) .environmentVariables( - Map.of("POWERTOOLS_SERVICE_NAME", service, + Map.of("POWERTOOLS_SERVICE_NAME", SERVICE, "POWERTOOLS_TRACER_CAPTURE_RESPONSE", "true")) .build(); Map<String, String> outputs = infrastructure.deploy(); @@ -55,14 +56,14 @@ public static void setup() { } @AfterAll - public static void tearDown() { + static void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } @Test - public void test_tracing() { + void test_tracing() { // GIVEN final String message = "Hello World"; final String event = String.format("{\"message\":\"%s\"}", message); @@ -79,25 +80,18 @@ public void test_tracing() { .build() .fetchTrace(); - assertThat(trace.getSubsegments()).hasSize(2); - - // We need to filter segments based on name because they are not returned in-order from the X-Ray API - // The Init segment is created by default for Lambda functions in X-Ray - final SubSegment initSegment = trace.getSubsegments().stream() - .filter(subSegment -> subSegment.getName().equals("Init")) - .findFirst().orElse(null); - assertThat(initSegment.getName()).isEqualTo("Init"); - assertThat(initSegment.getAnnotations()).isNull(); + assertThat(trace.getSubsegments()).hasSize(1); final SubSegment handleRequestSegment = trace.getSubsegments().stream() - .filter(subSegment -> subSegment.getName().equals("## handleRequest")) + .filter(subSegment -> "## handleRequest".equals(subSegment.getName())) .findFirst().orElse(null); + assertNotNull(handleRequestSegment); assertThat(handleRequestSegment.getName()).isEqualTo("## handleRequest"); assertThat(handleRequestSegment.getAnnotations()).hasSize(2); assertThat(handleRequestSegment.getAnnotations()).containsEntry("ColdStart", true); - assertThat(handleRequestSegment.getAnnotations()).containsEntry("Service", service); + assertThat(handleRequestSegment.getAnnotations()).containsEntry("Service", SERVICE); assertThat(handleRequestSegment.getMetadata()).hasSize(1); - final Map<String, Object> metadata = (Map<String, Object>) handleRequestSegment.getMetadata().get(service); + final Map<String, Object> metadata = (Map<String, Object>) handleRequestSegment.getMetadata().get(SERVICE); assertThat(metadata).containsEntry("handleRequest response", result); assertThat(handleRequestSegment.getSubsegments()).hasSize(2); @@ -108,14 +102,14 @@ public void test_tracing() { assertThat(sub.getName()).isIn("## internal_stuff", "## buildMessage"); SubSegment buildMessage = handleRequestSegment.getSubsegments().stream() - .filter(subSegment -> subSegment.getName().equals("## buildMessage")) + .filter(subSegment -> "## buildMessage".equals(subSegment.getName())) .findFirst().orElse(null); assertThat(buildMessage).isNotNull(); assertThat(buildMessage.getAnnotations()).hasSize(1); assertThat(buildMessage.getAnnotations()).containsEntry("message", message); assertThat(buildMessage.getMetadata()).hasSize(1); final Map<String, Object> buildMessageSegmentMetadata = (Map<String, Object>) buildMessage.getMetadata() - .get(service); + .get(SERVICE); assertThat(buildMessageSegmentMetadata).containsEntry("buildMessage response", result); } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java index 41696943a..bf90851cb 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationALBE2ET.java @@ -38,67 +38,70 @@ class ValidationALBE2ET { - private static final ObjectMapper objectMapper = new ObjectMapper(); - - private static Infrastructure infrastructure; - private static String functionName; - - @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { - infrastructure = Infrastructure.builder().testName(ValidationALBE2ET.class.getSimpleName()) - .pathToFunction("validation-alb-event").build(); - Map<String, String> outputs = infrastructure.deploy(); - functionName = outputs.get(FUNCTION_NAME_OUTPUT); - } - - @AfterAll - public static void tearDown() { - if (infrastructure != null) { - infrastructure.destroy(); - } - } - - @Test - void test_validInboundSQSEvent() throws IOException { - InputStream inputStream = this.getClass().getResourceAsStream("/validation/valid_alb_in_out_event.json"); - String validEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - // WHEN - InvocationResult invocationResult = invokeFunction(functionName, validEvent); - - // THEN - // invocation should pass validation and return 200 - JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); - assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(200); - assertThat(validJsonNode.get("body").asText()).isEqualTo("{\"price\": 150}"); - } - - @Test - void test_invalidInboundSQSEvent() throws IOException { - InputStream inputStream = this.getClass().getResourceAsStream("/validation/invalid_alb_in_event.json"); - String invalidEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - // WHEN - InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); - - // THEN - // invocation should fail inbound validation and return an error message - JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); - assertThat(validJsonNode.get("errorMessage").asText()).contains(": required property 'price' not found"); - } - - @Test - void test_invalidOutboundSQSEvent() throws IOException { - InputStream inputStream = this.getClass().getResourceAsStream("/validation/invalid_alb_out_event.json"); - String invalidEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - // WHEN - InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); - - // THEN - // invocation should fail outbound validation and return 400 - JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); - assertThat(validJsonNode.get("errorMessage").asText()).contains("/price: must have an exclusive maximum value of 1000"); - } + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private static Infrastructure infrastructure; + private static String functionName; + + @BeforeAll + @Timeout(value = 5, unit = TimeUnit.MINUTES) + static void setup() { + infrastructure = Infrastructure.builder().testName(ValidationALBE2ET.class.getSimpleName()) + .pathToFunction("validation-alb-event").build(); + Map<String, String> outputs = infrastructure.deploy(); + functionName = outputs.get(FUNCTION_NAME_OUTPUT); + } + + @AfterAll + static void tearDown() { + if (infrastructure != null) { + infrastructure.destroy(); + } + } + + @Test + void test_validInboundSQSEvent() throws IOException { + try (InputStream is = this.getClass().getResourceAsStream("/validation/valid_alb_in_out_event.json")) { + String validEvent = IOUtils.toString(is, StandardCharsets.UTF_8); + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, validEvent); + + // THEN + // invocation should pass validation and return 200 + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(200); + assertThat(validJsonNode.get("body").asText()).isEqualTo("{\"price\": 150}"); + } + } + + @Test + void test_invalidInboundSQSEvent() throws IOException { + try (InputStream is = this.getClass().getResourceAsStream("/validation/invalid_alb_in_event.json")) { + String invalidEvent = IOUtils.toString(is, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); + + // THEN + // invocation should fail inbound validation and return an error message + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("errorMessage").asText()).contains(": required property 'price' not found"); + } + } + + @Test + void test_invalidOutboundSQSEvent() throws IOException { + try (InputStream is = this.getClass().getResourceAsStream("/validation/invalid_alb_out_event.json")) { + String invalidEvent = IOUtils.toString(is, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); + + // THEN + // invocation should fail outbound validation and return 400 + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("errorMessage").asText()) + .contains("/price: must have an exclusive maximum value of 1000"); + } + } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java index 425399c95..2d1bf4657 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/ValidationApiGWE2ET.java @@ -38,70 +38,73 @@ class ValidationApiGWE2ET { - private static final ObjectMapper objectMapper = new ObjectMapper(); - - private static Infrastructure infrastructure; - private static String functionName; - - @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) - public static void setup() { - infrastructure = Infrastructure.builder().testName(ValidationApiGWE2ET.class.getSimpleName()) - .pathToFunction("validation-apigw-event").build(); - Map<String, String> outputs = infrastructure.deploy(); - functionName = outputs.get(FUNCTION_NAME_OUTPUT); - } - - @AfterAll - public static void tearDown() { - if (infrastructure != null) { - infrastructure.destroy(); - } - } - - @Test - void test_validInboundApiGWEvent() throws IOException { - InputStream inputStream = this.getClass().getResourceAsStream("/validation/valid_api_gw_in_out_event.json"); - String validEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - // WHEN - InvocationResult invocationResult = invokeFunction(functionName, validEvent); - - // THEN - // invocation should pass validation and return 200 - JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); - assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(200); - assertThat(validJsonNode.get("body").asText()).isEqualTo("{\"price\": 150}"); - } - - @Test - void test_invalidInboundApiGWEvent() throws IOException { - InputStream inputStream = this.getClass().getResourceAsStream("/validation/invalid_api_gw_in_event.json"); - String invalidEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - // WHEN - InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); - - // THEN - // invocation should fail inbound validation and return 400 - JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); - assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(400); - assertThat(validJsonNode.get("body").asText()).contains(": required property 'price' not found"); - } - - @Test - void test_invalidOutboundApiGWEvent() throws IOException { - InputStream inputStream = this.getClass().getResourceAsStream("/validation/invalid_api_gw_out_event.json"); - String invalidEvent = IOUtils.toString(inputStream, StandardCharsets.UTF_8); - - // WHEN - InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); - - // THEN - // invocation should fail outbound validation and return 400 - JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); - assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(400); - assertThat(validJsonNode.get("body").asText()) - .contains("/price: must have an exclusive maximum value of 1000"); - } + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private static Infrastructure infrastructure; + private static String functionName; + + @BeforeAll + @Timeout(value = 5, unit = TimeUnit.MINUTES) + static void setup() { + infrastructure = Infrastructure.builder().testName(ValidationApiGWE2ET.class.getSimpleName()) + .pathToFunction("validation-apigw-event").build(); + Map<String, String> outputs = infrastructure.deploy(); + functionName = outputs.get(FUNCTION_NAME_OUTPUT); + } + + @AfterAll + static void tearDown() { + if (infrastructure != null) { + infrastructure.destroy(); + } + } + + @Test + void test_validInboundApiGWEvent() throws IOException { + try (InputStream is = this.getClass().getResourceAsStream("/validation/valid_api_gw_in_out_event.json")) { + String validEvent = IOUtils.toString(is, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, validEvent); + + // THEN + // invocation should pass validation and return 200 + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(200); + assertThat(validJsonNode.get("body").asText()).isEqualTo("{\"price\": 150}"); + } + } + + @Test + void test_invalidInboundApiGWEvent() throws IOException { + try (InputStream is = this.getClass().getResourceAsStream("/validation/invalid_api_gw_in_event.json")) { + String invalidEvent = IOUtils.toString(is, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); + + // THEN + // invocation should fail inbound validation and return 400 + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(400); + assertThat(validJsonNode.get("body").asText()).contains(": required property 'price' not found"); + } + } + + @Test + void test_invalidOutboundApiGWEvent() throws IOException { + try (InputStream is = this.getClass().getResourceAsStream("/validation/invalid_api_gw_out_event.json")) { + String invalidEvent = IOUtils.toString(is, StandardCharsets.UTF_8); + + // WHEN + InvocationResult invocationResult = invokeFunction(functionName, invalidEvent); + + // THEN + // invocation should fail outbound validation and return 400 + JsonNode validJsonNode = objectMapper.readTree(invocationResult.getResult()); + assertThat(validJsonNode.get("statusCode").asInt()).isEqualTo(400); + assertThat(validJsonNode.get("body").asText()) + .contains("/price: must have an exclusive maximum value of 1000"); + } + } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DataNotReadyException.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DataNotReadyException.java new file mode 100644 index 000000000..0c16bb68b --- /dev/null +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DataNotReadyException.java @@ -0,0 +1,25 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.testutils; + +/** + * Exception thrown when test data is not ready yet. + * This exception is used to trigger retries in tests waiting for async operations. + */ +public class DataNotReadyException extends RuntimeException { + public DataNotReadyException(String message) { + super(message); + } +} diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java index c65871a0a..ea5ac3342 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.nio.file.Paths; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.Objects; import java.util.UUID; @@ -97,7 +98,7 @@ * `PutObjectRequest`) * and the CloudFormation stack is created (with the SDK `createStack`) */ -public class Infrastructure { +public final class Infrastructure { public static final String FUNCTION_NAME_OUTPUT = "functionName"; private static final Logger LOG = LoggerFactory.getLogger(Infrastructure.class); @@ -120,7 +121,6 @@ public class Infrastructure { private final String kinesisStream; private final String largeMessagesBucket; private String ddbStreamsTableName; - private String functionName; private Object cfnTemplate; private String cfnAssetDirectory; @@ -223,7 +223,7 @@ private Stack createStackWithLambda() { ? dockerConfig.createGraalVMBundlingOptions(pathToFunction, runtime) : dockerConfig.createJVMBundlingOptions(pathToFunction, runtime); - functionName = stackName + "-function"; + String functionName = stackName + "-function"; CfnOutput.Builder.create(e2eStack, FUNCTION_NAME_OUTPUT) .value(functionName) .build(); @@ -469,10 +469,18 @@ private Map<String, Asset> findAssets() { files.iterator().forEachRemaining(file -> { String assetPath = file.get("source").get("path").asText(); String assetPackaging = file.get("source").get("packaging").asText(); - String bucketName = file.get("destinations").get("current_account-current_region").get("bucketName") - .asText(); - String objectKey = file.get("destinations").get("current_account-current_region").get("objectKey") - .asText(); + JsonNode destinations = file.get("destinations"); + String bucketName = null; + String objectKey = null; + Iterator<String> fieldNames = destinations.fieldNames(); + while (fieldNames.hasNext()) { + String fieldName = fieldNames.next(); + if (fieldName.startsWith("current_account-current_region")) { + bucketName = destinations.get(fieldName).get("bucketName").asText(); + objectKey = destinations.get(fieldName).get("objectKey").asText(); + break; + } + } Asset asset = new Asset(assetPath, assetPackaging, bucketName.replace("${AWS::AccountId}", account) .replace("${AWS::Region}", region.toString())); assets.put(objectKey, asset); @@ -483,7 +491,7 @@ private Map<String, Asset> findAssets() { return assets; } - public static class Builder { + public static final class Builder { public long timeoutInSeconds = 30; public String pathToFunction; public String testName; diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/RetryUtils.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/RetryUtils.java new file mode 100644 index 000000000..054e9aa8e --- /dev/null +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/RetryUtils.java @@ -0,0 +1,75 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.testutils; + +import java.time.Duration; +import java.util.function.Supplier; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.resilience4j.retry.Retry; +import io.github.resilience4j.retry.RetryConfig; + +/** + * Utility class for consistent retry configuration across all test utilities. + */ +public final class RetryUtils { + private static final Logger LOG = LoggerFactory.getLogger(RetryUtils.class); + + private static final RetryConfig DEFAULT_RETRY_CONFIG = RetryConfig.custom() + .maxAttempts(60) // 60 attempts over 5 minutes + .waitDuration(Duration.ofSeconds(5)) // 5 seconds between attempts + .build(); + + private RetryUtils() { + // Utility class + } + + /** + * Creates a retry instance with default configuration for the specified throwable types. + * + * @param name the name for the retry instance + * @param retryOnThrowables the throwable classes to retry on + * @return configured Retry instance + */ + @SafeVarargs + public static Retry createRetry(String name, Class<? extends Throwable>... retryOnThrowables) { + RetryConfig config = RetryConfig.from(DEFAULT_RETRY_CONFIG) + .retryExceptions(retryOnThrowables) + .build(); + + Retry retry = Retry.of(name, config); + retry.getEventPublisher().onRetry(event -> LOG.warn("Retry attempt {} for {}: {}", + event.getNumberOfRetryAttempts(), name, event.getLastThrowable().getMessage())); + + return retry; + } + + /** + * Decorates a supplier with retry logic for the specified throwable types. + * + * @param supplier the supplier to decorate + * @param name the name for the retry instance + * @param retryOnThrowables the throwable classes to retry on + * @return decorated supplier with retry logic + */ + @SafeVarargs + public static <T> Supplier<T> withRetry(Supplier<T> supplier, String name, + Class<? extends Throwable>... retryOnThrowables) { + Retry retry = createRetry(name, retryOnThrowables); + return Retry.decorateSupplier(retry, supplier); + } +} diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricDataNotFoundException.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricDataNotFoundException.java new file mode 100644 index 000000000..79478c14e --- /dev/null +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricDataNotFoundException.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.testutils.metrics; + +import software.amazon.lambda.powertools.testutils.DataNotReadyException; + +/** + * Exception thrown when metric data is not found in CloudWatch. + * This exception is used to trigger retries as metrics may not be available immediately. + */ +public class MetricDataNotFoundException extends DataNotReadyException { + public MetricDataNotFoundException(String message) { + super(message); + } +} diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java index 186e72d13..f856d8f2f 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/metrics/MetricsFetcher.java @@ -14,20 +14,16 @@ package software.amazon.lambda.powertools.testutils.metrics; -import static java.time.Duration.ofSeconds; - -import com.evanlennick.retry4j.CallExecutor; -import com.evanlennick.retry4j.CallExecutorBuilder; -import com.evanlennick.retry4j.Status; -import com.evanlennick.retry4j.config.RetryConfig; -import com.evanlennick.retry4j.config.RetryConfigBuilder; import java.time.Instant; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; -import java.util.concurrent.Callable; +import java.util.function.Supplier; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.regions.Region; @@ -39,6 +35,7 @@ import software.amazon.awssdk.services.cloudwatch.model.MetricDataQuery; import software.amazon.awssdk.services.cloudwatch.model.MetricStat; import software.amazon.awssdk.services.cloudwatch.model.StandardUnit; +import software.amazon.lambda.powertools.testutils.RetryUtils; /** * Class in charge of retrieving the actual metrics of a Lambda execution on CloudWatch @@ -73,14 +70,14 @@ public List<Double> fetchMetrics(Instant start, Instant end, int period, String dimensions.forEach((key, value) -> dimensionsList.add(Dimension.builder().name(key).value(value).build())); } - Callable<List<Double>> callable = () -> { + Supplier<List<Double>> supplier = () -> { LOG.debug("Get Metrics for namespace {}, start {}, end {}, metric {}, dimensions {}", namespace, start, end, metricName, dimensionsList); GetMetricDataResponse metricData = cloudwatch.getMetricData(GetMetricDataRequest.builder() .startTime(start) .endTime(end) .metricDataQueries(MetricDataQuery.builder() - .id(metricName.toLowerCase()) + .id(metricName.toLowerCase(Locale.ROOT)) .metricStat(MetricStat.builder() .unit(StandardUnit.COUNT) .metric(Metric.builder() @@ -96,24 +93,11 @@ public List<Double> fetchMetrics(Instant start, Instant end, int period, String .build()); List<Double> values = metricData.metricDataResults().get(0).values(); if (values == null || values.isEmpty()) { - throw new Exception("No data found for metric " + metricName); + throw new MetricDataNotFoundException("No data found for metric " + metricName); } return values; }; - RetryConfig retryConfig = new RetryConfigBuilder() - .withMaxNumberOfTries(10) - .retryOnAnyException() - .withDelayBetweenTries(ofSeconds(2)) - .withRandomExponentialBackoff() - .build(); - CallExecutor<List<Double>> callExecutor = new CallExecutorBuilder<List<Double>>() - .config(retryConfig) - .afterFailedTryListener(s -> { - LOG.warn("{}, attempts: {}", s.getLastExceptionThatCausedRetry().getMessage(), s.getTotalTries()); - }) - .build(); - Status<List<Double>> status = callExecutor.execute(callable); - return status.getResult(); + return RetryUtils.withRetry(supplier, "metrics-fetcher-" + metricName, MetricDataNotFoundException.class).get(); } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java index 2b5b6e15b..fc2d061cc 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java @@ -14,25 +14,21 @@ package software.amazon.lambda.powertools.testutils.tracing; -import static java.time.Duration.ofSeconds; - -import com.evanlennick.retry4j.CallExecutor; -import com.evanlennick.retry4j.CallExecutorBuilder; -import com.evanlennick.retry4j.Status; -import com.evanlennick.retry4j.config.RetryConfig; -import com.evanlennick.retry4j.config.RetryConfigBuilder; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.concurrent.Callable; +import java.util.function.Supplier; import java.util.stream.Collectors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.regions.Region; @@ -43,6 +39,7 @@ import software.amazon.awssdk.services.xray.model.GetTraceSummariesResponse; import software.amazon.awssdk.services.xray.model.TimeRangeType; import software.amazon.awssdk.services.xray.model.TraceSummary; +import software.amazon.lambda.powertools.testutils.RetryUtils; import software.amazon.lambda.powertools.testutils.tracing.SegmentDocument.SubSegment; /** @@ -50,8 +47,8 @@ */ public class TraceFetcher { - private static final ObjectMapper MAPPER = - new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + private static final ObjectMapper MAPPER = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); private static final Logger LOG = LoggerFactory.getLogger(TraceFetcher.class); private static final SdkHttpClient httpClient = UrlConnectionHttpClient.builder().build(); private static final Region region = Region.of(System.getProperty("AWS_DEFAULT_REGION", "eu-west-1")); @@ -88,27 +85,12 @@ public static Builder builder() { * @return traces */ public Trace fetchTrace() { - Callable<Trace> callable = () -> - { + Supplier<Trace> supplier = () -> { List<String> traceIds = getTraceIds(); return getTrace(traceIds); }; - RetryConfig retryConfig = new RetryConfigBuilder() - .withMaxNumberOfTries(10) - .retryOnAnyException() - .withDelayBetweenTries(ofSeconds(5)) - .withRandomExponentialBackoff() - .build(); - CallExecutor<Trace> callExecutor = new CallExecutorBuilder<Trace>() - .config(retryConfig) - .afterFailedTryListener(s -> - { - LOG.warn(s.getLastExceptionThatCausedRetry().getMessage() + ", attempts: " + s.getTotalTries()); - }) - .build(); - Status<Trace> status = callExecutor.execute(callable); - return status.getResult(); + return RetryUtils.withRetry(supplier, "trace-fetcher", TraceNotFoundException.class).get(); } /** @@ -122,22 +104,19 @@ private Trace getTrace(List<String> traceIds) { .traceIds(traceIds) .build()); if (!tracesResponse.hasTraces()) { - throw new RuntimeException("No trace found"); + throw new TraceNotFoundException("No trace found"); } Trace traceRes = new Trace(); - tracesResponse.traces().forEach(trace -> - { + tracesResponse.traces().forEach(trace -> { if (trace.hasSegments()) { - trace.segments().forEach(segment -> - { + trace.segments().forEach(segment -> { try { SegmentDocument document = MAPPER.readValue(segment.document(), SegmentDocument.class); - if (document.getOrigin().equals("AWS::Lambda::Function")) { - if (document.hasSubsegments()) { - getNestedSubSegments(document.getSubsegments(), traceRes, - Collections.emptyList()); - } + if ("AWS::Lambda::Function".equals(document.getOrigin()) && document.hasSubsegments()) { + getNestedSubSegments(document.getSubsegments(), traceRes, + Collections.emptyList()); } + } catch (JsonProcessingException e) { LOG.error("Failed to parse segment document: " + e.getMessage()); throw new RuntimeException(e); @@ -149,8 +128,7 @@ private Trace getTrace(List<String> traceIds) { } private void getNestedSubSegments(List<SubSegment> subsegments, Trace traceRes, List<String> idsToIgnore) { - subsegments.forEach(subsegment -> - { + subsegments.forEach(subsegment -> { List<String> subSegmentIdsToIgnore = Collections.emptyList(); if (!excludedSegments.contains(subsegment.getName()) && !idsToIgnore.contains(subsegment.getId())) { traceRes.addSubSegment(subsegment); @@ -179,12 +157,12 @@ private List<String> getTraceIds() { .filterExpression(filterExpression) .build()); if (!traceSummaries.hasTraceSummaries()) { - throw new RuntimeException("No trace id found"); + throw new TraceNotFoundException("No trace id found"); } - List<String> traceIds = - traceSummaries.traceSummaries().stream().map(TraceSummary::id).collect(Collectors.toList()); + List<String> traceIds = traceSummaries.traceSummaries().stream().map(TraceSummary::id) + .collect(Collectors.toList()); if (traceIds.isEmpty()) { - throw new RuntimeException("No trace id found"); + throw new TraceNotFoundException("No trace id found"); } return traceIds; } @@ -193,7 +171,7 @@ public static class Builder { private Instant start; private Instant end; private String filterExpression; - private List<String> excludedSegments = Arrays.asList("Initialization", "Invocation", "Overhead"); + private List<String> excludedSegments = Arrays.asList("Initialization", "Init", "Invocation", "Overhead"); public TraceFetcher build() { if (filterExpression == null) { @@ -205,7 +183,8 @@ public TraceFetcher build() { if (end == null) { end = start.plus(1, ChronoUnit.MINUTES); } - LOG.debug("Looking for traces from {} to {} with filter {}", start, end, filterExpression); + LOG.debug("Looking for traces from {} to {} with filter {} and excluded segments {}", start, end, + filterExpression, excludedSegments); return new TraceFetcher(start, end, filterExpression, excludedSegments); } @@ -236,8 +215,8 @@ public Builder excludeSegments(List<String> excludedSegments) { } public Builder functionName(String functionName) { - this.filterExpression = - String.format("service(id(name: \"%s\", type: \"AWS::Lambda::Function\"))", functionName); + this.filterExpression = String.format("service(id(name: \"%s\", type: \"AWS::Lambda::Function\"))", + functionName); return this; } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceNotFoundException.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceNotFoundException.java new file mode 100644 index 000000000..453aae669 --- /dev/null +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceNotFoundException.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.testutils.tracing; + +import software.amazon.lambda.powertools.testutils.DataNotReadyException; + +/** + * Exception thrown when trace data is not found in X-Ray. + * This exception is used to trigger retries as traces may not be available immediately. + */ +public class TraceNotFoundException extends DataNotReadyException { + public TraceNotFoundException(String message) { + super(message); + } +} From 894ec0584a667e318e6b16cfc23361655af2367b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:48:13 +0200 Subject: [PATCH 332/577] chore: bump aws-actions/configure-aws-credentials from 4.2.1 to 4.3.1 (#2011) Bumps [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) from 4.2.1 to 4.3.1. - [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases) - [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/b47578312673ae6fa5b5096b330d9fbac3d116df...7474bc4690e29a8392af63c5b98e7449536d5c3a) --- updated-dependencies: - dependency-name: aws-actions/configure-aws-credentials dependency-version: 4.3.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 2 +- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/release.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index f9cbfe1ea..6de4dc4f7 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -41,7 +41,7 @@ jobs: docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df + uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 020b89b2a..2aef7a3f8 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -64,7 +64,7 @@ jobs: java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1 + uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -97,7 +97,7 @@ jobs: java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # v4.2.1 + uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a56301591..15a3cb23e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -278,7 +278,7 @@ jobs: docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df + uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} From e68637c02cc55a140d23d35cced575b3404d3943 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 11:48:52 +0200 Subject: [PATCH 333/577] chore: bump org.apache.maven.plugins:maven-surefire-plugin (#2013) Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.1.2 to 3.5.3. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.1.2...surefire-3.5.3) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-version: 3.5.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- pom.xml | 4 ++-- powertools-common/pom.xml | 2 +- powertools-logging/pom.xml | 4 ++-- powertools-logging/powertools-logging-log4j/pom.xml | 4 ++-- powertools-logging/powertools-logging-logback/pom.xml | 4 ++-- powertools-parameters/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-appconfig/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-dynamodb/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-secrets/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-ssm/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- 17 files changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index c80a9566d..98e3d60e4 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -126,7 +126,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.1.2</version> + <version>3.5.3</version> <configuration> <environmentVariables> <LAMBDA_TASK_ROOT>handler</LAMBDA_TASK_ROOT> diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 96f5002fe..d77cfa80b 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -135,7 +135,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.1.2</version> + <version>3.5.3</version> <configuration> <systemPropertyVariables> <sqlite4java.library.path>${project.build.directory}/native-libs</sqlite4java.library.path> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index fcdf1ffef..fdf7699d8 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -99,7 +99,7 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <!-- JUnit 5 requires Surefire version 3.1.0 or higher --> - <version>3.2.5</version> + <version>3.5.3</version> </plugin> <plugin> <groupId>dev.aspectj</groupId> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 129095534..e953e23a6 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -73,7 +73,7 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <!-- JUnit 5 requires Surefire version 3.1.0 or higher --> - <version>3.2.5</version> + <version>3.5.3</version> </plugin> <plugin> <groupId>dev.aspectj</groupId> diff --git a/pom.xml b/pom.xml index a1b714540..62213ab2f 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ <maven-gpg-plugin.version>3.2.1</maven-gpg-plugin.version> <junit.version>5.10.0</junit.version> <aspectj-maven-plugin.version>1.14</aspectj-maven-plugin.version> - <maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version> + <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version> <jacoco-maven-plugin.version>0.8.13</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version> <maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version> @@ -613,7 +613,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.1.2</version> + <version>3.5.3</version> <configuration> <argLine> @{argLine} diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index adc86547d..ace7cbe5a 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -103,7 +103,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index e6b9d6603..e926caf45 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -129,7 +129,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED @@ -214,7 +214,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.5</version> + <version>3.5.3</version> <configuration> <environmentVariables> <AWS_LAMBDA_LOG_FORMAT>JSON</AWS_LAMBDA_LOG_FORMAT> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 836ded5ed..02f34e7c2 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -108,7 +108,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED @@ -223,7 +223,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.1.2</version> + <version>3.5.3</version> <configuration> <environmentVariables> <POWERTOOLS_SERVICE_NAME>testLog4j</POWERTOOLS_SERVICE_NAME> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 1ad566809..f9b41a584 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -101,7 +101,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support</argLine> </configuration> @@ -216,7 +216,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.1.2</version> + <version>3.5.3</version> <configuration> <environmentVariables> <POWERTOOLS_SERVICE_NAME>testLogback</POWERTOOLS_SERVICE_NAME> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 1bc7efb52..c2ac064e7 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -80,7 +80,7 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.5</version> + <version>3.5.3</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> @@ -106,7 +106,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 06567c284..2498dbc41 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -95,7 +95,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED @@ -177,7 +177,7 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.1.2</version> + <version>3.5.3</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 39b1bf083..b2934e648 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -96,7 +96,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED @@ -178,7 +178,7 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.1.2</version> + <version>3.5.3</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 6d156e13c..dfb9edebe 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -96,7 +96,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED @@ -178,7 +178,7 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.1.2</version> + <version>3.5.3</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 3b7916e3e..bed3cd3d7 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -84,7 +84,7 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.1.2</version> + <version>3.5.3</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> @@ -110,7 +110,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index b83793200..fe629572b 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -106,7 +106,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 9905d0f82..e55d11601 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -106,7 +106,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization,experimental-class-define-support</argLine> </configuration> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 2fa82e708..d1ada1ed1 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -126,7 +126,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.2.3</version> + <version>3.5.3</version> <configuration> <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED From ee995f7f0af2f427c26b3eb9ceccc53384164682 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 7 Aug 2025 17:26:25 +0200 Subject: [PATCH 334/577] docs(examples): Add Bazel example for core utilities (#2022) * Add Bazel example. * Remove double _deploy suffix. * Use default .bazelrc setting and re-enable strict dependency checks. * Remove unused log method. --- .../sam-bazel/.bazelrc | 3 + .../sam-bazel/.gitignore | 20 ++++ .../sam-bazel/BUILD.bazel | 78 +++++++++++++ .../sam-bazel/MODULE.bazel | 27 +++++ .../sam-bazel/README.md | 63 ++++++++++ .../sam-bazel/events/event.json | 63 ++++++++++ .../src/main/java/helloworld/App.java | 108 ++++++++++++++++++ .../src/main/java/helloworld/AppStream.java | 58 ++++++++++ .../sam-bazel/src/main/resources/log4j2.xml | 16 +++ .../sam-bazel/template.yaml | 66 +++++++++++ 10 files changed, 502 insertions(+) create mode 100644 examples/powertools-examples-core-utilities/sam-bazel/.bazelrc create mode 100644 examples/powertools-examples-core-utilities/sam-bazel/.gitignore create mode 100644 examples/powertools-examples-core-utilities/sam-bazel/BUILD.bazel create mode 100644 examples/powertools-examples-core-utilities/sam-bazel/MODULE.bazel create mode 100644 examples/powertools-examples-core-utilities/sam-bazel/README.md create mode 100644 examples/powertools-examples-core-utilities/sam-bazel/events/event.json create mode 100644 examples/powertools-examples-core-utilities/sam-bazel/src/main/java/helloworld/App.java create mode 100644 examples/powertools-examples-core-utilities/sam-bazel/src/main/java/helloworld/AppStream.java create mode 100644 examples/powertools-examples-core-utilities/sam-bazel/src/main/resources/log4j2.xml create mode 100644 examples/powertools-examples-core-utilities/sam-bazel/template.yaml diff --git a/examples/powertools-examples-core-utilities/sam-bazel/.bazelrc b/examples/powertools-examples-core-utilities/sam-bazel/.bazelrc new file mode 100644 index 000000000..6cdf014a1 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-bazel/.bazelrc @@ -0,0 +1,3 @@ +# Java compilation settings +build --java_language_version=11 +build --java_runtime_version=11 diff --git a/examples/powertools-examples-core-utilities/sam-bazel/.gitignore b/examples/powertools-examples-core-utilities/sam-bazel/.gitignore new file mode 100644 index 000000000..4975e987e --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-bazel/.gitignore @@ -0,0 +1,20 @@ +# Bazel build outputs +bazel-* +MODULE.bazel.lock + +# SAM build outputs +.aws-sam/ + +# JAR files +*.jar + +# Maven lock file (generated) +maven_install.json + +# IDE files +.idea/ +.vscode/ +*.iml + +# OS files +.DS_Store diff --git a/examples/powertools-examples-core-utilities/sam-bazel/BUILD.bazel b/examples/powertools-examples-core-utilities/sam-bazel/BUILD.bazel new file mode 100644 index 000000000..97fa37394 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-bazel/BUILD.bazel @@ -0,0 +1,78 @@ +load("@rules_java//java:defs.bzl", "java_binary", "java_library") + +java_library( + name = "powertools_sam_lib_base", + srcs = glob(["src/main/java/**/*.java"]), + resources = glob(["src/main/resources/**"]), + deps = [ + "@maven//:software_amazon_lambda_powertools_tracing", + "@maven//:software_amazon_lambda_powertools_logging", + "@maven//:software_amazon_lambda_powertools_logging_log4j", + "@maven//:software_amazon_lambda_powertools_metrics", + "@maven//:com_amazonaws_aws_lambda_java_core", + "@maven//:com_amazonaws_aws_lambda_java_events", + "@maven//:org_aspectj_aspectjrt", + "@maven//:org_slf4j_slf4j_api", + "@maven//:com_fasterxml_jackson_core_jackson_databind", + "@maven//:org_apache_logging_log4j_log4j_api", + ], +) + +genrule( + name = "aspectj_weave", + srcs = [ + ":powertools_sam_lib_base", + "@maven//:software_amazon_lambda_powertools_tracing", + "@maven//:software_amazon_lambda_powertools_logging", + "@maven//:software_amazon_lambda_powertools_metrics", + "@maven//:com_amazonaws_aws_lambda_java_core", + "@maven//:com_amazonaws_aws_lambda_java_events", + "@maven//:org_aspectj_aspectjrt", + ], + outs = ["powertools_sam_lib_woven.jar"], + tools = [ + "@maven//:org_aspectj_aspectjweaver", + "@maven//:org_aspectj_aspectjtools", + ], + cmd = """ + # Get dependency JARs for classpath + ASPECTJ_TOOLS="$$(echo $(locations @maven//:org_aspectj_aspectjtools) $(locations @maven//:org_aspectj_aspectjweaver) | tr ' ' ':')" + ASPECTJ_RT="$(locations @maven//:org_aspectj_aspectjrt)" + LAMBDA_JARS="$$(echo $(locations @maven//:com_amazonaws_aws_lambda_java_core) $(locations @maven//:com_amazonaws_aws_lambda_java_events) | tr ' ' ':')" + ALL_DEPS="$$ASPECTJ_TOOLS:$$ASPECTJ_RT:$$LAMBDA_JARS" + + BASE_JAR=$$(echo $(locations :powertools_sam_lib_base) | cut -d' ' -f1) + POWERTOOLS_JARS="$$(echo $(locations @maven//:software_amazon_lambda_powertools_tracing) $(locations @maven//:software_amazon_lambda_powertools_logging) $(locations @maven//:software_amazon_lambda_powertools_metrics) | tr ' ' ':')" + + java -cp "$$ALL_DEPS" \ + org.aspectj.tools.ajc.Main \ + -inpath "$$BASE_JAR" \ + -aspectpath "$$POWERTOOLS_JARS" \ + -outjar $(location powertools_sam_lib_woven.jar) \ + -source 11 -target 11 -nowarn + """, +) + +java_import( + name = "powertools_sam_lib", + jars = [":powertools_sam_lib_woven.jar"], + deps = [ + "@maven//:software_amazon_lambda_powertools_tracing", + "@maven//:software_amazon_lambda_powertools_logging", + "@maven//:software_amazon_lambda_powertools_logging_log4j", + "@maven//:software_amazon_lambda_powertools_metrics", + "@maven//:com_amazonaws_aws_lambda_java_core", + "@maven//:com_amazonaws_aws_lambda_java_events", + "@maven//:org_aspectj_aspectjrt", + ], +) + +java_binary( + name = "powertools_sam", + main_class = "helloworld.App", + runtime_deps = [":powertools_sam_lib"], + deploy_manifest_lines = [ + "Main-Class: helloworld.App", + ], + create_executable = False, +) diff --git a/examples/powertools-examples-core-utilities/sam-bazel/MODULE.bazel b/examples/powertools-examples-core-utilities/sam-bazel/MODULE.bazel new file mode 100644 index 000000000..704b0cf1a --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-bazel/MODULE.bazel @@ -0,0 +1,27 @@ +module(name = "powertools_sam_bazel", version = "1.0.0") + +bazel_dep(name = "rules_java", version = "8.12.0") +bazel_dep(name = "rules_jvm_external", version = "6.3") + +maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven") + +maven.install( + artifacts = [ + "software.amazon.lambda:powertools-tracing:2.2.1", + "software.amazon.lambda:powertools-logging:2.2.1", + "software.amazon.lambda:powertools-logging-log4j:2.2.1", + "software.amazon.lambda:powertools-metrics:2.2.1", + "com.amazonaws:aws-lambda-java-core:1.3.0", + "com.amazonaws:aws-lambda-java-events:3.16.1", + "org.aspectj:aspectjrt:1.9.22", + "org.aspectj:aspectjweaver:1.9.22", + "org.aspectj:aspectjtools:1.9.22", + "org.slf4j:slf4j-api:2.0.16", + ], + repositories = [ + "https://repo1.maven.org/maven2", + ], + lock_file = "//:maven_install.json", +) + +use_repo(maven, "maven") diff --git a/examples/powertools-examples-core-utilities/sam-bazel/README.md b/examples/powertools-examples-core-utilities/sam-bazel/README.md new file mode 100644 index 000000000..a18af2dd5 --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-bazel/README.md @@ -0,0 +1,63 @@ +# Powertools for AWS Lambda (Java) - Core Utilities Example with Bazel + +This project demonstrates the Lambda for Powertools Java module deployed using [Serverless Application Model](https://aws.amazon.com/serverless/sam/) and built with Bazel. + +For general information on the deployed example itself, you can refer to the parent [README](../README.md) + +## Configuration + +SAM uses [template.yaml](template.yaml) to define the application's AWS resources. This file defines the Lambda function to be deployed as well as API Gateway for it. + +## Deploy the sample application + +To deploy the example, check out the instructions for getting started with SAM in [the examples directory](../../README.md) + +## Build and deploy + +```bash +# Build the application +bazel build //:powertools_sam_deploy.jar + +# Deploy the application +sam deploy --guided +``` + +## Local testing + +```bash +# Build the application +bazel build //:powertools_sam_deploy.jar + +# Test a single function locally +sam local invoke HelloWorldFunction --event events/event.json + +# Start the local API +sam local start-api + +# Test the API endpoints +curl http://127.0.0.1:3000/hello +curl http://127.0.0.1:3000/hellostream +``` + +## Additional notes + +You can watch the trace information or log information using the SAM CLI: + +```bash +# Tail the logs +sam logs --tail $MY_STACK + +# Tail the traces +sam traces --tail +``` + +### Pinning Maven versions + +To ensure reproducible builds, you can pin Maven dependency versions: + +```bash +# Generate lock file for reproducible builds +bazel run @maven//:pin +``` + +This creates `maven_install.json` which locks dependency versions and should be committed to version control. diff --git a/examples/powertools-examples-core-utilities/sam-bazel/events/event.json b/examples/powertools-examples-core-utilities/sam-bazel/events/event.json new file mode 100644 index 000000000..3822fadaa --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-bazel/events/event.json @@ -0,0 +1,63 @@ +{ + "body": "{\"message\": \"hello world\"}", + "resource": "/{proxy+}", + "path": "/path/to/resource", + "httpMethod": "POST", + "isBase64Encoded": false, + "queryStringParameters": { + "foo": "bar" + }, + "pathParameters": { + "proxy": "/path/to/resource" + }, + "stageVariables": { + "baz": "qux" + }, + "headers": { + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", + "Accept-Encoding": "gzip, deflate, sdch", + "Accept-Language": "en-US,en;q=0.8", + "Cache-Control": "max-age=0", + "CloudFront-Forwarded-Proto": "https", + "CloudFront-Is-Desktop-Viewer": "true", + "CloudFront-Is-Mobile-Viewer": "false", + "CloudFront-Is-SmartTV-Viewer": "false", + "CloudFront-Is-Tablet-Viewer": "false", + "CloudFront-Viewer-Country": "US", + "Host": "1234567890.execute-api.us-east-1.amazonaws.com", + "Upgrade-Insecure-Requests": "1", + "User-Agent": "Custom User Agent String", + "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", + "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", + "X-Forwarded-For": "127.0.0.1, 127.0.0.2", + "X-Forwarded-Port": "443", + "X-Forwarded-Proto": "https" + }, + "requestContext": { + "accountId": "123456789012", + "resourceId": "123456", + "stage": "prod", + "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", + "requestTime": "09/Apr/2015:12:34:56 +0000", + "requestTimeEpoch": 1428582896000, + "identity": { + "cognitoIdentityPoolId": null, + "accountId": null, + "cognitoIdentityId": null, + "caller": null, + "accessKey": null, + "sourceIp": "127.0.0.1", + "cognitoAuthenticationType": null, + "cognitoAuthenticationProvider": null, + "userArn": null, + "userAgent": "Custom User Agent String", + "user": null + }, + "path": "/prod/path/to/resource", + "resourcePath": "/{proxy+}", + "httpMethod": "POST", + "apiId": "1234567890", + "protocol": "HTTP/1.1" + } + } + \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-bazel/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam-bazel/src/main/java/helloworld/App.java new file mode 100644 index 000000000..2844e50fe --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-bazel/src/main/java/helloworld/App.java @@ -0,0 +1,108 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; +import static software.amazon.lambda.powertools.tracing.TracingUtils.putMetadata; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.FlushMetrics; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.MetricsFactory; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricResolution; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; +import software.amazon.lambda.powertools.tracing.CaptureMode; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.tracing.TracingUtils; + +/** + * Handler for requests to Lambda function. + */ +public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + private static final Logger log = LoggerFactory.getLogger(App.class); + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + + @Logging(logEvent = true, samplingRate = 0.7) + @Tracing(captureMode = CaptureMode.RESPONSE_AND_ERROR) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + Map<String, String> headers = new HashMap<>(); + + headers.put("Content-Type", "application/json"); + headers.put("X-Custom-Header", "application/json"); + + metrics.addMetric("CustomMetric1", 1, MetricUnit.COUNT); + + DimensionSet dimensionSet = new DimensionSet(); + dimensionSet.addDimension("AnotherService", "CustomService"); + dimensionSet.addDimension("AnotherService1", "CustomService1"); + metrics.flushSingleMetric("CustomMetric2", 1, MetricUnit.COUNT, "Another", dimensionSet); + + metrics.addMetric("CustomMetric3", 1, MetricUnit.COUNT, MetricResolution.HIGH); + + MDC.put("test", "willBeLogged"); + + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() + .withHeaders(headers); + try { + final String pageContents = this.getPageContents("https://checkip.amazonaws.com"); + log.info("", entry("ip", pageContents)); + TracingUtils.putAnnotation("Test", "New"); + String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); + + TracingUtils.withSubsegment("loggingResponse", subsegment -> { + String sampled = "log something out"; + log.info(sampled); + log.info(output); + }); + + log.info("After output"); + return response + .withStatusCode(200) + .withBody(output); + } catch (RuntimeException | IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + putMetadata("getPageContents", address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-core-utilities/sam-bazel/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/sam-bazel/src/main/java/helloworld/AppStream.java new file mode 100644 index 000000000..e04641ddc --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-bazel/src/main/java/helloworld/AppStream.java @@ -0,0 +1,58 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.metrics.FlushMetrics; + +import java.io.InputStreamReader; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; + +public class AppStream implements RequestStreamHandler { + private static final ObjectMapper mapper = new ObjectMapper(); + private final static Logger log = LogManager.getLogger(AppStream.class); + + @Override + @Logging(logEvent = true) + @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) + // RequestStreamHandler can be used instead of RequestHandler for cases when you'd like to deserialize request body or serialize response body yourself, instead of allowing that to happen automatically + // Note that you still need to return a proper JSON for API Gateway to handle + // See Lambda Response format for examples: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html + public void handleRequest(InputStream input, OutputStream output, Context context) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); + PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8)))) { + + log.info("Received: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(reader))); + + writer.write("{\"body\": \"" + System.currentTimeMillis() + "\"} "); + } catch (IOException e) { + log.error("Something has gone wrong: ", e); + } + } +} \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-bazel/src/main/resources/log4j2.xml b/examples/powertools-examples-core-utilities/sam-bazel/src/main/resources/log4j2.xml new file mode 100644 index 000000000..e1fd14cea --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-bazel/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + </Appenders> + <Loggers> + <Logger name="JsonLogger" level="INFO" additivity="false"> + <AppenderRef ref="JsonAppender"/> + </Logger> + <Root level="info"> + <AppenderRef ref="JsonAppender"/> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/examples/powertools-examples-core-utilities/sam-bazel/template.yaml b/examples/powertools-examples-core-utilities/sam-bazel/template.yaml new file mode 100644 index 000000000..1e489b8eb --- /dev/null +++ b/examples/powertools-examples-core-utilities/sam-bazel/template.yaml @@ -0,0 +1,66 @@ +AWSTemplateFormatVersion: "2010-09-09" +Transform: AWS::Serverless-2016-10-31 +Description: > + CoreUtilities + +# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst +Globals: + Function: + Timeout: 20 + Runtime: java11 + MemorySize: 512 + Tracing: Active # https://docs.aws.amazon.com/lambda/latest/dg/lambda-x-ray.html + Environment: + Variables: + # Powertools for AWS Lambda (Java) env vars: https://docs.powertools.aws.dev/lambda/java/#environment-variables + POWERTOOLS_LOG_LEVEL: INFO + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 + POWERTOOLS_LOGGER_LOG_EVENT: true + POWERTOOLS_METRICS_NAMESPACE: Coreutilities + +Resources: + HelloWorldFunction: + Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + Properties: + CodeUri: bazel-bin/powertools_sam_deploy.jar + Handler: helloworld.App::handleRequest + Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object + Variables: + POWERTOOLS_SERVICE_NAME: hello + Events: + HelloWorld: + Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api + Properties: + Path: /hello + Method: get + + HelloWorldStreamFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: bazel-bin/powertools_sam_deploy.jar + Handler: helloworld.AppStream::handleRequest + MemorySize: 512 + Tracing: Active + Environment: + Variables: + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.7 + Events: + HelloWorld: + Type: Api + Properties: + Path: /hellostream + Method: get + +Outputs: + # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function + # Find out more about other implicit resources you can reference within SAM + # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api + HelloWorldApi: + Description: "API Gateway endpoint URL for Prod stage for Hello World function" + Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/" + HelloWorldFunction: + Description: "Hello World Lambda Function ARN" + Value: !GetAtt HelloWorldFunction.Arn + HelloWorldFunctionIamRole: + Description: "Implicit IAM Role created for Hello World function" + Value: !GetAtt HelloWorldFunctionRole.Arn From 2b2e96f01a57718df32e2cde9ab0c8a6ac5208e2 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 7 Aug 2025 18:14:02 +0200 Subject: [PATCH 335/577] chore(ci): Improve reliability of retries in TracingE2ET (#2018) * Expand timewindow for X-RAY trace summary search during E2E tests. * Add retries for trace subsegments as well. * Add log.debug for subsegement population. * Add retries for custom subsegment population. * Add longer retries for TracingE2ET and capability to pass custom retry config to RetryUtils. * Add 1 minute padding around MetricsFetcher. * Revert 1 minute time padding for MetricsFetcher. * Add retry loop around datapoint fetching for first metrics datapoints. --- powertools-e2e-tests/pom.xml | 10 +++ .../amazon/lambda/powertools/MetricsE2ET.java | 14 ++-- .../powertools/testutils/RetryUtils.java | 32 ++++++++- .../testutils/tracing/TraceFetcher.java | 66 +++++++++++++++---- 4 files changed, 103 insertions(+), 19 deletions(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index ccd87e95e..d12395676 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -150,6 +150,16 @@ <version>2.4</version> <scope>test</scope> </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jsr310</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java index feb9537d5..35f8b5ba3 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/MetricsE2ET.java @@ -34,7 +34,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; +import software.amazon.lambda.powertools.testutils.DataNotReadyException; import software.amazon.lambda.powertools.testutils.Infrastructure; +import software.amazon.lambda.powertools.testutils.RetryUtils; import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; import software.amazon.lambda.powertools.testutils.metrics.MetricsFetcher; @@ -89,16 +91,20 @@ void test_recordMetrics() { { "FunctionName", functionName }, { "Service", SERVICE } }).collect(Collectors.toMap(data -> data[0], data -> data[1]))); assertThat(coldStart.get(0)).isEqualTo(1); - List<Double> orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), - 60, NAMESPACE, - "orders", Collections.singletonMap("Environment", "test")); + List<Double> orderMetrics = RetryUtils.withRetry(() -> { + List<Double> metrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), + 60, NAMESPACE, "orders", Collections.singletonMap("Environment", "test")); + if (metrics.get(0) != 2.0) { + throw new DataNotReadyException("Expected 2.0 orders but got " + metrics.get(0)); + } + return metrics; + }, "orderMetricsRetry", DataNotReadyException.class).get(); assertThat(orderMetrics.get(0)).isEqualTo(2); List<Double> productMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, NAMESPACE, "products", Collections.singletonMap("Environment", "test")); // When searching across a 1 minute time period with a period of 60 we find both metrics and the sum is 12 - assertThat(productMetrics.get(0)).isEqualTo(12); orderMetrics = metricsFetcher.fetchMetrics(invocationResult.getStart(), invocationResult.getEnd(), 60, diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/RetryUtils.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/RetryUtils.java index 054e9aa8e..ce64f04ea 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/RetryUtils.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/RetryUtils.java @@ -47,7 +47,21 @@ private RetryUtils() { */ @SafeVarargs public static Retry createRetry(String name, Class<? extends Throwable>... retryOnThrowables) { - RetryConfig config = RetryConfig.from(DEFAULT_RETRY_CONFIG) + return createRetry(name, DEFAULT_RETRY_CONFIG, retryOnThrowables); + } + + /** + * Creates a retry instance with custom configuration for the specified throwable types. + * + * @param name the name for the retry instance + * @param customConfig the custom retry configuration + * @param retryOnThrowables the throwable classes to retry on + * @return configured Retry instance + */ + @SafeVarargs + public static Retry createRetry(String name, RetryConfig customConfig, + Class<? extends Throwable>... retryOnThrowables) { + RetryConfig config = RetryConfig.from(customConfig) .retryExceptions(retryOnThrowables) .build(); @@ -72,4 +86,20 @@ public static <T> Supplier<T> withRetry(Supplier<T> supplier, String name, Retry retry = createRetry(name, retryOnThrowables); return Retry.decorateSupplier(retry, supplier); } + + /** + * Decorates a supplier with custom retry logic for the specified throwable types. + * + * @param supplier the supplier to decorate + * @param name the name for the retry instance + * @param customConfig the custom retry configuration + * @param retryOnThrowables the throwable classes to retry on + * @return decorated supplier with retry logic + */ + @SafeVarargs + public static <T> Supplier<T> withRetry(Supplier<T> supplier, String name, RetryConfig customConfig, + Class<? extends Throwable>... retryOnThrowables) { + Retry retry = createRetry(name, customConfig, retryOnThrowables); + return Retry.decorateSupplier(retry, supplier); + } } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java index fc2d061cc..0aed9e811 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/tracing/TraceFetcher.java @@ -14,6 +14,7 @@ package software.amazon.lambda.powertools.testutils.tracing; +import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Arrays; @@ -27,8 +28,11 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.json.JsonMapper; +import io.github.resilience4j.retry.RetryConfig; import software.amazon.awssdk.http.SdkHttpClient; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; import software.amazon.awssdk.regions.Region; @@ -46,9 +50,10 @@ * Class in charge of retrieving the actual traces of a Lambda execution on X-Ray */ public class TraceFetcher { - - private static final ObjectMapper MAPPER = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + private static final ObjectMapper MAPPER = JsonMapper.builder() + .disable(MapperFeature.REQUIRE_HANDLERS_FOR_JAVA8_TIMES) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .build(); private static final Logger LOG = LoggerFactory.getLogger(TraceFetcher.class); private static final SdkHttpClient httpClient = UrlConnectionHttpClient.builder().build(); private static final Region region = Region.of(System.getProperty("AWS_DEFAULT_REGION", "eu-west-1")); @@ -90,7 +95,12 @@ public Trace fetchTrace() { return getTrace(traceIds); }; - return RetryUtils.withRetry(supplier, "trace-fetcher", TraceNotFoundException.class).get(); + RetryConfig customConfig = RetryConfig.custom() + .maxAttempts(120) // 120 attempts over 10 minutes + .waitDuration(Duration.ofSeconds(5)) // 5 seconds between attempts + .build(); + + return RetryUtils.withRetry(supplier, "trace-fetcher", customConfig, TraceNotFoundException.class).get(); } /** @@ -104,8 +114,9 @@ private Trace getTrace(List<String> traceIds) { .traceIds(traceIds) .build()); if (!tracesResponse.hasTraces()) { - throw new TraceNotFoundException("No trace found"); + throw new TraceNotFoundException(String.format("No trace found for traceIds %s", traceIds)); } + Trace traceRes = new Trace(); tracesResponse.traces().forEach(trace -> { if (trace.hasSegments()) { @@ -113,17 +124,31 @@ private Trace getTrace(List<String> traceIds) { try { SegmentDocument document = MAPPER.readValue(segment.document(), SegmentDocument.class); if ("AWS::Lambda::Function".equals(document.getOrigin()) && document.hasSubsegments()) { - getNestedSubSegments(document.getSubsegments(), traceRes, - Collections.emptyList()); + LOG.debug("Populating subsegments for document {}", MAPPER.writeValueAsString(document)); + getNestedSubSegments(document.getSubsegments(), traceRes, Collections.emptyList()); + // If only the default (excluded) subsegments were populated we need to keep retrying for + // our custom subsegments. They might appear later. + if (traceRes.getSubsegments().isEmpty()) { + throw new TraceNotFoundException( + "Found AWS::Lambda::Function SegmentDocument with no non-excluded subsegments."); + } + } else if ("AWS::Lambda::Function".equals(document.getOrigin())) { + LOG.debug( + "Found AWS::Lambda::Function SegmentDocument with no subsegments. Retrying {}", + MAPPER.writeValueAsString(document)); + throw new TraceNotFoundException( + "Found AWS::Lambda::Function SegmentDocument with no subsegments."); } - } catch (JsonProcessingException e) { LOG.error("Failed to parse segment document: " + e.getMessage()); throw new RuntimeException(e); } }); + } else { + throw new TraceNotFoundException(String.format("No segments found in trace %s", trace.id())); } }); + return traceRes; } @@ -149,21 +174,30 @@ private void getNestedSubSegments(List<SubSegment> subsegments, Trace traceRes, * @return a list of trace ids */ private List<String> getTraceIds() { + LOG.debug("Searching for traces from {} to {} with filter: {}", start, end, filterExpression); GetTraceSummariesResponse traceSummaries = xray.getTraceSummaries(GetTraceSummariesRequest.builder() .startTime(start) .endTime(end) - .timeRangeType(TimeRangeType.EVENT) + .timeRangeType(TimeRangeType.TRACE_ID) .sampling(false) .filterExpression(filterExpression) .build()); + + LOG.debug("Found {} trace summaries", + traceSummaries.hasTraceSummaries() ? traceSummaries.traceSummaries().size() : 0); + if (!traceSummaries.hasTraceSummaries()) { - throw new TraceNotFoundException("No trace id found"); + throw new TraceNotFoundException(String.format("No trace id found for filter '%s' between %s and %s", + filterExpression, start, end)); } List<String> traceIds = traceSummaries.traceSummaries().stream().map(TraceSummary::id) .collect(Collectors.toList()); if (traceIds.isEmpty()) { - throw new TraceNotFoundException("No trace id found"); + throw new TraceNotFoundException( + String.format("Empty trace summary found for filter '%s' between %s and %s", + filterExpression, start, end)); } + LOG.debug("Found trace IDs: {}", traceIds); return traceIds; } @@ -183,9 +217,13 @@ public TraceFetcher build() { if (end == null) { end = start.plus(1, ChronoUnit.MINUTES); } - LOG.debug("Looking for traces from {} to {} with filter {} and excluded segments {}", start, end, - filterExpression, excludedSegments); - return new TraceFetcher(start, end, filterExpression, excludedSegments); + // Expand search window by 1 minute on each side to account for timing imprecisions + Instant expandedStart = start.minus(1, ChronoUnit.MINUTES); + Instant expandedEnd = end.plus(1, ChronoUnit.MINUTES); + LOG.debug( + "Looking for traces from {} to {} (expanded from {} to {}) with filter {} and excluded segments {}", + expandedStart, expandedEnd, start, end, filterExpression, excludedSegments); + return new TraceFetcher(expandedStart, expandedEnd, filterExpression, excludedSegments); } public Builder start(Instant start) { From 68cad233ff932aff562b27b3368fead7c8becb53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 11:02:08 +0200 Subject: [PATCH 336/577] build(deps): bump aws.xray.recorder.version from 2.18.2 to 2.18.3 (#1986) * build(deps): bump aws.xray.recorder.version from 2.18.2 to 2.18.3 Bumps `aws.xray.recorder.version` from 2.18.2 to 2.18.3. Updates `com.amazonaws:aws-xray-recorder-sdk-core` from 2.18.2 to 2.18.3 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.18.2...v2.18.3) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core` from 2.18.2 to 2.18.3 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.18.2...v2.18.3) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2` from 2.18.2 to 2.18.3 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.18.2...v2.18.3) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor` from 2.18.2 to 2.18.3 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.18.2...v2.18.3) --- updated-dependencies: - dependency-name: com.amazonaws:aws-xray-recorder-sdk-core dependency-version: 2.18.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core dependency-version: 2.18.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2 dependency-version: 2.18.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor dependency-version: 2.18.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> * Add missing dependencies after removal of AWS SDK v1. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> Co-authored-by: Philipp Page <pagejep@amazon.com> --- pom.xml | 7 ++++++- powertools-tracing/pom.xml | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 62213ab2f..434427aaa 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> <aws.sdk.version>2.32.10</aws.sdk.version> - <aws.xray.recorder.version>2.18.2</aws.xray.recorder.version> + <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <lambda.core.version>1.3.0</lambda.core.version> @@ -225,6 +225,11 @@ <artifactId>jackson-core</artifactId> <version>${jackson.version}</version> </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <version>${jackson.version}</version> + </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index d1ada1ed1..deaca4cf4 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -66,6 +66,14 @@ <groupId>com.amazonaws</groupId> <artifactId>aws-xray-recorder-sdk-aws-sdk-v2-instrumentor</artifactId> </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + </dependency> <!-- Test dependencies --> <dependency> From 56cc000d61a1d786540040c3b94bb4eeaa9687d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 11:09:22 +0200 Subject: [PATCH 337/577] chore: bump actions/download-artifact from 4.3.0 to 5.0.0 (#2017) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4.3.0 to 5.0.0. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/d3f86a106a0bac45b974a628896c90dbdf5c8093...634f93cb2916e3fdff6788551b99b062d0335ce0) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 15a3cb23e..eb8f422e9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -133,7 +133,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.6.1 + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4.6.1 with: name: source - name: Setup Java @@ -168,7 +168,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.6.1 + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4.6.1 with: name: source - name: Setup Java @@ -191,7 +191,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.6.1 + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4.6.1 with: name: source - name: Setup Java @@ -229,7 +229,7 @@ jobs: ref: ${{ env.RELEASE_COMMIT }} - id: download_source name: Download artifacts - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.6.1 + uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4.6.1 with: name: source - id: setup-git From b1f06d74fee5890d41a6c57553c92c2fd51b5a90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 11:10:00 +0200 Subject: [PATCH 338/577] chore: bump io.github.ascopes:protobuf-maven-plugin from 3.6.1 to 3.7.0 (#2016) Bumps [io.github.ascopes:protobuf-maven-plugin](https://github.com/ascopes/protobuf-maven-plugin) from 3.6.1 to 3.7.0. - [Release notes](https://github.com/ascopes/protobuf-maven-plugin/releases) - [Commits](https://github.com/ascopes/protobuf-maven-plugin/compare/v3.6.1...v3.7.0) --- updated-dependencies: - dependency-name: io.github.ascopes:protobuf-maven-plugin dependency-version: 3.7.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 7c87a964b..5fa7cd384 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -141,7 +141,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.6.1</version> + <version>3.7.0</version> <executions> <execution> <goals> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 0e1a85b6d..9c8557fe1 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -181,7 +181,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.6.1</version> + <version>3.7.0</version> <executions> <execution> <id>generate-test-sources</id> From ca5f3abfe936712d7f62a8e12aeae75072f6a5ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 11:10:38 +0200 Subject: [PATCH 339/577] chore: bump aws.sdk.version from 2.32.10 to 2.32.16 (#2014) Bumps `aws.sdk.version` from 2.32.10 to 2.32.16. Updates `software.amazon.awssdk:bom` from 2.32.10 to 2.32.16 Updates `software.amazon.awssdk:http-client-spi` from 2.32.10 to 2.32.16 Updates `software.amazon.awssdk:url-connection-client` from 2.32.6 to 2.32.16 Updates `software.amazon.awssdk:dynamodb` from 2.32.10 to 2.32.16 Updates `software.amazon.awssdk:s3` from 2.32.6 to 2.32.16 Updates `software.amazon.awssdk:lambda` from 2.32.10 to 2.32.16 Updates `software.amazon.awssdk:kinesis` from 2.32.6 to 2.32.16 Updates `software.amazon.awssdk:cloudwatch` from 2.32.10 to 2.32.16 Updates `software.amazon.awssdk:xray` from 2.32.10 to 2.32.16 Updates `software.amazon.awssdk:sqs` from 2.32.6 to 2.32.16 Updates `software.amazon.awssdk:cloudformation` from 2.32.10 to 2.32.16 Updates `software.amazon.awssdk:sts` from 2.32.10 to 2.32.16 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.16 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.16 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.16 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.16 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.16 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.16 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.16 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.16 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.16 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.16 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.16 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.16 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 619ccfcba..b957fb8bc 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.10</aws.sdk.version> + <aws.sdk.version>2.32.18</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 434427aaa..7f6d6c658 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.32.10</aws.sdk.version> + <aws.sdk.version>2.32.18</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> From 81ca77a64628d285091aad7d6f850745004aa68a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 11:10:43 +0200 Subject: [PATCH 340/577] chore: bump org.codehaus.mojo:exec-maven-plugin from 3.3.0 to 3.5.1 (#2015) Bumps [org.codehaus.mojo:exec-maven-plugin](https://github.com/mojohaus/exec-maven-plugin) from 3.3.0 to 3.5.1. - [Release notes](https://github.com/mojohaus/exec-maven-plugin/releases) - [Commits](https://github.com/mojohaus/exec-maven-plugin/compare/3.3.0...3.5.1) --- updated-dependencies: - dependency-name: org.codehaus.mojo:exec-maven-plugin dependency-version: 3.5.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 317277af9..576397dbb 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -25,7 +25,7 @@ <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> - <version>3.3.0</version> + <version>3.5.1</version> <configuration> <mainClass>cdk.CdkApp</mainClass> </configuration> From ccb7a6ec9acd1493200b69dc780520371ae9e052 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 14:32:35 +0200 Subject: [PATCH 341/577] chore: bump org.junit.jupiter:junit-jupiter from 5.11.1 to 5.13.4 (#2023) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework) from 5.11.1 to 5.13.4. - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](https://github.com/junit-team/junit-framework/compare/r5.11.1...r5.13.4) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.13.4 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 576397dbb..00affa9f4 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -9,7 +9,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.208.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> - <junit.version>5.11.1</junit.version> + <junit.version>5.13.4</junit.version> </properties> <build> <plugins> From ee79c204acc674fe26df4ce0cb062be5f38361f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 14:32:58 +0200 Subject: [PATCH 342/577] chore: bump aws.sdk.version from 2.32.6 to 2.32.18 (#2024) Bumps `aws.sdk.version` from 2.32.6 to 2.32.18. Updates `software.amazon.awssdk:url-connection-client` from 2.32.6 to 2.32.18 Updates `software.amazon.awssdk:sdk-core` from 2.32.6 to 2.32.18 Updates `software.amazon.awssdk:s3` from 2.32.6 to 2.32.18 Updates `software.amazon.awssdk:kinesis` from 2.32.6 to 2.32.18 Updates `software.amazon.awssdk:sqs` from 2.32.6 to 2.32.18 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.32.6 to 2.32.18 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.18 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.32.18 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.18 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.18 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.18 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.32.18 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 0d288f8ba..f4425d09e 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.32.6</sdk.version> + <sdk.version>2.32.18</sdk.version> </properties> <dependencies> From ca75f24cdadf3a06858bd3d0ebf8c74bd5fca905 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 14:33:26 +0200 Subject: [PATCH 343/577] chore: bump org.crac:crac from 1.4.0 to 1.5.0 (#2025) Bumps [org.crac:crac](https://github.com/crac/org.crac) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/crac/org.crac/releases) - [Commits](https://github.com/crac/org.crac/compare/1.4.0...1.5.0) --- updated-dependencies: - dependency-name: org.crac:crac dependency-version: 1.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7f6d6c658..94741fd81 100644 --- a/pom.xml +++ b/pom.xml @@ -117,7 +117,7 @@ <mockito.version>5.18.0</mockito.version> <mockito-junit-jupiter.version>5.18.0</mockito-junit-jupiter.version> <junit-pioneer.version>2.3.0</junit-pioneer.version> - <crac.version>1.4.0</crac.version> + <crac.version>1.5.0</crac.version> <!-- As we have a .mvn directory at the root of the project, this will evaluate to the root directory regardless of where maven is run - sub-module, or root. --> From bed5106ab6c4264239e44b8f561e657f9a9aa717 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 14:34:46 +0200 Subject: [PATCH 344/577] chore: bump github/codeql-action from 3.29.7 to 3.29.8 (#2027) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.7 to 3.29.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/51f77329afa6477de8c49fc9c7046c15b9a4e79d...76621b61decf072c1cee8dd1ce2d2a82d33c17ed) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 6367d2452..023ff41fd 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5 + uses: github/codeql-action/upload-sarif@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # v3.29.5 with: sarif_file: results.sarif From 58e09cbf812dd25e177e6c4cb5964dea763f8e8f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 10 Aug 2025 13:30:17 +0100 Subject: [PATCH 345/577] chore: bump com.amazonaws:aws-lambda-java-runtime-interface-client (#2026) Bumps [com.amazonaws:aws-lambda-java-runtime-interface-client](https://github.com/aws/aws-lambda-java-libs) from 2.8.2 to 2.8.3. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-runtime-interface-client dependency-version: 2.8.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index d0fb3b8ea..55a23440f 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -49,7 +49,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.2</version> + <version>2.8.3</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index fdf7699d8..aef7f1f97 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -49,7 +49,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.2</version> + <version>2.8.3</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index a67433a08..145275915 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -36,7 +36,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.2</version> + <version>2.8.3</version> </dependency> </dependencies> From 6c84fb7d0c49debe55beb6cb0620f1e0e8b608ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 16:57:06 +0200 Subject: [PATCH 346/577] chore: bump com.github.spotbugs:spotbugs-maven-plugin from 4.8.4.0 to 4.9.3.2 (#2010) * chore: bump com.github.spotbugs:spotbugs-maven-plugin Bumps [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) from 4.8.4.0 to 4.9.3.2. - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.8.4.0...spotbugs-maven-plugin-4.9.3.2) --- updated-dependencies: - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-version: 4.9.3.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Make raiseOnEmptyMetrics an AtomicBoolean. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> Co-authored-by: Philipp Page <pagejep@amazon.com> --- pom.xml | 2 +- .../powertools/metrics/internal/EmfMetricsLogger.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 94741fd81..e35e13d52 100644 --- a/pom.xml +++ b/pom.xml @@ -591,7 +591,7 @@ <plugin> <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> - <version>4.8.4.0</version> + <version>4.9.3.2</version> <executions> <execution> <id>test</id> diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java index 1eedd270d..2f6f9e689 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java @@ -50,7 +50,7 @@ public class EmfMetricsLogger implements Metrics { private final software.amazon.cloudwatchlogs.emf.logger.MetricsLogger emfLogger; private final EnvironmentProvider environmentProvider; - private boolean raiseOnEmptyMetrics = false; + private AtomicBoolean raiseOnEmptyMetrics = new AtomicBoolean(false); private String namespace; private Map<String, String> defaultDimensions = new HashMap<>(); private final AtomicBoolean hasMetrics = new AtomicBoolean(false); @@ -133,7 +133,7 @@ public void setNamespace(String namespace) { @Override public void setRaiseOnEmptyMetrics(boolean raiseOnEmptyMetrics) { - this.raiseOnEmptyMetrics = raiseOnEmptyMetrics; + this.raiseOnEmptyMetrics.set(raiseOnEmptyMetrics); } @Override @@ -159,7 +159,7 @@ public void flush() { Validator.validateNamespace(namespace); if (!hasMetrics.get()) { - if (raiseOnEmptyMetrics) { + if (raiseOnEmptyMetrics.get()) { throw new IllegalStateException("No metrics were emitted"); } else { LOGGER.warn("No metrics were emitted"); From 174a19fd9ca256ec983f90bfabceddbfbba6330c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:47:22 +0200 Subject: [PATCH 347/577] chore: bump co.elastic.logging:logback-ecs-encoder from 1.6.0 to 1.7.0 (#2028) Bumps [co.elastic.logging:logback-ecs-encoder](https://github.com/elastic/ecs-logging-java) from 1.6.0 to 1.7.0. - [Release notes](https://github.com/elastic/ecs-logging-java/releases) - [Commits](https://github.com/elastic/ecs-logging-java/compare/v1.6.0...v1.7.0) --- updated-dependencies: - dependency-name: co.elastic.logging:logback-ecs-encoder dependency-version: 1.7.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e35e13d52..49d6c111c 100644 --- a/pom.xml +++ b/pom.xml @@ -113,7 +113,7 @@ <jmespath.version>0.6.0</jmespath.version> <aws.sdk.v1.version>1.12.781</aws.sdk.v1.version> <versions-maven-plugin.version>2.18.0</versions-maven-plugin.version> - <elastic.version>1.6.0</elastic.version> + <elastic.version>1.7.0</elastic.version> <mockito.version>5.18.0</mockito.version> <mockito-junit-jupiter.version>5.18.0</mockito-junit-jupiter.version> <junit-pioneer.version>2.3.0</junit-pioneer.version> From 877042bf7fc0053cc21facbb4924b52289c4af69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:47:39 +0200 Subject: [PATCH 348/577] chore: bump aws.sdk.version from 2.32.18 to 2.32.19 (#2029) Bumps `aws.sdk.version` from 2.32.18 to 2.32.19. Updates `software.amazon.awssdk:url-connection-client` from 2.32.18 to 2.32.19 Updates `software.amazon.awssdk:sdk-core` from 2.32.18 to 2.32.19 Updates `software.amazon.awssdk:s3` from 2.32.18 to 2.32.19 Updates `software.amazon.awssdk:kinesis` from 2.32.18 to 2.32.19 Updates `software.amazon.awssdk:sqs` from 2.32.18 to 2.32.19 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.32.18 to 2.32.19 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.19 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.32.19 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.19 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.19 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.19 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.32.19 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index f4425d09e..3b8f8b509 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.32.18</sdk.version> + <sdk.version>2.32.19</sdk.version> </properties> <dependencies> From ab66f95f65ad19375012de23c655aec20bfafd7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:47:55 +0200 Subject: [PATCH 349/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.208.0 to 2.210.0 (#2030) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.208.0 to 2.210.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.208.0...v2.210.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.210.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 00affa9f4..45826e3c8 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.2.1</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.208.0</cdk.version> + <cdk.version>2.210.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.13.4</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index d12395676..73ac6c638 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.2</constructs.version> - <cdk.version>2.208.0</cdk.version> + <cdk.version>2.210.0</cdk.version> </properties> <dependencies> From 74d3e66481a9d0c0bfae1dc5278e81a5c9ab1788 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:48:10 +0200 Subject: [PATCH 350/577] chore: bump org.assertj:assertj-core from 3.27.3 to 3.27.4 (#2031) Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.27.3 to 3.27.4. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.27.3...assertj-build-3.27.4) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-version: 3.27.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 49d6c111c..957703825 100644 --- a/pom.xml +++ b/pom.xml @@ -334,7 +334,7 @@ <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> - <version>3.27.3</version> + <version>3.27.4</version> <scope>test</scope> <exclusions> <exclusion> From f21054eae93252fd22e52c0c7402291e2768427a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 13:51:32 +0200 Subject: [PATCH 351/577] chore(ci): bump version to 2.3.0 (#2034) Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/README.md | 4 ++-- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- .../powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 44 files changed, 51 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index d5f240b6e..c7d3c6b71 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-metrics</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> </dependency> ... </dependencies> diff --git a/examples/pom.xml b/examples/pom.xml index bbf2f991e..f1cb326ce 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-examples</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Examples</name> diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 3b8f8b509..3e9840e7e 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-batch</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Batch</name> diff --git a/examples/powertools-examples-cloudformation/README.md b/examples/powertools-examples-cloudformation/README.md index 98302aab9..b2951b28b 100644 --- a/examples/powertools-examples-cloudformation/README.md +++ b/examples/powertools-examples-cloudformation/README.md @@ -15,7 +15,7 @@ Run the following in your shell: ```bash cd infra/sam sam build -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.2.1718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.3.0718 ``` ### Deploy with CDK @@ -32,5 +32,5 @@ To build and deploy this application for the first time, run the following in yo cd infra/cdk mvn package cdk synth -cdk deploy -c BucketNameParam=my-unique-bucket-2.2.1718 +cdk deploy -c BucketNameParam=my-unique-bucket-2.3.0718 ``` \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index b957fb8bc..c74a9e9ad 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-cloudformation</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 67705c89e..4801dc591 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ <groupId>software.amazon.lambda.examples</groupId> <!-- TODO TODO TODO this should build from SNAPSHOT, but it doesn't, because the snapshots don't appear in the docker environment CDK builds it in in our CDK tests. How to procede? V2 blocker --> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-core-utilities-cdk</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 45826e3c8..e2caf8b68 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <artifactId>cdk</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.210.0</cdk.version> diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 124c7b60b..8770d5b31 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.2.1' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.2.1' - aspect 'software.amazon.lambda:powertools-metrics:2.2.1' + aspect 'software.amazon.lambda:powertools-tracing:2.3.0' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.3.0' + aspect 'software.amazon.lambda:powertools-metrics:2.3.0' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 25ff24fac..ca0604517 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.2.1") - aspect("software.amazon.lambda:powertools-logging-log4j:2.2.1") - aspect("software.amazon.lambda:powertools-metrics:2.2.1") + aspect("software.amazon.lambda:powertools-tracing:2.3.0") + aspect("software.amazon.lambda:powertools-logging-log4j:2.3.0") + aspect("software.amazon.lambda:powertools-metrics:2.3.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 55a23440f..3e2477719 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-core-utilities-sam-graalvm</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 0208798fc..578897e86 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-core-utilities-sam</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index a715553fb..2d795831c 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-core-utilities-serverless</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 98e3d60e4..a69f4a140 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-core-utilities-terraform</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index d77cfa80b..43e34a48d 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -17,7 +17,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-idempotency</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency</name> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 5fa7cd384..ca208aff2 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-kafka</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Kafka</name> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index aef7f1f97..1641817aa 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-parameters-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index e953e23a6..44641102f 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-parameters-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters</name> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index 145275915..3f6dc295f 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-serialization-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 78bb6caad..3d9d4159e 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-serialization-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization</name> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 1227acc42..3ab151aec 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <artifactId>powertools-examples-validation</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Validation</name> diff --git a/mkdocs.yml b/mkdocs.yml index e258d8c5a..45ea8e64b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -121,7 +121,7 @@ extra_javascript: extra: powertools: - version: 2.2.1 + version: 2.3.0 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index 957703825..69686d508 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Parent</name> diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 74eae5726..bbdc5b0c2 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <description>A suite of utilities that makes batch message processing using AWS Lambda easier.</description> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index b4d247178..355e8a3ed 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Cloudformation</name> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index ace7cbe5a..9f8456842 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Common Internal Utilities</name> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 73ac6c638..fb88cd60f 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <artifactId>powertools-e2e-tests</artifactId> diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 08eefc473..e20d90565 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <artifactId>powertools-idempotency</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 0f2c2dec1..6f15bfc3d 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <artifactId>powertools-idempotency-core</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index d63719bbe..ed5b8d5c0 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <artifactId>powertools-idempotency-dynamodb</artifactId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 9c8557fe1..cd696d103 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <artifactId>powertools-kafka</artifactId> diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index c9bfb2476..d61dacf48 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <artifactId>powertools-large-messages</artifactId> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index e926caf45..7757be572 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Logging</name> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 02f34e7c2..b28f307a6 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index f9b41a584..e44d97377 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 7e59bdbf9..57da447dd 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Metrics</name> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index c2ac064e7..d43221b5e 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <artifactId>powertools-parameters</artifactId> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 2498dbc41..4d650c58b 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index b2934e648..1834b229d 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index dfb9edebe..ef032f0c3 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index bed3cd3d7..fcb7b5311 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index fe629572b..ea29ffea2 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.2.1</version> + <version>2.3.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index e55d11601..d6cc33891 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <artifactId>powertools-serialization</artifactId> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index deaca4cf4..cb7f8218f 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Tracing</name> diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index b845bdb20..30e56802f 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.2.1</version> + <version>2.3.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Validation</name> From 777e12853a8f83eb3a55349903c306eb2e25359e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 10:16:40 +0200 Subject: [PATCH 352/577] chore: bump dev.aspectj:aspectj-maven-plugin from 1.14 to 1.14.1 (#2037) Bumps [dev.aspectj:aspectj-maven-plugin](https://github.com/dev-aspectj/aspectj-maven-plugin) from 1.14 to 1.14.1. - [Release notes](https://github.com/dev-aspectj/aspectj-maven-plugin/releases) - [Commits](https://github.com/dev-aspectj/aspectj-maven-plugin/compare/aspectj-maven-plugin-1.14...aspectj-maven-plugin-1.14.1) --- updated-dependencies: - dependency-name: dev.aspectj:aspectj-maven-plugin dependency-version: 1.14.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- examples/powertools-examples-core-utilities/serverless/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 3e9840e7e..99f979cf6 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -86,7 +86,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index c74a9e9ad..b845b89ed 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -87,7 +87,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 4801dc591..6e344ff87 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -66,7 +66,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 578897e86..dc53d834d 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -52,7 +52,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 2d795831c..28b68a930 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -53,7 +53,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index a69f4a140..925c1a69f 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -53,7 +53,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 43e34a48d..39f639aae 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -79,7 +79,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index ca208aff2..390f999a7 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -91,7 +91,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 1641817aa..24ccd3642 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -104,7 +104,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 44641102f..a67895bd5 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -78,7 +78,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 3d9d4159e..7598f9930 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -49,7 +49,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 3ab151aec..90d89546e 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -75,7 +75,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/pom.xml b/pom.xml index 69686d508..9ccf1065c 100644 --- a/pom.xml +++ b/pom.xml @@ -101,7 +101,7 @@ <maven-source-plugin.version>3.3.1</maven-source-plugin.version> <maven-gpg-plugin.version>3.2.1</maven-gpg-plugin.version> <junit.version>5.10.0</junit.version> - <aspectj-maven-plugin.version>1.14</aspectj-maven-plugin.version> + <aspectj-maven-plugin.version>1.14.1</aspectj-maven-plugin.version> <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version> <jacoco-maven-plugin.version>0.8.13</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index b28f307a6..88e1ced39 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -193,7 +193,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index e44d97377..41750ec70 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -186,7 +186,7 @@ <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14</version> + <version>1.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> From 7520ec2e8058f6814a995bad9bfd418fcef0ab98 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 10:17:09 +0200 Subject: [PATCH 353/577] chore: bump github/codeql-action from 3.29.8 to 3.29.9 (#2038) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.8 to 3.29.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/76621b61decf072c1cee8dd1ce2d2a82d33c17ed...df559355d593797519d70b90fc8edd5db049e7a2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 023ff41fd..c482a0c3e 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # v3.29.5 + uses: github/codeql-action/upload-sarif@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.5 with: sarif_file: results.sarif From b90ce6caf93d589e5f2845c3a712775fb1868d6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 10:18:28 +0200 Subject: [PATCH 354/577] chore: bump org.apache.maven.plugins:maven-deploy-plugin (#2040) Bumps [org.apache.maven.plugins:maven-deploy-plugin](https://github.com/apache/maven-deploy-plugin) from 3.1.2 to 3.1.4. - [Release notes](https://github.com/apache/maven-deploy-plugin/releases) - [Commits](https://github.com/apache/maven-deploy-plugin/compare/maven-deploy-plugin-3.1.2...maven-deploy-plugin-3.1.4) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-deploy-plugin dependency-version: 3.1.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- .../powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 4 ++-- 17 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/pom.xml b/examples/pom.xml index f1cb326ce..2c561b00f 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -52,7 +52,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 99f979cf6..7c050e76b 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -147,7 +147,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index b845b89ed..4180db75d 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -144,7 +144,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 6e344ff87..e02a636bf 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -132,7 +132,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index e2caf8b68..0d3a21e80 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -34,7 +34,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 3e2477719..302fa8074 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -143,7 +143,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index dc53d834d..3df44f441 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -117,7 +117,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 28b68a930..c4dc9c099 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -118,7 +118,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 925c1a69f..f02189948 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -118,7 +118,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/pom.xml index 39f639aae..eb235437b 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/pom.xml @@ -176,7 +176,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 24ccd3642..815506325 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -161,7 +161,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index a67895bd5..f10a20aab 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -108,7 +108,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index 3f6dc295f..e660aeba2 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -46,7 +46,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 7598f9930..64ee8c465 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -41,7 +41,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 90d89546e..bdd14e5fb 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -106,7 +106,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index fb88cd60f..b89125da6 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -184,7 +184,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index ea29ffea2..abd2a02d2 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -83,7 +83,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> @@ -182,7 +182,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.2</version> + <version>3.1.4</version> <configuration> <skip>true</skip> </configuration> From a0969a778d4552592f0147949f32c9e543340def Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 10:18:41 +0200 Subject: [PATCH 355/577] chore: bump aws.sdk.version from 2.32.18 to 2.32.21 (#2041) Bumps `aws.sdk.version` from 2.32.18 to 2.32.21. Updates `software.amazon.awssdk:bom` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:http-client-spi` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:url-connection-client` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:dynamodb` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:s3` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:lambda` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:kinesis` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:cloudwatch` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:xray` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:sqs` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:cloudformation` from 2.32.18 to 2.32.21 Updates `software.amazon.awssdk:sts` from 2.32.18 to 2.32.21 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.21 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.21 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.21 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.21 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.21 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.21 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.21 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.21 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.21 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.21 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.21 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.21 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 4180db75d..e4154c024 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.18</aws.sdk.version> + <aws.sdk.version>2.32.21</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 9ccf1065c..9b09ffc1f 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.32.18</aws.sdk.version> + <aws.sdk.version>2.32.21</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> From c746acfcbd191195551212d9a01166e319f34fe6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Aug 2025 10:18:51 +0200 Subject: [PATCH 356/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.210.0 to 2.211.0 (#2042) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.210.0 to 2.211.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.210.0...v2.211.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.211.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 0d3a21e80..f8fdc5bf0 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.3.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.210.0</cdk.version> + <cdk.version>2.211.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.13.4</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index b89125da6..be1efef45 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.2</constructs.version> - <cdk.version>2.210.0</cdk.version> + <cdk.version>2.211.0</cdk.version> </properties> <dependencies> From deb53dec112db41f84b931b7154bd7cf66b48208 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 14 Aug 2025 10:59:45 +0200 Subject: [PATCH 357/577] chore(ci): Remove non-PR triggers for verify dependencies workflow. (#2044) --- .github/workflows/security-dependencies-check.yml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml index 108ba26fe..8f9e4600b 100644 --- a/.github/workflows/security-dependencies-check.yml +++ b/.github/workflows/security-dependencies-check.yml @@ -6,20 +6,12 @@ # # Triggers: # - pull_request -# - push -# - workflow_dispatch -# - cron: daily at 12:00PM on: - pull_request: - workflow_dispatch: - push: - branches: [ main ] - schedule: - - cron: '0 12 * * *' # Run daily at 12:00 UTC + pull_request: name: Verify Dependencies -run-name: Verify Dependencies – ${{ github.event_name }} +run-name: Verify Dependencies – ${{ github.event_name }} permissions: contents: read @@ -36,4 +28,4 @@ jobs: - name: Verify Contents uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 with: - config-file: './.github/dependency-review-config.yml' \ No newline at end of file + config-file: './.github/dependency-review-config.yml' From ab467c6bc2c8b332149fa0f00cb95eeb91043d80 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi <dreamorosi@gmail.com> Date: Thu, 14 Aug 2025 16:53:10 +0200 Subject: [PATCH 358/577] docs: update readme (#2045) * docs: update readme * Update README.md Co-authored-by: Philipp Page <github@philipp.page> --------- Co-authored-by: Philipp Page <github@philipp.page> --- README.md | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c7d3c6b71..62d34e9c5 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ -# Powertools for AWS Lambda (Java) V2 +# Powertools for AWS Lambda (Java) -**This is pre-release code for Powertools for AWS Lambda (Java) V2! Please check out the `main` branch for the stable release** - -![aws provider](https://img.shields.io/badge/provider-AWS-orange?logo=amazon-aws&color=ff9900) [![V2 Build Status](https://github.com/aws-powertools/powertools-lambda-java/actions/workflows/pr_build.yml/badge.svg?branch=v2)](https://github.com/aws-powertools/powertools-lambda-java/actions/workflows/pr_build.yml) **MAVEN DEPLOY NOT DONE** [![codecov.io](https://codecov.io/github/aws-powertools/powertools-lambda-java/branch/v2/graphs/badge.svg)](https://app.codecov.io/gh/aws-powertools/powertools-lambda-java/tree/v2) +![aws provider](https://img.shields.io/badge/provider-AWS-orange?logo=amazon-aws&color=ff9900) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=aws-powertools_powertools-lambda-java&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=aws-powertools_powertools-lambda-java) +[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=aws-powertools_powertools-lambda-java&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=aws-powertools_powertools-lambda-java) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/aws-powertools/powertools-lambda-java/badge)](https://api.securityscorecards.dev/projects/github.com/aws-powertools/powertools-lambda-java) ![Maven Central](https://img.shields.io/maven-central/v/software.amazon.lambda/powertools-parent) [![codecov.io](https://codecov.io/github/aws-powertools/powertools-lambda-java/branch/main/graphs/badge.svg)](https://app.codecov.io/gh/aws-powertools/powertools-lambda-java) Powertools for AWS Lambda (Java) is a developer toolkit to implement Serverless best practices and increase developer velocity. > Also available in [Python](https://github.com/aws-powertools/powertools-lambda-python), [TypeScript](https://github.com/aws-powertools/powertools-lambda-typescript), and [.NET](https://github.com/aws-powertools/powertools-lambda-dotnet). -**[📜Documentation](https://docs.powertools.aws.dev/lambda-java/preview)** | **[Feature request](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=feature-request%2C+triage&template=feature_request.md&title=)** | **[🐛Bug Report](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=bug%2C+triage&template=bug_report.md&title=)** | **[Detailed blog post](https://aws.amazon.com/blogs/opensource/simplifying-serverless-best-practices-with-aws-lambda-powertools-java/)** +**[📜Documentation](https://docs.powertools.aws.dev/lambda-java/latest)** | **[Feature request](https://github.com/aws-powertools/powertools-lambda-java/issues/new?template=feature_request.yml)** | **[🐛Bug Report](https://github.com/aws-powertools/powertools-lambda-java/issues/new?template=bug_report.yml)** | **[Detailed blog post](https://aws.amazon.com/blogs/compute/introducing-v2-of-powertools-for-aws-lambda-java/)** ## Installation @@ -153,7 +153,7 @@ More info [here](https://github.com/aws-powertools/powertools-lambda-java/pull/1 ## Examples -See the latest release of the **[examples](https://github.com/aws-powertools/powertools-lambda-java/tree/v1.18.0/examples)** for example projects showcasing usage of different utilities. +See the latest release of the **[examples](https://github.com/aws-powertools/powertools-lambda-java/tree/main/examples)** for example projects showcasing usage of different utilities. Have a demo project to contribute which showcase usage of different utilities from powertools? We are happy to accept it [here](CONTRIBUTING.md#security-issue-notifications). @@ -161,7 +161,7 @@ Have a demo project to contribute which showcase usage of different utilities fr ### Becoming a reference customer -Knowing which companies are using this library is important to help prioritize the project internally. If your company is using Powertools for AWS Lambda (Java), you can request to have your name and logo added to the README file by raising a [Support Powertools for AWS Lambda (Java) (become a reference)](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=customer-reference&template=support_powertools.yml&title=%5BSupport+Lambda+Powertools%5D%3A+%3Cyour+organization+name%3E) issue. +Knowing which companies are using this library is important to help prioritize the project internally. If your company is using Powertools for AWS Lambda (Java), you can request to have your name and logo added to the README file by raising a [Support Powertools for AWS Lambda (Java) (become a reference)](https://github.com/aws-powertools/powertools-lambda-java/issues/new?template=support_powertools.yml) issue. The following companies, among others, use Powertools: @@ -170,15 +170,10 @@ The following companies, among others, use Powertools: * [Europace AG](https://europace.de/) * [Vertex Pharmaceuticals](https://www.vrtx.com/) -## Credits - -* [MkDocs](https://www.mkdocs.org/) -* [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) - ## Connect -* **Powertools for AWS Lambda on Discord**: `#java` - **[Invite link](https://discord.gg/B8zZKbbyET)** -* **Email**: <aws-lambda-powertools-feedback@amazon.com> +- **Powertools for AWS Lambda on Discord**: `#java` - **[Invite link](https://discord.gg/B8zZKbbyET)** +- **Email**: <aws-powertools-maintainers@amazon.com> ## Security disclosures @@ -186,4 +181,4 @@ If you think you’ve found a potential security issue, please do not post it in ## License -This library is licensed under the Apache License, Version 2.0. See the LICENSE file. +This library is licensed under the MIT-0 License. See the [LICENSE](https://github.com/aws-powertools/powertools-lambda-java/blob/main/LICENSE) file. From 7e9ff02ea344ceeb0c9aa2b9736d28532085726a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 09:15:05 +0200 Subject: [PATCH 359/577] chore: bump aws.sdk.version from 2.32.21 to 2.32.22 (#2046) Bumps `aws.sdk.version` from 2.32.21 to 2.32.22. Updates `software.amazon.awssdk:bom` from 2.32.21 to 2.32.22 Updates `software.amazon.awssdk:http-client-spi` from 2.32.21 to 2.32.22 Updates `software.amazon.awssdk:url-connection-client` from 2.32.19 to 2.32.22 Updates `software.amazon.awssdk:dynamodb` from 2.32.21 to 2.32.22 Updates `software.amazon.awssdk:s3` from 2.32.19 to 2.32.22 Updates `software.amazon.awssdk:lambda` from 2.32.21 to 2.32.22 Updates `software.amazon.awssdk:kinesis` from 2.32.19 to 2.32.22 Updates `software.amazon.awssdk:cloudwatch` from 2.32.21 to 2.32.22 Updates `software.amazon.awssdk:xray` from 2.32.21 to 2.32.22 Updates `software.amazon.awssdk:sqs` from 2.32.19 to 2.32.22 Updates `software.amazon.awssdk:cloudformation` from 2.32.21 to 2.32.22 Updates `software.amazon.awssdk:sts` from 2.32.21 to 2.32.22 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.22 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.22 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.22 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.22 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.22 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.22 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.22 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.22 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.22 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.22 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.22 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.22 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index e4154c024..6e260a4d8 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.21</aws.sdk.version> + <aws.sdk.version>2.32.22</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 9b09ffc1f..d649f9f09 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.32.21</aws.sdk.version> + <aws.sdk.version>2.32.22</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> From 439b342715409a74977fb19f731bd895e47a190e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 10:15:32 +0200 Subject: [PATCH 360/577] chore: bump com.google.protobuf:protobuf-java from 4.31.1 to 4.32.0 (#2050) Bumps [com.google.protobuf:protobuf-java](https://github.com/protocolbuffers/protobuf) from 4.31.1 to 4.32.0. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl) - [Commits](https://github.com/protocolbuffers/protobuf/commits) --- updated-dependencies: - dependency-name: com.google.protobuf:protobuf-java dependency-version: 4.32.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 390f999a7..7f7038564 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -12,7 +12,7 @@ <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> <avro.version>1.12.0</avro.version> - <protobuf.version>4.31.1</protobuf.version> + <protobuf.version>4.32.0</protobuf.version> </properties> <dependencies> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index cd696d103..f8504a3ec 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -36,7 +36,7 @@ <properties> <kafka-clients.version>4.0.0</kafka-clients.version> <avro.version>1.12.0</avro.version> - <protobuf.version>4.31.1</protobuf.version> + <protobuf.version>4.32.0</protobuf.version> <lambda-serialization.version>1.1.6</lambda-serialization.version> </properties> From 6204bd103306dd55aa6cf239d7741768f5e7a842 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 10:15:37 +0200 Subject: [PATCH 361/577] chore: bump aws.sdk.version from 2.32.22 to 2.32.23 (#2048) Bumps `aws.sdk.version` from 2.32.22 to 2.32.23. Updates `software.amazon.awssdk:bom` from 2.32.22 to 2.32.23 Updates `software.amazon.awssdk:http-client-spi` from 2.32.22 to 2.32.23 Updates `software.amazon.awssdk:url-connection-client` from 2.32.19 to 2.32.23 Updates `software.amazon.awssdk:dynamodb` from 2.32.22 to 2.32.23 Updates `software.amazon.awssdk:s3` from 2.32.19 to 2.32.23 Updates `software.amazon.awssdk:lambda` from 2.32.22 to 2.32.23 Updates `software.amazon.awssdk:kinesis` from 2.32.19 to 2.32.23 Updates `software.amazon.awssdk:cloudwatch` from 2.32.22 to 2.32.23 Updates `software.amazon.awssdk:xray` from 2.32.22 to 2.32.23 Updates `software.amazon.awssdk:sqs` from 2.32.19 to 2.32.23 Updates `software.amazon.awssdk:cloudformation` from 2.32.22 to 2.32.23 Updates `software.amazon.awssdk:sts` from 2.32.22 to 2.32.23 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.23 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.23 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.23 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.23 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.23 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.23 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.23 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.23 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.23 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.23 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.23 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.23 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 6e260a4d8..39b2f9edf 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.22</aws.sdk.version> + <aws.sdk.version>2.32.23</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index d649f9f09..bb2854c33 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.32.22</aws.sdk.version> + <aws.sdk.version>2.32.23</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> From 006f8ff61244649f59a47f2d4fcb63bc6288b336 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Mon, 18 Aug 2025 11:56:58 +0200 Subject: [PATCH 362/577] docs: Rename wrong POWERTOOLS_DISABLE_METRICS to correct POWERTOOLS_METRICS_DISABLED environment variable. (#2043) --- docs/core/metrics.md | 4 ++-- docs/index.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 35d08b140..31079a76e 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -540,7 +540,7 @@ The following example shows how to configure a custom `Metrics` Singleton using ### Suppressing metrics output -If you would like to suppress metrics output during your unit tests, you can use the `POWERTOOLS_DISABLE_METRICS` environment variable. For example, using Maven you can set in your build plugins: +If you would like to suppress metrics output during your unit tests, you can use the `POWERTOOLS_METRICS_DISABLED` environment variable. For example, using Maven you can set in your build plugins: ```xml <plugin> @@ -548,7 +548,7 @@ If you would like to suppress metrics output during your unit tests, you can use <artifactId>maven-surefire-plugin</artifactId> <configuration> <environmentVariables> - <POWERTOOLS_DISABLE_METRICS>true</POWERTOOLS_DISABLE_METRICS> + <POWERTOOLS_METRICS_DISABLED>true</POWERTOOLS_METRICS_DISABLED> </environmentVariables> </configuration> </plugin> diff --git a/docs/index.md b/docs/index.md index 3c6b9506b..17f3b397b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,7 +10,7 @@ Powertools for AWS Lambda (Java) is a suite of utilities for AWS Lambda Function ???+ tip "Looking for a quick run through of the core utilities?" - Check out [this detailed blog post](https://aws.amazon.com/blogs/opensource/simplifying-serverless-best-practices-with-aws-lambda-powertools-java/) with a practical example. To dive deeper, + Check out [this detailed blog post](https://aws.amazon.com/blogs/compute/introducing-v2-of-powertools-for-aws-lambda-java/) with a practical example. To dive deeper, the [Powertools for AWS Lambda (Java) workshop](https://catalog.us-east-1.prod.workshops.aws/workshops/a7011c82-e4af-4a52-80fa-fcd61f1dacd9/en-US/introduction) is a great next step. ## Tenets From 30ffa57ff9e2b2379076175d921b83587716b1e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Aug 2025 13:13:01 +0200 Subject: [PATCH 363/577] chore: bump actions/checkout from 4.2.2 to 5.0.0 (#2036) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 5.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/11bd71901bbe5b1630ceea73d27597364c9af683...08c6903cd8c0fde910a37f88322edcfb5dd907a8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- .github/workflows/build-docs.yml | 2 +- .github/workflows/check-build.yml | 2 +- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/check-pmd.yml | 2 +- .github/workflows/check-spotbugs.yml | 2 +- .github/workflows/release.yml | 6 +++--- .github/workflows/security-branch-protections.yml | 2 +- .github/workflows/security-dependencies-check.yml | 2 +- .github/workflows/security-scorecard.yml | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 6de4dc4f7..bf241cc1b 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -32,7 +32,7 @@ jobs: environment: Docs steps: - name: Checkout Repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 with: fetch-depth: 0 - name: Build diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 45fef40b9..257d83eee 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -94,7 +94,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup Java uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 with: diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 2aef7a3f8..d05e2d650 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -56,7 +56,7 @@ jobs: - 21 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup java uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: @@ -89,7 +89,7 @@ jobs: - 21 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup java uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: diff --git a/.github/workflows/check-pmd.yml b/.github/workflows/check-pmd.yml index 7ef10c1de..906fdabd8 100644 --- a/.github/workflows/check-pmd.yml +++ b/.github/workflows/check-pmd.yml @@ -29,7 +29,7 @@ jobs: id-token: write steps: - name: Checkout Repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup Java uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: diff --git a/.github/workflows/check-spotbugs.yml b/.github/workflows/check-spotbugs.yml index 754672448..c4668be21 100644 --- a/.github/workflows/check-spotbugs.yml +++ b/.github/workflows/check-spotbugs.yml @@ -40,7 +40,7 @@ jobs: codecheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup Java uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eb8f422e9..c90b035da 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -103,7 +103,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - id: version name: version uses: ./.github/actions/version @@ -224,7 +224,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: ref: ${{ env.RELEASE_COMMIT }} - id: download_source @@ -271,7 +271,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Build run: | mkdir -p dist diff --git a/.github/workflows/security-branch-protections.yml b/.github/workflows/security-branch-protections.yml index 05a082b0b..af6477802 100644 --- a/.github/workflows/security-branch-protections.yml +++ b/.github/workflows/security-branch-protections.yml @@ -46,7 +46,7 @@ jobs: - v1 steps: - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Fetch branch protections id: fetch env: diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml index 8f9e4600b..6233a9ad9 100644 --- a/.github/workflows/security-dependencies-check.yml +++ b/.github/workflows/security-dependencies-check.yml @@ -24,7 +24,7 @@ jobs: pull-requests: write steps: - name: Checkout Repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Verify Contents uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 with: diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index c482a0c3e..9026fac5a 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -35,7 +35,7 @@ jobs: id-token: write steps: - name: Checkout Repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: persist-credentials: false - name: Run Analysis From 091569965853d4401bc00921d132302122e14f0e Mon Sep 17 00:00:00 2001 From: Simon Thulbourn <sthulb@users.noreply.github.com> Date: Tue, 19 Aug 2025 18:47:09 +0200 Subject: [PATCH 364/577] fix(ci): Update branch protection output (#2053) --- .github/branch_protection_settings/main.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/branch_protection_settings/main.json b/.github/branch_protection_settings/main.json index 9fc6cc07d..8ca32bb45 100644 --- a/.github/branch_protection_settings/main.json +++ b/.github/branch_protection_settings/main.json @@ -19,7 +19,7 @@ "required_pull_request_reviews": { "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_pull_request_reviews", "dismiss_stale_reviews": true, - "require_code_owner_reviews": false, + "require_code_owner_reviews": true, "require_last_push_approval": true, "required_approving_review_count": 1, "dismissal_restrictions": { @@ -37,7 +37,7 @@ }, "enforce_admins": { "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/enforce_admins", - "enabled": false + "enabled": true }, "required_linear_history": { "enabled": true From c7d2437e2f1f37b1eb4c8ced66faf6e3c49b894b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 11:40:39 +0200 Subject: [PATCH 365/577] chore: bump aws.sdk.version from 2.32.19 to 2.32.26 (#2060) Bumps `aws.sdk.version` from 2.32.19 to 2.32.26. Updates `software.amazon.awssdk:url-connection-client` from 2.32.19 to 2.32.26 Updates `software.amazon.awssdk:sdk-core` from 2.32.19 to 2.32.26 Updates `software.amazon.awssdk:s3` from 2.32.19 to 2.32.26 Updates `software.amazon.awssdk:kinesis` from 2.32.19 to 2.32.26 Updates `software.amazon.awssdk:sqs` from 2.32.19 to 2.32.26 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.32.19 to 2.32.26 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.26 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.32.26 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.26 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.26 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.26 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.32.26 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 7c050e76b..c456ace5a 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.32.19</sdk.version> + <sdk.version>2.32.26</sdk.version> </properties> <dependencies> From 8b84bc3c18b6e59a8cd9b81ecdd01aa919d0bdf7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 11:40:51 +0200 Subject: [PATCH 366/577] chore: bump aws.sdk.version from 2.32.23 to 2.32.25 (#2054) Bumps `aws.sdk.version` from 2.32.23 to 2.32.25. Updates `software.amazon.awssdk:bom` from 2.32.23 to 2.32.25 Updates `software.amazon.awssdk:http-client-spi` from 2.32.23 to 2.32.25 Updates `software.amazon.awssdk:url-connection-client` from 2.32.19 to 2.32.25 Updates `software.amazon.awssdk:dynamodb` from 2.32.23 to 2.32.25 Updates `software.amazon.awssdk:s3` from 2.32.19 to 2.32.25 Updates `software.amazon.awssdk:lambda` from 2.32.23 to 2.32.25 Updates `software.amazon.awssdk:kinesis` from 2.32.19 to 2.32.25 Updates `software.amazon.awssdk:cloudwatch` from 2.32.23 to 2.32.25 Updates `software.amazon.awssdk:xray` from 2.32.23 to 2.32.25 Updates `software.amazon.awssdk:sqs` from 2.32.19 to 2.32.25 Updates `software.amazon.awssdk:cloudformation` from 2.32.23 to 2.32.25 Updates `software.amazon.awssdk:sts` from 2.32.23 to 2.32.25 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.25 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.25 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.25 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.25 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.25 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.25 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.25 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.25 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.25 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.25 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.25 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.25 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 39b2f9edf..476d7c228 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.23</aws.sdk.version> + <aws.sdk.version>2.32.25</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index bb2854c33..ba7366d1a 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.32.23</aws.sdk.version> + <aws.sdk.version>2.32.25</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> From 6a0ae2f8f38360f4bc17f633f8677c57b702c741 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 11:41:18 +0200 Subject: [PATCH 367/577] chore: bump actions/dependency-review-action from 4.7.1 to 4.7.2 (#2055) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.1 to 4.7.2. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/da24556b548a50705dd671f47852072ea4c105d9...bc41886e18ea39df68b1b1245f4184881938e050) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.7.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-dependencies-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml index 6233a9ad9..3e0ca168c 100644 --- a/.github/workflows/security-dependencies-check.yml +++ b/.github/workflows/security-dependencies-check.yml @@ -26,6 +26,6 @@ jobs: - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Verify Contents - uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 + uses: actions/dependency-review-action@bc41886e18ea39df68b1b1245f4184881938e050 # v4.7.2 with: config-file: './.github/dependency-review-config.yml' From f5e955bfa7cdabbe5d734c04a5cd433a604a1049 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 11:41:38 +0200 Subject: [PATCH 368/577] chore: bump github/codeql-action from 3.29.9 to 3.29.10 (#2056) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.9 to 3.29.10. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/df559355d593797519d70b90fc8edd5db049e7a2...96f518a34f7a870018057716cc4d7a5c014bd61c) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 9026fac5a..18b523f14 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.5 + uses: github/codeql-action/upload-sarif@96f518a34f7a870018057716cc4d7a5c014bd61c # v3.29.5 with: sarif_file: results.sarif From 92c87153fe70e42198670f29c4c5f681c56befb8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 11:41:59 +0200 Subject: [PATCH 369/577] chore: bump io.github.ascopes:protobuf-maven-plugin from 3.7.0 to 3.8.0 (#2057) Bumps [io.github.ascopes:protobuf-maven-plugin](https://github.com/ascopes/protobuf-maven-plugin) from 3.7.0 to 3.8.0. - [Release notes](https://github.com/ascopes/protobuf-maven-plugin/releases) - [Commits](https://github.com/ascopes/protobuf-maven-plugin/compare/v3.7.0...v3.8.0) --- updated-dependencies: - dependency-name: io.github.ascopes:protobuf-maven-plugin dependency-version: 3.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 7f7038564..956ca7d8d 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -141,7 +141,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.7.0</version> + <version>3.8.0</version> <executions> <execution> <goals> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index f8504a3ec..75167ff92 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -181,7 +181,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.7.0</version> + <version>3.8.0</version> <executions> <execution> <id>generate-test-sources</id> From 20e4798da1fc66bbe418aa2fe553e5f4c1fa1bfa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 11:42:11 +0200 Subject: [PATCH 370/577] chore: bump org.apache.maven.plugins:maven-javadoc-plugin (#2059) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.2 to 3.11.3. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.2...maven-javadoc-plugin-3.11.3) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-version: 3.11.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ba7366d1a..e6347b224 100644 --- a/pom.xml +++ b/pom.xml @@ -97,7 +97,7 @@ <maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version> <jacoco-maven-plugin.version>0.8.11</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version> - <maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version> + <maven-javadoc-plugin.version>3.11.3</maven-javadoc-plugin.version> <maven-source-plugin.version>3.3.1</maven-source-plugin.version> <maven-gpg-plugin.version>3.2.1</maven-gpg-plugin.version> <junit.version>5.10.0</junit.version> From 4bf7abde78206e60f99d883a149b5adf9f2a6637 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Aug 2025 11:47:44 +0200 Subject: [PATCH 371/577] chore: bump squidfunk/mkdocs-material in /docs (#2058) Bumps squidfunk/mkdocs-material from `bb7b015` to `405aeb6`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: 405aeb6dbf1fcddd1082993eacf288a46648ea56b846323f001aee619015a23b dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 858c60705..b3c40662a 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -FROM squidfunk/mkdocs-material@sha256:bb7b015690d9fb5ef0dbc98ca3520f153aa43129fb96aec5ca54c9154dc3b729 +FROM squidfunk/mkdocs-material@sha256:405aeb6dbf1fcddd1082993eacf288a46648ea56b846323f001aee619015a23b COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From da2b6584c85fb74cbc735a11b4cd5a309ee4b858 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Fri, 22 Aug 2025 09:43:49 +0200 Subject: [PATCH 372/577] chore(ci): Add powertools-e2e-tests/handlers as module to capture it in GitHub actions version upgrades. (#2063) --- .../demo/kafka/protobuf/ProtobufProduct.java | 6 +++--- .../protobuf/ProtobufProductOrBuilder.java | 2 +- .../protobuf/ProtobufProductOuterClass.java | 6 +++--- pom.xml | 1 + powertools-e2e-tests/handlers/batch/pom.xml | 4 ++-- .../handlers/idempotency/pom.xml | 4 ++-- .../handlers/largemessage/pom.xml | 4 ++-- .../handlers/largemessage_idempotent/pom.xml | 4 ++-- powertools-e2e-tests/handlers/logging/pom.xml | 4 ++-- powertools-e2e-tests/handlers/metrics/pom.xml | 4 ++-- .../handlers/parameters/pom.xml | 4 ++-- powertools-e2e-tests/handlers/pom.xml | 21 +++++++++---------- powertools-e2e-tests/handlers/tracing/pom.xml | 4 ++-- .../handlers/validation-alb-event/pom.xml | 4 ++-- .../handlers/validation-apigw-event/pom.xml | 4 ++-- powertools-e2e-tests/pom.xml | 2 +- 16 files changed, 39 insertions(+), 39 deletions(-) diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java index 250f37090..21961ad2b 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.31.1 +// Protobuf Java Version: 4.32.0 package org.demo.kafka.protobuf; @@ -18,8 +18,8 @@ public final class ProtobufProduct extends com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, - /* minor= */ 31, - /* patch= */ 1, + /* minor= */ 32, + /* patch= */ 0, /* suffix= */ "", ProtobufProduct.class.getName()); } diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java index b2d185f6d..347ea854a 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.31.1 +// Protobuf Java Version: 4.32.0 package org.demo.kafka.protobuf; diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java index adbfdd73a..046283d9a 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.31.1 +// Protobuf Java Version: 4.32.0 package org.demo.kafka.protobuf; @@ -12,8 +12,8 @@ private ProtobufProductOuterClass() {} com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, - /* minor= */ 31, - /* patch= */ 1, + /* minor= */ 32, + /* patch= */ 0, /* suffix= */ "", ProtobufProductOuterClass.class.getName()); } diff --git a/pom.xml b/pom.xml index e6347b224..3e633d818 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,7 @@ <module>powertools-idempotency</module> <module>powertools-large-messages</module> <module>powertools-e2e-tests</module> + <module>powertools-e2e-tests/handlers</module> <module>powertools-batch</module> <module>powertools-parameters/powertools-parameters-ssm</module> <module>powertools-parameters/powertools-parameters-secrets</module> diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index 3b7238b4e..630ff7cfa 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> </parent> <artifactId>e2e-test-handler-batch</artifactId> <packaging>jar</packaging> - <name>A Lambda function using Powertools for AWS Lambda (Java) batch</name> + <name>E2E test handler – Batch</name> <dependencies> <dependency> diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index dfa97225a..8b9b015bc 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> </parent> <artifactId>e2e-test-handler-idempotency</artifactId> <packaging>jar</packaging> - <name>A Lambda function using Powertools for AWS Lambda (Java) idempotency</name> + <name>E2E test handler – Idempotency</name> <dependencies> <dependency> diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index ce3fbbdd5..3aa876bfc 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> </parent> <artifactId>e2e-test-handler-largemessage</artifactId> <packaging>jar</packaging> - <name>A Lambda function using Powertools for AWS Lambda (Java) large message</name> + <name>E2E test handler – Large message</name> <dependencies> <dependency> diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index e9e87da2b..dea0f7263 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> </parent> <artifactId>e2e-test-handler-large-msg-idempotent</artifactId> <packaging>jar</packaging> - <name>A Lambda function using Powertools for AWS Lambda (Java) idempotency with large messages</name> + <name>E2E test handler – Large message idempotent</name> <dependencies> <dependency> diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml index f5eacf5c5..d4d42d593 100644 --- a/powertools-e2e-tests/handlers/logging/pom.xml +++ b/powertools-e2e-tests/handlers/logging/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> </parent> <artifactId>e2e-test-handler-logging</artifactId> <packaging>jar</packaging> - <name>A Lambda function using Powertools for AWS Lambda (Java) logging</name> + <name>E2E test handler – Logging</name> <dependencies> <dependency> diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 7bdc75591..809f7faa2 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> </parent> <artifactId>e2e-test-handler-metrics</artifactId> <packaging>jar</packaging> - <name>A Lambda function using Powertools for AWS Lambda (Java) Metrics</name> + <name>E2E test handler – Metrics</name> <dependencies> <dependency> diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index 46e6dc1e5..d1cd4bf74 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> </parent> <artifactId>e2e-test-handler-parameters</artifactId> <packaging>jar</packaging> - <name>A Lambda function using powertools parameters</name> + <name>E2E test handler – Parameters</name> <dependencies> <dependency> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 1b3eaf3e0..393e3fecb 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -4,13 +4,12 @@ <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> <packaging>pom</packaging> <name>Handlers for End-to-End tests</name> <description>Fake handlers that use Powertools for AWS Lambda (Java).</description> <properties> - <lambda.powertools.version>2.0.0</lambda.powertools.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> @@ -55,47 +54,47 @@ <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging-log4j</artifactId> - <version>${lambda.powertools.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> - <version>${lambda.powertools.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-metrics</artifactId> - <version>${lambda.powertools.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>${lambda.powertools.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency-dynamodb</artifactId> - <version>${lambda.powertools.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parameters-appconfig</artifactId> - <version>${lambda.powertools.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-large-messages</artifactId> - <version>${lambda.powertools.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-batch</artifactId> - <version>${lambda.powertools.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-validation</artifactId> - <version>${lambda.powertools.version}</version> + <version>${project.version}</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index 67bcee662..304941b0c 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> </parent> <artifactId>e2e-test-handler-tracing</artifactId> <packaging>jar</packaging> - <name>A Lambda function using powertools tracing</name> + <name>E2E test handler – Tracing</name> <dependencies> <dependency> diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml index 36695b9a4..c595b7201 100644 --- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> </parent> <artifactId>e2e-test-handler-validation-alb-event</artifactId> <packaging>jar</packaging> - <name>A Lambda function using Powertools for AWS Lambda (Java) validation</name> + <name>E2E test handler – Validation ALB event</name> <dependencies> <dependency> diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml index 8bb927778..bdcc6813b 100644 --- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.0.0</version> + <version>2.3.0</version> </parent> <artifactId>e2e-test-handler-validation-apigw-event</artifactId> <packaging>jar</packaging> - <name>A Lambda function using Powertools for AWS Lambda (Java) validation</name> + <name>E2E test handler – Validation API Gateway event</name> <dependencies> <dependency> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index be1efef45..8b39b510e 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -25,7 +25,7 @@ <artifactId>powertools-e2e-tests</artifactId> <name>Powertools for AWS Lambda (Java) - End-to-end tests</name> - <description>Powertools for AWS Lambda (Java)End-To-End Tests</description> + <description>Powertools for AWS Lambda (Java) – End-To-End Tests</description> <properties> <maven.compiler.source>11</maven.compiler.source> From cc2df502c84830a2426ff69e1f4dddf68004890b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:28:52 +0200 Subject: [PATCH 373/577] chore: bump aws.sdk.version from 2.32.25 to 2.32.27 (#2064) Bumps `aws.sdk.version` from 2.32.25 to 2.32.27. Updates `software.amazon.awssdk:bom` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:http-client-spi` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:url-connection-client` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:dynamodb` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:s3` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:lambda` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:kinesis` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:cloudwatch` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:xray` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:sqs` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:cloudformation` from 2.32.25 to 2.32.27 Updates `software.amazon.awssdk:sts` from 2.32.25 to 2.32.27 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.27 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.27 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.27 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.27 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.27 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.27 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.27 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.27 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.27 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.27 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.27 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.27 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 476d7c228..c85e68352 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.25</aws.sdk.version> + <aws.sdk.version>2.32.27</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 3e633d818..4ae3fccec 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.32.25</aws.sdk.version> + <aws.sdk.version>2.32.27</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> From 78e161f23a54d4539b2a582afad101ab2c0d7c19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:29:06 +0200 Subject: [PATCH 374/577] chore: bump org.apache.maven.plugins:maven-javadoc-plugin (#2065) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.2 to 3.11.3. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.2...maven-javadoc-plugin-3.11.3) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-version: 3.11.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4ae3fccec..c4d36cc31 100644 --- a/pom.xml +++ b/pom.xml @@ -106,7 +106,7 @@ <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version> <jacoco-maven-plugin.version>0.8.13</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version> - <maven-javadoc-plugin.version>3.11.2</maven-javadoc-plugin.version> + <maven-javadoc-plugin.version>3.11.3</maven-javadoc-plugin.version> <maven-source-plugin.version>3.3.1</maven-source-plugin.version> <maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version> <junit.version>5.13.4</junit.version> From d2aa836f1d0c6f90075698176ff2714bbb2e09a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:31:59 +0200 Subject: [PATCH 375/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.211.0 to 2.212.0 (#2066) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.211.0 to 2.212.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.211.0...v2.212.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.212.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index f8fdc5bf0..bac4f78ff 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.3.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.211.0</cdk.version> + <cdk.version>2.212.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.13.4</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 8b39b510e..15ac7650e 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.2</constructs.version> - <cdk.version>2.211.0</cdk.version> + <cdk.version>2.212.0</cdk.version> </properties> <dependencies> From 172f8945c98086aa8f3f92082a0d2613f3a99ed4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 11:32:31 +0200 Subject: [PATCH 376/577] chore: bump actions/setup-java from 4.7.1 to 5.0.0 (#2067) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.7.1 to 5.0.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/c5195efecf7bdfc987ee8bae7a71cb8b11521c00...dded0888837ed1f317902acf8a20df0ad188d165) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 2 +- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/check-pmd.yml | 2 +- .github/workflows/check-spotbugs.yml | 2 +- .github/workflows/release.yml | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 257d83eee..bde305dce 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -96,7 +96,7 @@ jobs: name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup Java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 with: distribution: corretto java-version: ${{ matrix.java }} diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index d05e2d650..462bfbc34 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -58,7 +58,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: 'corretto' java-version: ${{ matrix.java }} @@ -91,7 +91,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: 'corretto' java-version: ${{ matrix.java }} diff --git a/.github/workflows/check-pmd.yml b/.github/workflows/check-pmd.yml index 906fdabd8..41983f89b 100644 --- a/.github/workflows/check-pmd.yml +++ b/.github/workflows/check-pmd.yml @@ -31,7 +31,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup Java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: java-version: 21 distribution: corretto diff --git a/.github/workflows/check-spotbugs.yml b/.github/workflows/check-spotbugs.yml index c4668be21..214125ed4 100644 --- a/.github/workflows/check-spotbugs.yml +++ b/.github/workflows/check-spotbugs.yml @@ -42,7 +42,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Setup Java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: 'corretto' java-version: 21 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c90b035da..4e321cc49 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -137,7 +137,7 @@ jobs: with: name: source - name: Setup Java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 with: distribution: corretto java-version: 21 @@ -172,7 +172,7 @@ jobs: with: name: source - name: Setup Java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 with: distribution: corretto java-version: ${{ matrix.java }} @@ -195,7 +195,7 @@ jobs: with: name: source - name: Setup Java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 with: distribution: corretto java-version: 21 From bbb591b116a6d21adaf74d1a80a825e9d4d2aac1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 14:23:14 +0200 Subject: [PATCH 377/577] chore: bump aws.sdk.version from 2.32.2 to 2.32.28 (#2068) Bumps `aws.sdk.version` from 2.32.2 to 2.32.28. Updates `software.amazon.awssdk:bom` from 2.32.2 to 2.32.28 Updates `software.amazon.awssdk:http-client-spi` from 2.32.27 to 2.32.28 Updates `software.amazon.awssdk:url-connection-client` from 2.32.26 to 2.32.28 Updates `software.amazon.awssdk:dynamodb` from 2.32.27 to 2.32.28 Updates `software.amazon.awssdk:s3` from 2.32.26 to 2.32.28 Updates `software.amazon.awssdk:lambda` from 2.32.27 to 2.32.28 Updates `software.amazon.awssdk:kinesis` from 2.32.26 to 2.32.28 Updates `software.amazon.awssdk:cloudwatch` from 2.32.27 to 2.32.28 Updates `software.amazon.awssdk:xray` from 2.32.27 to 2.32.28 Updates `software.amazon.awssdk:sqs` from 2.32.26 to 2.32.28 Updates `software.amazon.awssdk:cloudformation` from 2.32.27 to 2.32.28 Updates `software.amazon.awssdk:sts` from 2.32.27 to 2.32.28 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.28 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.28 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.28 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.28 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.28 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.28 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.28 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.28 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.28 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.28 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.28 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.28 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index c85e68352..cfb757440 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.27</aws.sdk.version> + <aws.sdk.version>2.32.28</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index c4d36cc31..5896ffeb7 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.32.27</aws.sdk.version> + <aws.sdk.version>2.32.28</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 393e3fecb..a3ca9bef1 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -20,7 +20,7 @@ <maven.shade.version>3.5.0</maven.shade.version> <aspectj.plugin.version>1.13.1</aspectj.plugin.version> <maven.compiler.version>3.11.0</maven.compiler.version> - <aws.sdk.version>2.32.2</aws.sdk.version> + <aws.sdk.version>2.32.28</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> From 8c397bc97f4d36e80208c677a287fd5c5b7a3504 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 14:23:32 +0200 Subject: [PATCH 378/577] chore: bump com.amazonaws:aws-lambda-java-runtime-interface-client (#2069) Bumps [com.amazonaws:aws-lambda-java-runtime-interface-client](https://github.com/aws/aws-lambda-java-libs) from 2.8.2 to 2.8.3. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-runtime-interface-client dependency-version: 2.8.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/handlers/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index a3ca9bef1..68cf5c748 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -114,7 +114,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.2</version> + <version>2.8.3</version> </dependency> </dependencies> </dependencyManagement> From 2caf5dc12439c728aa271d0430707ceb83fc4c37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 14:23:53 +0200 Subject: [PATCH 379/577] chore: bump org.graalvm.buildtools:native-maven-plugin (#2070) Bumps [org.graalvm.buildtools:native-maven-plugin](https://github.com/graalvm/native-build-tools) from 0.10.6 to 0.11.0. - [Release notes](https://github.com/graalvm/native-build-tools/releases) - [Commits](https://github.com/graalvm/native-build-tools/compare/0.10.6...0.11.0) --- updated-dependencies: - dependency-name: org.graalvm.buildtools:native-maven-plugin dependency-version: 0.11.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/handlers/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 68cf5c748..17ac6825d 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -193,7 +193,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.10.6</version> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> From ab1540da9791ee8f1d1c27047a6366da47a429ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 14:24:58 +0200 Subject: [PATCH 380/577] chore: bump org.apache.maven.plugins:maven-shade-plugin (#2071) Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.5.0 to 3.6.0. - [Release notes](https://github.com/apache/maven-shade-plugin/releases) - [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.5.0...maven-shade-plugin-3.6.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-shade-plugin dependency-version: 3.6.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/handlers/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 17ac6825d..8200b6ca3 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -17,7 +17,7 @@ <lambda.java.core>1.3.0</lambda.java.core> <lambda.java.serialization>1.1.6</lambda.java.serialization> <lambda.java.events>3.16.1</lambda.java.events> - <maven.shade.version>3.5.0</maven.shade.version> + <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.13.1</aspectj.plugin.version> <maven.compiler.version>3.11.0</maven.compiler.version> <aws.sdk.version>2.32.28</aws.sdk.version> From 55a4628a7dd4620ed483c623ad08f1ab823fd03c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 14:26:15 +0200 Subject: [PATCH 381/577] chore: bump log4j.version from 2.25.1 to 2.25.1 (#2072) Bumps `log4j.version` from 2.25.1 to 2.25.1. Updates `org.apache.logging.log4j:log4j-core` from 2.25.1 to 2.25.1 Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.25.1 to 2.25.1 Updates `org.apache.logging.log4j:log4j-slf4j2-impl` from 2.25.1 to 2.25.1 Updates `org.apache.logging.log4j:log4j-api` from 2.25.1 to 2.25.1 Updates `org.apache.logging.log4j:log4j-layout-template-json` from 2.20.0 to 2.25.1 Updates `org.apache.logging.log4j:log4j-jcl` from 2.25.1 to 2.25.1 --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-slf4j-impl dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-slf4j2-impl dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-api dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-layout-template-json dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.logging.log4j:log4j-jcl dependency-version: 2.25.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/handlers/logging/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging/pom.xml index d4d42d593..f8b5689c8 100644 --- a/powertools-e2e-tests/handlers/logging/pom.xml +++ b/powertools-e2e-tests/handlers/logging/pom.xml @@ -20,7 +20,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-layout-template-json</artifactId> - <version>2.20.0</version> + <version>2.25.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> From 95b9c644323cffb3a4efbbfa6fd1e30b0abf6073 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 14:27:44 +0200 Subject: [PATCH 382/577] chore: bump github/codeql-action from 3.29.10 to 3.29.11 (#2073) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.10 to 3.29.11. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/96f518a34f7a870018057716cc4d7a5c014bd61c...3c3833e0f8c1c83d449a7478aa59c036a9165498) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 18b523f14..4047f0da2 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@96f518a34f7a870018057716cc4d7a5c014bd61c # v3.29.5 + uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.5 with: sarif_file: results.sarif From 90a2c1aa4df22fb11c4886930a9a701185f28f34 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 14:27:59 +0200 Subject: [PATCH 383/577] chore: bump squidfunk/mkdocs-material in /docs (#2074) Bumps squidfunk/mkdocs-material from `405aeb6` to `1a4e939`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: 1a4e939cfd62b90943b6a829eb8544933e4e94eab18b8ca1d0f912fa9a532c37 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index b3c40662a..4d3135506 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -FROM squidfunk/mkdocs-material@sha256:405aeb6dbf1fcddd1082993eacf288a46648ea56b846323f001aee619015a23b +FROM squidfunk/mkdocs-material@sha256:1a4e939cfd62b90943b6a829eb8544933e4e94eab18b8ca1d0f912fa9a532c37 COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From 7bb7b29ee5133f4df93633233afa63a086642c6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 14:28:16 +0200 Subject: [PATCH 384/577] chore: bump sam/build-java21 (#2075) Bumps sam/build-java21 from `44e9166` to `6ad1664`. --- updated-dependencies: - dependency-name: sam/build-java21 dependency-version: 6ad16645a48cbc9aa6ab9b707350d1976804f410bb47dd0f87bf106cd69ff36a dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index 927a221c4..a4cacd9cb 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:44e9166767b12df862da6f76b4622f89e3b97a31bab73bfbb3b1df13515bfd23 +FROM public.ecr.aws/sam/build-java21@sha256:6ad16645a48cbc9aa6ab9b707350d1976804f410bb47dd0f87bf106cd69ff36a # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From cbdf81fb4be6f8b793a2fc4597ea91a1fa0c2a05 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Fri, 22 Aug 2025 15:32:42 +0200 Subject: [PATCH 385/577] chore(ci): Fix bug where docs were released with old version during release workflow. (#2076) --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4e321cc49..08dfa90dc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -272,6 +272,9 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + # Checkout PR branch to make sure we build the version-bumped docs + ref: ci-${{ github.run_id }} - name: Build run: | mkdir -p dist From a9ce7be3c56923c01e0c0721e144c1e3bc793d25 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Mon, 25 Aug 2025 13:59:00 +0200 Subject: [PATCH 386/577] chore(ci): Run unit tests for GraalVM as well during build. (#2047) * chore(ci): Run unit tests for GraalVM as well during build. * Test GraalVM unit tests on Mockito 5.16.0. * Fix native tests in powertools-serialization. Remove mockito dependency there. * Remove mockito from powertools-common. * Remove mockito from powertools-metrics and re-use TestLamdaContext from powertools-common. * Remove mockito from powertools-serialization. * Remove mockito from powertools-logging. * Remove mockito from powertools-logging-log4j. * Add --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier * Remove mockito from powertools-logging-logback. * Remove mockito from powertools-tracing. * Build project first to make sure test-jar dependencies are available for graalvm unit tests. * Enable maven quite mode and search recursively for graalvm profiles to make sure sub-sub-modules are also covered. * Add back Mockito to powertools-common. * Simplify graalvm config for logback and log4j modules. * Simplify graalvm config in powertools-logging. * Cleanup GRM files for logback module. * Simplify GraalVM config for powertools-metrics, powertools-serialization, powertools-tracing. * Remove <! or newer version --> comment. * Simplify powertools-parameters-tests GraalVM config and fix issues in unit tests. * Simplify powertools-parameters-ssm GraalVM config and fix issues in unit tests. * Simplify powertools-parameters-secrets GraalVM config and fix issues in unit tests. * Simplify powertools-parameters-dynamodb GraalVM config and fix issues in unit tests. * Simplify powertools-parameters-appconfig GraalVM config and fix issues in unit tests. * Fix SonarCube finding. * Allowlist UPL-1.0 license. * Add TT ID to UPL license. * Enable Maven Central snapshot repo temporarily. * Potential fix for code scanning alert no. 54: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Disable verbose resource registration logs. --------- Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/dependency-review-config.yml | 4 +- .github/workflows/check-build.yml | 65 ++++---- pom.xml | 22 ++- powertools-common/pom.xml | 58 +++---- .../internal/LambdaHandlerProcessorTest.java | 49 +++--- .../common/stubs/TestLambdaContext.java | 22 +-- powertools-logging/pom.xml | 64 ++------ .../powertools-logging-log4j/pom.xml | 68 +++----- .../PowerToolsResolverFactoryTest.java | 27 ++-- .../PowertoolsResolverArgumentsTest.java | 31 ++-- .../powertools-logging-logback/pom.xml | 70 +++------ .../jni-config.json | 4 - .../reflect-config.json | 148 ++++-------------- .../resource-config.json | 10 -- .../internal/LambdaEcsEncoderTest.java | 36 ++--- .../internal/LambdaJsonEncoderTest.java | 80 +++++----- .../internal/LambdaLoggingAspectTest.java | 66 ++++---- powertools-metrics/pom.xml | 73 ++------- .../metrics/ConfigurationPrecedenceTest.java | 10 +- .../internal/EmfMetricsLoggerTest.java | 8 +- .../internal/LambdaMetricsAspectTest.java | 18 +-- powertools-parameters/pom.xml | 53 +------ .../powertools-parameters-appconfig/pom.xml | 49 +++--- .../appconfig/AppConfigParamAspectTest.java | 1 + .../appconfig/AppConfigProviderTest.java | 6 +- .../powertools-parameters-dynamodb/pom.xml | 49 +++--- .../dynamodb/DynamoDbProviderTest.java | 25 +-- .../powertools-parameters-secrets/pom.xml | 49 +++--- .../secrets/SecretsProviderTest.java | 16 +- .../powertools-parameters-ssm/pom.xml | 51 +++--- .../powertools-parameters-tests/pom.xml | 49 +++--- .../parameters/BaseProviderTest.java | 10 +- .../ParamProvidersIntegrationTest.java | 17 +- powertools-serialization/pom.xml | 63 ++------ powertools-tracing/pom.xml | 59 ++----- .../powertools/tracing/TracingUtilsTest.java | 63 ++------ .../internal/LambdaTracingAspectTest.java | 62 +++----- 37 files changed, 544 insertions(+), 1011 deletions(-) rename powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java => powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestLambdaContext.java (73%) diff --git a/.github/dependency-review-config.yml b/.github/dependency-review-config.yml index 6d737ee55..2ea218503 100644 --- a/.github/dependency-review-config.yml +++ b/.github/dependency-review-config.yml @@ -27,4 +27,6 @@ allow-licenses: - 'BSD-3-Clause-No-Nuclear-License-2014' - 'BSD-3-Clause-No-Nuclear-Warranty' - 'BSD-3-Clause-Open-MPI' -comment-summary-in-pr: on-failure \ No newline at end of file + # TT: D290816995 + - 'UPL-1.0' +comment-summary-in-pr: on-failure diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index bde305dce..98e1eae6e 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -2,15 +2,13 @@ # # Description: # Runs the build for every java version we support -# +# # Triggers: # - pull_request: when a PR is sent to us # - push: when code is pushed to a specified branch # # Notes: -# The matrix build for this workflow is unusual, we need to make it dyanmic since -# we need to change java versions we build for depending on the branch. - +# Builds against Java 11, 17, and 21 which are the supported versions. on: workflow_dispatch: @@ -38,7 +36,7 @@ on: push: branches: - main - paths: # add other modules when there are under e2e tests + paths: - 'powertools-batch/**' - 'powertools-core/**' - 'powertools-cloudformation/**' @@ -60,34 +58,16 @@ on: - '.github/workflows/**' name: Build +permissions: + contents: read run-name: Build - ${{ github.event_name }} jobs: - setup: - runs-on: ubuntu-latest - outputs: - build_matrix: ${{ format('{0}{1}', steps.build_matrix_v1.outputs.build_matrix, steps.build_matrix_v1.outputs.build_matrix) }} - steps: - - id: base - name: Base - run: | - echo build_version=$(test ${{ github.ref }} == "v2" && echo "v2" || echo "v1") >> $GITHUB_OUTPUT - - id: build_matrix_v1 - name: Build matrix (v1) - if: ${{ steps.base.outputs.build_version == 'v1' }} - run: | - echo build_matrix='["8", "11", "17", "21"]' >> "$GITHUB_OUTPUT" - - id: build_matrix_v2 - name: Build matrix (v2) - if: ${{ steps.base.outputs.build_version == 'v2' }} - run: | - echo build_matrix='["11", "17", "21"]'>> "$GITHUB_OUTPUT" - build: + java-build: runs-on: ubuntu-latest strategy: matrix: java: - - 8 - 11 - 17 - 21 @@ -103,6 +83,35 @@ jobs: cache: maven - id: build-maven name: Build (Maven) - if: ${{ matrix.java != '8' }} run: | - mvn -B install --file pom.xml \ No newline at end of file + mvn -B -q install --file pom.xml + + graalvm-build: + runs-on: ubuntu-latest + steps: + - id: checkout + name: Checkout repository + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Setup GraalVM + uses: graalvm/setup-graalvm@7f488cf82a3629ee755e4e97342c01d6bed318fa # v1.3.5 + with: + java-version: "21" + distribution: "graalvm" + cache: maven + - id: graalvm-native-test + name: GraalVM Native Test + run: | + # Build the entire project first to ensure test-jar dependencies are available + mvn -B -q install -DskipTests + + # Find modules with graalvm-native profile and run tests recursively. + # This will make sure to discover new GraalVM supported modules automatically in the future. + find . -name "pom.xml" -path "./powertools-*" | while read module; do + if grep -q "<id>graalvm-native</id>" "$module"; then + module_dir=$(dirname "$module") + echo "Regenerating GraalVM metadata for $module_dir" + mvn -B -q -f "$module" -Pgenerate-graalvm-files clean test + echo "Running GraalVM native tests for $module_dir" + mvn -B -q -f "$module" -Pgraalvm-native test + fi + done diff --git a/pom.xml b/pom.xml index 5896ffeb7..f6ccb5056 100644 --- a/pom.xml +++ b/pom.xml @@ -101,7 +101,6 @@ <maven-javadoc-plugin.version>3.11.3</maven-javadoc-plugin.version> <maven-source-plugin.version>3.3.1</maven-source-plugin.version> <maven-gpg-plugin.version>3.2.1</maven-gpg-plugin.version> - <junit.version>5.10.0</junit.version> <aspectj-maven-plugin.version>1.14.1</aspectj-maven-plugin.version> <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version> <jacoco-maven-plugin.version>0.8.13</jacoco-maven-plugin.version> @@ -115,8 +114,8 @@ <aws.sdk.v1.version>1.12.781</aws.sdk.v1.version> <versions-maven-plugin.version>2.18.0</versions-maven-plugin.version> <elastic.version>1.7.0</elastic.version> - <mockito.version>5.18.0</mockito.version> - <mockito-junit-jupiter.version>5.18.0</mockito-junit-jupiter.version> + <mockito.version>5.19.1-SNAPSHOT</mockito.version> + <mockito-junit-jupiter.version>5.19.1-SNAPSHOT</mockito-junit-jupiter.version> <junit-pioneer.version>2.3.0</junit-pioneer.version> <crac.version>1.5.0</crac.version> @@ -132,6 +131,21 @@ </snapshotRepository> </distributionManagement> + <!-- https://central.sonatype.org/publish/publish-portal-snapshots/#consuming-via-maven --> + <repositories> + <repository> + <name>Central Portal Snapshots</name> + <id>central-portal-snapshots</id> + <url>https://central.sonatype.com/repository/maven-snapshots/</url> + <releases> + <enabled>false</enabled> + </releases> + <snapshots> + <enabled>true</enabled> + </snapshots> + </repository> + </repositories> + <dependencyManagement> <dependencies> <dependency> @@ -323,7 +337,7 @@ <dependency> <groupId>org.junit-pioneer</groupId> <artifactId>junit-pioneer</artifactId> - <version>2.0.0</version> + <version>${junit-pioneer.version}</version> <scope>test</scope> </dependency> <dependency> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 9f8456842..ea9baa98c 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -14,8 +14,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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>powertools-common</artifactId> @@ -77,13 +77,13 @@ <scope>test</scope> </dependency> <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> <scope>test</scope> </dependency> <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-simple</artifactId> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> </dependencies> @@ -94,7 +94,6 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -105,7 +104,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-common,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -120,7 +121,6 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -129,7 +129,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -146,33 +146,10 @@ <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> <buildArg>--native-image-info</buildArg> <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> - <buildArg>-H:Log=registerResource:5</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> @@ -192,5 +169,18 @@ <directory>src/main/resources</directory> </resource> </resources> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> </build> </project> diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index 15d7bccdb..17732cdf0 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -33,14 +33,14 @@ import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -class LambdaHandlerProcessorTest { +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; - private Signature signature = mock(Signature.class); - private ProceedingJoinPoint pjpMock = mock(ProceedingJoinPoint.class); +class LambdaHandlerProcessorTest { @Test void isHandlerMethod_shouldRecognizeRequestHandler() { - Object[] args = {new Object(), mock(Context.class)}; + Context context = new TestLambdaContext(); + Object[] args = { new Object(), context }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args); assertThat(LambdaHandlerProcessor.isHandlerMethod(pjpMock)).isTrue(); @@ -48,7 +48,7 @@ void isHandlerMethod_shouldRecognizeRequestHandler() { @Test void isHandlerMethod_shouldRecognizeRequestStreamHandler() { - Object[] args = {mock(InputStream.class), mock(OutputStream.class), mock(Context.class)}; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.isHandlerMethod(pjpMock)).isTrue(); @@ -65,7 +65,7 @@ void isHandlerMethod_shouldReturnFalse() { @Test void placedOnRequestHandler_shouldRecognizeRequestHandler() { - Object[] args = {new Object(), mock(Context.class)}; + Object[] args = { new Object(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args); assertThat(LambdaHandlerProcessor.placedOnRequestHandler(pjpMock)).isTrue(); @@ -73,7 +73,7 @@ void placedOnRequestHandler_shouldRecognizeRequestHandler() { @Test void placedOnStreamHandler_shouldRecognizeRequestStreamHandler() { - Object[] args = {mock(InputStream.class), mock(OutputStream.class), mock(Context.class)}; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); assertThat(LambdaHandlerProcessor.placedOnStreamHandler(pjpMock)).isTrue(); @@ -81,7 +81,7 @@ void placedOnStreamHandler_shouldRecognizeRequestStreamHandler() { @Test void placedOnRequestHandler_shouldInvalidateOnWrongNoOfArgs() { - Object[] args = {new Object()}; + Object[] args = { new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args); boolean isPlacedOnRequestHandler = LambdaHandlerProcessor.placedOnRequestHandler(pjpMock); @@ -91,7 +91,7 @@ void placedOnRequestHandler_shouldInvalidateOnWrongNoOfArgs() { @Test void placedOnRequestHandler_shouldInvalidateOnWrongTypeOfArgs() { - Object[] args = {new Object(), new Object()}; + Object[] args = { new Object(), new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args); boolean isPlacedOnRequestHandler = LambdaHandlerProcessor.placedOnRequestHandler(pjpMock); @@ -101,7 +101,7 @@ void placedOnRequestHandler_shouldInvalidateOnWrongTypeOfArgs() { @Test void placedOnStreamHandler_shouldInvalidateOnWrongNoOfArgs() { - Object[] args = {new Object()}; + Object[] args = { new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -111,7 +111,7 @@ void placedOnStreamHandler_shouldInvalidateOnWrongNoOfArgs() { @Test void placedOnStreamHandler_shouldInvalidateOnWrongTypeOfArgs() { - Object[] args = {new Object(), new Object(), new Object()}; + Object[] args = { new Object(), new Object(), new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -121,7 +121,7 @@ void placedOnStreamHandler_shouldInvalidateOnWrongTypeOfArgs() { @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() { - Object[] args = {mock(InputStream.class), new Object(), mock(Context.class)}; + Object[] args = { mock(InputStream.class), new Object(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -131,7 +131,7 @@ void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidOutputStreamArg() @Test void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidContextArg() { - Object[] args = {mock(InputStream.class), mock(OutputStream.class), new Object()}; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); boolean isPlacedOnStreamHandler = LambdaHandlerProcessor.placedOnStreamHandler(pjpMock); @@ -144,9 +144,9 @@ void placedOnStreamHandler_shouldInvalidateOnTypeOfArgs_invalidContextArg() { void getXrayTraceId_present() { String traceID = "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1\""; - Optional xRayTraceId = LambdaHandlerProcessor.getXrayTraceId(); + Optional<String> xRayTraceId = LambdaHandlerProcessor.getXrayTraceId(); - assertThat(xRayTraceId.isPresent()).isTrue(); + assertThat(xRayTraceId).isPresent(); assertThat(traceID.split(";")[0].replace(LambdaConstants.ROOT_EQUALS, "")).isEqualTo(xRayTraceId.get()); } @@ -161,7 +161,7 @@ void getXrayTraceId_notPresent() { @Test void extractContext_fromRequestHandler() { - Object[] args = {new Object(), mock(Context.class)}; + Object[] args = { new Object(), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestHandler.class, args); Context context = LambdaHandlerProcessor.extractContext(pjpMock); @@ -171,7 +171,7 @@ void extractContext_fromRequestHandler() { @Test void extractContext_fromStreamRequestHandler() { - Object[] args = {mock(InputStream.class), mock(OutputStream.class), mock(Context.class)}; + Object[] args = { mock(InputStream.class), mock(OutputStream.class), new TestLambdaContext() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(RequestStreamHandler.class, args); Context context = LambdaHandlerProcessor.extractContext(pjpMock); @@ -181,7 +181,7 @@ void extractContext_fromStreamRequestHandler() { @Test void extractContext_notKnownHandler() { - Object[] args = {new Object()}; + Object[] args = { new Object() }; ProceedingJoinPoint pjpMock = mockRequestHandlerPjp(Object.class, args); Context context = LambdaHandlerProcessor.extractContext(pjpMock); @@ -230,10 +230,15 @@ void serviceName_Undefined() { assertThat(LambdaHandlerProcessor.serviceName()).isEqualTo(LambdaConstants.SERVICE_UNDEFINED); } - private ProceedingJoinPoint mockRequestHandlerPjp(Class handlerClass, Object[] handlerArgs) { + private ProceedingJoinPoint mockRequestHandlerPjp(Class<?> handlerClass, Object[] handlerArgs) { + ProceedingJoinPoint pjp = mock(ProceedingJoinPoint.class); + Signature signature = mock(Signature.class); + when(signature.getDeclaringType()).thenReturn(handlerClass); - when(pjpMock.getArgs()).thenReturn(handlerArgs); - when(pjpMock.getSignature()).thenReturn(signature); - return pjpMock; + when(signature.getName()).thenReturn("handleRequest"); + when(pjp.getSignature()).thenReturn(signature); + when(pjp.getArgs()).thenReturn(handlerArgs); + + return pjp; } } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestLambdaContext.java similarity index 73% rename from powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java rename to powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestLambdaContext.java index c4f5e4455..6b66b66b7 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestContext.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/stubs/TestLambdaContext.java @@ -12,14 +12,14 @@ * */ -package software.amazon.lambda.powertools.metrics.testutils; +package software.amazon.lambda.powertools.common.stubs; +import com.amazonaws.services.lambda.runtime.ClientContext; +import com.amazonaws.services.lambda.runtime.CognitoIdentity; import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.LambdaLogger; -/** - * Simple Lambda context implementation for unit tests - */ -public class TestContext implements Context { +public class TestLambdaContext implements Context { @Override public String getAwsRequestId() { return "test-request-id"; @@ -42,27 +42,27 @@ public String getFunctionName() { @Override public String getFunctionVersion() { - return "test-version"; + return "1"; } @Override public String getInvokedFunctionArn() { - return "test-arn"; + return "arn:aws:lambda:us-east-1:123456789012:function:test"; } @Override - public com.amazonaws.services.lambda.runtime.CognitoIdentity getIdentity() { + public CognitoIdentity getIdentity() { return null; } @Override - public com.amazonaws.services.lambda.runtime.ClientContext getClientContext() { + public ClientContext getClientContext() { return null; } @Override public int getRemainingTimeInMillis() { - return 1000; + return 30000; } @Override @@ -71,7 +71,7 @@ public int getMemoryLimitInMB() { } @Override - public com.amazonaws.services.lambda.runtime.LambdaLogger getLogger() { + public LambdaLogger getLogger() { return null; } } diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 7757be572..7a288870a 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -14,8 +14,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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -67,11 +67,6 @@ <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - <scope>test</scope> - </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> @@ -112,18 +107,17 @@ <artifactId>jsonassert</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> </dependencies> <profiles> <profile> <id>generate-graalvm-files</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> @@ -131,7 +125,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging,experimental-class-define-support + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -142,20 +138,12 @@ </profile> <profile> <id>graalvm-native</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -172,30 +160,10 @@ <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> + <buildArg>--native-image-info</buildArg> + <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 88e1ced39..836f8c53f 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -1,7 +1,7 @@ <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -51,11 +51,6 @@ <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - <scope>test</scope> - </dependency> <dependency> <groupId>org.junit-pioneer</groupId> <artifactId>junit-pioneer</artifactId> @@ -91,18 +86,17 @@ <artifactId>jsonassert</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> </dependencies> <profiles> <profile> <id>generate-graalvm-files</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> @@ -110,7 +104,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -121,20 +117,12 @@ </profile> <profile> <id>graalvm-native</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -148,33 +136,16 @@ <configuration> <imageName>powertools-logging-log4j</imageName> <buildArgs> + <buildArg> + --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier$1 + </buildArg> <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> + <buildArg>--native-image-info</buildArg> + <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> @@ -234,5 +205,4 @@ </plugin> </plugins> </build> - </project> diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java index 4cf798a47..7ea81d690 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java @@ -17,37 +17,36 @@ import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; -import com.amazonaws.services.lambda.runtime.Context; import java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; import java.nio.file.NoSuchFileException; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import org.mockito.Mock; import org.slf4j.MDC; + +import com.amazonaws.services.lambda.runtime.Context; + import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled; @Order(1) class PowerToolsResolverFactoryTest { - @Mock private Context context; @BeforeEach void setUp() throws IllegalAccessException, IOException { - openMocks(this); MDC.clear(); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); + context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); @@ -58,7 +57,7 @@ void setUp() throws IllegalAccessException, IOException { } @AfterEach - void cleanUp() throws IOException{ + void cleanUp() throws IOException { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } @@ -70,7 +69,7 @@ void shouldLogInJsonFormat() { File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)).contains( - "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":\"1\",\"service\":\"testLog4j\",\"timestamp\":") + "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"function_memory_size\":128,\"function_name\":\"test-function\",\"function_request_id\":\"test-request-id\",\"function_version\":\"1\",\"service\":\"testLog4j\",\"timestamp\":") .contains("\"xray_trace_id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); } @@ -81,15 +80,7 @@ void shouldLogInEcsFormat() { File logFile = new File("target/ecslogfile.json"); assertThat(contentOf(logFile)).contains( - "\"ecs.version\":\"1.2.0\",\"log.level\":\"DEBUG\",\"message\":\"Test debug event\",\"service.name\":\"testLog4j\",\"service.version\":\"1\",\"log.logger\":\"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled\",\"process.thread.name\":\"main\",\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-central-1\",\"cloud.account.id\":\"012345678910\",\"faas.id\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"faas.name\":\"testFunction\",\"faas.version\":\"1\",\"faas.memory\":1024,\"faas.execution\":\"RequestId\",\"faas.coldstart\":true,\"trace.id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); + "\"ecs.version\":\"1.2.0\",\"log.level\":\"DEBUG\",\"message\":\"Test debug event\",\"service.name\":\"testLog4j\",\"service.version\":\"1\",\"log.logger\":\"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled\",\"process.thread.name\":\"main\",\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-central-1\",\"cloud.account.id\":\"123456789012\",\"faas.id\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"faas.name\":\"test-function\",\"faas.version\":\"1\",\"faas.memory\":128,\"faas.execution\":\"test-request-id\",\"faas.coldstart\":true,\"trace.id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn( - "arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(1024); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } } diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java index 463ad043d..5432e45ae 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java @@ -16,11 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; import java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; @@ -29,27 +25,29 @@ import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.Collections; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import org.mockito.Mock; import org.slf4j.MDC; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; + +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments; @Order(2) class PowertoolsResolverArgumentsTest { - @Mock private Context context; @BeforeEach void setUp() throws IOException { - openMocks(this); MDC.clear(); - setupContext(); + context = new TestLambdaContext(); try { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); @@ -61,7 +59,7 @@ void setUp() throws IOException { @AfterEach void cleanUp() throws IOException { - //Make sure file is cleaned up before running full stack logging regression + // Make sure file is cleaned up before running full stack logging regression FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } @@ -74,7 +72,7 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { msg.setMessageId("1212abcd"); msg.setBody("plop"); msg.setEventSource("eb"); - msg.setAwsRegion("eu-west-1"); + msg.setAwsRegion("us-east-1"); SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); @@ -86,7 +84,7 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) .contains( - "\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + "\"input\":{\"awsRegion\":\"us-east-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); // Reserved keys should be ignored @@ -106,7 +104,7 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { msg.setMessageId("1212abcd"); msg.setBody("plop"); msg.setEventSource("eb"); - msg.setAwsRegion("eu-west-1"); + msg.setAwsRegion("us-east-1"); SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); @@ -118,7 +116,7 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) .contains( - "\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + "\"input\":{\"awsRegion\":\"us-east-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); @@ -131,11 +129,4 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { }); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } } diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 41750ec70..433a3774a 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -1,7 +1,7 @@ <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>powertools-parent</artifactId> @@ -49,8 +49,10 @@ <scope>test</scope> </dependency> <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + <type>test-jar</type> <scope>test</scope> </dependency> <dependency> @@ -88,14 +90,6 @@ <profiles> <profile> <id>generate-graalvm-files</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> @@ -103,7 +97,12 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support</argLine> + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + </argLine> </configuration> </plugin> </plugins> @@ -111,20 +110,12 @@ </profile> <profile> <id>graalvm-native</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -136,37 +127,18 @@ </execution> </executions> <configuration> - <agent> - <enabled>true</enabled> - <defaultMode>Standard</defaultMode> - </agent> <imageName>powertools-logging-logback</imageName> <buildArgs> - <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable + --initialize-at-build-time=org.junit.platform.launcher.core.DiscoveryIssueNotifier$1 </buildArg> + <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> + <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> + <buildArg>--no-fallback</buildArg> <buildArg>--verbose</buildArg> + <buildArg>--native-image-info</buildArg> + <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> @@ -227,6 +199,4 @@ </plugin> </plugins> </build> - - </project> diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json index 2c4de0562..753dafdea 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json @@ -15,10 +15,6 @@ "name":"org.apache.maven.surefire.booter.ForkedBooter", "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] }, -{ - "name":"sun.instrument.InstrumentationImpl", - "methods":[{"name":"<init>","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] -}, { "name":"sun.management.VMManagementImpl", "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json index 0d3bdbe7e..683933a77 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json @@ -21,11 +21,7 @@ "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] }, { - "name":"com.amazonaws.services.lambda.runtime.Context", - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] + "name":"com.amazonaws.services.lambda.runtime.Context" }, { "name":"com.amazonaws.services.lambda.runtime.events.SQSEvent$MessageAttribute", @@ -49,12 +45,6 @@ "name":"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl", "methods":[{"name":"<init>","parameterTypes":[] }] }, -{ - "name":"com.sun.tools.attach.VirtualMachine" -}, -{ - "name":"java.io.FilePermission" -}, { "name":"java.io.IOException" }, @@ -66,132 +56,64 @@ }, { "name":"java.io.Serializable", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true -}, -{ - "name":"java.lang.Class", - "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] -}, -{ - "name":"java.lang.ClassLoader", - "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] + "queryAllDeclaredMethods":true }, { "name":"java.lang.Cloneable", "queryAllDeclaredMethods":true }, { - "name":"java.lang.Module", - "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] -}, -{ - "name":"java.lang.Object", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] -}, -{ - "name":"java.lang.ProcessHandle", - "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] -}, -{ - "name":"java.lang.Runtime", - "methods":[{"name":"version","parameterTypes":[] }] -}, -{ - "name":"java.lang.Runtime$Version", - "methods":[{"name":"feature","parameterTypes":[] }] + "name":"java.lang.Iterable", + "queryAllDeclaredMethods":true }, { - "name":"java.lang.RuntimePermission" + "name":"java.lang.Object" }, { - "name":"java.lang.StackWalker" + "name":"java.lang.String" }, { - "name":"java.lang.String" + "name":"java.util.AbstractCollection", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true }, { - "name":"java.lang.System", - "methods":[{"name":"getSecurityManager","parameterTypes":[] }] + "name":"java.util.AbstractList", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true }, { - "name":"java.lang.annotation.Retention", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true + "name":"java.util.AbstractMap", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true }, { - "name":"java.lang.annotation.Target", + "name":"java.util.Arrays$ArrayList", + "allDeclaredFields":true, "queryAllDeclaredMethods":true, "queryAllDeclaredConstructors":true }, { - "name":"java.lang.invoke.MethodHandle", - "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] -}, -{ - "name":"java.lang.invoke.MethodHandles", - "methods":[{"name":"lookup","parameterTypes":[] }] -}, -{ - "name":"java.lang.invoke.MethodHandles$Lookup", - "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] -}, -{ - "name":"java.lang.invoke.MethodType", - "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] -}, -{ - "name":"java.lang.reflect.AccessibleObject", - "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] -}, -{ - "name":"java.lang.reflect.AnnotatedArrayType", - "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.AnnotatedType", - "methods":[{"name":"getType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.Executable", - "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.Method", - "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.Parameter", - "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] -}, -{ - "name":"java.net.NetPermission" -}, -{ - "name":"java.net.SocketPermission" -}, -{ - "name":"java.net.URLPermission", - "methods":[{"name":"<init>","parameterTypes":["java.lang.String","java.lang.String"] }] -}, -{ - "name":"java.security.AccessController", - "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] + "name":"java.util.Collection", + "queryAllDeclaredMethods":true }, { - "name":"java.security.AllPermission" + "name":"java.util.Collections$SingletonMap", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true }, { - "name":"java.security.SecurityPermission" + "name":"java.util.List", + "queryAllDeclaredMethods":true }, { - "name":"java.util.PropertyPermission" + "name":"java.util.Map", + "queryAllDeclaredMethods":true }, { - "name":"java.util.concurrent.ForkJoinTask", - "fields":[{"name":"aux"}, {"name":"status"}] + "name":"java.util.RandomAccess", + "queryAllDeclaredMethods":true }, { "name":"java.util.concurrent.atomic.AtomicBoolean", @@ -202,13 +124,7 @@ "fields":[{"name":"value"}] }, { - "name":"javax.smartcardio.CardPermission" -}, -{ - "name":"jdk.internal.misc.Unsafe" -}, -{ - "name":"kotlin.jvm.JvmInline" + "name":"kotlin.Metadata" }, { "name":"org.apiguardian.api.API", @@ -282,9 +198,5 @@ "name":"software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder", "queryAllPublicMethods":true, "methods":[{"name":"<init>","parameterTypes":[] }] -}, -{ - "name":"sun.reflect.ReflectionFactory", - "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] } ] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json index dea71883a..2fc3c56bd 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json @@ -8,20 +8,10 @@ "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" }, { "pattern":"\\QMETA-INF/services/javax.xml.parsers.SAXParserFactory\\E" - }, { - "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" - }, { - "pattern":"\\QMETA-INF/services/org.assertj.core.configuration.Configuration\\E" - }, { - "pattern":"\\QMETA-INF/services/org.assertj.core.presentation.Representation\\E" }, { "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" }, { "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" - }, { - "pattern":"\\Qlogback-test.scmo\\E" - }, { - "pattern":"\\Qlogback-test.xml\\E" }, { "pattern":"\\Qlogback.scmo\\E" }]}, diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java index 7e8977508..65277e3d6 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java @@ -17,8 +17,6 @@ import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; @@ -36,7 +34,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import org.mockito.Mock; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; @@ -48,16 +46,13 @@ class LambdaEcsEncoderTest { private static final Logger logger = (Logger) LoggerFactory.getLogger(LambdaEcsEncoderTest.class.getName()); - - @Mock private Context context; @BeforeEach void setUp() throws IllegalAccessException, IOException { - openMocks(this); MDC.clear(); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); + context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); @@ -67,7 +62,7 @@ void setUp() throws IllegalAccessException, IOException { } @AfterEach - void cleanUp() throws IOException{ + void cleanUp() throws IOException { FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } @@ -78,7 +73,7 @@ void shouldLogInEcsFormat() { File logFile = new File("target/ecslogfile.json"); assertThat(contentOf(logFile)).contains( - "\"ecs.version\":\"1.2.0\",\"log.level\":\"DEBUG\",\"message\":\"Test debug event\",\"service.name\":\"testLogback\",\"service.version\":\"1\",\"log.logger\":\"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled\",\"process.thread.name\":\"main\",\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-west-1\",\"cloud.account.id\":\"012345678910\",\"faas.id\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"faas.name\":\"testFunction\",\"faas.version\":\"1\",\"faas.memory\":\"1024\",\"faas.execution\":\"RequestId\",\"faas.coldstart\":\"true\",\"trace.id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); + "\"ecs.version\":\"1.2.0\",\"log.level\":\"DEBUG\",\"message\":\"Test debug event\",\"service.name\":\"testLogback\",\"service.version\":\"1\",\"log.logger\":\"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled\",\"process.thread.name\":\"main\",\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"us-east-1\",\"cloud.account.id\":\"123456789012\",\"faas.id\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"faas.name\":\"test-function\",\"faas.version\":\"1\",\"faas.memory\":\"128\",\"faas.execution\":\"test-request-id\",\"faas.coldstart\":\"true\",\"trace.id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\"}\n"); } private final LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "message", null, null); @@ -94,7 +89,8 @@ void shouldNotLogFunctionInfo() { String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("\"faas.id\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"faas.name\":\"testFunction\",\"faas.version\":\"1\",\"faas.memory\":\"1024\",\"faas.execution\":\"RequestId\",\"faas.coldstart\":\"false\""); + assertThat(result).contains( + "\"faas.id\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"faas.name\":\"test-function\",\"faas.version\":\"1\",\"faas.memory\":\"128\",\"faas.execution\":\"test-request-id\",\"faas.coldstart\":\"false\""); // WHEN (includeFaasInfo = false) encoder.setIncludeFaasInfo(false); @@ -116,7 +112,8 @@ void shouldNotLogCloudInfo() { String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"eu-west-1\",\"cloud.account.id\":\"012345678910\""); + assertThat(result).contains( + "\"cloud.provider\":\"aws\",\"cloud.service.name\":\"lambda\",\"cloud.region\":\"us-east-1\",\"cloud.account.id\":\"123456789012\""); // WHEN (includeCloudInfo = false) encoder.setIncludeCloudInfo(false); @@ -132,14 +129,16 @@ void shouldLogException() { // GIVEN LambdaEcsEncoder encoder = new LambdaEcsEncoder(); encoder.start(); - LoggingEvent errorloggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Error", new IllegalStateException("Unexpected value"), null); + LoggingEvent errorloggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Error", + new IllegalStateException("Unexpected value"), null); // WHEN byte[] encoded = encoder.encode(errorloggingEvent); String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"[software.amazon.lambda.powertools.logging.internal.LambdaEcsEncoderTest.shouldLogException"); + assertThat(result).contains( + "\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"[software.amazon.lambda.powertools.logging.internal.LambdaEcsEncoderTest.shouldLogException"); // WHEN (configure a custom throwableConverter) encoder = new LambdaEcsEncoder(); @@ -150,7 +149,8 @@ void shouldLogException() { result = new String(encoded, StandardCharsets.UTF_8); // THEN (stack is logged with root cause first) - assertThat(result).contains("\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"java.lang.IllegalStateException: Unexpected value\\n"); + assertThat(result).contains( + "\"message\":\"Error\",\"error.message\":\"Unexpected value\",\"error.type\":\"java.lang.IllegalStateException\",\"error.stack_trace\":\"java.lang.IllegalStateException: Unexpected value\\n"); } private void setMDC() { @@ -165,12 +165,4 @@ private void setMDC() { MDC.put(PowertoolsLoggedFields.SERVICE.getName(), "Service"); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn( - "arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(1024); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } } diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index c0eecf6f3..912e2fde9 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -19,8 +19,6 @@ import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; @@ -29,7 +27,6 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.util.JSONPObject; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -51,7 +48,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import org.mockito.Mock; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; @@ -69,16 +66,15 @@ @Order(2) class LambdaJsonEncoderTest { private static final Logger logger = (Logger) LoggerFactory.getLogger(LambdaJsonEncoderTest.class.getName()); + private final LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "message", null, null); - @Mock private Context context; @BeforeEach void setUp() throws IllegalAccessException, IOException { - openMocks(this); MDC.clear(); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); + context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); @@ -88,7 +84,7 @@ void setUp() throws IllegalAccessException, IOException { } @AfterEach - void cleanUp() throws IOException{ + void cleanUp() throws IOException { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } @@ -103,7 +99,7 @@ void shouldLogInJsonFormat() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)).contains( - "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":1,\"service\":\"testLogback\",\"xray_trace_id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\",\"timestamp\":"); + "{\"level\":\"DEBUG\",\"message\":\"Test debug event\",\"cold_start\":true,\"function_arn\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"function_memory_size\":128,\"function_name\":\"test-function\",\"function_request_id\":\"test-request-id\",\"function_version\":1,\"service\":\"testLogback\",\"xray_trace_id\":\"1-63441c4a-abcdef012345678912345678\",\"myKey\":\"myValue\",\"timestamp\":"); } @Test @@ -114,7 +110,7 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { msg.setMessageId("1212abcd"); msg.setBody("plop"); msg.setEventSource("eb"); - msg.setAwsRegion("eu-west-1"); + msg.setAwsRegion("eu-central-1"); SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); @@ -125,7 +121,8 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + .contains( + "\"input\":{\"awsRegion\":\"eu-central-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") // Should auto-escape double quotes around id .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); @@ -146,7 +143,7 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { msg.setMessageId("1212abcd"); msg.setBody("plop"); msg.setEventSource("eb"); - msg.setAwsRegion("eu-west-1"); + msg.setAwsRegion("eu-central-1"); SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); @@ -157,7 +154,8 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"input\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") + .contains( + "\"input\":{\"awsRegion\":\"eu-central-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") // Should auto-escape double quotes around id .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); @@ -170,8 +168,6 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { }); } - private final LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "message", null, null); - @Test void shouldNotLogPowertoolsInfo() { // GIVEN @@ -192,7 +188,8 @@ void shouldNotLogPowertoolsInfo() { String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("{\"level\":\"INFO\",\"message\":\"message\",\"cold_start\":false,\"function_arn\":\"arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1\",\"function_memory_size\":1024,\"function_name\":\"testFunction\",\"function_request_id\":\"RequestId\",\"function_version\":1,\"sampling_rate\":0.2,\"service\":\"Service\",\"timestamp\":"); + assertThat(result).contains( + "{\"level\":\"INFO\",\"message\":\"message\",\"cold_start\":false,\"function_arn\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"function_memory_size\":128,\"function_name\":\"test-function\",\"function_request_id\":\"test-request-id\",\"function_version\":1,\"sampling_rate\":0.2,\"service\":\"Service\",\"timestamp\":"); // WHEN (powertoolsInfo = false) encoder.setIncludePowertoolsInfo(false); @@ -200,7 +197,8 @@ void shouldNotLogPowertoolsInfo() { result = new String(encoded, StandardCharsets.UTF_8); // THEN (no powertools info in logs) - assertThat(result).doesNotContain("cold_start", "function_arn", "function_memory_size", "function_name", "function_request_id", "function_version", "sampling_rate", "service"); + assertThat(result).doesNotContain("cold_start", "function_arn", "function_memory_size", "function_name", + "function_request_id", "function_version", "sampling_rate", "service"); } @Test @@ -212,20 +210,22 @@ void shouldLogStructuredArgumentsAsNewEntries() { msg.setMessageId("1212abcd"); msg.setBody("plop"); msg.setEventSource("eb"); - msg.setAwsRegion("eu-west-1"); + msg.setAwsRegion("eu-central-1"); SQSEvent.MessageAttribute attribute = new SQSEvent.MessageAttribute(); attribute.setStringListValues(Arrays.asList("val1", "val2", "val3")); msg.setMessageAttributes(Collections.singletonMap("keyAttribute", attribute)); StructuredArgument argument = StructuredArguments.entry("msg", msg); // WHEN - LoggingEvent loggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, new Object[]{argument}); - byte[] encoded = encoder.encode(loggingEvent); + LoggingEvent structuredLoggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "A message", null, + new Object[] { argument }); + byte[] encoded = encoder.encode(structuredLoggingEvent); String result = new String(encoded, StandardCharsets.UTF_8); // THEN (logged as JSON) assertThat(result) - .contains("\"message\":\"A message\",\"msg\":{\"awsRegion\":\"eu-west-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}"); + .contains( + "\"message\":\"A message\",\"msg\":{\"awsRegion\":\"eu-central-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}"); } @Test @@ -252,7 +252,7 @@ void shouldLogEventForHandlerWhenEnvVariableSetToTrue() { SQSEvent.SQSMessage message = new SQSEvent.SQSMessage(); message.setBody("body"); message.setMessageId("1234abcd"); - message.setAwsRegion("eu-west-1"); + message.setAwsRegion("eu-central-1"); // WHEN requestHandler.handleRequest(message, context); @@ -260,8 +260,9 @@ void shouldLogEventForHandlerWhenEnvVariableSetToTrue() { // THEN File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"message\":\"Handler Event\"") - .contains("\"event\":{\"awsRegion\":\"eu-west-1\",\"body\":\"body\",\"messageId\":\"1234abcd\"}"); + .contains("\"message\":\"Handler Event\"") + .contains( + "\"event\":{\"awsRegion\":\"eu-central-1\",\"body\":\"body\",\"messageId\":\"1234abcd\"}"); } finally { LoggingConstants.POWERTOOLS_LOG_EVENT = false; } @@ -288,7 +289,10 @@ void shouldLogEventAsStringForStreamHandler() throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); // WHEN - requestStreamHandler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(Collections.singletonMap("key", "value"))), output, context); + requestStreamHandler.handleRequest( + new ByteArrayInputStream( + new ObjectMapper().writeValueAsBytes(Collections.singletonMap("key", "value"))), + output, context); // THEN assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) @@ -345,7 +349,8 @@ void shouldLogResponseForStreamHandler() throws IOException { String input = "<user><firstName>Bob</firstName><lastName>The Sponge</lastName></user>"; // WHEN - requestStreamHandler.handleRequest(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)), output, context); + requestStreamHandler.handleRequest(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)), output, + context); // THEN assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) @@ -353,8 +358,8 @@ void shouldLogResponseForStreamHandler() throws IOException { File logFile = new File("target/logfile.json"); assertThat(contentOf(logFile)) - .contains("\"message\":\"Handler Response\"") - .contains("\"response\":\""+input+"\""); + .contains("\"message\":\"Handler Response\"") + .contains("\"response\":\"" + input + "\""); } @Test @@ -368,7 +373,8 @@ void shouldLogThreadInfo() { String result = new String(encoded, StandardCharsets.UTF_8); // THEN - assertThat(result).contains("\"thread\":\"main\",\"thread_id\":"+ Thread.currentThread().getId() +",\"thread_priority\":5"); + assertThat(result).contains( + "\"thread\":\"main\",\"thread_id\":" + Thread.currentThread().getId() + ",\"thread_priority\":5"); } @Test @@ -388,7 +394,7 @@ void shouldLogTimestampDifferently() { // THEN SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); simpleDateFormat.setTimeZone(TimeZone.getTimeZone(timeZone)); - assertThat(result).contains("\"timestamp\":\""+simpleDateFormat.format(date)+"\""); + assertThat(result).contains("\"timestamp\":\"" + simpleDateFormat.format(date) + "\""); } @Test @@ -396,7 +402,8 @@ void shouldLogException() { // GIVEN LambdaJsonEncoder encoder = new LambdaJsonEncoder(); encoder.start(); - LoggingEvent errorloggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Error", new IllegalStateException("Unexpected value"), null); + LoggingEvent errorloggingEvent = new LoggingEvent("fqcn", logger, Level.INFO, "Error", + new IllegalStateException("Unexpected value"), null); // WHEN byte[] encoded = encoder.encode(errorloggingEvent); @@ -406,7 +413,8 @@ void shouldLogException() { assertThat(result).contains("\"message\":\"Error\",\"error\":{") .contains("\"message\":\"Unexpected value\"") .contains("\"name\":\"java.lang.IllegalStateException\"") - .contains("\"stack\":\"[software.amazon.lambda.powertools.logging.internal.LambdaJsonEncoderTest.shouldLogException"); + .contains( + "\"stack\":\"[software.amazon.lambda.powertools.logging.internal.LambdaJsonEncoderTest.shouldLogException"); // WHEN (configure a custom throwableConverter) encoder = new LambdaJsonEncoder(); @@ -422,12 +430,4 @@ void shouldLogException() { .contains("\"stack\":\"java.lang.IllegalStateException: Unexpected value\\n"); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn( - "arn:aws:lambda:eu-west-1:012345678910:function:testFunction:1"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(1024); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index aba4664fe..751d195b5 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -18,8 +18,6 @@ import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; @@ -54,7 +52,6 @@ import org.junitpioneer.jupiter.ClearEnvironmentVariable; import org.junitpioneer.jupiter.SetEnvironmentVariable; import org.junitpioneer.jupiter.SetSystemProperty; -import org.mockito.Mock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; @@ -72,6 +69,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.logging.argument.StructuredArgument; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId; @@ -99,15 +97,13 @@ class LambdaLoggingAspectTest { private RequestStreamHandler requestStreamHandler; private RequestHandler<Object, Object> requestHandler; - @Mock private Context context; @BeforeEach void setUp() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException { - openMocks(this); MDC.clear(); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); + context = new TestLambdaContext(); requestHandler = new PowertoolsLogEnabled(); requestStreamHandler = new PowertoolsLogEnabledForStream(); resetLogLevel(Level.INFO); @@ -124,7 +120,7 @@ void setUp() throws IllegalAccessException, NoSuchMethodException, InvocationTar @AfterEach void cleanUp() throws IOException { - //Make sure file is cleaned up before running full stack logging regression + // Make sure file is cleaned up before running full stack logging regression FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } @@ -224,7 +220,8 @@ void shouldLogWarnWhenPowertoolsLevelEnvVarIsWarnAndLambdaLevelVarIsInfo() throw assertThat(LOG.isInfoEnabled()).isFalse(); assertThat(LOG.isWarnEnabled()).isTrue(); File logFile = new File("target/logfile.json"); - assertThat(contentOf(logFile)).doesNotContain(" does not match AWS Lambda Advanced Logging Controls minimum log level"); + assertThat(contentOf(logFile)) + .doesNotContain(" does not match AWS Lambda Advanced Logging Controls minimum log level"); } @Test @@ -241,7 +238,8 @@ void shouldLogInfoWhenPowertoolsLevelEnvVarIsInfoAndLambdaLevelVarIsWarn() throw assertThat(LOG.isInfoEnabled()).isTrue(); File logFile = new File("target/logfile.json"); // should log a warning as powertools level is lower than lambda level - assertThat(contentOf(logFile)).contains("Current log level (INFO) does not match AWS Lambda Advanced Logging Controls minimum log level (WARN). This can lead to data loss, consider adjusting them."); + assertThat(contentOf(logFile)).contains( + "Current log level (INFO) does not match AWS Lambda Advanced Logging Controls minimum log level (WARN). This can lead to data loss, consider adjusting them."); } @Test @@ -265,11 +263,11 @@ void shouldSetLambdaContextWhenEnabled() { assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) - .containsEntry(FUNCTION_ARN.getName(), "testArn") - .containsEntry(FUNCTION_MEMORY_SIZE.getName(), "10") + .containsEntry(FUNCTION_ARN.getName(), "arn:aws:lambda:us-east-1:123456789012:function:test") + .containsEntry(FUNCTION_MEMORY_SIZE.getName(), "128") .containsEntry(FUNCTION_VERSION.getName(), "1") - .containsEntry(FUNCTION_NAME.getName(), "testFunction") - .containsEntry(FUNCTION_REQUEST_ID.getName(), "RequestId") + .containsEntry(FUNCTION_NAME.getName(), "test-function") + .containsEntry(FUNCTION_REQUEST_ID.getName(), "test-request-id") .containsKey(FUNCTION_COLD_START.getName()) .containsKey(SERVICE.getName()); } @@ -278,30 +276,30 @@ void shouldSetLambdaContextWhenEnabled() { void shouldSetLambdaContextForStreamHandlerWhenEnabled() throws IOException { requestStreamHandler = new PowertoolsLogEnabledForStream(); - requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), + requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), context); assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) - .containsEntry(FUNCTION_ARN.getName(), "testArn") - .containsEntry(FUNCTION_MEMORY_SIZE.getName(), "10") + .containsEntry(FUNCTION_ARN.getName(), "arn:aws:lambda:us-east-1:123456789012:function:test") + .containsEntry(FUNCTION_MEMORY_SIZE.getName(), "128") .containsEntry(FUNCTION_VERSION.getName(), "1") - .containsEntry(FUNCTION_NAME.getName(), "testFunction") - .containsEntry(FUNCTION_REQUEST_ID.getName(), "RequestId") + .containsEntry(FUNCTION_NAME.getName(), "test-function") + .containsEntry(FUNCTION_REQUEST_ID.getName(), "test-request-id") .containsKey(FUNCTION_COLD_START.getName()) .containsKey(SERVICE.getName()); } @Test void shouldSetColdStartFlagOnFirstCallNotOnSecondCall() throws IOException { - requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), + requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), context); assertThat(MDC.getCopyOfContextMap()) .hasSize(EXPECTED_CONTEXT_SIZE) .containsEntry(FUNCTION_COLD_START.getName(), "true"); - requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[]{}), new ByteArrayOutputStream(), + requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), context); assertThat(MDC.getCopyOfContextMap()) @@ -346,7 +344,7 @@ void shouldLogDebugWhenSamplingEqualsOne() { } @Test - void shouldLogDebugWhenSamplingEnvVarEqualsOne() throws IllegalAccessException { + void shouldLogDebugWhenSamplingEnvVarEqualsOne() { // GIVEN LoggingConstants.POWERTOOLS_SAMPLING_RATE = "1"; PowertoolsLogEnabled handler = new PowertoolsLogEnabled(); @@ -360,7 +358,7 @@ void shouldLogDebugWhenSamplingEnvVarEqualsOne() throws IllegalAccessException { } @Test - void shouldNotLogDebugWhenSamplingEnvVarIsTooBig() throws IllegalAccessException { + void shouldNotLogDebugWhenSamplingEnvVarIsTooBig() { // GIVEN LoggingConstants.POWERTOOLS_SAMPLING_RATE = "42"; @@ -378,7 +376,7 @@ void shouldNotLogDebugWhenSamplingEnvVarIsInvalid() { LoggingConstants.POWERTOOLS_SAMPLING_RATE = "NotANumber"; // WHEN - requestHandler.handleRequest(new Object(), context); + requestHandler.handleRequest(new Object(), context); // THEN File logFile = new File("target/logfile.json"); @@ -509,7 +507,7 @@ void shouldNotLogEventForHandlerWhenEnvVariableSetToFalse() { requestHandler.handleRequest(singletonList("ListOfOneElement"), context); // THEN - TestLogger logger = (TestLogger) ((PowertoolsLogEventEnvVar)requestHandler).getLogger(); + TestLogger logger = (TestLogger) ((PowertoolsLogEventEnvVar) requestHandler).getLogger(); assertThat(logger.getArguments()).isNull(); } @@ -521,7 +519,8 @@ void shouldLogEventForStreamHandler() throws IOException { Map<String, String> map = Collections.singletonMap("key", "value"); // WHEN - requestStreamHandler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(map)), output, context); + requestStreamHandler.handleRequest(new ByteArrayInputStream(new ObjectMapper().writeValueAsBytes(map)), output, + context); // THEN assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) @@ -586,7 +585,8 @@ void shouldLogResponseForStreamHandler() throws IOException { String input = "<user><firstName>Bob</firstName><lastName>The Sponge</lastName></user>"; // WHEN - requestStreamHandler.handleRequest(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)), output, context); + requestStreamHandler.handleRequest(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8)), output, + context); // THEN assertThat(new String(output.toByteArray(), StandardCharsets.UTF_8)) @@ -737,7 +737,8 @@ void testMultipleLoggingManagers_shouldWarnAndSelectFirstOne() throws Unsupporte String output = outputStream.toString("UTF-8"); assertThat(output) .contains("WARN. Multiple LoggingManagers were found on the classpath") - .contains("WARN. Make sure to have only one of powertools-logging-log4j OR powertools-logging-logback to your dependencies") + .contains( + "WARN. Make sure to have only one of powertools-logging-log4j OR powertools-logging-logback to your dependencies") .contains("WARN. Using the first LoggingManager found on the classpath: [" + list.get(0) + "]"); } @@ -757,19 +758,12 @@ void testNoLoggingManagers_shouldWarnAndCreateDefault() throws UnsupportedEncodi assertThat(output) .contains("ERROR. No LoggingManager was found on the classpath") .contains("ERROR. Applying default LoggingManager: POWERTOOLS_LOG_LEVEL variable is ignored") - .contains("ERROR. Make sure to add either powertools-logging-log4j or powertools-logging-logback to your dependencies"); + .contains( + "ERROR. Make sure to add either powertools-logging-log4j or powertools-logging-logback to your dependencies"); assertThat(loggingManager).isExactlyInstanceOf(DefautlLoggingManager.class); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - when(context.getAwsRequestId()).thenReturn("RequestId"); - } - private void resetLogLevel(Level level) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Method setLogLevels = LambdaLoggingAspect.class.getDeclaredMethod("setLogLevels", Level.class); diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 57da447dd..4bccab505 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -85,16 +85,6 @@ <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-junit-jupiter</artifactId> - <scope>test</scope> - </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> @@ -115,6 +105,13 @@ <artifactId>assertj-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> </dependencies> <profiles> @@ -126,7 +123,8 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <argLine>-Xlog:class+load=info:classesloaded.txt + <argLine> + -Xlog:class+load=info:classesloaded.txt --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -137,20 +135,14 @@ </profile> <profile> <id>generate-graalvm-files</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED @@ -162,13 +154,6 @@ </profile> <profile> <id>graalvm-native</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> @@ -191,40 +176,10 @@ <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg> - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg> - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg> - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg> - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg> - --initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg> - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg> - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg> - --initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg> - --initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg> - --initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> + <buildArg>--native-image-info</buildArg> + <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java index 1bf3b6a69..ecc7c13a1 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java @@ -34,7 +34,7 @@ import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.metrics.model.MetricUnit; -import software.amazon.lambda.powertools.metrics.testutils.TestContext; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; /** * Tests to verify the hierarchy of precedence for configuration: @@ -89,7 +89,7 @@ void annotationShouldOverrideBuilderAndEnvironment() throws Exception { .build(); RequestHandler<Map<String, Object>, String> handler = new HandlerWithMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When @@ -118,7 +118,7 @@ void builderShouldOverrideEnvironment() throws Exception { .build(); RequestHandler<Map<String, Object>, String> handler = new HandlerWithDefaultMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When @@ -141,7 +141,7 @@ void builderShouldOverrideEnvironment() throws Exception { void environmentVariablesShouldBeUsedWhenNoOverrides() throws Exception { // Given RequestHandler<Map<String, Object>, String> handler = new HandlerWithDefaultMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When @@ -166,7 +166,7 @@ void shouldUseDefaultsWhenNoConfiguration() throws Exception { .build(); RequestHandler<Map<String, Object>, String> handler = new HandlerWithDefaultMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java index a4fc0d61c..6c324221c 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java @@ -45,7 +45,7 @@ import software.amazon.lambda.powertools.metrics.model.DimensionSet; import software.amazon.lambda.powertools.metrics.model.MetricResolution; import software.amazon.lambda.powertools.metrics.model.MetricUnit; -import software.amazon.lambda.powertools.metrics.testutils.TestContext; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; class EmfMetricsLoggerTest { @@ -373,7 +373,7 @@ void shouldClearDefaultDimensions() throws Exception { @Test void shouldCaptureColdStartMetric() throws Exception { // Given - Context testContext = new TestContext(); + Context testContext = new TestLambdaContext(); // When metrics.captureColdStartMetric(testContext); @@ -425,7 +425,7 @@ void shouldReuseNamespaceForColdStartMetric() throws Exception { String customNamespace = "CustomNamespace"; metrics.setNamespace(customNamespace); - Context testContext = new TestContext(); + Context testContext = new TestLambdaContext(); DimensionSet dimensions = DimensionSet.of("CustomDim", "CustomValue"); @@ -497,7 +497,7 @@ void shouldNotFlushMetricsWhenDisabled() { @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_DISABLED", value = "true") void shouldNotCaptureColdStartMetricWhenDisabled() { // Given - Context testContext = new TestContext(); + Context testContext = new TestLambdaContext(); // When metrics.captureColdStartMetric(testContext); diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java index 068d19ccb..326dd2ffe 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java @@ -37,7 +37,7 @@ import software.amazon.lambda.powertools.metrics.Metrics; import software.amazon.lambda.powertools.metrics.MetricsFactory; import software.amazon.lambda.powertools.metrics.model.MetricUnit; -import software.amazon.lambda.powertools.metrics.testutils.TestContext; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; class LambdaMetricsAspectTest { @@ -74,7 +74,7 @@ void tearDown() throws Exception { void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { // Given RequestHandler<Map<String, Object>, String> handler = new HandlerWithMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When @@ -98,7 +98,7 @@ void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { void shouldOverrideEnvironmentVariablesWithAnnotation() throws Exception { // Given RequestHandler<Map<String, Object>, String> handler = new HandlerWithMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When @@ -120,7 +120,7 @@ void shouldOverrideEnvironmentVariablesWithAnnotation() throws Exception { void shouldUseEnvironmentVariablesWhenNoAnnotationOverrides() throws Exception { // Given RequestHandler<Map<String, Object>, String> handler = new HandlerWithDefaultMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When @@ -140,7 +140,7 @@ void shouldUseEnvironmentVariablesWhenNoAnnotationOverrides() throws Exception { void shouldCaptureColdStartMetricWhenConfigured() throws Exception { // Given RequestHandler<Map<String, Object>, String> handler = new HandlerWithColdStartMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When @@ -166,7 +166,7 @@ void shouldCaptureColdStartMetricWhenConfigured() throws Exception { void shouldNotIncludeServiceDimensionInColdStartMetricWhenServiceUndefined() throws Exception { // Given - no service name set, so it will use the default undefined value RequestHandler<Map<String, Object>, String> handler = new HandlerWithColdStartMetricsAnnotation(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When @@ -195,7 +195,7 @@ void shouldNotIncludeServiceDimensionInColdStartMetricWhenServiceUndefined() thr void shouldUseCustomFunctionNameWhenProvidedForColdStartMetric() throws Exception { // Given RequestHandler<Map<String, Object>, String> handler = new HandlerWithCustomFunctionName(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When @@ -228,7 +228,7 @@ void shouldUseCustomFunctionNameWhenProvidedForColdStartMetric() throws Exceptio void shouldUseServiceNameWhenProvidedForColdStartMetric() throws Exception { // Given RequestHandler<Map<String, Object>, String> handler = new HandlerWithServiceNameAndColdStart(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When @@ -247,7 +247,7 @@ void shouldUseServiceNameWhenProvidedForColdStartMetric() throws Exception { void shouldHaveNoEffectOnNonHandlerMethod() { // Given RequestHandler<Map<String, Object>, String> handler = new HandlerWithAnnotationOnWrongMethod(); - Context context = new TestContext(); + Context context = new TestLambdaContext(); Map<String, Object> input = new HashMap<>(); // When diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index d43221b5e..617e0cc00 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -14,8 +14,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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -43,11 +43,11 @@ <groupId>software.amazon.awssdk</groupId> <artifactId>url-connection-client</artifactId> </dependency> - <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> + <!-- Test dependencies --> <dependency> <groupId>org.junit.jupiter</groupId> @@ -93,14 +93,6 @@ <profiles> <profile> <id>generate-graalvm-files</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> @@ -108,7 +100,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -119,20 +113,12 @@ </profile> <profile> <id>graalvm-native</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -149,33 +135,10 @@ <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> <buildArg>--native-image-info</buildArg> <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> - <buildArg>-H:Log=registerResource:5</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 4d650c58b..ed92930fc 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -1,7 +1,7 @@ <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -57,6 +57,11 @@ <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> @@ -86,7 +91,6 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -97,7 +101,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig,experimental-class-define-support + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -112,7 +118,13 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> + <scope>test</scope> + </dependency> + + <!-- Required explicitly for @Captor ArgumentCaptor --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> <scope>test</scope> </dependency> </dependencies> @@ -121,7 +133,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -138,33 +150,10 @@ <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> <buildArg>--native-image-info</buildArg> <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> - <buildArg>-H:Log=registerResource:5</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> diff --git a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java index f50e88ec5..df3191632 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java @@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.function.BiFunction; + import org.junit.jupiter.api.Test; import org.mockito.Mockito; diff --git a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java index da01d7d9a..7f06ed412 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProviderTest.java @@ -18,15 +18,16 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; import static org.assertj.core.api.Assertions.assertThatRuntimeException; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.mockito.MockitoAnnotations.openMocks; import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; @@ -37,6 +38,7 @@ import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; +@ExtendWith(MockitoExtension.class) class AppConfigProviderTest { private static final String ENVIRONMENT_NAME = "test"; @@ -55,8 +57,6 @@ class AppConfigProviderTest { @BeforeEach void init() { - openMocks(this); - provider = AppConfigProvider.builder() .withClient(client) .withApplication(APPLICATION_NAME) diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 1834b229d..b8857b0c9 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -1,7 +1,7 @@ <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -58,6 +58,11 @@ <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> @@ -87,7 +92,6 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -98,7 +102,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb,experimental-class-define-support + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -113,7 +119,13 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> + <scope>test</scope> + </dependency> + + <!-- Required explicitly for @Captor ArgumentCaptor --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> <scope>test</scope> </dependency> </dependencies> @@ -122,7 +134,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -139,33 +151,10 @@ <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> <buildArg>--native-image-info</buildArg> <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> - <buildArg>-H:Log=registerResource:5</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java index 10d756c69..68d48b01c 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java @@ -23,13 +23,17 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.GetItemRequest; @@ -40,17 +44,23 @@ import software.amazon.lambda.powertools.parameters.dynamodb.exception.DynamoDbProviderSchemaException; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; +@ExtendWith(MockitoExtension.class) public class DynamoDbProviderTest { private final String tableName = "ddb-test-table"; + @Mock DynamoDbClient client; + @Mock TransformationManager transformationManager; + @Captor ArgumentCaptor<GetItemRequest> getItemValueCaptor; + @Captor ArgumentCaptor<QueryRequest> queryRequestCaptor; + private DynamoDbProvider provider; @BeforeEach @@ -60,7 +70,6 @@ public void init() { provider = new DynamoDbProvider(cacheManager, transformationManager, client, tableName); } - @Test public void getValue() { @@ -84,7 +93,6 @@ public void getValue() { assertThat(getItemValueCaptor.getValue().key().get("id").s()).isEqualTo(key); } - @Test public void getValueWithNullResultsReturnsNull() { // Arrange @@ -124,13 +132,11 @@ public void getValueWithMalformedRowThrows() { .item(responseData) .build()); // Act - Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> - { + Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> { provider.getValue(key); }); } - @Test public void getValues() { @@ -191,8 +197,7 @@ public void getMultipleValuesMissingSortKey_throwsException() { Mockito.when(client.query(queryRequestCaptor.capture())).thenReturn(response); // Assert - Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> - { + Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> { // Act provider.getMultipleValues(key); }); @@ -212,8 +217,7 @@ public void getValuesWithMalformedRowThrows() { Mockito.when(client.query(queryRequestCaptor.capture())).thenReturn(response); // Assert - Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> - { + Assertions.assertThrows(DynamoDbProviderSchemaException.class, () -> { // Act provider.getMultipleValues(key); }); @@ -227,6 +231,7 @@ public void testDynamoDBBuilderMissingTable_throwsException() { .withCacheManager(new CacheManager()) .build()); } + @Test public void testDynamoDBBuilder_withoutParameter_shouldHaveDefaultTransformationManager() { @@ -234,7 +239,7 @@ public void testDynamoDBBuilder_withoutParameter_shouldHaveDefaultTransformation DynamoDbProvider dynamoDbProvider = DynamoDbProvider.builder().withTable("test-table") .build(); // Assert - assertDoesNotThrow(()->dynamoDbProvider.withTransformation(json)); + assertDoesNotThrow(() -> dynamoDbProvider.withTransformation(json)); } } diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index ef032f0c3..b486a1bb3 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -1,7 +1,7 @@ <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -58,6 +58,11 @@ <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> @@ -87,7 +92,6 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -98,7 +102,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets,experimental-class-define-support + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -113,7 +119,13 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> + <scope>test</scope> + </dependency> + + <!-- Required explicitly for @Captor ArgumentCaptor --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> <scope>test</scope> </dependency> </dependencies> @@ -122,7 +134,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -139,33 +151,10 @@ <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> <buildArg>--native-image-info</buildArg> <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> - <buildArg>-H:Log=registerResource:5</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> diff --git a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java index a2607dd2c..d0b32874a 100644 --- a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java +++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java @@ -25,11 +25,13 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; + import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; @@ -37,6 +39,7 @@ import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; +@ExtendWith(MockitoExtension.class) public class SecretsProviderTest { @Mock @@ -54,7 +57,6 @@ public class SecretsProviderTest { @BeforeEach public void init() { - MockitoAnnotations.openMocks(this); cacheManager = new CacheManager(); provider = new SecretsProvider(cacheManager, transformationManager, client); } @@ -78,8 +80,8 @@ public void getValueBase64() { String key = "Key2"; String expectedValue = "Value2"; byte[] valueb64 = Base64.getEncoder().encode(expectedValue.getBytes()); - GetSecretValueResponse response = - GetSecretValueResponse.builder().secretBinary(SdkBytes.fromByteArray(valueb64)).build(); + GetSecretValueResponse response = GetSecretValueResponse.builder() + .secretBinary(SdkBytes.fromByteArray(valueb64)).build(); Mockito.when(client.getSecretValue(paramCaptor.capture())).thenReturn(response); String value = provider.getValue(key); @@ -90,16 +92,13 @@ public void getValueBase64() { @Test public void getMultipleValuesThrowsException() { - // Act & Assert assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path")) .withMessage("Impossible to get multiple values from AWS Secrets Manager"); - } @Test public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() { - // Act SecretsProvider secretsProvider = SecretsProvider.builder() .build(); @@ -111,11 +110,10 @@ public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() @Test public void testGetSecretsProvider_withoutParameter_shouldHaveDefaultTransformationManager() { - // Act SecretsProvider secretsProvider = SecretsProvider.builder() .build(); // Assert - assertDoesNotThrow(()->secretsProvider.withTransformation(json)); + assertDoesNotThrow(() -> secretsProvider.withTransformation(json)); } } diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index fcb7b5311..709ea6634 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -1,7 +1,7 @@ <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -58,6 +58,11 @@ <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> @@ -101,7 +106,6 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -112,7 +116,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm,experimental-class-define-support + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -127,7 +133,13 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> + <scope>test</scope> + </dependency> + + <!-- Required explicitly for @Captor ArgumentCaptor --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> <scope>test</scope> </dependency> </dependencies> @@ -136,7 +148,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -153,33 +165,10 @@ <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> <buildArg>--native-image-info</buildArg> <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> - <buildArg>-H:Log=registerResource:5</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> @@ -187,4 +176,4 @@ </build> </profile> </profiles> -</project> \ No newline at end of file +</project> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index abd2a02d2..6dcf2c4ae 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -1,7 +1,7 @@ <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>software.amazon.lambda</groupId> @@ -50,6 +50,11 @@ <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> @@ -97,7 +102,6 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> <scope>test</scope> </dependency> </dependencies> @@ -108,7 +112,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -123,7 +129,13 @@ <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> + <scope>test</scope> + </dependency> + + <!-- Required explicitly for @Captor ArgumentCaptor --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> <scope>test</scope> </dependency> </dependencies> @@ -132,7 +144,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -149,33 +161,10 @@ <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> <buildArg>--native-image-info</buildArg> <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> - <buildArg>-H:Log=registerResource:5</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java index 5fa740253..cbc8f5b30 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java @@ -20,7 +20,6 @@ import static java.time.temporal.ChronoUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.mockito.MockitoAnnotations.openMocks; import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; @@ -30,8 +29,10 @@ import java.util.Base64; import java.util.HashMap; import java.util.Map; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; + import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.ObjectToDeserialize; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; @@ -43,13 +44,10 @@ public class BaseProviderTest { CacheManager cacheManager; TransformationManager transformationManager; BasicProvider provider; - boolean getFromStore = false; @BeforeEach public void setup() { - openMocks(this); - clock = Clock.systemDefaultZone(); cacheManager = new CacheManager(); transformationManager = new TransformationManager(); @@ -197,8 +195,8 @@ public void get_basicTransformation_shouldTransformInString() { public void get_complexTransformation_shouldTransformInObject() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); - ObjectToDeserialize objectToDeserialize = - provider.withTransformation(json).get("foo", ObjectToDeserialize.class); + ObjectToDeserialize objectToDeserialize = provider.withTransformation(json).get("foo", + ObjectToDeserialize.class); assertThat(objectToDeserialize).matches( o -> o.getFoo().equals("Foo") diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java index 7d790d140..6b3cf7641 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java @@ -19,17 +19,19 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; import java.util.ArrayList; import java.util.List; import java.util.Map; + import org.assertj.core.data.MapEntry; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient; import software.amazon.awssdk.services.secretsmanager.model.GetSecretValueRequest; @@ -43,27 +45,26 @@ import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider; import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; +@ExtendWith(MockitoExtension.class) public class ParamProvidersIntegrationTest { - @Mock SsmClient ssmClient; @Mock DynamoDbClient ddbClient; + @Captor ArgumentCaptor<GetParameterRequest> ssmParamCaptor; + @Captor ArgumentCaptor<GetParametersByPathRequest> ssmParamByPathCaptor; + @Mock SecretsManagerClient secretsManagerClient; + @Captor ArgumentCaptor<GetSecretValueRequest> secretsCaptor; - @BeforeEach - public void setup() throws IllegalAccessException { - openMocks(this); - } - @Test public void ssmProvider_get() { SSMProvider ssmProvider = SSMProvider.builder() diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index d6cc33891..7e4e2af15 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -14,8 +14,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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -54,6 +54,11 @@ <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> @@ -93,14 +98,6 @@ <profiles> <profile> <id>generate-graalvm-files</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> @@ -108,7 +105,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization,experimental-class-define-support</argLine> + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-serialization,experimental-class-define-support</argLine> </configuration> </plugin> </plugins> @@ -116,20 +115,12 @@ </profile> <profile> <id>graalvm-native</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -141,37 +132,15 @@ </execution> </executions> <configuration> - <agent> - <enabled>true</enabled> - <defaultMode>Standard</defaultMode> - </agent> <imageName>powertools-serialization</imageName> <buildArgs> + <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> + <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> + <buildArg>--native-image-info</buildArg> + <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index cb7f8218f..67de0be7d 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -14,8 +14,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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>powertools-tracing</artifactId> @@ -87,8 +87,10 @@ <scope>test</scope> </dependency> <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + <type>test-jar</type> <scope>test</scope> </dependency> <dependency> @@ -121,14 +123,6 @@ <profiles> <profile> <id>generate-graalvm-files</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> @@ -136,7 +130,9 @@ <artifactId>maven-surefire-plugin</artifactId> <version>3.5.3</version> <configuration> - <argLine>-Dmockito.mock.maker=subclass -Dorg.graalvm.nativeimage.imagecode=agent -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing,experimental-class-define-support + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing,experimental-class-define-support --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED </argLine> @@ -147,20 +143,12 @@ </profile> <profile> <id>graalvm-native</id> - <dependencies> - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-subclass</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - </dependencies> <build> <plugins> <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> <!-- or newer version --> + <version>0.11.0</version> <extensions>true</extensions> <executions> <execution> @@ -178,35 +166,10 @@ <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> <buildArg>--enable-url-protocols=http</buildArg> <buildArg>--no-fallback</buildArg> - <buildArg>-Dorg.graalvm.nativeimage.imagecode=agent</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.ClassFileVersion:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.dispatcher.JavaDispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.Invoker$Dispatcher:rerun</buildArg> - <buildArg>-H:ClassInitialization=net.bytebuddy.utility.GraalImageCode:rerun</buildArg> - <buildArg>-H:IncludeResources=version.properties</buildArg> - <buildArg>-H:IncludeResources=unreadable.properties</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.simple.SimpleLogger</buildArg> - <buildArg>--initialize-at-build-time=org.slf4j.LoggerFactory</buildArg> - <buildArg>--initialize-at-build-time=org.junit.Ignore</buildArg> - <buildArg>--initialize-at-build-time=java.lang.annotation.Annotation</buildArg> - <buildArg>--initialize-at-build-time=org.junit.runners.model.FrameworkField</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$AbstractBase</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.type.TypeDescription$ForLoadedType</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.description.method.MethodDescription$ForLoadedMethod</buildArg> - <buildArg>--initialize-at-build-time=net.bytebuddy.implementation.bind.annotation.Super$Instantiation$2</buildArg> - <buildArg> - --trace-class-initialization=net.bytebuddy.description.type.TypeDescription$ForLoadedType,net.bytebuddy.description.method.MethodDescription$ForLoadedMethod,net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable - </buildArg> <buildArg>--verbose</buildArg> <buildArg>--native-image-info</buildArg> <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> - <buildArg>-H:Log=registerResource:5</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> </buildArgs> </configuration> </plugin> diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java index 01f25f37a..db9807dbd 100644 --- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java +++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/TracingUtilsTest.java @@ -16,17 +16,15 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import static software.amazon.lambda.powertools.tracing.TracingUtils.withEntitySubsegment; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.xray.AWSXRay; -import com.amazonaws.xray.entities.Entity; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.amazonaws.xray.AWSXRay; +import com.amazonaws.xray.entities.Entity; + class TracingUtilsTest { @BeforeEach void setUp() { @@ -55,8 +53,7 @@ void shouldSetAnnotationOnCurrentSubSegment() { .contains( entry("stringKey", "val"), entry("numberKey", 10), - entry("booleanKey", false) - ); + entry("booleanKey", false)); } @Test @@ -76,10 +73,8 @@ void shouldSetMetadataOnCurrentSubSegment() { assertThat(AWSXRay.getTraceEntity().getMetadata()) .hasSize(1) .containsKey("service_undefined") - .satisfies(map -> - assertThat(map.get("service_undefined")) - .containsEntry("key", "val") - ); + .satisfies(map -> assertThat(map.get("service_undefined")) + .containsEntry("key", "val")); } @Test @@ -92,21 +87,14 @@ void shouldNotSetMetaDataIfNoCurrentSubSegment() { @Test void shouldInvokeCodeBlockWrappedWithinSubsegment() { - Context test = mock(Context.class); - - TracingUtils.withSubsegment("testSubSegment", subsegment -> - { + TracingUtils.withSubsegment("testSubSegment", subsegment -> { subsegment.putAnnotation("key", "val"); subsegment.putMetadata("key", "val"); - test.getFunctionName(); }); - verify(test).getFunctionName(); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getName()) .isEqualTo("## testSubSegment"); @@ -142,21 +130,14 @@ void shouldAddAnnotationIfValidCharactersInKey() { @Test void shouldInvokeCodeBlockWrappedWithinNamespacedSubsegment() { - Context test = mock(Context.class); - - TracingUtils.withSubsegment("testNamespace", "testSubSegment", subsegment -> - { + TracingUtils.withSubsegment("testNamespace", "testSubSegment", subsegment -> { subsegment.putAnnotation("key", "val"); subsegment.putMetadata("key", "val"); - test.getFunctionName(); }); - verify(test).getFunctionName(); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getName()) .isEqualTo("## testSubSegment"); @@ -174,25 +155,18 @@ void shouldInvokeCodeBlockWrappedWithinNamespacedSubsegment() { @Test void shouldInvokeCodeBlockWrappedWithinEntitySubsegment() throws InterruptedException { - Context test = mock(Context.class); - Entity traceEntity = AWSXRay.getTraceEntity(); - Thread thread = new Thread(() -> withEntitySubsegment("testSubSegment", traceEntity, subsegment -> - { + Thread thread = new Thread(() -> withEntitySubsegment("testSubSegment", traceEntity, subsegment -> { subsegment.putAnnotation("key", "val"); - test.getFunctionName(); })); thread.start(); thread.join(); - verify(test).getFunctionName(); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getName()) .isEqualTo("## testSubSegment"); @@ -207,26 +181,19 @@ void shouldInvokeCodeBlockWrappedWithinEntitySubsegment() throws InterruptedExce @Test void shouldInvokeCodeBlockWrappedWithinNamespacedEntitySubsegment() throws InterruptedException { - Context test = mock(Context.class); - Entity traceEntity = AWSXRay.getTraceEntity(); - Thread thread = - new Thread(() -> withEntitySubsegment("testNamespace", "testSubSegment", traceEntity, subsegment -> - { + Thread thread = new Thread( + () -> withEntitySubsegment("testNamespace", "testSubSegment", traceEntity, subsegment -> { subsegment.putAnnotation("key", "val"); - test.getFunctionName(); })); thread.start(); thread.join(); - verify(test).getFunctionName(); - assertThat(AWSXRay.getTraceEntity().getSubsegments()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getName()) .isEqualTo("## testSubSegment"); diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java index 1d108ed5f..4d2e481b1 100644 --- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java +++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java @@ -18,8 +18,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatNoException; import static org.assertj.core.api.Assertions.catchThrowable; -import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -29,7 +27,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.SetEnvironmentVariable; -import org.mockito.Mock; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; @@ -37,6 +34,7 @@ import com.amazonaws.xray.AWSXRay; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.tracing.handlers.PowerToolDisabled; import software.amazon.lambda.powertools.tracing.handlers.PowerToolDisabledForStream; import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabled; @@ -50,7 +48,6 @@ import software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabledWithNoMetaData; import software.amazon.lambda.powertools.tracing.nonhandler.PowerToolNonHandler; - @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_RESPONSE", value = "false") @SetEnvironmentVariable(key = "POWERTOOLS_TRACER_CAPTURE_ERROR", value = "false") class LambdaTracingAspectTest { @@ -58,14 +55,12 @@ class LambdaTracingAspectTest { private RequestStreamHandler streamHandler; private PowerToolNonHandler nonHandlerMethod; - @Mock private Context context; @BeforeEach void setUp() throws IllegalAccessException { - openMocks(this); writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); - setupContext(); + context = new TestLambdaContext(); requestHandler = new PowerTracerToolEnabled(); streamHandler = new PowerTracerToolEnabledForStream(); nonHandlerMethod = new PowerToolNonHandler(); @@ -86,8 +81,7 @@ void shouldCaptureNonHandlerMethod() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .anySatisfy(segment -> - assertThat(segment.getName()).isEqualTo("## doSomething")); + .anySatisfy(segment -> assertThat(segment.getName()).isEqualTo("## doSomething")); } @Test @@ -99,8 +93,7 @@ void shouldCaptureNonHandlerMethodWithCustomSegmentName() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .anySatisfy(segment -> - assertThat(segment.getName()).isEqualTo("custom")); + .anySatisfy(segment -> assertThat(segment.getName()).isEqualTo("custom")); } @Test @@ -112,15 +105,14 @@ void shouldCaptureTraces() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) .containsEntry("Service", "lambdaHandler"); assertThat(subsegment.getMetadata()) - .hasSize(0); + .isEmpty(); }); } @@ -134,8 +126,7 @@ void shouldCaptureTracesWithResponseMetadata() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -159,8 +150,7 @@ void shouldCaptureTracesWithExceptionMetaData() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -185,8 +175,7 @@ void shouldCaptureTracesForStream() throws IOException { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -204,8 +193,7 @@ void shouldCaptureTracesForStreamWithResponseMetadata() throws IOException { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -246,8 +234,7 @@ void shouldCaptureTracesWithNoMetadata() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -269,8 +256,7 @@ void shouldCaptureTracesForStreamWithNoMetadata() throws IOException { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -291,8 +277,7 @@ void shouldNotCaptureTracesIfDisabledViaEnvironmentVariable() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -315,8 +300,7 @@ void shouldCaptureTracesIfExplicitlyEnabledAndEnvironmentVariableIsDisabled() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -339,8 +323,7 @@ void shouldCaptureTracesForSelfReferencingReturnTypesViaCustomMapper() { assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getMetadata()) .hasSize(1) .containsKey("lambdaHandler"); @@ -368,8 +351,7 @@ void shouldCaptureTracesIfExplicitlyEnabledBothAndEnvironmentVariableIsDisabled( assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -396,8 +378,7 @@ void shouldNotCaptureTracesWithExceptionMetaDataIfDisabledViaEnvironmentVariable assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -420,8 +401,7 @@ void shouldCaptureTracesWithExceptionMetaDataEnabledExplicitlyAndEnvironmentVari assertThat(AWSXRay.getTraceEntity().getSubsegmentsCopy()) .hasSize(1) - .allSatisfy(subsegment -> - { + .allSatisfy(subsegment -> { assertThat(subsegment.getAnnotations()) .hasSize(2) .containsEntry("ColdStart", true) @@ -437,10 +417,4 @@ void shouldCaptureTracesWithExceptionMetaDataEnabledExplicitlyAndEnvironmentVari }); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(10); - } } From 5647e0d4c64e96e7f582b9a7fc19b1182eb54c8b Mon Sep 17 00:00:00 2001 From: ARYAN RAJ <nikhilaryan0928@gmail.com> Date: Mon, 25 Aug 2025 19:55:29 +0530 Subject: [PATCH 387/577] chore(gitignore): add .kiro, .claude, .amazonq to prevent deletion (#2078) * add: .kiro, .claude, .amazonq to .gitignore to prevent deletion * docs: add .github/instructions explaining ignored folders * chore: remove .github/instructions * chore(gitignore): add .github/instructions to ignore local instructions file * Update .gitignore Co-authored-by: Philipp Page <philipp.page@yahoo.de> * Update .gitignore Co-authored-by: Philipp Page <philipp.page@yahoo.de> --------- Co-authored-by: Andrea Amorosi <dreamorosi@gmail.com> Co-authored-by: Philipp Page <philipp.page@yahoo.de> --- .gitignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 0972d7449..eb2ea4f18 100644 --- a/.gitignore +++ b/.gitignore @@ -111,3 +111,10 @@ example/HelloWorldFunction/build build/ .terraform* terraform.tfstate* + +# LLMs +.kiro/ +.claude/ +.amazonq/ +.github/instructions + From f273dcc89f10a25b091e1ac169495fa31c2c0489 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Aug 2025 08:56:44 -0300 Subject: [PATCH 388/577] chore: bump aws.sdk.version from 2.32.28 to 2.32.30 (#2089) Bumps `aws.sdk.version` from 2.32.28 to 2.32.30. Updates `software.amazon.awssdk:bom` from 2.32.28 to 2.32.30 Updates `software.amazon.awssdk:http-client-spi` from 2.32.28 to 2.32.30 Updates `software.amazon.awssdk:url-connection-client` from 2.32.26 to 2.32.30 Updates `software.amazon.awssdk:dynamodb` from 2.32.28 to 2.32.30 Updates `software.amazon.awssdk:s3` from 2.32.26 to 2.32.30 Updates `software.amazon.awssdk:lambda` from 2.32.28 to 2.32.30 Updates `software.amazon.awssdk:kinesis` from 2.32.26 to 2.32.30 Updates `software.amazon.awssdk:cloudwatch` from 2.32.28 to 2.32.30 Updates `software.amazon.awssdk:xray` from 2.32.28 to 2.32.30 Updates `software.amazon.awssdk:sqs` from 2.32.26 to 2.32.30 Updates `software.amazon.awssdk:cloudformation` from 2.32.28 to 2.32.30 Updates `software.amazon.awssdk:sts` from 2.32.28 to 2.32.30 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.30 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.30 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.30 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.30 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.30 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.30 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.30 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.30 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.30 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.30 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.30 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.30 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index cfb757440..b92f458b0 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.28</aws.sdk.version> + <aws.sdk.version>2.32.30</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index f6ccb5056..f2e9b1cdf 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.32.28</aws.sdk.version> + <aws.sdk.version>2.32.30</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 8200b6ca3..8cc580958 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -20,7 +20,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.13.1</aspectj.plugin.version> <maven.compiler.version>3.11.0</maven.compiler.version> - <aws.sdk.version>2.32.28</aws.sdk.version> + <aws.sdk.version>2.32.30</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> From 7594e5ae4b35c113ea8c82188b206fbe91df78c4 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Wed, 27 Aug 2025 15:21:02 +0200 Subject: [PATCH 389/577] feat(graalvm): GraalVM support for Idempotency utility (#2080) * Add Idempotency GraalVM example and remove unncessary dependencies from pom.xml * Add native maven profiles to idempotency-core. * Configure GraalVM profile for idempotency-dynamodb. Refactor unit tests to treat DynamoDBLocal as external process instead of starting it via JVM which is not compatible with GraalVM. * Add GRM data for idempotency dynamodb. * Remove verbose register resource logs. * Remove redundant APIGatewayProxyResponseEvent reflect metadata. * Remove unncessary includeGroupIds. * Add back Log4j2PluginCacheFileTransformer * Address sonar findings. * Fix sonar findings. * Use aws-powertools_ubuntu-latest_8-core for graalvm-build. * Enable Idempotency E2E test for GraalVM. * Add GraalVM support to Idempotency E2E test handler. * Add required Lambda dependencies for native images. * Increase Idempotency E2E test timeout. * Add --platform linux/amd64 to bundling options. --- .github/workflows/check-build.yml | 2 +- examples/README.md | 30 +- examples/pom.xml | 3 +- .../sam-graalvm/Dockerfile | 14 + .../sam-graalvm/Makefile | 5 + .../sam-graalvm/README.md | 61 ++++ .../sam-graalvm/pom.xml | 167 +++++++++ .../sam-graalvm/src/main/config/bootstrap | 4 + .../src/main/java/helloworld/App.java | 0 .../aws-lambda-java-core/reflect-config.json | 13 + .../reflect-config.json | 30 ++ .../jni-config.json | 11 + .../native-image.properties | 1 + .../reflect-config.json | 34 ++ .../resource-config.json | 19 + .../reflect-config.json | 25 ++ .../helloworld/reflect-config.json | 11 + .../helloworld/resource-config.json | 7 + .../src/main/resources/log4j2.xml | 0 .../sam-graalvm/template.yaml | 60 ++++ .../{ => sam}/README.md | 0 .../{ => sam}/pom.xml | 54 +-- .../sam/src/main/java/helloworld/App.java | 142 ++++++++ .../sam/src/main/resources/log4j2.xml | 16 + .../{ => sam}/template.yaml | 0 pom.xml | 5 + .../handlers/idempotency/pom.xml | 24 +- .../aws-lambda-java-core/reflect-config.json | 13 + .../reflect-config.json | 35 ++ .../jni-config.json | 11 + .../native-image.properties | 1 + .../reflect-config.json | 61 ++++ .../resource-config.json | 19 + .../reflect-config.json | 25 ++ .../reflect-config.json | 20 ++ .../resource-config.json | 7 + powertools-e2e-tests/pom.xml | 1 + .../lambda/powertools/IdempotencyE2ET.java | 2 +- .../testutils/DockerConfiguration.java | 2 + .../powertools-idempotency-core/pom.xml | 95 ++++- .../internal/IdempotencyAspectTest.java | 68 ++-- .../internal/cache/LRUCacheTest.java | 8 +- .../persistence/BasePersistenceStoreTest.java | 168 ++++----- .../test/resources/simplelogger.properties | 7 + .../dynamodb-local-metadata.json | 1 - .../powertools-idempotency-dynamodb/pom.xml | 164 ++++++++- .../reflect-config.json | 325 ++++++++++++++++++ .../resource-config.json | 27 ++ .../persistence/dynamodb/DynamoDBConfig.java | 69 +--- .../DynamoDBPersistenceStoreTest.java | 192 +++++------ .../persistence/dynamodb/IdempotencyTest.java | 16 +- .../test/resources/simplelogger.properties | 7 + 52 files changed, 1697 insertions(+), 385 deletions(-) create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/Dockerfile create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/Makefile create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/README.md create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/pom.xml create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/config/bootstrap rename examples/powertools-examples-idempotency/{ => sam-graalvm}/src/main/java/helloworld/App.java (100%) create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json rename examples/powertools-examples-idempotency/{ => sam-graalvm}/src/main/resources/log4j2.xml (100%) create mode 100644 examples/powertools-examples-idempotency/sam-graalvm/template.yaml rename examples/powertools-examples-idempotency/{ => sam}/README.md (100%) rename examples/powertools-examples-idempotency/{ => sam}/pom.xml (71%) create mode 100644 examples/powertools-examples-idempotency/sam/src/main/java/helloworld/App.java create mode 100644 examples/powertools-examples-idempotency/sam/src/main/resources/log4j2.xml rename examples/powertools-examples-idempotency/{ => sam}/template.yaml (100%) create mode 100644 powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json create mode 100644 powertools-idempotency/powertools-idempotency-core/src/test/resources/simplelogger.properties delete mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/dynamodb-local-metadata.json create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/resource-config.json create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/src/test/resources/simplelogger.properties diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 98e1eae6e..3abb1440c 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -87,7 +87,7 @@ jobs: mvn -B -q install --file pom.xml graalvm-build: - runs-on: ubuntu-latest + runs-on: aws-powertools_ubuntu-latest_8-core steps: - id: checkout name: Checkout repository diff --git a/examples/README.md b/examples/README.md index 41640b5ad..727bc652e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,26 +1,35 @@ # Powertools for AWS Lambda (Java) Examples This directory holds example projects demoing different components of the Powertools for AWS Lambda (Java). + Each example can be copied from its subdirectory and used independently of the rest of this repository. ## Examples * [powertools-examples-core-utilities](powertools-examples-core-utilities) - Demonstrates the core logging, tracing, and metrics modules with different build tools and languages * [CDK](./powertools-examples-core-utilities/cdk) - * [Gradle](./powertools-examples-core-utilities/gradle) * [SAM](./powertools-examples-core-utilities/sam) + * [SAM GraalVM](./powertools-examples-core-utilities/sam-graalvm) * [Serverless](./powertools-examples-core-utilities/serverless) + * [Terraform](./powertools-examples-core-utilities/terraform) + * [Gradle](./powertools-examples-core-utilities/gradle) * [Kotlin](./powertools-examples-core-utilities/kotlin) * [powertools-examples-idempotency](powertools-examples-idempotency) - An idempotent HTTP API + * [SAM](./powertools-examples-idempotency/sam) + * [SAM GraalVM](./powertools-examples-idempotency/sam-graalvm) * [powertools-examples-parameters](powertools-examples-parameters) - Uses the parameters module to provide runtime parameters to a function + * [SAM](./powertools-examples-parameters/sam) + * [SAM GraalVM](./powertools-examples-parameters/sam-graalvm) * [powertools-examples-serialization](powertools-examples-serialization) - Uses the serialization module to serialize and deserialize API Gateway & SQS payloads + * [SAM](./powertools-examples-serialization/sam) + * [SAM GraalVM](./powertools-examples-serialization/sam-graalvm) * [powertools-examples-validation](powertools-examples-validation) - Uses the validation module to validate user requests received via API Gateway * [powertools-examples-cloudformation](powertools-examples-cloudformation) - Deploys a Cloudformation custom resource * [powertools-examples-batch](powertools-examples-batch) - Examples for each of the different batch processing deployments +* [powertools-examples-kafka](powertools-examples-kafka) - Examples for Kafka event processing ## Working with AWS Serverless Application Model (SAM) Examples -Many of the examples use [AWS Serverless Application Model](https://aws.amazon.com/serverless/sam/) (SAM). To get started -with them, you can use the SAM Command Line Interface (SAM CLI) to build it and deploy an example to AWS. +Many of the examples use [AWS Serverless Application Model](https://aws.amazon.com/serverless/sam/) (SAM). To get started with them, you can use the SAM Command Line Interface (SAM CLI) to build it and deploy an example to AWS. To use the SAM CLI, you need the following tools. @@ -29,17 +38,13 @@ To use the SAM CLI, you need the following tools. * Maven - [Install Maven](https://maven.apache.org/install.html) * Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community) -To learn more about SAM, -[check out the developer guide](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli.html). -You can use the CLI to [test events locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-invoke.html), -and [run the application locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-start-api.html), -amongst other things. +To learn more about SAM, [check out the developer guide](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli.html). You can use the CLI to [test events locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-invoke.html), and [run the application locally](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/using-sam-cli-local-start-api.html), amongst other things. To build and deploy an example application for the first time, run the following in your shell: ```bash # Switch to the directory containing an example for the powertools-idempotency module -$ cd powertools-examples-idempotency +$ cd powertools-examples-idempotency/sam # Build and deploy the example $ sam build @@ -56,7 +61,7 @@ The first command will build the source of your application. The second command You can find your API Gateway Endpoint URL in the output values displayed after deployment. -If you're not using SAM, you can look for examples for other tools under [powertools-examples-core](./powertools-examples-core) +If you're not using SAM, you can look for examples for other tools under [powertools-examples-core-utilities](./powertools-examples-core-utilities) ### External examples @@ -69,10 +74,9 @@ You can find more examples in the https://github.com/aws/aws-sam-cli-app-templat ### SAM - Other Tools -If you prefer to use an integrated development environment (IDE) to build and test your application, you can use the AWS Toolkit. -The AWS Toolkit is an open source plug-in for popular IDEs that uses the SAM CLI to build and deploy serverless applications on AWS. The AWS Toolkit also adds a simplified step-through debugging experience for Lambda function code. See the following links to get started. +If you prefer to use an integrated development environment (IDE) to build and test your application, you can use the AWS Toolkit. The AWS Toolkit is an open source plug-in for popular IDEs that uses the SAM CLI to build and deploy serverless applications on AWS. The AWS Toolkit also adds a simplified step-through debugging experience for Lambda function code. See the following links to get started. * [PyCharm](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html) * [IntelliJ](https://docs.aws.amazon.com/toolkit-for-jetbrains/latest/userguide/welcome.html) * [VS Code](https://docs.aws.amazon.com/toolkit-for-vscode/latest/userguide/welcome.html) -* [Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html) \ No newline at end of file +* [Visual Studio](https://docs.aws.amazon.com/toolkit-for-visual-studio/latest/user-guide/welcome.html) diff --git a/examples/pom.xml b/examples/pom.xml index 2c561b00f..554e97168 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -35,7 +35,8 @@ <module>powertools-examples-core-utilities/cdk/infra</module> <module>powertools-examples-core-utilities/serverless</module> <module>powertools-examples-core-utilities/terraform</module> - <module>powertools-examples-idempotency</module> + <module>powertools-examples-idempotency/sam</module> + <module>powertools-examples-idempotency/sam-graalvm</module> <module>powertools-examples-parameters/sam</module> <module>powertools-examples-parameters/sam-graalvm</module> <module>powertools-examples-serialization/sam</module> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/Dockerfile b/examples/powertools-examples-idempotency/sam-graalvm/Dockerfile new file mode 100644 index 000000000..dac9390e5 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/Dockerfile @@ -0,0 +1,14 @@ +# Use the official AWS SAM base image for Java 21 +FROM public.ecr.aws/sam/build-java21@sha256:a5554d68374e19450c6c88448516ac95a9acedc779f318040f5c230134b4e461 + +# Install GraalVM dependencies +RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz +RUN mv graalvm-jdk-21.* /usr/lib/graalvm + +# Make native image and mvn available on CLI +RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image +RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn + +# Set GraalVM as default +ENV JAVA_HOME=/usr/lib/graalvm +ENV PATH=/usr/lib/graalvm/bin:$PATH diff --git a/examples/powertools-examples-idempotency/sam-graalvm/Makefile b/examples/powertools-examples-idempotency/sam-graalvm/Makefile new file mode 100644 index 000000000..6fb4e537c --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/Makefile @@ -0,0 +1,5 @@ +build-IdempotencyFunction: + chmod +x target/hello-world + cp target/hello-world $(ARTIFACTS_DIR) # (ARTIFACTS_DIR --> https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/custom_make/DESIGN.md#implementation) + chmod +x src/main/config/bootstrap + cp src/main/config/bootstrap $(ARTIFACTS_DIR) diff --git a/examples/powertools-examples-idempotency/sam-graalvm/README.md b/examples/powertools-examples-idempotency/sam-graalvm/README.md new file mode 100644 index 000000000..1c44bd791 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/README.md @@ -0,0 +1,61 @@ +# Powertools for AWS Lambda (Java) - Idempotency Example with SAM on GraalVM + +This project contains an example of a Lambda function using the idempotency module of Powertools for AWS Lambda (Java). For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda-java/utilities/idempotency/). + +The example exposes a HTTP POST endpoint. When the user sends the address of a webpage to it, the endpoint fetches the contents of the URL and returns them to the user. + +Have a look at [App.java](src/main/java/helloworld/App.java) for the full details. + +## Build the sample application + +> [!NOTE] +> Building AWS Lambda packages on macOS (ARM64/Intel) for deployment on AWS Lambda (Linux x86_64 or ARM64) will result in incompatible binary dependencies that cause import errors at runtime. + +Choose the appropriate build method based on your operating system: + +### Build locally using Docker + +Recommended for macOS and Windows users: Cross-compile using Docker to match target platform of Lambda: + +```shell +docker build --platform linux/amd64 . -t powertools-examples-idempotency-sam-graalvm +docker run --platform linux/amd64 -it -v `pwd`:`pwd` -w `pwd` -v ~/.m2:/root/.m2 powertools-examples-idempotency-sam-graalvm mvn clean -Pnative-image package -DskipTests +sam build --use-container --build-image powertools-examples-idempotency-sam-graalvm +``` + +**Note**: The Docker run command mounts your local Maven cache (`~/.m2`) and builds the native binary with SNAPSHOT support, then SAM packages the pre-built binary. + +### Build on native OS + +For Linux users with GraalVM installed: + +```shell +export JAVA_HOME=<path to GraalVM> +mvn clean -Pnative-image package -DskipTests +sam build +``` + +## Deploy the sample application + +```shell +sam deploy +``` + +This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting started with SAM in [the examples directory](../../README.md) + +## Test the application + +```bash +curl -X POST https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/helloidem/ -H "Content-Type: application/json" -d '{"address": "https://checkip.amazonaws.com"}' +``` + +this should return the contents of the webpage, for instance: + +```json +{ "message": "hello world", "location": "123.123.123.1" } +``` + +- First call will execute the handleRequest normally, and store the response in the idempotency table (Look into DynamoDB) +- Second call (and next ones) will retrieve from the cache (if cache is enabled, which is by default) or from the store, the handler won't be called. Until the expiration happens (by default 1 hour). + +Check out [App.java](src/main/java/helloworld/App.java) to see how it works! diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml new file mode 100644 index 000000000..6abb743f9 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -0,0 +1,167 @@ +<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 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>software.amazon.lambda.examples</groupId> + <version>2.3.0</version> + <artifactId>powertools-examples-idempotency-sam-graalvm</artifactId> + <packaging>jar</packaging> + <name>Powertools for AWS Lambda (Java) - Examples - Idempotency GraalVM</name> + + <properties> + <maven.compiler.source>11</maven.compiler.source> + <maven.compiler.target>11</maven.compiler.target> + <aspectj.version>1.9.20.1</aspectj.version> + </properties> + + <dependencies> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-tracing</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging-log4j</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-idempotency-dynamodb</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + <version>1.3.0</version> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-events</artifactId> + <version>3.16.1</version> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + <version>2.8.3</version> + </dependency> + + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjrt</artifactId> + <version>${aspectj.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>dev.aspectj</groupId> + <artifactId>aspectj-maven-plugin</artifactId> + <version>1.14.1</version> + <configuration> + <source>${maven.compiler.source}</source> + <target>${maven.compiler.target}</target> + <complianceLevel>${maven.compiler.target}</complianceLevel> + <aspectLibraries> + <aspectLibrary> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-tracing</artifactId> + </aspectLibrary> + <aspectLibrary> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging</artifactId> + </aspectLibrary> + <aspectLibrary> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-idempotency-core</artifactId> + </aspectLibrary> + </aspectLibraries> + </configuration> + <executions> + <execution> + <goals> + <goal>compile</goal> + </goals> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjtools</artifactId> + <version>${aspectj.version}</version> + </dependency> + </dependencies> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>3.6.0</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <createDependencyReducedPom>false</createDependencyReducedPom> + <transformers> + <transformer + implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer" /> + </transformers> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> + <version>0.2.0</version> + </dependency> + </dependencies> + </plugin> + <!-- Don't deploy the example --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <version>3.1.4</version> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + <version>0.11.0</version> + <extensions>true</extensions> + <executions> + <execution> + <id>build-native</id> + <goals> + <goal>build</goal> + </goals> + <phase>package</phase> + </execution> + </executions> + <configuration> + <imageName>hello-world</imageName> + <mainClass>com.amazonaws.services.lambda.runtime.api.client.AWSLambda</mainClass> + <buildArgs> + <!-- required for AWS Lambda Runtime Interface Client --> + <arg>--enable-url-protocols=http,https</arg> + <arg>--add-opens java.base/java.util=ALL-UNNAMED</arg> + </buildArgs> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/config/bootstrap b/examples/powertools-examples-idempotency/sam-graalvm/src/main/config/bootstrap new file mode 100644 index 000000000..8e7928cd3 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/config/bootstrap @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +./hello-world $_HANDLER \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/src/main/java/helloworld/App.java b/examples/powertools-examples-idempotency/sam-graalvm/src/main/java/helloworld/App.java similarity index 100% rename from examples/powertools-examples-idempotency/src/main/java/helloworld/App.java rename to examples/powertools-examples-idempotency/sam-graalvm/src/main/java/helloworld/App.java diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..b60cce0ea --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,30 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..10152cc64 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,34 @@ +[ + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"<init>","parameterTypes":[] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields":[{"name":"logger"}] + }, + { + "name":"java.lang.Void", + "methods":[{"name":"<init>","parameterTypes":[] }] + }, + { + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] + }, + { + "name":"jdk.internal.module.IllegalAccessLogger", + "fields":[{"name":"logger"}] + }, + { + "name":"sun.misc.Unsafe", + "fields":[{"name":"theUnsafe"}] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json new file mode 100644 index 000000000..d01f93780 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/reflect-config.json @@ -0,0 +1,11 @@ +[ + { + "name": "helloworld.App", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/helloworld/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/examples/powertools-examples-idempotency/src/main/resources/log4j2.xml b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/log4j2.xml similarity index 100% rename from examples/powertools-examples-idempotency/src/main/resources/log4j2.xml rename to examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/log4j2.xml diff --git a/examples/powertools-examples-idempotency/sam-graalvm/template.yaml b/examples/powertools-examples-idempotency/sam-graalvm/template.yaml new file mode 100644 index 000000000..5ffd70255 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam-graalvm/template.yaml @@ -0,0 +1,60 @@ +AWSTemplateFormatVersion: "2010-09-09" +Transform: AWS::Serverless-2016-10-31 +Description: > + Idempotency demo with GraalVM + +Globals: + Function: + Timeout: 20 + MemorySize: 512 + Tracing: Active + Environment: + Variables: + POWERTOOLS_LOG_LEVEL: INFO + POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 + POWERTOOLS_LOGGER_LOG_EVENT: true + +Resources: + IdempotencyTable: + Type: AWS::DynamoDB::Table + Properties: + AttributeDefinitions: + - AttributeName: id + AttributeType: S + KeySchema: + - AttributeName: id + KeyType: HASH + TimeToLiveSpecification: + AttributeName: expiration + Enabled: true + BillingMode: PAY_PER_REQUEST + + IdempotencyFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: helloworld.App::handleRequest + Runtime: provided.al2023 + MemorySize: 512 + Tracing: Active + Policies: + - DynamoDBCrudPolicy: + TableName: !Ref IdempotencyTable + Environment: + Variables: + POWERTOOLS_SERVICE_NAME: idempotency + IDEMPOTENCY_TABLE: !Ref IdempotencyTable + Events: + HelloWorld: + Type: Api + Properties: + Path: /helloidem + Method: post + +Outputs: + HelloWorldApi: + Description: "API Gateway endpoint URL for Prod stage for Idempotent function" + Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/helloidem/" + HelloWorldFunction: + Description: "Idempotent Lambda Function ARN" + Value: !GetAtt IdempotencyFunction.Arn diff --git a/examples/powertools-examples-idempotency/README.md b/examples/powertools-examples-idempotency/sam/README.md similarity index 100% rename from examples/powertools-examples-idempotency/README.md rename to examples/powertools-examples-idempotency/sam/README.md diff --git a/examples/powertools-examples-idempotency/pom.xml b/examples/powertools-examples-idempotency/sam/pom.xml similarity index 71% rename from examples/powertools-examples-idempotency/pom.xml rename to examples/powertools-examples-idempotency/sam/pom.xml index eb235437b..a5f49d9c6 100644 --- a/examples/powertools-examples-idempotency/pom.xml +++ b/examples/powertools-examples-idempotency/sam/pom.xml @@ -13,7 +13,7 @@ --> <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 http://maven.apache.org/maven-v4_0_0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> @@ -44,6 +44,7 @@ <artifactId>powertools-idempotency-dynamodb</artifactId> <version>${project.version}</version> </dependency> + <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> @@ -54,24 +55,12 @@ <artifactId>aws-lambda-java-events</artifactId> <version>3.16.1</version> </dependency> + <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> </dependency> - - <dependency> - <groupId>org.mockito</groupId> - <artifactId>mockito-core</artifactId> - <version>5.18.0</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-api</artifactId> - <version>5.11.1</version> - <scope>test</scope> - </dependency> </dependencies> <build> @@ -114,39 +103,7 @@ </dependency> </dependencies> </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-dependency-plugin</artifactId> - <executions> - <execution> - <id>copy</id> - <phase>test-compile</phase> - <goals> - <goal>copy-dependencies</goal> - </goals> - <configuration> - <includeScope>test</includeScope> - <includeTypes>so,dll,dylib</includeTypes> - <outputDirectory>${project.build.directory}/native-libs</outputDirectory> - </configuration> - </execution> - </executions> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> - <configuration> - <systemPropertyVariables> - <sqlite4java.library.path>${project.build.directory}/native-libs</sqlite4java.library.path> - </systemPropertyVariables> - <environmentVariables> - <IDEMPOTENCY_TABLE>idempotency</IDEMPOTENCY_TABLE> - <AWS_REGION>eu-central-1</AWS_REGION> - <AWS_XRAY_CONTEXT_MISSING>LOG_ERROR</AWS_XRAY_CONTEXT_MISSING> - </environmentVariables> - </configuration> - </plugin> + <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> @@ -160,7 +117,8 @@ <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> <transformers> - <transformer implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer"/> + <transformer + implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer" /> </transformers> </configuration> </execution> diff --git a/examples/powertools-examples-idempotency/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-idempotency/sam/src/main/java/helloworld/App.java new file mode 100644 index 000000000..ebe9fac22 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam/src/main/java/helloworld/App.java @@ -0,0 +1,142 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package helloworld; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; +import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.lambda.powertools.idempotency.Idempotency; +import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; +import software.amazon.lambda.powertools.idempotency.Idempotent; +import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.tracing.Tracing; +import software.amazon.lambda.powertools.utilities.JsonConfig; + +public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + private static final Logger log = LoggerFactory.getLogger(App.class); + + public App() { + this(null); + } + + public App(DynamoDbClient client) { + Idempotency.config().withConfig( + IdempotencyConfig.builder() + .withEventKeyJMESPath("powertools_json(body).address") + .withResponseHook((responseData, dataRecord) -> { + if (responseData instanceof APIGatewayProxyResponseEvent) { + APIGatewayProxyResponseEvent proxyResponse = (APIGatewayProxyResponseEvent) responseData; + final Map<String, String> headers = new HashMap<>(); + headers.putAll(proxyResponse.getHeaders()); + headers.put("x-idempotency-response", "true"); + headers.put("x-idempotency-expiration", + String.valueOf(dataRecord.getExpiryTimestamp())); + + proxyResponse.setHeaders(headers); + + return proxyResponse; + } + + return responseData; + }) + .build()) + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withDynamoDbClient(client) + .withTableName(System.getenv("IDEMPOTENCY_TABLE")) + .build()) + .configure(); + } + + /** + * This is your Lambda event handler. It accepts HTTP POST requests from API gateway and returns the contents of the + * given URL. Requests are made idempotent + * by the idempotency library, and results are cached for the default 1h expiry time. + * <p> + * You can test the endpoint like this: + * + * <pre> + * curl -X POST https://[REST-API-ID].execute-api.[REGION].amazonaws.com/Prod/helloidem/ -H "Content-Type: application/json" -d '{"address": "https://checkip.amazonaws.com"}' + * </pre> + * <ul> + * <li>First call will execute the handleRequest normally, and store the response in the idempotency table (Look + * into DynamoDB)</li> + * <li>Second call (and next ones) will retrieve from the cache (if cache is enabled, which is by default) or from + * the store, the handler won't be called. Until the expiration happens (by default 1 hour).</li> + * </ul> + */ + @Idempotent // The magic is here! + @Logging(logEvent = true) + @Tracing + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + Map<String, String> headers = new HashMap<>(); + + headers.put("Content-Type", "application/json"); + headers.put("Access-Control-Allow-Origin", "*"); + headers.put("Access-Control-Allow-Methods", "GET, OPTIONS"); + headers.put("Access-Control-Allow-Headers", "*"); + + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent() + .withHeaders(headers); + try { + // Read the 'address' field from the JSON post body + String address = JsonConfig.get().getObjectMapper().readTree(input.getBody()).get("address").asText(); + final String pageContents = this.getPageContents(address); + String output = String.format("{ \"message\": \"hello world\", \"location\": \"%s\" }", pageContents); + + log.info("ip is {}", pageContents); + return response + .withStatusCode(200) + .withBody(output); + + } catch (IOException e) { + return response + .withBody("{}") + .withStatusCode(500); + } + } + + /** + * Helper to retrieve the contents of the given URL and return them as a string. + * <p> + * We could also put the @Idempotent annotation here if we only wanted this sub-operation to be idempotent. Putting + * it on the handler, however, reduces total execution time and saves us time! + * + * @param address + * The URL to fetch + * @return The contents of the given URL + * @throws IOException + */ + @Tracing + private String getPageContents(String address) throws IOException { + URL url = new URL(address); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) { + return br.lines().collect(Collectors.joining(System.lineSeparator())); + } + } +} diff --git a/examples/powertools-examples-idempotency/sam/src/main/resources/log4j2.xml b/examples/powertools-examples-idempotency/sam/src/main/resources/log4j2.xml new file mode 100644 index 000000000..5dede7b58 --- /dev/null +++ b/examples/powertools-examples-idempotency/sam/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + </Appenders> + <Loggers> + <Logger name="JsonLogger" level="INFO" additivity="false"> + <AppenderRef ref="JsonAppender" /> + </Logger> + <Root level="info"> + <AppenderRef ref="JsonAppender" /> + </Root> + </Loggers> +</Configuration> diff --git a/examples/powertools-examples-idempotency/template.yaml b/examples/powertools-examples-idempotency/sam/template.yaml similarity index 100% rename from examples/powertools-examples-idempotency/template.yaml rename to examples/powertools-examples-idempotency/sam/template.yaml diff --git a/pom.xml b/pom.xml index f2e9b1cdf..c63e78d7e 100644 --- a/pom.xml +++ b/pom.xml @@ -459,6 +459,11 @@ <artifactId>maven-gpg-plugin</artifactId> <version>${maven-gpg-plugin.version}</version> </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>3.5.1</version> + </plugin> </plugins> </pluginManagement> <plugins> diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index 8b9b015bc..b9555ee47 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -1,5 +1,5 @@ <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 http://maven.apache.org/maven-v4_0_0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -29,6 +29,14 @@ <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + </dependency> </dependencies> <build> @@ -65,4 +73,18 @@ </plugin> </plugins> </build> + + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 15ac7650e..4094bfb20 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -253,6 +253,7 @@ <include>**/LoggingE2ET.java</include> <include>**/ParametersE2ET.java</include> <include>**/TracingE2ET.java</include> + <include>**/IdempotencyE2ET.java</include> </includes> <systemPropertyVariables> <graalvm.enabled>true</graalvm.enabled> diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java index 292f46bfa..c73a6d761 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java @@ -36,7 +36,7 @@ class IdempotencyE2ET { private static String functionName; @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) + @Timeout(value = 15, unit = TimeUnit.MINUTES) static void setup() { String random = UUID.randomUUID().toString().substring(0, 6); infrastructure = Infrastructure.builder() diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java index 204d5863a..0508534c2 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/DockerConfiguration.java @@ -88,6 +88,7 @@ public BundlingOptions createGraalVMBundlingOptions(String pathToFunction, JavaR .environment(environmentVariables) .user("root") .outputType(BundlingOutput.ARCHIVED) + .platform("linux/amd64") .build(); } @@ -111,6 +112,7 @@ public BundlingOptions createJVMBundlingOptions(String pathToFunction, JavaRunti .volumes(volumes) .user("root") .outputType(BundlingOutput.ARCHIVED) + .platform("linux/amd64") .build(); } diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 6f15bfc3d..2f575d3de 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -37,16 +37,109 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-serialization</artifactId> </dependency> + <!-- Test dependencies --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> </dependencies> -</project> \ No newline at end of file + + <profiles> + <profile> + <id>generate-graalvm-files</id> + <dependencies> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-subclass</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-core,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + </argLine> + </configuration> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>graalvm-native</id> + <dependencies> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-subclass</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + <version>0.11.0</version> + <extensions>true</extensions> + <executions> + <execution> + <id>test-native</id> + <goals> + <goal>test</goal> + </goals> + <phase>test</phase> + </execution> + </executions> + <configuration> + <imageName>powertools-idempotency-core</imageName> + <buildArgs> + <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> + <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> + <buildArg>--no-fallback</buildArg> + <buildArg>--verbose</buildArg> + <buildArg>--native-image-info</buildArg> + <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> + </buildArgs> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java index 12113fc9e..0ccb1e5aa 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java @@ -24,23 +24,23 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.when; import java.time.Instant; import java.util.OptionalInt; import java.util.OptionalLong; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.junitpioneer.jupiter.SetEnvironmentVariable; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import com.amazonaws.services.lambda.runtime.Context; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.idempotency.Constants; import software.amazon.lambda.powertools.idempotency.Idempotency; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; @@ -61,21 +61,16 @@ import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; import software.amazon.lambda.powertools.utilities.JsonConfig; -public class IdempotencyAspectTest { +@ExtendWith(MockitoExtension.class) +class IdempotencyAspectTest { - @Mock - private Context context; + private Context context = new TestLambdaContext(); @Mock private BasePersistenceStore store; - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } - @Test - public void firstCall_shouldPutInStore() { + void firstCall_shouldPutInStore() { Idempotency.config() .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder() @@ -85,8 +80,6 @@ public void firstCall_shouldPutInStore() { IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); - when(context.getRemainingTimeInMillis()).thenReturn(30000); - Product p = new Product(42, "fake product", 12); Basket basket = function.handleRequest(p, context); assertThat(basket.getProducts()).hasSize(1); @@ -107,12 +100,13 @@ public void firstCall_shouldPutInStore() { } @Test - public void firstCall_shouldPutInStoreAndNotApplyResponseHook() { + void firstCall_shouldPutInStoreAndNotApplyResponseHook() { Idempotency.config() .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder() .withEventKeyJMESPath("id") - // This hook will add a second product to the basket. It should not run here. Only for + // This hook will add a second product to the basket. It should not run here. + // Only for // idempotent responses. .withResponseHook((responseData, dataRecord) -> { final Basket basket = (Basket) responseData; @@ -124,8 +118,6 @@ public void firstCall_shouldPutInStoreAndNotApplyResponseHook() { IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); - when(context.getRemainingTimeInMillis()).thenReturn(30000); - Product p = new Product(42, "fake product", 12); Basket basket = function.handleRequest(p, context); assertThat(basket.getProducts()).hasSize(1); // Size should be 1 because response hook should not run @@ -146,7 +138,7 @@ public void firstCall_shouldPutInStoreAndNotApplyResponseHook() { } @Test - public void secondCall_notExpired_shouldGetFromStore() throws JsonProcessingException { + void secondCall_notExpired_shouldGetFromStore() throws JsonProcessingException { // GIVEN Idempotency.config() .withPersistenceStore(store) @@ -177,7 +169,7 @@ public void secondCall_notExpired_shouldGetFromStore() throws JsonProcessingExce } @Test - public void secondCall_notExpired_shouldNotGetFromStoreIfPresentOnIdempotencyException() + void secondCall_notExpired_shouldNotGetFromStoreIfPresentOnIdempotencyException() throws JsonProcessingException { // GIVEN Idempotency.config() @@ -196,12 +188,13 @@ public void secondCall_notExpired_shouldNotGetFromStoreIfPresentOnIdempotencyExc JsonConfig.get().getObjectMapper().writer().writeValueAsString(b), null); - // A data record on this exception should take precedence over fetching a record from the store / cache + // A data record on this exception should take precedence over fetching a record + // from the store / cache doThrow(new IdempotencyItemAlreadyExistsException( "Test message", new RuntimeException("Test Cause"), dr)) - .when(store).saveInProgress(any(), any(), any()); + .when(store).saveInProgress(any(), any(), any()); // WHEN IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); @@ -210,12 +203,13 @@ public void secondCall_notExpired_shouldNotGetFromStoreIfPresentOnIdempotencyExc // THEN assertThat(basket).isEqualTo(b); assertThat(function.handlerCalled()).isFalse(); - // Should never call the store because item is already present on IdempotencyItemAlreadyExistsException + // Should never call the store because item is already present on + // IdempotencyItemAlreadyExistsException verify(store, never()).getRecord(any(), any()); } @Test - public void secondCall_notExpired_shouldGetStringFromStore() { + void secondCall_notExpired_shouldGetStringFromStore() { // GIVEN Idempotency.config() .withPersistenceStore(store) @@ -245,7 +239,7 @@ public void secondCall_notExpired_shouldGetStringFromStore() { } @Test - public void secondCall_notExpired_shouldGetStringFromStoreWithResponseHook() { + void secondCall_notExpired_shouldGetStringFromStoreWithResponseHook() { // GIVEN final String RESPONSE_HOOK_SUFFIX = " ResponseHook"; Idempotency.config() @@ -280,7 +274,7 @@ public void secondCall_notExpired_shouldGetStringFromStoreWithResponseHook() { } @Test - public void secondCall_inProgress_shouldThrowIdempotencyAlreadyInProgressException() + void secondCall_inProgress_shouldThrowIdempotencyAlreadyInProgressException() throws JsonProcessingException { // GIVEN Idempotency.config() @@ -312,7 +306,7 @@ public void secondCall_inProgress_shouldThrowIdempotencyAlreadyInProgressExcepti } @Test - public void secondCall_inProgress_lambdaTimeout_timeoutExpired_shouldThrowInconsistentState() + void secondCall_inProgress_lambdaTimeout_timeoutExpired_shouldThrowInconsistentState() throws JsonProcessingException { // GIVEN Idempotency.config() @@ -344,7 +338,7 @@ public void secondCall_inProgress_lambdaTimeout_timeoutExpired_shouldThrowIncons } @Test - public void functionThrowException_shouldDeleteRecord_andThrowFunctionException() { + void functionThrowException_shouldDeleteRecord_andThrowFunctionException() { // GIVEN Idempotency.config() .withPersistenceStore(store) @@ -365,7 +359,7 @@ public void functionThrowException_shouldDeleteRecord_andThrowFunctionException( @Test @SetEnvironmentVariable(key = Constants.IDEMPOTENCY_DISABLED_ENV, value = "true") - public void testIdempotencyDisabled_shouldJustRunTheFunction() { + void testIdempotencyDisabled_shouldJustRunTheFunction() { // GIVEN Idempotency.config() .withPersistenceStore(store) @@ -386,15 +380,13 @@ public void testIdempotencyDisabled_shouldJustRunTheFunction() { } @Test - public void idempotencyOnSubMethodAnnotated_firstCall_shouldPutInStore() { + void idempotencyOnSubMethodAnnotated_firstCall_shouldPutInStore() { Idempotency.config() .withPersistenceStore(store) .configure(); // WHEN boolean registerContext = true; - when(context.getRemainingTimeInMillis()).thenReturn(30000); - IdempotencyInternalFunction function = new IdempotencyInternalFunction(registerContext); Product p = new Product(42, "fake product", 12); Basket basket = function.handleRequest(p, context); @@ -416,7 +408,7 @@ public void idempotencyOnSubMethodAnnotated_firstCall_shouldPutInStore() { } @Test - public void idempotencyOnSubMethodAnnotated_firstCall_contextNotRegistered_shouldPutInStore() { + void idempotencyOnSubMethodAnnotated_firstCall_contextNotRegistered_shouldPutInStore() { Idempotency.config() .withPersistenceStore(store) .configure(); @@ -444,7 +436,7 @@ public void idempotencyOnSubMethodAnnotated_firstCall_contextNotRegistered_shoul } @Test - public void idempotencyOnSubMethodAnnotated_secondCall_notExpired_shouldGetFromStore() + void idempotencyOnSubMethodAnnotated_secondCall_notExpired_shouldGetFromStore() throws JsonProcessingException { // GIVEN Idempotency.config() @@ -473,7 +465,7 @@ public void idempotencyOnSubMethodAnnotated_secondCall_notExpired_shouldGetFromS } @Test - public void idempotencyOnSubMethodAnnotated_keyJMESPath_shouldPutInStoreWithKey() { + void idempotencyOnSubMethodAnnotated_keyJMESPath_shouldPutInStoreWithKey() { BasePersistenceStore persistenceStore = spy(BasePersistenceStore.class); Idempotency.config() @@ -495,7 +487,7 @@ public void idempotencyOnSubMethodAnnotated_keyJMESPath_shouldPutInStoreWithKey( } @Test - public void idempotencyOnSubMethodAnnotated_keyJMESPathArray_shouldPutInStoreWithKey() { + void idempotencyOnSubMethodAnnotated_keyJMESPathArray_shouldPutInStoreWithKey() { BasePersistenceStore persistenceStore = spy(BasePersistenceStore.class); Idempotency.config() @@ -517,7 +509,7 @@ public void idempotencyOnSubMethodAnnotated_keyJMESPathArray_shouldPutInStoreWit } @Test - public void idempotencyOnSubMethodNotAnnotated_shouldThrowException() { + void idempotencyOnSubMethodNotAnnotated_shouldThrowException() { Idempotency.config() .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder().build()).configure(); @@ -532,7 +524,7 @@ public void idempotencyOnSubMethodNotAnnotated_shouldThrowException() { } @Test - public void idempotencyOnSubMethodVoid_shouldThrowException() { + void idempotencyOnSubMethodVoid_shouldThrowException() { Idempotency.config() .withPersistenceStore(store) .withConfig(IdempotencyConfig.builder().build()).configure(); diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCacheTest.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCacheTest.java index 053b56430..d14f07315 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCacheTest.java +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCacheTest.java @@ -14,14 +14,14 @@ package software.amazon.lambda.powertools.idempotency.internal.cache; -import org.junit.jupiter.api.Test; - import static org.assertj.core.api.Assertions.assertThat; -public class LRUCacheTest { +import org.junit.jupiter.api.Test; + +class LRUCacheTest { @Test - public void testLRUCache_shouldRemoveEldestEntry() { + void testLRUCache_shouldRemoveEldestEntry() { LRUCache<String, String> cache = new LRUCache<>(3); cache.put("key1", "value1"); cache.put("key2", "value2"); diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java index f770679ee..d5d45c78f 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java @@ -14,13 +14,23 @@ package software.amazon.lambda.powertools.idempotency.persistence; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.OptionalInt; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.tests.EventLoader; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.node.DoubleNode; import com.fasterxml.jackson.databind.node.TextNode; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; + import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; @@ -30,15 +40,7 @@ import software.amazon.lambda.powertools.idempotency.model.Product; import software.amazon.lambda.powertools.utilities.JsonConfig; -import java.time.Duration; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.OptionalInt; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -public class BasePersistenceStoreTest { +class BasePersistenceStoreTest { private DataRecord dr; private BasePersistenceStore persistenceStore; @@ -46,7 +48,7 @@ public class BasePersistenceStoreTest { private String validationHash; @BeforeEach - public void setup() { + void setup() { validationHash = null; dr = null; status = -1; @@ -59,14 +61,14 @@ public DataRecord getRecord(String idempotencyKey) throws IdempotencyItemNotFoun } @Override - public void putRecord(DataRecord record, Instant now) throws IdempotencyItemAlreadyExistsException { - dr = record; + public void putRecord(DataRecord dataRecord, Instant now) throws IdempotencyItemAlreadyExistsException { + dr = dataRecord; status = 1; } @Override - public void updateRecord(DataRecord record) { - dr = record; + public void updateRecord(DataRecord dataRecord) { + dr = dataRecord; status = 2; } @@ -78,10 +80,8 @@ public void deleteRecord(String idempotencyKey) { }; } - // ================================================================= - //<editor-fold desc="saveInProgress"> @Test - public void saveInProgress_defaultConfig() { + void saveInProgress_defaultConfig() { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); persistenceStore.configure(IdempotencyConfig.builder().build(), null); @@ -92,13 +92,13 @@ public void saveInProgress_defaultConfig() { assertThat(dr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); assertThat(dr.getResponseData()).isNull(); assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction#8d6a8f173b46479eff55e0997864a514"); - assertThat(dr.getPayloadHash()).isEqualTo(""); + assertThat(dr.getPayloadHash()).isEmpty(); assertThat(dr.getInProgressExpiryTimestamp()).isEmpty(); assertThat(status).isEqualTo(1); } @Test - public void saveInProgress_withRemainingTime() { + void saveInProgress_withRemainingTime() { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); persistenceStore.configure(IdempotencyConfig.builder().build(), null); @@ -110,14 +110,14 @@ public void saveInProgress_withRemainingTime() { assertThat(dr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); assertThat(dr.getResponseData()).isNull(); assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction#8d6a8f173b46479eff55e0997864a514"); - assertThat(dr.getPayloadHash()).isEqualTo(""); + assertThat(dr.getPayloadHash()).isEmpty(); assertThat(dr.getInProgressExpiryTimestamp().orElse(-1)).isEqualTo( now.plus(lambdaTimeoutMs, ChronoUnit.MILLIS).toEpochMilli()); assertThat(status).isEqualTo(1); } @Test - public void saveInProgress_jmespath() { + void saveInProgress_jmespath() { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); persistenceStore.configure(IdempotencyConfig.builder() .withEventKeyJMESPath("powertools_json(body).id") @@ -130,12 +130,12 @@ public void saveInProgress_jmespath() { assertThat(dr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); assertThat(dr.getResponseData()).isNull(); assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction.myfunc#2fef178cc82be5ce3da6c5e0466a6182"); - assertThat(dr.getPayloadHash()).isEqualTo(""); + assertThat(dr.getPayloadHash()).isEmpty(); assertThat(status).isEqualTo(1); } @Test - public void saveInProgress_jmespath_NotFound_shouldThrowException() { + void saveInProgress_jmespath_NotFound_shouldThrowException() { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); persistenceStore.configure(IdempotencyConfig.builder() .withEventKeyJMESPath("unavailable") @@ -151,7 +151,7 @@ public void saveInProgress_jmespath_NotFound_shouldThrowException() { } @Test - public void saveInProgress_jmespath_NotFound_shouldNotPersist() { + void saveInProgress_jmespath_NotFound_shouldNotPersist() { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); persistenceStore.configure(IdempotencyConfig.builder() .withEventKeyJMESPath("unavailable") @@ -164,7 +164,7 @@ public void saveInProgress_jmespath_NotFound_shouldNotPersist() { } @Test - public void saveInProgress_withLocalCache_NotExpired_ShouldThrowException() { + void saveInProgress_withLocalCache_NotExpired_ShouldThrowException() { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); LRUCache<String, DataRecord> cache = new LRUCache<>(2); persistenceStore.configure(IdempotencyConfig.builder() @@ -177,8 +177,7 @@ public void saveInProgress_withLocalCache_NotExpired_ShouldThrowException() { "testFunction#2fef178cc82be5ce3da6c5e0466a6182", DataRecord.Status.INPROGRESS, now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(), - null, null) - ); + null, null)); assertThatThrownBy( () -> persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty())) @@ -187,7 +186,7 @@ public void saveInProgress_withLocalCache_NotExpired_ShouldThrowException() { } @Test - public void saveInProgress_withLocalCache_Expired_ShouldRemoveFromCache() { + void saveInProgress_withLocalCache_Expired_ShouldRemoveFromCache() { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); LRUCache<String, DataRecord> cache = new LRUCache<>(2); persistenceStore.configure(IdempotencyConfig.builder() @@ -201,22 +200,16 @@ public void saveInProgress_withLocalCache_Expired_ShouldRemoveFromCache() { "testFunction#2fef178cc82be5ce3da6c5e0466a6182", DataRecord.Status.INPROGRESS, now.minus(3, ChronoUnit.SECONDS).getEpochSecond(), - null, null) - ); + null, null)); persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty()); assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS); assertThat(cache).isEmpty(); assertThat(status).isEqualTo(1); } - //</editor-fold> - // ================================================================= - - // ================================================================= - //<editor-fold desc="saveSuccess"> @Test - public void saveSuccess_shouldUpdateRecord() throws JsonProcessingException { + void saveSuccess_shouldUpdateRecord() throws JsonProcessingException { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); LRUCache<String, DataRecord> cache = new LRUCache<>(2); persistenceStore.configure(IdempotencyConfig.builder().build(), null, cache); @@ -229,13 +222,13 @@ public void saveSuccess_shouldUpdateRecord() throws JsonProcessingException { assertThat(dr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); assertThat(dr.getResponseData()).isEqualTo(JsonConfig.get().getObjectMapper().writeValueAsString(product)); assertThat(dr.getIdempotencyKey()).isEqualTo("testFunction#8d6a8f173b46479eff55e0997864a514"); - assertThat(dr.getPayloadHash()).isEqualTo(""); + assertThat(dr.getPayloadHash()).isEmpty(); assertThat(status).isEqualTo(2); assertThat(cache).isEmpty(); } @Test - public void saveSuccess_withCacheEnabled_shouldSaveInCache() throws JsonProcessingException { + void saveSuccess_withCacheEnabled_shouldSaveInCache() throws JsonProcessingException { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); LRUCache<String, DataRecord> cache = new LRUCache<>(2); persistenceStore.configure(IdempotencyConfig.builder() @@ -247,37 +240,31 @@ public void saveSuccess_withCacheEnabled_shouldSaveInCache() throws JsonProcessi assertThat(status).isEqualTo(2); assertThat(cache).hasSize(1); - DataRecord record = cache.get("testFunction#8d6a8f173b46479eff55e0997864a514"); - assertThat(record.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); - assertThat(record.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); - assertThat(record.getResponseData()).isEqualTo(JsonConfig.get().getObjectMapper().writeValueAsString(product)); - assertThat(record.getIdempotencyKey()).isEqualTo("testFunction#8d6a8f173b46479eff55e0997864a514"); - assertThat(record.getPayloadHash()).isEqualTo(""); + DataRecord cachedDr = cache.get("testFunction#8d6a8f173b46479eff55e0997864a514"); + assertThat(cachedDr.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); + assertThat(cachedDr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); + assertThat(cachedDr.getResponseData()).isEqualTo(JsonConfig.get().getObjectMapper().writeValueAsString(product)); + assertThat(cachedDr.getIdempotencyKey()).isEqualTo("testFunction#8d6a8f173b46479eff55e0997864a514"); + assertThat(cachedDr.getPayloadHash()).isEmpty(); } - //</editor-fold> - // ================================================================= - - // ================================================================= - //<editor-fold desc="getRecord"> - @Test - public void getRecord_shouldReturnRecordFromPersistence() + void getRecord_shouldReturnRecordFromPersistence() throws IdempotencyItemNotFoundException, IdempotencyValidationException { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); LRUCache<String, DataRecord> cache = new LRUCache<>(2); persistenceStore.configure(IdempotencyConfig.builder().build(), "myfunc", cache); Instant now = Instant.now(); - DataRecord record = persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), now); - assertThat(record.getIdempotencyKey()).isEqualTo("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514"); - assertThat(record.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS); - assertThat(record.getResponseData()).isEqualTo("Response"); - assertThat(status).isEqualTo(0); + DataRecord freshDr = persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), now); + assertThat(freshDr.getIdempotencyKey()).isEqualTo("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514"); + assertThat(freshDr.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS); + assertThat(freshDr.getResponseData()).isEqualTo("Response"); + assertThat(status).isZero(); } @Test - public void getRecord_cacheEnabledNotExpired_shouldReturnRecordFromCache() + void getRecord_cacheEnabledNotExpired_shouldReturnRecordFromCache() throws IdempotencyItemNotFoundException, IdempotencyValidationException { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); LRUCache<String, DataRecord> cache = new LRUCache<>(2); @@ -285,23 +272,23 @@ public void getRecord_cacheEnabledNotExpired_shouldReturnRecordFromCache() .withUseLocalCache(true).build(), "myfunc", cache); Instant now = Instant.now(); - DataRecord dr = new DataRecord( + DataRecord dr1 = new DataRecord( "testFunction.myfunc#8d6a8f173b46479eff55e0997864a514", DataRecord.Status.COMPLETED, now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(), "result of the function", null); - cache.put("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514", dr); + cache.put("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514", dr1); - DataRecord record = persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), now); - assertThat(record.getIdempotencyKey()).isEqualTo("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514"); - assertThat(record.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); - assertThat(record.getResponseData()).isEqualTo("result of the function"); + DataRecord dr2 = persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), now); + assertThat(dr2.getIdempotencyKey()).isEqualTo("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514"); + assertThat(dr2.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); + assertThat(dr2.getResponseData()).isEqualTo("result of the function"); assertThat(status).isEqualTo(-1); // getRecord must not be called (retrieve from cache) } @Test - public void getRecord_cacheEnabledExpired_shouldReturnRecordFromPersistence() + void getRecord_cacheEnabledExpired_shouldReturnRecordFromPersistence() throws IdempotencyItemNotFoundException, IdempotencyValidationException { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); LRUCache<String, DataRecord> cache = new LRUCache<>(2); @@ -309,29 +296,29 @@ public void getRecord_cacheEnabledExpired_shouldReturnRecordFromPersistence() .withUseLocalCache(true).build(), "myfunc", cache); Instant now = Instant.now(); - DataRecord dr = new DataRecord( + DataRecord dr1 = new DataRecord( "testFunction.myfunc#8d6a8f173b46479eff55e0997864a514", DataRecord.Status.COMPLETED, now.minus(3, ChronoUnit.SECONDS).getEpochSecond(), "result of the function", null); - cache.put("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514", dr); + cache.put("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514", dr1); - DataRecord record = persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), now); - assertThat(record.getIdempotencyKey()).isEqualTo("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514"); - assertThat(record.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS); - assertThat(record.getResponseData()).isEqualTo("Response"); - assertThat(status).isEqualTo(0); + DataRecord dr2 = persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), now); + assertThat(dr2.getIdempotencyKey()).isEqualTo("testFunction.myfunc#8d6a8f173b46479eff55e0997864a514"); + assertThat(dr2.getStatus()).isEqualTo(DataRecord.Status.INPROGRESS); + assertThat(dr2.getResponseData()).isEqualTo("Response"); + assertThat(status).isZero(); assertThat(cache).isEmpty(); } @Test - public void getRecord_invalidPayload_shouldThrowValidationException() { + void getRecord_invalidPayload_shouldThrowValidationException() { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); persistenceStore.configure(IdempotencyConfig.builder() - .withEventKeyJMESPath("powertools_json(body).id") - .withPayloadValidationJMESPath("powertools_json(body).message") - .build(), + .withEventKeyJMESPath("powertools_json(body).id") + .withPayloadValidationJMESPath("powertools_json(body).message") + .build(), "myfunc"); this.validationHash = "different hash"; // "Lambda rocks" ==> 70c24d88041893f7fbab4105b76fd9e1 @@ -341,14 +328,8 @@ public void getRecord_invalidPayload_shouldThrowValidationException() { .isInstanceOf(IdempotencyValidationException.class); } - //</editor-fold> - // ================================================================= - - // ================================================================= - //<editor-fold desc="deleteRecord"> - @Test - public void deleteRecord_shouldDeleteRecordFromPersistence() { + void deleteRecord_shouldDeleteRecordFromPersistence() { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); persistenceStore.configure(IdempotencyConfig.builder().build(), null); @@ -357,7 +338,7 @@ public void deleteRecord_shouldDeleteRecordFromPersistence() { } @Test - public void deleteRecord_cacheEnabled_shouldDeleteRecordFromCache() { + void deleteRecord_cacheEnabled_shouldDeleteRecordFromCache() { APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); LRUCache<String, DataRecord> cache = new LRUCache<>(2); persistenceStore.configure(IdempotencyConfig.builder() @@ -371,11 +352,8 @@ public void deleteRecord_cacheEnabled_shouldDeleteRecordFromCache() { assertThat(cache).isEmpty(); } - //</editor-fold> - // ================================================================= - @Test - public void generateHashString_shouldGenerateMd5ofString() { + void generateHashString_shouldGenerateMd5ofString() { persistenceStore.configure(IdempotencyConfig.builder().build(), null); String expectedHash = "70c24d88041893f7fbab4105b76fd9e1"; // MD5(Lambda rocks) String generatedHash = persistenceStore.generateHash(new TextNode("Lambda rocks")); @@ -383,7 +361,7 @@ public void generateHashString_shouldGenerateMd5ofString() { } @Test - public void generateHashObject_shouldGenerateMd5ofJsonObject() { + void generateHashObject_shouldGenerateMd5ofJsonObject() { persistenceStore.configure(IdempotencyConfig.builder().build(), null); Product product = new Product(42, "Product", 12); String expectedHash = "e71c41727848ed68050d82740894c29b"; // MD5({"id":42,"name":"Product","price":12.0}) @@ -392,7 +370,7 @@ public void generateHashObject_shouldGenerateMd5ofJsonObject() { } @Test - public void generateHashDouble_shouldGenerateMd5ofDouble() { + void generateHashDouble_shouldGenerateMd5ofDouble() { persistenceStore.configure(IdempotencyConfig.builder().build(), null); String expectedHash = "bb84c94278119c8838649706df4db42b"; // MD5(256.42) String generatedHash = persistenceStore.generateHash(new DoubleNode(256.42)); @@ -400,16 +378,16 @@ public void generateHashDouble_shouldGenerateMd5ofDouble() { } @Test - public void generateHashString_withSha256Algorithm_shouldGenerateSha256ofString() { + void generateHashString_withSha256Algorithm_shouldGenerateSha256ofString() { persistenceStore.configure(IdempotencyConfig.builder().withHashFunction("SHA-256").build(), null); - String expectedHash = - "e6139efa88ef3337e901e826e6f327337f414860fb499d9f26eefcff21d719af"; // SHA-256(Lambda rocks) + String expectedHash = "e6139efa88ef3337e901e826e6f327337f414860fb499d9f26eefcff21d719af"; // SHA-256(Lambda + // rocks) String generatedHash = persistenceStore.generateHash(new TextNode("Lambda rocks")); assertThat(generatedHash).isEqualTo(expectedHash); } @Test - public void generateHashString_unknownAlgorithm_shouldGenerateMd5ofString() { + void generateHashString_unknownAlgorithm_shouldGenerateMd5ofString() { persistenceStore.configure(IdempotencyConfig.builder().withHashFunction("HASH").build(), null); String expectedHash = "70c24d88041893f7fbab4105b76fd9e1"; // MD5(Lambda rocks) String generatedHash = persistenceStore.generateHash(new TextNode("Lambda rocks")); diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/resources/simplelogger.properties b/powertools-idempotency/powertools-idempotency-core/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..dcded6172 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-core/src/test/resources/simplelogger.properties @@ -0,0 +1,7 @@ +org.slf4j.simpleLogger.logFile=target/idempotency-core-test.log +org.slf4j.simpleLogger.defaultLogLevel=warn +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS +org.slf4j.simpleLogger.showThreadName=false +org.slf4j.simpleLogger.showLogName=true +org.slf4j.simpleLogger.showShortLogName=false diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/dynamodb-local-metadata.json b/powertools-idempotency/powertools-idempotency-dynamodb/dynamodb-local-metadata.json deleted file mode 100644 index c76c2c76d..000000000 --- a/powertools-idempotency/powertools-idempotency-dynamodb/dynamodb-local-metadata.json +++ /dev/null @@ -1 +0,0 @@ -{"installationId":"e43b8515-8484-485c-8315-bead4568972b","telemetryEnabled":"true"} \ No newline at end of file diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index ed5b8d5c0..b7c4f317c 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -63,6 +63,29 @@ </dependency> <!-- Test dependencies --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-api</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <!-- DynamoDB Local for testing --> <dependency> <groupId>com.amazonaws</groupId> <artifactId>DynamoDBLocal</artifactId> @@ -71,17 +94,132 @@ <version>2.2.0</version> <scope>test</scope> </dependency> - <!--Needed when building locally on M1 Mac--> - <dependency> - <groupId>io.github.ganadist.sqlite4java</groupId> - <artifactId>libsqlite4java-osx-aarch64</artifactId> - <version>1.0.392</version> - <scope>test</scope> - <type>dylib</type> - </dependency> </dependencies> + + <profiles> + <profile> + <id>generate-graalvm-files</id> + <!-- The AWS DynamoDBClient uses com.amazonaws.xray.interceptors.TracingInterceptor if available on the + classpath. If the DynamoDB persistence store is used together with tracing, this would fail in GraalVM + otherwise since it tries to load the tracing interceptor at runtime. This makes sure it is included in + reflect-config.json --> + <dependencies> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-xray-recorder-sdk-aws-sdk-v2-instrumentor</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + </argLine> + </configuration> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>graalvm-native</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + <version>0.11.0</version> + <extensions>true</extensions> + <executions> + <execution> + <id>test-native</id> + <goals> + <goal>test</goal> + </goals> + <phase>test</phase> + </execution> + </executions> + <configuration> + <imageName>powertools-idempotency-dynamodb</imageName> + <exclusions> + <exclusion> + <groupId>com.amazonaws</groupId> + <artifactId>DynamoDBLocal</artifactId> + </exclusion> + </exclusions> + <buildArgs> + <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> + <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> + <buildArg>--enable-url-protocols=http</buildArg> + <buildArg>--no-fallback</buildArg> + <buildArg>--verbose</buildArg> + <buildArg>--native-image-info</buildArg> + <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> + </buildArgs> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> + <build> <plugins> + <!-- Copy DynamoDB Local JAR --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dynamodb-local</id> + <phase>generate-test-resources</phase> + <goals> + <goal>copy-dependencies</goal> + </goals> + <configuration> + <includeScope>test</includeScope> + <excludeTransitive>false</excludeTransitive> + <outputDirectory>${project.build.directory}/dynamodb-local</outputDirectory> + </configuration> + </execution> + </executions> + </plugin> + <!-- Start DynamoDB Local before tests --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <executions> + <execution> + <id>start-dynamodb-local</id> + <phase>process-test-classes</phase> + <goals> + <goal>exec</goal> + </goals> + <configuration> + <executable>java</executable> + <workingDirectory>${project.build.directory}/dynamodb-local</workingDirectory> + <arguments> + <argument>-Djava.library.path=${project.build.directory}/dynamodb-local</argument> + <argument>-cp</argument> + <argument>${project.build.directory}/dynamodb-local/*</argument> + <argument>com.amazonaws.services.dynamodbv2.local.main.ServerRunner</argument> + <argument>-inMemory</argument> + <argument>-port</argument> + <argument>8000</argument> + </arguments> + <async>true</async> + <asyncDestroyOnShutdown>true</asyncDestroyOnShutdown> + </configuration> + </execution> + </executions> + </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> @@ -94,6 +232,16 @@ </archive> </configuration> </plugin> + <!-- Configure Surefire to expose external DynamoDB Local address --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <systemPropertyVariables> + <dynamodb.endpoint>http://localhost:8000</dynamodb.endpoint> + </systemPropertyVariables> + </configuration> + </plugin> <plugin> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json new file mode 100644 index 000000000..f0ba9c4c2 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json @@ -0,0 +1,325 @@ +[ +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.KeyDeserializers;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiators;" +}, +{ + "name":"[Lcom.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers;" +}, +{ + "name":"[Lcom.fasterxml.jackson.databind.deser.Deserializers;" +}, +{ + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.Context" +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getBody","parameterTypes":[] }, {"name":"getHeaders","parameterTypes":[] }, {"name":"getHttpMethod","parameterTypes":[] }, {"name":"getIsBase64Encoded","parameterTypes":[] }, {"name":"getMultiValueHeaders","parameterTypes":[] }, {"name":"getMultiValueQueryStringParameters","parameterTypes":[] }, {"name":"getPath","parameterTypes":[] }, {"name":"getPathParameters","parameterTypes":[] }, {"name":"getQueryStringParameters","parameterTypes":[] }, {"name":"getRequestContext","parameterTypes":[] }, {"name":"getResource","parameterTypes":[] }, {"name":"getStageVariables","parameterTypes":[] }, {"name":"getVersion","parameterTypes":[] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setHttpMethod","parameterTypes":["java.lang.String"] }, {"name":"setIsBase64Encoded","parameterTypes":["java.lang.Boolean"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setPathParameters","parameterTypes":["java.util.Map"] }, {"name":"setQueryStringParameters","parameterTypes":["java.util.Map"] }, {"name":"setRequestContext","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext"] }, {"name":"setResource","parameterTypes":["java.lang.String"] }, {"name":"setStageVariables","parameterTypes":["java.util.Map"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getAccountId","parameterTypes":[] }, {"name":"getApiId","parameterTypes":[] }, {"name":"getAuthorizer","parameterTypes":[] }, {"name":"getDomainName","parameterTypes":[] }, {"name":"getDomainPrefix","parameterTypes":[] }, {"name":"getExtendedRequestId","parameterTypes":[] }, {"name":"getHttpMethod","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getOperationName","parameterTypes":[] }, {"name":"getPath","parameterTypes":[] }, {"name":"getProtocol","parameterTypes":[] }, {"name":"getRequestId","parameterTypes":[] }, {"name":"getRequestTime","parameterTypes":[] }, {"name":"getRequestTimeEpoch","parameterTypes":[] }, {"name":"getResourceId","parameterTypes":[] }, {"name":"getResourcePath","parameterTypes":[] }, {"name":"getStage","parameterTypes":[] }, {"name":"setAccountId","parameterTypes":["java.lang.String"] }, {"name":"setApiId","parameterTypes":["java.lang.String"] }, {"name":"setHttpMethod","parameterTypes":["java.lang.String"] }, {"name":"setIdentity","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity"] }, {"name":"setPath","parameterTypes":["java.lang.String"] }, {"name":"setProtocol","parameterTypes":["java.lang.String"] }, {"name":"setRequestId","parameterTypes":["java.lang.String"] }, {"name":"setRequestTime","parameterTypes":["java.lang.String"] }, {"name":"setRequestTimeEpoch","parameterTypes":["java.lang.Long"] }, {"name":"setResourceId","parameterTypes":["java.lang.String"] }, {"name":"setResourcePath","parameterTypes":["java.lang.String"] }, {"name":"setStage","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getAccessKey","parameterTypes":[] }, {"name":"getAccountId","parameterTypes":[] }, {"name":"getApiKey","parameterTypes":[] }, {"name":"getCaller","parameterTypes":[] }, {"name":"getCognitoAuthenticationProvider","parameterTypes":[] }, {"name":"getCognitoAuthenticationType","parameterTypes":[] }, {"name":"getCognitoIdentityId","parameterTypes":[] }, {"name":"getCognitoIdentityPoolId","parameterTypes":[] }, {"name":"getPrincipalOrgId","parameterTypes":[] }, {"name":"getSourceIp","parameterTypes":[] }, {"name":"getUser","parameterTypes":[] }, {"name":"getUserAgent","parameterTypes":[] }, {"name":"getUserArn","parameterTypes":[] }, {"name":"setAccessKey","parameterTypes":["java.lang.String"] }, {"name":"setAccountId","parameterTypes":["java.lang.String"] }, {"name":"setCaller","parameterTypes":["java.lang.String"] }, {"name":"setCognitoAuthenticationProvider","parameterTypes":["java.lang.String"] }, {"name":"setCognitoAuthenticationType","parameterTypes":["java.lang.String"] }, {"name":"setCognitoIdentityId","parameterTypes":["java.lang.String"] }, {"name":"setCognitoIdentityPoolId","parameterTypes":["java.lang.String"] }, {"name":"setSourceIp","parameterTypes":["java.lang.String"] }, {"name":"setUser","parameterTypes":["java.lang.String"] }, {"name":"setUserAgent","parameterTypes":["java.lang.String"] }, {"name":"setUserArn","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getBody","parameterTypes":[] }, {"name":"getHeaders","parameterTypes":[] }, {"name":"getIsBase64Encoded","parameterTypes":[] }, {"name":"getMultiValueHeaders","parameterTypes":[] }, {"name":"getStatusCode","parameterTypes":[] }, {"name":"setBody","parameterTypes":["java.lang.String"] }, {"name":"setHeaders","parameterTypes":["java.util.Map"] }, {"name":"setStatusCode","parameterTypes":["java.lang.Integer"] }] +}, +{ + "name":"com.amazonaws.xray.handlers.config.AWSOperationHandler", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.handlers.config.AWSOperationHandlerManifest", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.handlers.config.AWSOperationHandlerRequestDescriptor", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.handlers.config.AWSOperationHandlerResponseDescriptor", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.handlers.config.AWSServiceHandlerManifest", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.interceptors.TracingInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.xray.strategy.sampling.manifest.SamplingRuleManifest", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"setDefaultRule","parameterTypes":["com.amazonaws.xray.strategy.sampling.rule.SamplingRule"] }, {"name":"setRules","parameterTypes":["java.util.List"] }, {"name":"setVersion","parameterTypes":["int"] }] +}, +{ + "name":"com.amazonaws.xray.strategy.sampling.reservoir.Reservoir", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.xray.strategy.sampling.rule.SamplingRule", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"setFixedTarget","parameterTypes":["int"] }, {"name":"setRate","parameterTypes":["float"] }] +}, +{ + "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.AESCipher$General", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ARCFOURCipher", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESCipher", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESedeCipher", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.HmacCore$HmacSHA256", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"java.io.IOException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.Cloneable", + "queryAllDeclaredMethods":true +}, +{ + "name":"java.lang.ProcessEnvironment", + "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] +}, +{ + "name":"java.lang.String" +}, +{ + "name":"java.lang.Thread", + "fields":[{"name":"threadLocalRandomProbe"}], + "methods":[{"name":"getContextClassLoader","parameterTypes":[] }] +}, +{ + "name":"java.security.AlgorithmParametersSpi" +}, +{ + "name":"java.security.KeyStoreSpi" +}, +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.Striped64", + "fields":[{"name":"base"}, {"name":"cellsBusy"}] +}, +{ + "name":"javax.crac.Resource" +}, +{ + "name":"javax.security.auth.x500.X500Principal", + "fields":[{"name":"thisX500Name"}], + "methods":[{"name":"<init>","parameterTypes":["sun.security.x509.X500Name"] }] +}, +{ + "name":"jdk.crac.Resource" +}, +{ + "name":"kotlin.Metadata" +}, +{ + "name":"kotlin.Unit" +}, +{ + "name":"org.apache.commons.logging.LogFactory" +}, +{ + "name":"org.apache.commons.logging.impl.Jdk14Logger", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }, {"name":"setLogFactory","parameterTypes":["org.apache.commons.logging.LogFactory"] }] +}, +{ + "name":"org.apache.commons.logging.impl.Log4JLogger" +}, +{ + "name":"org.apache.commons.logging.impl.LogFactoryImpl", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"org.apache.commons.logging.impl.WeakHashtable", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"org.joda.time.DateTime" +}, +{ + "name":"scala.util.Properties" +}, +{ + "name":"software.amazon.awssdk.enhanced.dynamodb.internal.ApplyUserAgentInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.MD5", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"<init>","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.SHA2$SHA256", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.X509Factory", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAKeyFactory$Legacy", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.SSLContextImpl$TLSContext", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.x509.AuthorityInfoAccessExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.AuthorityKeyIdentifierExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.BasicConstraintsExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CRLDistributionPointsExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CertificatePoliciesExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.ExtendedKeyUsageExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.KeyUsageExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.NetscapeCertTypeExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.PrivateKeyUsageExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectKeyIdentifierExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +} +] diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/resource-config.json b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/resource-config.json new file mode 100644 index 000000000..98e775bb6 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/resource-config.json @@ -0,0 +1,27 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.InetAddressResolverProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.apache.commons.logging.LogFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qcom/amazonaws/xray/interceptors/DefaultOperationParameterWhitelist.json\\E" + }, { + "pattern":"\\Qcom/amazonaws/xray/sdk.properties\\E" + }, { + "pattern":"\\Qcom/amazonaws/xray/strategy/sampling/DefaultSamplingRules.json\\E" + }, { + "pattern":"\\Qcommons-logging.properties\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/services/dynamodb/execution.interceptors\\E" + }]}, + "bundles":[] +} diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java index 289b0f1cd..9f6875689 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBConfig.java @@ -14,16 +14,10 @@ package software.amazon.lambda.powertools.idempotency.persistence.dynamodb; -import java.io.IOException; -import java.net.ServerSocket; import java.net.URI; -import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import com.amazonaws.services.dynamodbv2.local.main.ServerRunner; -import com.amazonaws.services.dynamodbv2.local.server.DynamoDBProxyServer; - import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; @@ -32,71 +26,40 @@ import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; import software.amazon.awssdk.services.dynamodb.model.BillingMode; import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest; -import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest; -import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse; import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement; import software.amazon.awssdk.services.dynamodb.model.KeyType; +import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException; import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType; -public class DynamoDBConfig { +class DynamoDBConfig { protected static final String TABLE_NAME = "idempotency_table"; - protected static DynamoDBProxyServer dynamoProxy; protected static DynamoDbClient client; @BeforeAll - public static void setupDynamo() { - int port = getFreePort(); - try { - dynamoProxy = ServerRunner.createServerFromCommandLineArgs(new String[] { - "-inMemory", - "-port", - Integer.toString(port) - }); - dynamoProxy.start(); - } catch (Exception e) { - throw new RuntimeException(); - } + static void setupDynamo() { + String endpoint = System.getProperty("dynamodb.endpoint", "http://localhost:8000"); client = DynamoDbClient.builder() .httpClient(UrlConnectionHttpClient.builder().build()) .region(Region.EU_WEST_1) - .endpointOverride(URI.create("http://localhost:" + port)) + .endpointOverride(URI.create(endpoint)) .credentialsProvider(StaticCredentialsProvider.create( AwsBasicCredentials.create("FAKE", "FAKE"))) .build(); - client.createTable(CreateTableRequest.builder() - .tableName(TABLE_NAME) - .keySchema(KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("id").build()) - .attributeDefinitions( - AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S).build()) - .billingMode(BillingMode.PAY_PER_REQUEST) - .build()); - - DescribeTableResponse response = client - .describeTable(DescribeTableRequest.builder().tableName(TABLE_NAME).build()); - if (response == null) { - throw new RuntimeException("Table was not created within expected time"); - } - } - - @AfterAll - public static void teardownDynamo() { try { - dynamoProxy.stop(); + client.createTable(CreateTableRequest.builder() + .tableName(TABLE_NAME) + .keySchema(KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("id").build()) + .attributeDefinitions( + AttributeDefinition.builder().attributeName("id").attributeType(ScalarAttributeType.S) + .build()) + .billingMode(BillingMode.PAY_PER_REQUEST) + .build()); + } catch (ResourceInUseException e) { + // Table already exists, ignore } catch (Exception e) { - throw new RuntimeException(); - } - } - - private static int getFreePort() { - try { - ServerSocket socket = new ServerSocket(0); - int port = socket.getLocalPort(); - socket.close(); - return port; - } catch (IOException ioe) { - throw new RuntimeException(ioe); + throw new RuntimeException("Failed to create DynamoDB table", e); } } } diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java index 56b32c4f9..b5c816286 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/DynamoDBPersistenceStoreTest.java @@ -14,10 +14,20 @@ package software.amazon.lambda.powertools.idempotency.persistence.dynamodb; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.SetEnvironmentVariable; + import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.BillingMode; @@ -32,47 +42,35 @@ import software.amazon.awssdk.services.dynamodb.model.ScanRequest; import software.amazon.lambda.powertools.idempotency.Constants; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; - import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - /** * These test are using DynamoDBLocal and sqlite, see https://nickolasfisher.com/blog/Configuring-an-In-Memory-DynamoDB-instance-with-Java-for-Integration-Testing * NOTE: on a Mac with Apple Chipset, you need to use the Oracle JDK x86 64-bit */ -public class DynamoDBPersistenceStoreTest extends DynamoDBConfig { +class DynamoDBPersistenceStoreTest extends DynamoDBConfig { protected static final String TABLE_NAME_CUSTOM = "idempotency_table_custom"; private Map<String, AttributeValue> key; private DynamoDBPersistenceStore dynamoDBPersistenceStore; - // ================================================================= - //<editor-fold desc="putRecord"> @Test - public void putRecord_shouldCreateRecordInDynamoDB() throws IdempotencyItemAlreadyExistsException { + void putRecord_shouldCreateRecordInDynamoDB() throws IdempotencyItemAlreadyExistsException { Instant now = Instant.now(); long expiry = now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(); dynamoDBPersistenceStore.putRecord(new DataRecord("key", DataRecord.Status.COMPLETED, expiry, null, null), now); key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); - Map<String, AttributeValue> item = - client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); + Map<String, AttributeValue> item = client + .getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); assertThat(item).isNotNull(); assertThat(item.get("status").s()).isEqualTo("COMPLETED"); assertThat(item.get("expiration").n()).isEqualTo(String.valueOf(expiry)); } @Test - public void putRecord_shouldCreateRecordInDynamoDB_IfPreviousExpired() { + void putRecord_shouldCreateRecordInDynamoDB_IfPreviousExpired() { key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); // GIVEN: Insert a fake item with same id and expired @@ -91,22 +89,23 @@ public void putRecord_shouldCreateRecordInDynamoDB_IfPreviousExpired() { DataRecord.Status.INPROGRESS, expiry2, null, - null - ), now); + null), + now); // THEN: an item is inserted - Map<String, AttributeValue> itemInDb = - client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); + Map<String, AttributeValue> itemInDb = client + .getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); assertThat(itemInDb).isNotNull(); assertThat(itemInDb.get("status").s()).isEqualTo("INPROGRESS"); assertThat(itemInDb.get("expiration").n()).isEqualTo(String.valueOf(expiry2)); } @Test - public void putRecord_shouldCreateRecordInDynamoDB_IfLambdaWasInProgressAndTimedOut() { + void putRecord_shouldCreateRecordInDynamoDB_IfLambdaWasInProgressAndTimedOut() { key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); - // GIVEN: Insert a fake item with same id and progress expired (Lambda timed out before and we allow a new execution) + // GIVEN: Insert a fake item with same id and progress expired (Lambda timed out before and we allow a new + // execution) Map<String, AttributeValue> item = new HashMap<>(key); Instant now = Instant.now(); long expiry = now.plus(30, ChronoUnit.SECONDS).getEpochSecond(); @@ -124,19 +123,19 @@ public void putRecord_shouldCreateRecordInDynamoDB_IfLambdaWasInProgressAndTimed DataRecord.Status.INPROGRESS, expiry2, null, - null - ), now); + null), + now); // THEN: an item is inserted - Map<String, AttributeValue> itemInDb = - client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); + Map<String, AttributeValue> itemInDb = client + .getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); assertThat(itemInDb).isNotNull(); assertThat(itemInDb.get("status").s()).isEqualTo("INPROGRESS"); assertThat(itemInDb.get("expiration").n()).isEqualTo(String.valueOf(expiry2)); } @Test - public void putRecord_shouldThrowIdempotencyItemAlreadyExistsException_IfRecordAlreadyExist() { + void putRecord_shouldThrowIdempotencyItemAlreadyExistsException_IfRecordAlreadyExist() { key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); // GIVEN: Insert a fake item with same id @@ -150,15 +149,15 @@ public void putRecord_shouldThrowIdempotencyItemAlreadyExistsException_IfRecordA // WHEN: call putRecord long expiry2 = now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(); - assertThatThrownBy(() -> dynamoDBPersistenceStore.putRecord( - new DataRecord("key", - DataRecord.Status.INPROGRESS, - expiry2, - null, - null), - now)).isInstanceOf(IdempotencyItemAlreadyExistsException.class) - // DataRecord should be present due to returnValuesOnConditionCheckFailure("ALL_OLD") - .matches(e -> ((IdempotencyItemAlreadyExistsException) e).getDataRecord().isPresent()); + DataRecord recordToInsert = new DataRecord("key", + DataRecord.Status.INPROGRESS, + expiry2, + null, + null); + assertThatThrownBy(() -> dynamoDBPersistenceStore.putRecord(recordToInsert, now)) + .isInstanceOf(IdempotencyItemAlreadyExistsException.class) + // DataRecord should be present due to returnValuesOnConditionCheckFailure("ALL_OLD") + .matches(e -> ((IdempotencyItemAlreadyExistsException) e).getDataRecord().isPresent()); // THEN: item was not updated, retrieve the initial one Map<String, AttributeValue> itemInDb = client @@ -170,7 +169,7 @@ public void putRecord_shouldThrowIdempotencyItemAlreadyExistsException_IfRecordA } @Test - public void putRecord_shouldBlockUpdate_IfRecordAlreadyExistAndProgressNotExpiredAfterLambdaTimedOut() { + void putRecord_shouldBlockUpdate_IfRecordAlreadyExistAndProgressNotExpiredAfterLambdaTimedOut() { key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); // GIVEN: Insert a fake item with same id @@ -186,17 +185,15 @@ public void putRecord_shouldBlockUpdate_IfRecordAlreadyExistAndProgressNotExpire // WHEN: call putRecord long expiry2 = now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(); - assertThatThrownBy(() -> dynamoDBPersistenceStore.putRecord( - new DataRecord("key", - DataRecord.Status.INPROGRESS, - expiry2, - "Fake Data 2", - null), - now)) - .isInstanceOf(IdempotencyItemAlreadyExistsException.class) - // DataRecord should be present due to returnValuesOnConditionCheckFailure("ALL_OLD") - .matches(e -> ((IdempotencyItemAlreadyExistsException) e).getDataRecord().isPresent()); - ; + DataRecord recordToInsert = new DataRecord("key", + DataRecord.Status.INPROGRESS, + expiry2, + "Fake Data 2", + null); + assertThatThrownBy(() -> dynamoDBPersistenceStore.putRecord(recordToInsert, now)) + .isInstanceOf(IdempotencyItemAlreadyExistsException.class) + // DataRecord should be present due to returnValuesOnConditionCheckFailure("ALL_OLD") + .matches(e -> ((IdempotencyItemAlreadyExistsException) e).getDataRecord().isPresent()); // THEN: item was not updated, retrieve the initial one Map<String, AttributeValue> itemInDb = client @@ -207,15 +204,8 @@ public void putRecord_shouldBlockUpdate_IfRecordAlreadyExistAndProgressNotExpire assertThat(itemInDb.get("data").s()).isEqualTo("Fake Data"); } - - //</editor-fold> - // ================================================================= - - // ================================================================= - //<editor-fold desc="getRecord"> - @Test - public void getRecord_shouldReturnExistingRecord() throws IdempotencyItemNotFoundException { + void getRecord_shouldReturnExistingRecord() throws IdempotencyItemNotFoundException { key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); // GIVEN: Insert a fake item with same id @@ -228,29 +218,23 @@ public void getRecord_shouldReturnExistingRecord() throws IdempotencyItemNotFoun client.putItem(PutItemRequest.builder().tableName(TABLE_NAME).item(item).build()); // WHEN - DataRecord record = dynamoDBPersistenceStore.getRecord("key"); + DataRecord dr = dynamoDBPersistenceStore.getRecord("key"); // THEN - assertThat(record.getIdempotencyKey()).isEqualTo("key"); - assertThat(record.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); - assertThat(record.getResponseData()).isEqualTo("Fake Data"); - assertThat(record.getExpiryTimestamp()).isEqualTo(expiry); + assertThat(dr.getIdempotencyKey()).isEqualTo("key"); + assertThat(dr.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); + assertThat(dr.getResponseData()).isEqualTo("Fake Data"); + assertThat(dr.getExpiryTimestamp()).isEqualTo(expiry); } @Test - public void getRecord_shouldThrowException_whenRecordIsAbsent() { - assertThatThrownBy(() -> dynamoDBPersistenceStore.getRecord("key")).isInstanceOf( - IdempotencyItemNotFoundException.class); + void getRecord_shouldThrowException_whenRecordIsAbsent() { + assertThatThrownBy(() -> dynamoDBPersistenceStore.getRecord("key")) + .isInstanceOf(IdempotencyItemNotFoundException.class); } - //</editor-fold> - // ================================================================= - - // ================================================================= - //<editor-fold desc="updateRecord"> - @Test - public void updateRecord_shouldUpdateRecord() { + void updateRecord_shouldUpdateRecord() { // GIVEN: Insert a fake item with same id key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); Map<String, AttributeValue> item = new HashMap<>(key); @@ -265,26 +249,20 @@ public void updateRecord_shouldUpdateRecord() { // WHEN expiry = now.plus(3600, ChronoUnit.SECONDS).getEpochSecond(); - DataRecord record = new DataRecord("key", DataRecord.Status.COMPLETED, expiry, "Fake result", "hash"); - dynamoDBPersistenceStore.updateRecord(record); + DataRecord dr = new DataRecord("key", DataRecord.Status.COMPLETED, expiry, "Fake result", "hash"); + dynamoDBPersistenceStore.updateRecord(dr); // THEN - Map<String, AttributeValue> itemInDb = - client.getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); + Map<String, AttributeValue> itemInDb = client + .getItem(GetItemRequest.builder().tableName(TABLE_NAME).key(key).build()).item(); assertThat(itemInDb.get("status").s()).isEqualTo("COMPLETED"); assertThat(itemInDb.get("expiration").n()).isEqualTo(String.valueOf(expiry)); assertThat(itemInDb.get("data").s()).isEqualTo("Fake result"); assertThat(itemInDb.get("validation").s()).isEqualTo("hash"); } - //</editor-fold> - // ================================================================= - - // ================================================================= - //<editor-fold desc="deleteRecord"> - @Test - public void deleteRecord_shouldDeleteRecord() { + void deleteRecord_shouldDeleteRecord() { // GIVEN: Insert a fake item with same id key = Collections.singletonMap("id", AttributeValue.builder().s("key").build()); Map<String, AttributeValue> item = new HashMap<>(key); @@ -299,27 +277,22 @@ public void deleteRecord_shouldDeleteRecord() { dynamoDBPersistenceStore.deleteRecord("key"); // THEN - assertThat(client.scan(ScanRequest.builder().tableName(TABLE_NAME).build()).count()).isEqualTo(0); + assertThat(client.scan(ScanRequest.builder().tableName(TABLE_NAME).build()).count()).isZero(); } - //</editor-fold> - // ================================================================= - @Test - public void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFoundException { + void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFoundException { try { client.createTable(CreateTableRequest.builder() .tableName(TABLE_NAME_CUSTOM) .keySchema( KeySchemaElement.builder().keyType(KeyType.HASH).attributeName("key").build(), - KeySchemaElement.builder().keyType(KeyType.RANGE).attributeName("sortkey").build() - ) + KeySchemaElement.builder().keyType(KeyType.RANGE).attributeName("sortkey").build()) .attributeDefinitions( AttributeDefinition.builder().attributeName("key").attributeType(ScalarAttributeType.S) .build(), AttributeDefinition.builder().attributeName("sortkey").attributeType(ScalarAttributeType.S) - .build() - ) + .build()) .billingMode(BillingMode.PAY_PER_REQUEST) .build()); @@ -336,22 +309,21 @@ public void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFou .build(); Instant now = Instant.now(); - DataRecord record = new DataRecord( + DataRecord dr = new DataRecord( "mykey", DataRecord.Status.INPROGRESS, now.plus(400, ChronoUnit.SECONDS).getEpochSecond(), null, - null - ); + null); // PUT - persistenceStore.putRecord(record, now); + persistenceStore.putRecord(dr, now); Map<String, AttributeValue> customKey = new HashMap<>(); customKey.put("key", AttributeValue.builder().s("pk").build()); customKey.put("sortkey", AttributeValue.builder().s("mykey").build()); - Map<String, AttributeValue> itemInDb = - client.getItem(GetItemRequest.builder().tableName(TABLE_NAME_CUSTOM).key(customKey).build()).item(); + Map<String, AttributeValue> itemInDb = client + .getItem(GetItemRequest.builder().tableName(TABLE_NAME_CUSTOM).key(customKey).build()).item(); // GET DataRecord recordInDb = persistenceStore.getRecord("mykey"); @@ -368,8 +340,7 @@ public void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFou DataRecord.Status.COMPLETED, now.plus(500, ChronoUnit.SECONDS).getEpochSecond(), "response", - null - ); + null); persistenceStore.updateRecord(updatedRecord); recordInDb = persistenceStore.getRecord("mykey"); assertThat(recordInDb).isEqualTo(updatedRecord); @@ -389,13 +360,14 @@ public void endToEndWithCustomAttrNamesAndSortKey() throws IdempotencyItemNotFou @Test @SetEnvironmentVariable(key = Constants.IDEMPOTENCY_DISABLED_ENV, value = "true") - public void idempotencyDisabled_noClientShouldBeCreated() { + void idempotencyDisabled_noClientShouldBeCreated() { DynamoDBPersistenceStore store = DynamoDBPersistenceStore.builder().withTableName(TABLE_NAME).build(); - assertThatThrownBy(() -> store.getRecord("fake")).isInstanceOf(NullPointerException.class); + assertThatThrownBy(() -> store.getRecord("fake")) + .isInstanceOf(NullPointerException.class); } @BeforeEach - public void setup() { + void setup() { dynamoDBPersistenceStore = DynamoDBPersistenceStore.builder() .withTableName(TABLE_NAME) .withDynamoDbClient(client) @@ -403,10 +375,14 @@ public void setup() { } @AfterEach - public void emptyDB() { - if (key != null) { - client.deleteItem(DeleteItemRequest.builder().tableName(TABLE_NAME).key(key).build()); - key = null; - } + void emptyDB() { + // Clear all items from the table + client.scan(ScanRequest.builder().tableName(TABLE_NAME).build()) + .items() + .forEach(item -> { + Map<String, AttributeValue> itemKey = Collections.singletonMap("id", item.get("id")); + client.deleteItem(DeleteItemRequest.builder().tableName(TABLE_NAME).key(itemKey).build()); + }); + key = null; } } diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java index 7b43542c8..e85614580 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/dynamodb/IdempotencyTest.java @@ -16,30 +16,22 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import com.amazonaws.services.lambda.runtime.tests.EventLoader; import software.amazon.awssdk.services.dynamodb.model.ScanRequest; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.handlers.IdempotencyFunction; -public class IdempotencyTest extends DynamoDBConfig { +class IdempotencyTest extends DynamoDBConfig { - @Mock - private Context context; - - @BeforeEach - void setUp() { - MockitoAnnotations.openMocks(this); - } + private Context context = new TestLambdaContext(); @Test - public void endToEndTest() { + void endToEndTest() { IdempotencyFunction function = new IdempotencyFunction(client); APIGatewayProxyResponseEvent response = function diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/resources/simplelogger.properties b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..6d188691f --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/resources/simplelogger.properties @@ -0,0 +1,7 @@ +org.slf4j.simpleLogger.logFile=target/idempotency-dynamodb-test.log +org.slf4j.simpleLogger.defaultLogLevel=warn +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS +org.slf4j.simpleLogger.showThreadName=false +org.slf4j.simpleLogger.showLogName=true +org.slf4j.simpleLogger.showShortLogName=false \ No newline at end of file From 65f00fee20c0182233df2ae79b93b5637b0df4f6 Mon Sep 17 00:00:00 2001 From: kjswaruph <jyothiswaruphkolli@gmail.com> Date: Wed, 27 Aug 2025 22:37:27 +0530 Subject: [PATCH 390/577] feat: Support CRaC priming of powertools validation (#2081) * feat: support CRaC priming of powertools validation - Add org.crac dependency and generate-classesloaded-file profile in pom.xml - Add classesloaded.txt in src/main/resources for automatic class preloading - Update ValidationConfig to register for Crac resource - Update spotbugs-exclude.xml to suppress RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT spotbug error in beforeCheckpoint method * test: add ValidationConfigTest to assert beforeCheckpoint and afterRestore hooks do not throw exception * docs: Add SnapStart priming subsection for validation * test: Remove public modifier from ValidationConfigTest class and methods * docs: Improve Lambda SnapStart priming section Co-authored-by: Philipp Page <philipp.page@yahoo.de> --------- Co-authored-by: Philipp Page <philipp.page@yahoo.de> --- docs/utilities/validation.md | 50 + powertools-validation/pom.xml | 25 + .../validation/ValidationConfig.java | 32 +- .../src/main/resources/classesloaded.txt | 7285 +++++++++++++++++ .../validation/ValidationConfigTest.java | 38 + spotbugs-exclude.xml | 5 + 6 files changed, 7434 insertions(+), 1 deletion(-) create mode 100644 powertools-validation/src/main/resources/classesloaded.txt create mode 100644 powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationConfigTest.java diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index 96bdd142b..ec35b7034 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -292,3 +292,53 @@ If you need to configure the Jackson ObjectMapper, you can use the `ValidationCo } } ``` + +## Advanced + +### Lambda SnapStart priming + +The Validation utility integrates with AWS Lambda SnapStart to improve restore durations. To make sure the SnapStart priming logic of this utility runs correctly, you need an explicit reference to `ValidationConfig` in your code to allow the library to register before SnapStart takes a memory snapshot. Learn more about what priming is in this [blog post](https://aws.amazon.com/blogs/compute/optimizing-cold-start-performance-of-aws-lambda-using-advanced-priming-strategies-with-snapstart/){target="_blank"}. + +If you don't set a custom `ValidationConfig` in your code yet, make sure to reference `ValidationConfig` in your Lambda handler initialization code. This can be done by adding one of the following lines to your handler class: + +=== "Constructor" + + ```java hl_lines="7" + import software.amazon.lambda.powertools.validation.Validation; + import software.amazon.lambda.powertools.validation.ValidationConfig; + + public class MyFunctionHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + public MyFunctionHandler() { + ValidationConfig.get(); // Ensure ValidationConfig is loaded for SnapStart + } + + @Override + @Validation(inboundSchema = "classpath:/schema_in.json", outboundSchema = "classpath:/schema_out.json") + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + // ... + return something; + } + } + ``` + +=== "Static Initializer" + + ```java hl_lines="7" + import software.amazon.lambda.powertools.validation.Validation; + import software.amazon.lambda.powertools.validation.ValidationConfig; + + public class MyFunctionHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + static { + ValidationConfig.get(); // Ensure ValidationConfig is loaded for SnapStart + } + + @Override + @Validation(inboundSchema = "classpath:/schema_in.json", outboundSchema = "classpath:/schema_out.json") + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + // ... + return something; + } + } + ``` diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 30e56802f..118edc66f 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -71,6 +71,10 @@ <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-serialization</artifactId> </dependency> + <dependency> + <groupId>org.crac</groupId> + <artifactId>crac</artifactId> + </dependency> <!-- Test dependencies --> <dependency> @@ -119,4 +123,25 @@ <scope>test</scope> </dependency> </dependencies> + + <profiles> + <profile> + <id>generate-classesloaded-file</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine> + -Xlog:class+load=info:classesloaded.txt + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + </argLine> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java index 3f643ab00..346dc6fa3 100644 --- a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/ValidationConfig.java @@ -16,10 +16,15 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.networknt.schema.JsonSchema; import com.networknt.schema.JsonSchemaFactory; import com.networknt.schema.SpecVersion; import io.burt.jmespath.JmesPath; import io.burt.jmespath.function.BaseFunction; +import org.crac.Context; +import org.crac.Core; +import org.crac.Resource; +import software.amazon.lambda.powertools.common.internal.ClassPreLoader; import software.amazon.lambda.powertools.utilities.JsonConfig; import software.amazon.lambda.powertools.utilities.jmespath.Base64Function; import software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunction; @@ -31,10 +36,15 @@ * For everything but the validation features (factory, schemaVersion), {@link ValidationConfig} * is just a wrapper of {@link JsonConfig}. */ -public class ValidationConfig { +public class ValidationConfig implements Resource { private SpecVersion.VersionFlag jsonSchemaVersion = SpecVersion.VersionFlag.V7; private JsonSchemaFactory factory = JsonSchemaFactory.getInstance(jsonSchemaVersion); + // Static block to ensure CRaC registration happens at class loading time + static { + Core.getGlobalContext().register(get()); + } + private ValidationConfig() { } @@ -102,6 +112,26 @@ public ObjectMapper getObjectMapper() { return JsonConfig.get().getObjectMapper(); } + @Override + public void beforeCheckpoint(Context<? extends Resource> context) throws Exception { + // Initialize key components + getObjectMapper(); + getJmesPath(); + getFactory(); + + // Dummy validation + String sampleSchema = "{\"type\":\"object\"}"; + JsonSchema schema = ValidationUtils.getJsonSchema(sampleSchema); + ValidationUtils.validate("{\"test\":\"dummy\"}", schema); + + ClassPreLoader.preloadClasses(); + } + + @Override + public void afterRestore(Context<? extends Resource> context) throws Exception { + // No action needed after restore + } + private static class ConfigHolder { private static final ValidationConfig instance = new ValidationConfig(); } diff --git a/powertools-validation/src/main/resources/classesloaded.txt b/powertools-validation/src/main/resources/classesloaded.txt new file mode 100644 index 000000000..adf442b37 --- /dev/null +++ b/powertools-validation/src/main/resources/classesloaded.txt @@ -0,0 +1,7285 @@ +java.lang.Object +java.io.Serializable +java.lang.Comparable +java.lang.CharSequence +java.lang.constant.Constable +java.lang.constant.ConstantDesc +java.lang.String +java.lang.reflect.AnnotatedElement +java.lang.reflect.GenericDeclaration +java.lang.reflect.Type +java.lang.invoke.TypeDescriptor +java.lang.invoke.TypeDescriptor$OfField +java.lang.Class +java.lang.Cloneable +java.lang.ClassLoader +java.lang.System +java.lang.Throwable +java.lang.Error +java.lang.ThreadDeath +java.lang.Exception +java.lang.RuntimeException +java.lang.SecurityManager +java.security.ProtectionDomain +java.security.AccessControlContext +java.security.AccessController +java.security.SecureClassLoader +java.lang.ReflectiveOperationException +java.lang.ClassNotFoundException +java.lang.Record +java.lang.LinkageError +java.lang.NoClassDefFoundError +java.lang.ClassCastException +java.lang.ArrayStoreException +java.lang.VirtualMachineError +java.lang.InternalError +java.lang.OutOfMemoryError +java.lang.StackOverflowError +java.lang.IllegalMonitorStateException +java.lang.ref.Reference +java.lang.ref.SoftReference +java.lang.ref.WeakReference +java.lang.ref.FinalReference +java.lang.ref.PhantomReference +java.lang.ref.Finalizer +java.lang.Runnable +java.lang.Thread +java.lang.Thread$UncaughtExceptionHandler +java.lang.ThreadGroup +java.util.Dictionary +java.util.Map +java.util.Hashtable +java.util.Properties +java.lang.Module +java.lang.reflect.AccessibleObject +java.lang.reflect.Member +java.lang.reflect.Field +java.lang.reflect.Parameter +java.lang.reflect.Executable +java.lang.reflect.Method +java.lang.reflect.Constructor +jdk.internal.reflect.MagicAccessorImpl +jdk.internal.reflect.MethodAccessor +jdk.internal.reflect.MethodAccessorImpl +jdk.internal.reflect.ConstructorAccessor +jdk.internal.reflect.ConstructorAccessorImpl +jdk.internal.reflect.DelegatingClassLoader +jdk.internal.reflect.ConstantPool +jdk.internal.reflect.FieldAccessor +jdk.internal.reflect.FieldAccessorImpl +jdk.internal.reflect.UnsafeFieldAccessorImpl +jdk.internal.reflect.UnsafeStaticFieldAccessorImpl +java.lang.annotation.Annotation +jdk.internal.reflect.CallerSensitive +jdk.internal.reflect.NativeConstructorAccessorImpl +java.lang.invoke.MethodHandle +java.lang.invoke.DirectMethodHandle +java.lang.invoke.VarHandle +java.lang.invoke.MemberName +java.lang.invoke.ResolvedMethodName +java.lang.invoke.MethodHandleNatives +java.lang.invoke.LambdaForm +java.lang.invoke.TypeDescriptor$OfMethod +java.lang.invoke.MethodType +java.lang.BootstrapMethodError +java.lang.invoke.CallSite +jdk.internal.invoke.NativeEntryPoint +java.lang.invoke.MethodHandleNatives$CallSiteContext +java.lang.invoke.ConstantCallSite +java.lang.invoke.MutableCallSite +java.lang.invoke.VolatileCallSite +java.lang.AssertionStatusDirectives +java.lang.Appendable +java.lang.AbstractStringBuilder +java.lang.StringBuffer +java.lang.StringBuilder +jdk.internal.misc.UnsafeConstants +jdk.internal.misc.Unsafe +jdk.internal.module.Modules +java.lang.AutoCloseable +java.io.Closeable +java.io.InputStream +java.io.ByteArrayInputStream +java.net.URL +java.util.jar.Manifest +jdk.internal.loader.BuiltinClassLoader +jdk.internal.loader.ClassLoaders +jdk.internal.loader.ClassLoaders$AppClassLoader +jdk.internal.loader.ClassLoaders$PlatformClassLoader +java.security.CodeSource +java.util.AbstractMap +java.util.concurrent.ConcurrentMap +java.util.concurrent.ConcurrentHashMap +java.lang.Iterable +java.util.Collection +java.util.AbstractCollection +java.util.List +java.util.AbstractList +java.util.RandomAccess +java.util.ArrayList +java.lang.StackTraceElement +java.nio.Buffer +java.lang.StackWalker +java.lang.StackStreamFactory$AbstractStackWalker +java.lang.StackWalker$StackFrame +java.lang.StackFrameInfo +java.lang.LiveStackFrame +java.lang.LiveStackFrameInfo +java.util.concurrent.locks.AbstractOwnableSynchronizer +java.lang.Boolean +java.lang.Character +java.lang.Number +java.lang.Float +java.lang.Double +java.lang.Byte +java.lang.Short +java.lang.Integer +java.lang.Long +java.util.Iterator +java.lang.reflect.RecordComponent +jdk.internal.vm.vector.VectorSupport +jdk.internal.vm.vector.VectorSupport$VectorPayload +jdk.internal.vm.vector.VectorSupport$Vector +jdk.internal.vm.vector.VectorSupport$VectorMask +jdk.internal.vm.vector.VectorSupport$VectorShuffle +java.lang.Integer$IntegerCache +java.lang.Long$LongCache +java.lang.Byte$ByteCache +java.lang.Short$ShortCache +java.lang.Character$CharacterCache +java.util.jar.Attributes$Name +java.util.ImmutableCollections$AbstractImmutableMap +java.util.ImmutableCollections$MapN +sun.util.locale.BaseLocale +jdk.internal.module.ArchivedModuleGraph +java.lang.module.ModuleFinder +jdk.internal.module.SystemModuleFinders$SystemModuleFinder +java.util.ImmutableCollections$AbstractImmutableCollection +java.util.Set +java.util.ImmutableCollections$AbstractImmutableSet +java.util.ImmutableCollections$SetN +java.lang.module.ModuleReference +jdk.internal.module.ModuleReferenceImpl +java.lang.module.ModuleDescriptor +java.lang.module.ModuleDescriptor$Version +java.util.ImmutableCollections$Set12 +java.lang.module.ModuleDescriptor$Requires +java.lang.Enum +java.lang.module.ModuleDescriptor$Requires$Modifier +java.lang.module.ModuleDescriptor$Exports +java.net.URI +java.util.function.Supplier +jdk.internal.module.SystemModuleFinders$2 +jdk.internal.module.ModuleHashes$HashSupplier +jdk.internal.module.SystemModuleFinders$3 +java.lang.module.ModuleDescriptor$Provides +java.util.ImmutableCollections$AbstractImmutableList +java.util.ImmutableCollections$List12 +java.util.ImmutableCollections$ListN +java.lang.module.ModuleDescriptor$Opens +jdk.internal.module.ModuleTarget +jdk.internal.module.ModuleHashes +java.util.Collections$UnmodifiableMap +java.util.HashMap +java.util.Map$Entry +java.util.HashMap$Node +java.lang.module.Configuration +java.lang.module.ResolvedModule +java.util.function.Function +jdk.internal.module.ModuleLoaderMap$Mapper +java.util.ImmutableCollections +java.lang.ModuleLayer +jdk.internal.math.FDBigInteger +java.lang.NullPointerException +java.lang.ArithmeticException +java.io.ObjectStreamField +java.util.Comparator +java.lang.String$CaseInsensitiveComparator +java.lang.Module$ArchivedData +jdk.internal.misc.CDS +java.util.Objects +jdk.internal.access.JavaLangReflectAccess +java.lang.reflect.ReflectAccess +jdk.internal.access.SharedSecrets +java.lang.invoke.MethodHandles +java.lang.invoke.MemberName$Factory +java.security.Guard +java.security.Permission +java.security.BasicPermission +java.lang.reflect.ReflectPermission +java.lang.StringLatin1 +java.lang.invoke.MethodHandles$Lookup +jdk.internal.reflect.Reflection +java.lang.Math +java.util.AbstractSet +java.util.ImmutableCollections$MapN$1 +java.util.ImmutableCollections$MapN$MapNIterator +java.util.KeyValueHolder +java.util.LinkedHashMap$Entry +java.util.HashMap$TreeNode +java.lang.Runtime +java.util.concurrent.locks.Lock +java.util.concurrent.locks.ReentrantLock +java.util.concurrent.ConcurrentHashMap$Segment +java.util.concurrent.ConcurrentHashMap$CounterCell +java.util.concurrent.ConcurrentHashMap$Node +java.util.concurrent.locks.LockSupport +java.util.concurrent.ConcurrentHashMap$ReservationNode +java.security.PrivilegedAction +jdk.internal.reflect.ReflectionFactory$GetReflectionFactoryAction +jdk.internal.reflect.ReflectionFactory +java.lang.ref.Reference$ReferenceHandler +jdk.internal.ref.Cleaner +java.lang.ref.ReferenceQueue +java.lang.ref.ReferenceQueue$Null +java.lang.ref.ReferenceQueue$Lock +jdk.internal.access.JavaLangRefAccess +java.lang.ref.Reference$1 +java.lang.ref.Finalizer$FinalizerThread +jdk.internal.access.JavaLangAccess +java.lang.System$2 +jdk.internal.misc.VM +jdk.internal.util.SystemProps +jdk.internal.util.SystemProps$Raw +java.lang.StringConcatHelper +java.lang.VersionProps +java.util.Arrays +java.lang.CharacterData +java.lang.CharacterDataLatin1 +java.util.HashMap$EntrySet +java.util.HashMap$HashIterator +java.util.HashMap$EntryIterator +jdk.internal.util.StaticProperty +java.io.FileInputStream +java.io.FileDescriptor +jdk.internal.access.JavaIOFileDescriptorAccess +java.io.FileDescriptor$1 +java.io.Flushable +java.io.OutputStream +java.io.FileOutputStream +java.io.FilterInputStream +java.io.BufferedInputStream +java.io.FilterOutputStream +java.io.PrintStream +java.io.BufferedOutputStream +java.io.Writer +java.io.OutputStreamWriter +java.nio.charset.Charset +java.nio.charset.spi.CharsetProvider +sun.nio.cs.StandardCharsets +java.lang.ThreadLocal +java.util.concurrent.atomic.AtomicInteger +sun.security.action.GetPropertyAction +sun.nio.cs.HistoricallyNamedCharset +sun.nio.cs.Unicode +sun.nio.cs.UTF_8 +sun.nio.cs.StreamEncoder +java.nio.charset.CharsetEncoder +sun.nio.cs.UTF_8$Encoder +java.nio.charset.CodingErrorAction +java.nio.ByteBuffer +jdk.internal.misc.ScopedMemoryAccess +jdk.internal.access.JavaNioAccess +java.nio.Buffer$1 +java.nio.HeapByteBuffer +java.nio.ByteOrder +java.io.BufferedWriter +java.lang.Terminator +jdk.internal.misc.Signal$Handler +java.lang.Terminator$1 +jdk.internal.misc.Signal +java.util.Hashtable$Entry +jdk.internal.misc.Signal$NativeHandler +jdk.internal.misc.OSEnvironment +java.util.Collections +java.util.Collections$EmptySet +java.util.Collections$EmptyList +java.util.Collections$EmptyMap +java.lang.IllegalArgumentException +java.lang.invoke.MethodHandleStatics +jdk.internal.module.ModuleBootstrap +sun.invoke.util.VerifyAccess +java.lang.reflect.Modifier +jdk.internal.access.JavaLangModuleAccess +java.lang.module.ModuleDescriptor$1 +java.io.File +java.io.DefaultFileSystem +java.io.FileSystem +java.io.UnixFileSystem +jdk.internal.util.ArraysSupport +jdk.internal.module.ModulePatcher +jdk.internal.module.ModuleBootstrap$Counters +jdk.internal.module.ArchivedBootLayer +jdk.internal.access.JavaNetUriAccess +java.net.URI$1 +jdk.internal.loader.ArchivedClassLoaders +jdk.internal.loader.ClassLoaders$BootClassLoader +java.security.cert.Certificate +java.lang.ClassLoader$ParallelLoaders +java.util.WeakHashMap +java.util.WeakHashMap$Entry +java.util.Collections$SetFromMap +java.util.WeakHashMap$KeySet +jdk.internal.access.JavaSecurityAccess +java.security.ProtectionDomain$JavaSecurityAccessImpl +java.security.ProtectionDomain$Key +java.security.Principal +jdk.internal.loader.NativeLibraries +jdk.internal.loader.ClassLoaderHelper +java.util.HashSet +java.util.Queue +java.util.Deque +java.util.ArrayDeque +jdk.internal.loader.URLClassPath +java.net.URLStreamHandlerFactory +java.net.URL$DefaultFactory +jdk.internal.access.JavaNetURLAccess +java.net.URL$3 +java.io.File$PathStatus +sun.net.www.ParseUtil +java.util.HexFormat +java.net.URLStreamHandler +sun.net.www.protocol.file.Handler +sun.net.util.IPAddressUtil +jdk.internal.util.Preconditions +sun.net.www.protocol.jar.Handler +jdk.internal.module.ServicesCatalog +jdk.internal.loader.AbstractClassLoaderValue +jdk.internal.loader.ClassLoaderValue +java.util.Optional +jdk.internal.loader.BootLoader +jdk.internal.loader.BuiltinClassLoader$LoadedModule +java.util.ImmutableCollections$SetN$SetNIterator +java.util.ImmutableCollections$Set12$1 +java.util.ListIterator +java.util.ImmutableCollections$ListItr +jdk.internal.module.ModuleLoaderMap +jdk.internal.loader.AbstractClassLoaderValue$Memoizer +jdk.internal.module.ServicesCatalog$ServiceProvider +java.util.concurrent.CopyOnWriteArrayList +java.util.HashMap$KeySet +java.util.HashMap$KeyIterator +java.lang.ModuleLayer$Controller +java.lang.invoke.LambdaMetafactory +java.lang.invoke.MethodType$ConcurrentWeakInternSet +java.lang.Void +java.lang.invoke.MethodTypeForm +java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry +sun.invoke.util.Wrapper +sun.invoke.util.Wrapper$Format +java.lang.invoke.LambdaForm$NamedFunction +java.lang.invoke.DirectMethodHandle$Holder +sun.invoke.util.ValueConversions +java.lang.invoke.MethodHandleImpl +java.lang.invoke.Invokers +java.lang.invoke.LambdaForm$Kind +java.lang.NoSuchMethodException +java.lang.invoke.LambdaForm$BasicType +java.lang.reflect.Array +java.lang.invoke.LambdaForm$Name +java.lang.invoke.LambdaForm$Holder +java.lang.invoke.InvokerBytecodeGenerator +java.lang.invoke.InvokerBytecodeGenerator$2 +java.lang.invoke.MethodHandleImpl$Intrinsic +java.lang.invoke.BootstrapMethodInvoker +java.lang.invoke.VarHandle$AccessMode +java.lang.invoke.VarHandle$AccessType +java.lang.invoke.Invokers$Holder +jdk.internal.access.JavaLangInvokeAccess +java.lang.invoke.MethodHandleImpl$1 +java.lang.invoke.AbstractValidatingLambdaMetafactory +java.lang.invoke.InnerClassLambdaMetafactory +jdk.internal.org.objectweb.asm.Type +sun.security.action.GetBooleanAction +jdk.internal.org.objectweb.asm.Handle +sun.invoke.util.BytecodeDescriptor +jdk.internal.org.objectweb.asm.ConstantDynamic +java.lang.invoke.MethodHandleInfo +java.lang.invoke.InfoFromMemberName +jdk.internal.org.objectweb.asm.ClassVisitor +jdk.internal.org.objectweb.asm.ClassWriter +jdk.internal.org.objectweb.asm.SymbolTable +jdk.internal.org.objectweb.asm.Symbol +jdk.internal.org.objectweb.asm.SymbolTable$Entry +jdk.internal.org.objectweb.asm.ByteVector +java.lang.invoke.LambdaProxyClassArchive +jdk.internal.org.objectweb.asm.MethodVisitor +jdk.internal.org.objectweb.asm.MethodWriter +jdk.internal.org.objectweb.asm.Label +java.lang.invoke.TypeConvertingMethodAdapter +java.lang.invoke.InnerClassLambdaMetafactory$ForwardingMethodGenerator +jdk.internal.org.objectweb.asm.Handler +jdk.internal.org.objectweb.asm.Attribute +jdk.internal.org.objectweb.asm.AnnotationVisitor +jdk.internal.org.objectweb.asm.AnnotationWriter +java.lang.invoke.MethodHandles$Lookup$ClassOption +java.lang.invoke.MethodHandles$Lookup$ClassFile +jdk.internal.org.objectweb.asm.ClassReader +java.lang.StringUTF16 +java.lang.invoke.MethodHandles$Lookup$ClassDefiner +jdk.internal.module.ModuleBootstrap$$Lambda$1/0x00007faab4040850 +java.lang.invoke.InnerClassLambdaMetafactory$1 +java.lang.Class$ReflectionData +java.lang.Class$Atomic +jdk.internal.reflect.DelegatingConstructorAccessorImpl +java.lang.invoke.BoundMethodHandle +java.lang.invoke.ClassSpecializer +java.lang.invoke.BoundMethodHandle$Specializer +java.lang.invoke.ClassSpecializer$1 +java.lang.invoke.ClassSpecializer$SpeciesData +java.lang.invoke.BoundMethodHandle$SpeciesData +java.lang.invoke.ClassSpecializer$Factory +java.lang.invoke.BoundMethodHandle$Specializer$Factory +java.lang.invoke.SimpleMethodHandle +java.lang.NoSuchFieldException +java.lang.invoke.BoundMethodHandle$Species_L +sun.invoke.util.VerifyType +sun.invoke.empty.Empty +java.lang.invoke.DirectMethodHandle$2 +java.lang.invoke.DirectMethodHandle$Accessor +java.lang.invoke.DelegatingMethodHandle +java.lang.invoke.MethodHandleImpl$IntrinsicMethodHandle +java.lang.invoke.DelegatingMethodHandle$Holder +sun.invoke.util.Wrapper$1 +java.lang.invoke.LambdaFormEditor +java.lang.invoke.LambdaFormEditor$TransformKey +java.lang.invoke.LambdaFormBuffer +java.lang.invoke.LambdaFormEditor$Transform +jdk.internal.org.objectweb.asm.Frame +java.lang.invoke.InvokerBytecodeGenerator$ClassData +java.util.ArrayList$Itr +jdk.internal.org.objectweb.asm.FieldVisitor +jdk.internal.org.objectweb.asm.FieldWriter +java.lang.invoke.LambdaForm$MH/0x00007faab4000400 +jdk.internal.ref.CleanerFactory +java.util.concurrent.ThreadFactory +jdk.internal.ref.CleanerFactory$1 +java.lang.ref.Cleaner +java.lang.ref.Cleaner$1 +jdk.internal.ref.CleanerImpl +java.lang.ref.Cleaner$Cleanable +jdk.internal.ref.PhantomCleanable +jdk.internal.ref.CleanerImpl$PhantomCleanableRef +jdk.internal.ref.CleanerImpl$CleanerCleanable +jdk.internal.misc.InnocuousThread +java.util.ArrayList$SubList +java.lang.Module$ReflectionData +java.lang.WeakPairMap +java.lang.WeakPairMap$Pair +java.lang.WeakPairMap$Pair$Lookup +java.util.function.BiFunction +java.lang.Module$$Lambda$2/0x00007faab4040a90 +java.lang.WeakPairMap$WeakRefPeer +java.lang.WeakPairMap$Pair$Weak +java.lang.WeakPairMap$Pair$Weak$1 +java.lang.WeakPairMap$$Lambda$3/0x00007faab40413e8 +java.lang.invoke.DirectMethodHandle$Constructor +java.lang.invoke.StringConcatFactory +java.lang.invoke.StringConcatFactory$1 +java.lang.invoke.StringConcatFactory$2 +java.lang.invoke.StringConcatFactory$3 +sun.launcher.LauncherHelper +java.lang.StringCoding +java.util.zip.ZipConstants +java.util.zip.ZipFile +java.util.jar.JarFile +jdk.internal.access.JavaUtilZipFileAccess +java.util.zip.ZipFile$1 +jdk.internal.access.JavaUtilJarAccess +java.util.jar.JavaUtilJarAccessImpl +java.lang.Runtime$Version +java.util.zip.ZipFile$CleanableResource +java.util.zip.ZipCoder +java.util.zip.ZipCoder$UTF8ZipCoder +java.util.zip.ZipFile$Source +sun.nio.fs.DefaultFileSystemProvider +java.nio.file.spi.FileSystemProvider +sun.nio.fs.AbstractFileSystemProvider +sun.nio.fs.UnixFileSystemProvider +sun.nio.fs.LinuxFileSystemProvider +java.nio.file.OpenOption +java.nio.file.StandardOpenOption +java.nio.file.FileSystem +sun.nio.fs.UnixFileSystem +sun.nio.fs.LinuxFileSystem +java.nio.file.Watchable +java.nio.file.Path +sun.nio.fs.UnixPath +sun.nio.fs.Util +sun.nio.fs.UnixNativeDispatcher +jdk.internal.loader.NativeLibraries$LibraryPaths +jdk.internal.loader.NativeLibraries$1 +java.util.ArrayDeque$DeqIterator +jdk.internal.loader.NativeLibrary +jdk.internal.loader.NativeLibraries$NativeLibraryImpl +java.util.concurrent.ConcurrentHashMap$CollectionView +java.util.concurrent.ConcurrentHashMap$ValuesView +java.util.concurrent.ConcurrentHashMap$Traverser +java.util.concurrent.ConcurrentHashMap$BaseIterator +java.util.Enumeration +java.util.concurrent.ConcurrentHashMap$ValueIterator +java.nio.file.attribute.BasicFileAttributes +java.nio.file.attribute.PosixFileAttributes +sun.nio.fs.UnixFileAttributes +sun.nio.fs.UnixFileStoreAttributes +sun.nio.fs.UnixMountEntry +java.util.zip.ZipFile$Source$Key +java.nio.file.CopyOption +java.nio.file.LinkOption +java.nio.file.Files +java.nio.file.attribute.DosFileAttributes +java.nio.file.attribute.AttributeView +java.nio.file.attribute.FileAttributeView +java.nio.file.attribute.BasicFileAttributeView +java.nio.file.attribute.DosFileAttributeView +java.nio.file.attribute.UserDefinedFileAttributeView +sun.nio.fs.UnixFileAttributeViews +sun.nio.fs.DynamicFileAttributeView +sun.nio.fs.AbstractBasicFileAttributeView +sun.nio.fs.UnixFileAttributeViews$Basic +sun.nio.fs.NativeBuffers +jdk.internal.misc.TerminatingThreadLocal +sun.nio.fs.NativeBuffers$1 +jdk.internal.misc.TerminatingThreadLocal$1 +java.lang.ThreadLocal$ThreadLocalMap +java.lang.ThreadLocal$ThreadLocalMap$Entry +java.util.IdentityHashMap +java.util.IdentityHashMap$KeySet +sun.nio.fs.NativeBuffer +sun.nio.fs.NativeBuffer$Deallocator +sun.nio.fs.UnixFileAttributes$UnixAsBasicFileAttributes +java.io.DataOutput +java.io.DataInput +java.io.RandomAccessFile +jdk.internal.access.JavaIORandomAccessFileAccess +java.io.RandomAccessFile$2 +java.io.FileCleanable +java.util.zip.ZipFile$Source$End +java.util.zip.ZipUtils +java.util.concurrent.TimeUnit +java.nio.file.attribute.FileTime +jdk.internal.perf.PerfCounter +jdk.internal.perf.Perf$GetPerfAction +jdk.internal.perf.Perf +jdk.internal.perf.PerfCounter$CoreCounters +sun.nio.ch.DirectBuffer +java.nio.MappedByteBuffer +java.nio.DirectByteBuffer +java.nio.Bits +java.util.concurrent.atomic.AtomicLong +jdk.internal.misc.VM$BufferPool +java.nio.Bits$1 +java.nio.LongBuffer +java.nio.DirectLongBufferU +java.util.zip.ZipEntry +java.util.jar.JarEntry +java.util.jar.JarFile$JarFileEntry +java.util.zip.ZipFile$ZipFileInputStream +java.util.zip.InflaterInputStream +java.util.zip.ZipFile$ZipFileInflaterInputStream +java.util.zip.Inflater +java.util.zip.Inflater$InflaterZStreamRef +java.util.zip.ZipFile$InflaterCleanupAction +sun.security.util.SignatureFileVerifier +sun.security.util.Debug +java.util.Locale +sun.util.locale.LocaleUtils +sun.security.action.GetIntegerAction +java.util.jar.JarVerifier +java.security.CodeSigner +java.io.ByteArrayOutputStream +java.util.jar.Attributes +java.util.LinkedHashMap +java.util.jar.Manifest$FastInputStream +java.io.RandomAccessFile$1 +sun.net.util.URLUtil +java.security.PrivilegedExceptionAction +jdk.internal.loader.URLClassPath$3 +jdk.internal.loader.URLClassPath$Loader +jdk.internal.loader.URLClassPath$JarLoader +jdk.internal.loader.URLClassPath$JarLoader$1 +jdk.internal.loader.FileURLMapper +jdk.internal.util.jar.JarIndex +java.util.StringTokenizer +jdk.internal.loader.Resource +jdk.internal.loader.URLClassPath$JarLoader$2 +java.lang.NamedPackage +java.lang.Package +java.lang.Package$VersionInfo +sun.nio.ByteBuffered +java.util.zip.Checksum +java.util.zip.CRC32 +java.util.zip.Checksum$1 +java.security.SecureClassLoader$CodeSourceKey +java.security.SecureClassLoader$1 +java.security.PermissionCollection +sun.security.util.LazyCodeSourcePermissionCollection +java.security.Permissions +java.lang.RuntimePermission +java.security.BasicPermissionCollection +java.security.AllPermission +java.security.UnresolvedPermission +java.security.SecureClassLoader$DebugHolder +org.apache.maven.surefire.booter.ForkedBooter +org.apache.maven.surefire.api.fork.ForkNodeArguments +org.apache.maven.plugin.surefire.log.api.ConsoleLogger +java.lang.SecurityException +java.security.AccessControlException +java.io.IOException +org.apache.maven.surefire.api.provider.CommandListener +org.apache.maven.surefire.api.report.ReporterFactory +java.util.concurrent.ConcurrentHashMap$ForwardingNode +org.apache.maven.surefire.api.provider.CommandChainReader +java.lang.InterruptedException +java.util.concurrent.Executor +java.util.concurrent.ExecutorService +java.util.concurrent.ScheduledExecutorService +java.lang.PublicMethods$MethodList +java.lang.PublicMethods$Key +java.util.concurrent.Semaphore +java.util.concurrent.locks.AbstractQueuedSynchronizer +java.util.concurrent.Semaphore$Sync +java.util.concurrent.Semaphore$NonfairSync +org.apache.maven.surefire.booter.BooterDeserializer +org.apache.maven.surefire.booter.SystemPropertyManager +java.util.Properties$LineReader +java.util.Properties$EntrySet +java.util.concurrent.ConcurrentHashMap$EntrySetView +java.util.Collections$SynchronizedCollection +java.util.Collections$SynchronizedSet +java.util.concurrent.ConcurrentHashMap$EntryIterator +java.util.concurrent.ConcurrentHashMap$MapEntry +java.util.Collections$UnmodifiableCollection +java.util.Collections$UnmodifiableSet +java.util.Collections$UnmodifiableCollection$1 +org.apache.maven.surefire.booter.KeyValueSource +org.apache.maven.surefire.booter.PropertiesWrapper +java.lang.IllegalStateException +java.io.FileInputStream$1 +org.apache.maven.surefire.booter.TypeEncodedValue +org.apache.maven.surefire.api.testset.DirectoryScannerParameters +org.apache.maven.surefire.api.util.RunOrder +org.apache.maven.surefire.api.testset.RunOrderParameters +org.apache.maven.surefire.api.testset.TestArtifactInfo +org.apache.maven.surefire.api.testset.TestRequest +org.apache.maven.surefire.api.testset.TestFilter +org.apache.maven.surefire.api.testset.GenericTestPattern +org.apache.maven.surefire.api.testset.TestListResolver +java.util.Collections$SingletonSet +org.apache.maven.surefire.api.testset.IncludedExcludedPatterns +java.util.LinkedHashSet +java.util.Collections$1 +org.apache.maven.surefire.shared.utils.StringUtils +java.lang.IndexOutOfBoundsException +java.lang.StringIndexOutOfBoundsException +org.apache.maven.surefire.api.testset.ResolvedTest +org.apache.maven.surefire.api.testset.ResolvedTest$Type +org.apache.maven.surefire.api.testset.ResolvedTest$ClassMatcher +org.apache.maven.surefire.api.testset.ResolvedTest$MethodMatcher +org.apache.maven.surefire.api.report.ReporterConfiguration +org.apache.maven.surefire.api.booter.Shutdown +java.lang.Class$3 +jdk.internal.reflect.NativeMethodAccessorImpl +jdk.internal.reflect.DelegatingMethodAccessorImpl +org.apache.maven.surefire.booter.ProviderConfiguration +org.apache.maven.surefire.api.cli.CommandLineOption +org.apache.maven.surefire.api.booter.DumpErrorSingleton +org.apache.maven.surefire.api.util.internal.DumpFileUtils +java.lang.ProcessEnvironment +java.lang.ProcessEnvironment$ExternalData +java.lang.ProcessEnvironment$Variable +java.lang.ProcessEnvironment$Value +java.lang.ProcessEnvironment$StringEnvironment +java.lang.management.ManagementFactory +java.lang.IncompatibleClassChangeError +java.lang.NoSuchMethodError +java.lang.invoke.LambdaForm$DMH/0x00007faab4006000 +java.lang.management.ManagementFactory$$Lambda$4/0x00007faab40451f8 +java.lang.management.PlatformManagedObject +java.lang.management.RuntimeMXBean +java.lang.management.ManagementFactory$PlatformMBeanFinder +java.lang.management.ManagementFactory$PlatformMBeanFinder$1 +java.io.FilePermission +jdk.internal.access.JavaIOFilePermissionAccess +java.io.FilePermission$1 +sun.security.util.FilePermCompat +sun.security.util.SecurityProperties +java.security.Security +jdk.internal.access.JavaSecuritySystemConfiguratorAccess +java.security.Security$1 +java.security.Security$2 +java.security.SystemConfigurator +java.security.SystemConfigurator$1 +sun.security.util.PropertyExpander +java.net.URLConnection +sun.net.www.URLConnection +sun.net.www.protocol.file.FileURLConnection +sun.net.www.MessageHeader +sun.net.ProgressMonitor +sun.net.ProgressMeteringPolicy +sun.net.DefaultProgressMeteringPolicy +jdk.internal.access.JavaSecurityPropertiesAccess +java.security.Security$3 +sun.management.spi.PlatformMBeanProvider +java.util.ServiceLoader +java.util.ServiceLoader$ModuleServicesLookupIterator +java.util.ServiceLoader$LazyClassPathLookupIterator +java.util.ServiceLoader$2 +java.util.ServiceLoader$3 +java.util.concurrent.CopyOnWriteArrayList$COWIterator +com.sun.management.internal.PlatformMBeanProviderImpl +java.util.ServiceLoader$1 +java.util.ServiceLoader$Provider +java.util.ServiceLoader$ProviderImpl +com.sun.management.internal.PlatformMBeanProviderImpl$$Lambda$5/0x00007faab40468a0 +sun.management.spi.PlatformMBeanProvider$PlatformComponent +com.sun.management.internal.PlatformMBeanProviderImpl$1 +java.util.stream.BaseStream +java.util.stream.Stream +java.util.Spliterators +java.util.Spliterators$EmptySpliterator +java.util.Spliterator +java.util.Spliterators$EmptySpliterator$OfRef +java.util.Spliterator$OfPrimitive +java.util.Spliterator$OfInt +java.util.Spliterators$EmptySpliterator$OfInt +java.util.Spliterator$OfLong +java.util.Spliterators$EmptySpliterator$OfLong +java.util.Spliterator$OfDouble +java.util.Spliterators$EmptySpliterator$OfDouble +java.util.Spliterators$ArraySpliterator +java.util.stream.StreamSupport +java.util.stream.PipelineHelper +java.util.stream.AbstractPipeline +java.util.stream.ReferencePipeline +java.util.stream.ReferencePipeline$Head +java.util.stream.StreamOpFlag +java.util.stream.StreamOpFlag$Type +java.util.stream.StreamOpFlag$MaskBuilder +java.util.EnumMap +java.util.EnumMap$1 +sun.reflect.annotation.AnnotationParser +java.util.stream.Collectors +java.util.stream.Collector$Characteristics +java.util.EnumSet +java.util.RegularEnumSet +java.util.stream.Collector +java.util.stream.Collectors$CollectorImpl +java.util.stream.Collectors$$Lambda$30/0x800000041 +java.util.function.BiConsumer +java.lang.invoke.DirectMethodHandle$Interface +java.util.stream.Collectors$$Lambda$22/0x800000035 +java.util.function.BinaryOperator +java.util.stream.Collectors$$Lambda$25/0x80000003c +java.util.stream.Collectors$$Lambda$27/0x80000003e +java.util.stream.ReduceOps +java.util.stream.TerminalOp +java.util.stream.ReduceOps$ReduceOp +java.util.stream.ReduceOps$3 +java.util.stream.StreamShape +java.util.stream.ReduceOps$Box +java.util.function.Consumer +java.util.stream.Sink +java.util.stream.TerminalSink +java.util.stream.ReduceOps$AccumulatingSink +java.util.stream.ReduceOps$3ReducingSink +com.sun.management.internal.PlatformMBeanProviderImpl$2 +com.sun.management.internal.PlatformMBeanProviderImpl$3 +com.sun.management.internal.PlatformMBeanProviderImpl$4 +javax.management.DynamicMBean +com.sun.management.DiagnosticCommandMBean +javax.management.NotificationBroadcaster +javax.management.NotificationEmitter +sun.management.NotificationEmitterSupport +com.sun.management.internal.DiagnosticCommandImpl +sun.management.ManagementFactoryHelper +sun.management.VMManagement +sun.management.VMManagementImpl +com.sun.management.internal.PlatformMBeanProviderImpl$5 +java.util.Collections$UnmodifiableList +java.util.Collections$UnmodifiableRandomAccessList +jdk.management.jfr.internal.FlightRecorderMXBeanProvider +java.util.concurrent.Callable +java.util.Collections$EmptyEnumeration +java.lang.management.DefaultPlatformMBeanProvider +java.lang.management.DefaultPlatformMBeanProvider$1 +java.lang.management.DefaultPlatformMBeanProvider$2 +java.lang.management.DefaultPlatformMBeanProvider$3 +java.lang.management.DefaultPlatformMBeanProvider$4 +java.lang.management.DefaultPlatformMBeanProvider$5 +java.lang.management.DefaultPlatformMBeanProvider$6 +java.lang.management.DefaultPlatformMBeanProvider$7 +java.lang.management.DefaultPlatformMBeanProvider$8 +sun.management.ManagementFactoryHelper$LoggingMXBeanAccess +sun.management.ManagementFactoryHelper$LoggingMXBeanAccess$1 +java.util.logging.LogManager +java.lang.management.DefaultPlatformMBeanProvider$9 +java.lang.management.DefaultPlatformMBeanProvider$10 +java.lang.management.DefaultPlatformMBeanProvider$11 +jdk.management.jfr.FlightRecorderMXBean +jdk.management.jfr.internal.FlightRecorderMXBeanProvider$SingleMBeanComponent +java.util.Collections$SingletonList +java.util.HashMap$Values +java.util.HashMap$HashMapSpliterator +java.util.HashMap$ValueSpliterator +java.util.function.Predicate +java.lang.management.ManagementFactory$PlatformMBeanFinder$$Lambda$10/0x00007faab404c288 +java.util.stream.ReferencePipeline$StatelessOp +java.util.stream.ReferencePipeline$2 +java.lang.management.ManagementFactory$PlatformMBeanFinder$$Lambda$11/0x00007faab404c4e0 +java.util.stream.ReduceOps$2 +java.util.stream.ReduceOps$2ReducingSink +java.util.stream.Sink$ChainedReference +java.util.stream.ReferencePipeline$2$1 +sun.management.RuntimeImpl +java.util.Collections$SingletonMap +java.util.Collections$2 +java.lang.invoke.LambdaForm$DMH/0x00007faab4006400 +sun.management.spi.PlatformMBeanProvider$PlatformComponent$$Lambda$12/0x00007faab404d2d0 +sun.management.spi.PlatformMBeanProvider$PlatformComponent$$Lambda$13/0x00007faab404d528 +java.util.stream.ReferencePipeline$3 +java.util.stream.Collectors$$Lambda$14/0x00007faab404d770 +java.util.stream.Collectors$$Lambda$15/0x00007faab404d990 +java.util.stream.Collectors$$Lambda$16/0x00007faab404dbc0 +java.util.stream.ReferencePipeline$3$1 +sun.management.Util +java.lang.management.ManagementPermission +java.util.Arrays$ArrayList +java.util.Arrays$ArrayItr +org.apache.maven.surefire.booter.ClassLoaderConfiguration +org.apache.maven.surefire.booter.AbstractPathConfiguration +org.apache.maven.surefire.booter.ClasspathConfiguration +org.apache.maven.surefire.booter.Classpath +java.net.MalformedURLException +java.net.URLClassLoader +org.apache.maven.surefire.booter.IsolatedClassLoader +org.apache.maven.surefire.booter.SurefireExecutionException +org.apache.maven.surefire.booter.ProcessCheckerType +org.apache.maven.surefire.booter.StartupConfiguration +org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory +java.util.Spliterators$1Adapter +java.util.HashMap$ValueIterator +jdk.internal.module.Resources +jdk.internal.loader.BuiltinClassLoader$2 +jdk.internal.loader.BuiltinClassLoader$5 +java.lang.module.ModuleReader +jdk.internal.module.SystemModuleFinders$SystemModuleReader +jdk.internal.module.SystemModuleFinders$SystemImage +jdk.internal.jimage.ImageReaderFactory +java.nio.file.Paths +java.nio.file.FileSystems +java.nio.file.FileSystems$DefaultFileSystemHolder +java.nio.file.FileSystems$DefaultFileSystemHolder$1 +java.net.URI$Parser +jdk.internal.jimage.ImageReaderFactory$1 +jdk.internal.jimage.ImageReader +jdk.internal.jimage.BasicImageReader +jdk.internal.jimage.ImageReader$SharedImageReader +jdk.internal.jimage.BasicImageReader$1 +jdk.internal.jimage.NativeImageBuffer +jdk.internal.jimage.NativeImageBuffer$1 +jdk.internal.jimage.ImageHeader +java.nio.IntBuffer +java.nio.DirectIntBufferU +java.nio.DirectByteBufferR +java.nio.DirectIntBufferRU +jdk.internal.jimage.ImageStrings +jdk.internal.jimage.ImageStringsReader +jdk.internal.jimage.decompressor.Decompressor +jdk.internal.jimage.ImageLocation +java.util.Collections$EmptyIterator +jdk.internal.loader.BuiltinClassLoader$1 +java.lang.CompoundEnumeration +jdk.internal.loader.URLClassPath$1 +jdk.internal.loader.URLClassPath$FileLoader +java.util.SortedSet +java.util.NavigableSet +java.util.TreeSet +java.util.SortedMap +java.util.NavigableMap +java.util.TreeMap +java.util.TreeMap$Entry +java.util.TreeMap$KeySet +java.util.TreeMap$PrivateEntryIterator +java.util.TreeMap$KeyIterator +java.lang.Readable +java.io.Reader +java.io.BufferedReader +java.io.InputStreamReader +sun.nio.cs.StreamDecoder +java.nio.charset.CharsetDecoder +sun.nio.cs.UTF_8$Decoder +java.util.Vector +java.nio.CharBuffer +java.nio.HeapCharBuffer +java.nio.charset.CoderResult +java.util.AbstractSequentialList +java.util.LinkedList +java.util.LinkedList$Node +java.net.JarURLConnection +sun.net.www.protocol.jar.JarURLConnection +sun.net.www.protocol.jar.URLJarFile$URLJarFileCloseController +sun.net.www.protocol.jar.JarFileFactory +sun.net.www.protocol.jar.URLJarFile +sun.nio.fs.UnixFileKey +sun.net.www.protocol.jar.URLJarFile$URLJarFileEntry +sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream +java.util.LinkedHashMap$LinkedKeySet +java.util.LinkedHashMap$LinkedHashIterator +java.util.LinkedHashMap$LinkedKeyIterator +org.apache.maven.surefire.booter.spi.AbstractMasterProcessChannelProcessorFactory +org.apache.maven.surefire.booter.spi.LegacyMasterProcessChannelProcessorFactory +org.apache.maven.surefire.api.booter.MasterProcessChannelEncoder +org.apache.maven.surefire.api.booter.MasterProcessChannelDecoder +org.apache.maven.surefire.api.util.internal.DaemonThreadFactory +java.util.concurrent.Executors +java.util.concurrent.Executors$DefaultThreadFactory +org.apache.maven.surefire.api.util.internal.DaemonThreadFactory$NamedThreadFactory +java.util.concurrent.AbstractExecutorService +java.util.concurrent.ThreadPoolExecutor +java.util.concurrent.ScheduledThreadPoolExecutor +java.util.concurrent.RejectedExecutionHandler +java.util.concurrent.ThreadPoolExecutor$AbortPolicy +java.util.concurrent.BlockingQueue +java.util.AbstractQueue +java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue +java.util.concurrent.Future +java.util.concurrent.RunnableFuture +java.util.concurrent.Delayed +java.util.concurrent.ScheduledFuture +java.util.concurrent.RunnableScheduledFuture +java.util.concurrent.locks.ReentrantLock$Sync +java.util.concurrent.locks.ReentrantLock$NonfairSync +java.util.concurrent.locks.Condition +java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject +org.apache.maven.surefire.booter.spi.SurefireMasterProcessChannelProcessorFactory +java.net.URISyntaxException +java.util.concurrent.ExecutionException +java.net.SocketAddress +java.net.InetSocketAddress +java.nio.channels.Channel +java.nio.channels.AsynchronousChannel +java.nio.channels.AsynchronousByteChannel +org.apache.maven.surefire.booter.ForkedNodeArg +java.lang.UnsupportedOperationException +org.apache.maven.plugin.surefire.log.api.NullConsoleLogger +org.apache.maven.surefire.api.util.internal.Channels +org.apache.maven.surefire.api.util.internal.Channels$2 +org.apache.maven.surefire.api.util.internal.Channels$1 +java.nio.channels.WritableByteChannel +org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel +java.nio.channels.ReadableByteChannel +org.apache.maven.surefire.api.util.internal.AbstractNoninterruptibleWritableChannel +org.apache.maven.surefire.api.util.internal.Channels$4 +java.nio.channels.ClosedChannelException +java.nio.channels.NonWritableChannelException +org.apache.maven.surefire.booter.spi.AbstractMasterProcessChannelProcessorFactory$1 +java.util.concurrent.FutureTask +java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask +java.lang.invoke.VarHandles +java.lang.invoke.VarHandleInts$FieldInstanceReadOnly +java.lang.invoke.VarHandleInts$FieldInstanceReadWrite +java.lang.invoke.VarHandle$1 +jdk.internal.util.Preconditions$1 +java.lang.invoke.VarHandleGuards +java.lang.invoke.VarForm +java.lang.invoke.VarHandleReferences$FieldInstanceReadOnly +java.lang.invoke.VarHandleReferences$FieldInstanceReadWrite +java.util.concurrent.FutureTask$WaitNode +java.util.concurrent.Executors$RunnableAdapter +java.util.concurrent.ThreadPoolExecutor$Worker +java.lang.Thread$State +java.util.concurrent.TimeUnit$1 +java.time.temporal.TemporalUnit +java.time.temporal.ChronoUnit +java.time.temporal.TemporalAmount +java.time.Duration +java.math.BigInteger +org.apache.maven.surefire.api.stream.AbstractStreamEncoder +org.apache.maven.surefire.booter.stream.EventEncoder +org.apache.maven.surefire.booter.spi.EventChannelEncoder +java.lang.invoke.VarHandle$AccessDescriptor +java.lang.AssertionError +org.apache.maven.surefire.api.booter.ForkedProcessEventType +java.util.concurrent.ForkJoinPool$ManagedBlocker +java.util.concurrent.locks.AbstractQueuedSynchronizer$Node +java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode +org.apache.maven.surefire.api.report.ReportEntry +java.util.concurrent.atomic.AtomicBoolean +org.apache.maven.surefire.booter.spi.CommandChannelDecoder +org.apache.maven.surefire.api.stream.MalformedChannelException +org.apache.maven.surefire.api.stream.AbstractStreamDecoder +org.apache.maven.surefire.booter.stream.CommandDecoder +org.apache.maven.surefire.api.util.internal.AbstractNoninterruptibleReadableChannel +org.apache.maven.surefire.api.util.internal.Channels$3 +java.nio.channels.NonReadableChannelException +java.io.EOFException +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$MalformedFrameException +java.io.FileNotFoundException +org.apache.maven.surefire.api.stream.SegmentType +org.apache.maven.surefire.api.booter.Constants +java.nio.charset.StandardCharsets +sun.nio.cs.US_ASCII +sun.nio.cs.ISO_8859_1 +sun.nio.cs.UTF_16BE +sun.nio.cs.UTF_16LE +sun.nio.cs.UTF_16 +org.apache.maven.surefire.api.booter.MasterProcessCommand +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$Segment +org.apache.maven.surefire.booter.ForkedBooter$8 +org.apache.maven.surefire.shared.utils.cli.ShutdownHookUtils +java.lang.ApplicationShutdownHooks +java.lang.ApplicationShutdownHooks$1 +java.lang.Shutdown +java.lang.Shutdown$Lock +org.apache.maven.surefire.api.booter.ForkingReporterFactory +org.apache.maven.surefire.api.report.RunListener +org.apache.maven.surefire.api.report.TestOutputReceiver +org.apache.maven.surefire.api.report.TestReportListener +org.apache.maven.surefire.api.booter.ForkingRunListener +org.apache.maven.surefire.booter.CommandReader +org.apache.maven.surefire.api.testset.TestSetFailedException +java.util.concurrent.ConcurrentLinkedQueue +java.util.concurrent.ConcurrentLinkedQueue$Node +org.apache.maven.surefire.booter.CommandReader$CommandRunnable +java.util.concurrent.atomic.AtomicReference +java.util.concurrent.CountDownLatch +java.util.concurrent.CountDownLatch$Sync +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$Memento +org.apache.maven.surefire.booter.PpidChecker +org.apache.maven.surefire.booter.PpidChecker$ProcessInfoConsumer +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$BufferedStream +org.apache.maven.surefire.booter.PpidChecker$1 +org.apache.maven.surefire.booter.PpidChecker$2 +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$StreamReadStatus +org.apache.maven.surefire.booter.stream.CommandDecoder$1 +java.lang.NoSuchFieldError +org.apache.maven.surefire.shared.lang3.SystemUtils +org.apache.maven.surefire.api.booter.Command +org.apache.maven.surefire.booter.CommandReader$1 +java.util.concurrent.ConcurrentLinkedQueue$Itr +org.apache.maven.surefire.shared.lang3.SystemProperties +org.apache.maven.surefire.shared.lang3.function.Suppliers +org.apache.maven.surefire.shared.lang3.function.Suppliers$$Lambda$17/0x00007faab4010000 +org.apache.maven.surefire.shared.lang3.StringUtils +java.util.regex.Pattern +java.util.regex.Pattern$Node +java.util.regex.Pattern$LastNode +java.util.regex.Pattern$GroupHead +java.util.regex.CharPredicates +java.lang.Character$Subset +java.lang.Character$UnicodeBlock +java.util.regex.Pattern$CharPredicate +java.lang.invoke.LambdaForm$DMH/0x00007faab4014000 +java.util.regex.CharPredicates$$Lambda$18/0x00007faab405bdc8 +java.util.regex.Pattern$BmpCharPredicate +java.util.regex.Pattern$CharProperty +java.util.regex.Pattern$Qtype +java.util.regex.Pattern$BmpCharProperty +java.util.regex.Pattern$CharPropertyGreedy +java.util.regex.Pattern$SliceNode +java.util.regex.Pattern$Slice +java.util.regex.Pattern$Begin +java.util.regex.Pattern$First +java.util.regex.Pattern$Start +java.util.regex.Pattern$StartS +java.util.regex.Pattern$TreeInfo +org.apache.maven.surefire.shared.lang3.JavaVersion +org.apache.maven.surefire.shared.lang3.SystemProperties$$Lambda$19/0x00007faab4010678 +org.apache.maven.surefire.shared.lang3.math.NumberUtils +java.lang.NumberFormatException +java.math.BigDecimal +jdk.internal.math.FloatingDecimal +jdk.internal.math.FloatingDecimal$BinaryToASCIIConverter +jdk.internal.math.FloatingDecimal$ExceptionalBinaryToASCIIBuffer +jdk.internal.math.FloatingDecimal$BinaryToASCIIBuffer +jdk.internal.math.FloatingDecimal$1 +jdk.internal.math.FloatingDecimal$ASCIIToBinaryConverter +jdk.internal.math.FloatingDecimal$PreparedASCIIToBinaryBuffer +jdk.internal.math.FloatingDecimal$ASCIIToBinaryBuffer +org.apache.maven.surefire.shared.lang3.SystemUtils$$Lambda$20/0x00007faab4010ca0 +java.util.regex.Pattern$GroupTail +java.util.regex.CharPredicates$$Lambda$16/0x800000024 +java.util.regex.Pattern$BmpCharPropertyGreedy +java.util.regex.Pattern$$Lambda$18/0x800000028 +java.util.regex.Pattern$Ques +java.util.regex.Pattern$BranchConn +java.util.regex.Pattern$Branch +java.util.regex.ASCII +java.util.regex.Pattern$Curly +java.util.regex.CharPredicates$$Lambda$17/0x800000025 +java.util.regex.Pattern$Dollar +java.util.regex.Pattern$BitClass +org.apache.maven.surefire.booter.ForkedBooter$4 +org.apache.maven.surefire.api.booter.BiProperty +org.apache.maven.surefire.booter.ForkedBooter$3 +org.apache.maven.surefire.booter.ForkedBooter$PingScheduler +org.apache.maven.surefire.api.provider.ProviderParameters +org.apache.maven.surefire.api.booter.BaseProviderFactory +org.apache.maven.surefire.api.util.DirectoryScanner +org.apache.maven.surefire.api.util.ScanResult +org.apache.maven.surefire.api.util.RunOrderCalculator +org.apache.maven.surefire.api.util.ReflectionUtils +org.apache.maven.surefire.api.util.SurefireReflectionException +java.lang.reflect.InvocationTargetException +java.lang.IllegalAccessException +org.apache.maven.surefire.api.provider.SurefireProvider +org.apache.maven.surefire.api.provider.AbstractProvider +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider +org.junit.platform.launcher.Launcher +org.apache.maven.surefire.api.util.ScannerFilter +java.io.StringReader +java.io.UncheckedIOException +org.apache.maven.surefire.junitplatform.LazyLauncher +org.junit.platform.launcher.TagFilter +org.junit.platform.commons.JUnitException +org.junit.platform.commons.util.PreconditionViolationException +org.junit.platform.commons.PreconditionViolationException +org.junit.platform.engine.Filter +org.junit.platform.launcher.PostDiscoveryFilter +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$24/0x00007faab4016200 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$25/0x00007faab4016440 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$26/0x00007faab4016678 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$27/0x00007faab40168b8 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$28/0x00007faab4016af0 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$29/0x00007faab4016d40 +org.apache.maven.surefire.junitplatform.TestMethodFilter +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$30/0x00007faab40171f0 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$31/0x00007faab4017430 +org.junit.platform.launcher.EngineFilter +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$32/0x00007faab40178c0 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$33/0x00007faab4017b00 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$34/0x00007faab4017d38 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$35/0x00007faab4015000 +org.junit.platform.launcher.TestExecutionListener +org.apache.maven.surefire.report.RunModeSetter +org.apache.maven.surefire.junitplatform.RunListenerAdapter +org.apache.maven.surefire.api.report.OutputReportEntry +org.apache.maven.surefire.api.report.TestSetReportEntry +org.apache.maven.surefire.api.report.StackTraceWriter +org.apache.maven.surefire.report.ClassMethodIndexer +org.apache.maven.surefire.api.report.RunMode +org.apache.maven.surefire.api.report.ConsoleOutputCapture +org.apache.maven.surefire.api.report.ConsoleOutputCapture$ForwardingPrintStream +org.apache.maven.surefire.api.report.ConsoleOutputCapture$NullOutputStream +java.util.logging.Logger +java.util.logging.Handler +java.util.logging.Level +java.util.logging.Level$KnownLevel +java.util.logging.Level$KnownLevel$$Lambda$13/0x800000021 +java.util.logging.Level$KnownLevel$$Lambda$14/0x800000022 +java.util.logging.Logger$LoggerBundle +java.util.logging.Logger$ConfigurationData +java.util.logging.LogManager$1 +java.util.logging.LogManager$LoggerContext +java.util.logging.LogManager$SystemLoggerContext +java.util.logging.LogManager$LogNode +java.util.Collections$SynchronizedMap +java.util.logging.LogManager$Cleaner +java.util.logging.LoggingPermission +sun.util.logging.internal.LoggingProviderImpl$LogManagerAccess +java.util.logging.LogManager$LoggingProviderAccess +java.lang.System$LoggerFinder +jdk.internal.logger.DefaultLoggerFinder +sun.util.logging.internal.LoggingProviderImpl +java.util.logging.LogManager$2 +java.util.logging.LogManager$RootLogger +java.util.logging.LogManager$LoggerWeakRef +java.lang.invoke.MethodHandleImpl$AsVarargsCollector +java.lang.invoke.BoundMethodHandle$Species_LL +java.lang.invoke.LambdaForm$MH/0x00007faab401c000 +java.util.logging.LogManager$VisitedLoggers +java.util.logging.LogManager$LoggerContext$1 +java.util.concurrent.ConcurrentHashMap$KeySetView +java.util.Collections$3 +java.util.concurrent.ConcurrentHashMap$KeyIterator +java.util.Hashtable$Enumerator +java.util.logging.Level$$Lambda$12/0x800000010 +java.util.ArrayList$ArrayListSpliterator +java.util.logging.Level$KnownLevel$$Lambda$15/0x800000023 +java.util.stream.ReferencePipeline$7 +java.util.stream.FindOps +java.util.stream.FindOps$FindSink +java.util.stream.FindOps$FindSink$OfRef +java.util.stream.FindOps$FindOp +java.util.stream.FindOps$FindSink$OfRef$$Lambda$40/0x80000004b +java.util.stream.FindOps$FindSink$OfRef$$Lambda$38/0x800000049 +java.util.stream.FindOps$FindSink$OfRef$$Lambda$39/0x80000004a +java.util.stream.FindOps$FindSink$OfRef$$Lambda$37/0x800000048 +java.util.stream.ReferencePipeline$7$1 +java.util.stream.Streams$AbstractStreamBuilderImpl +java.util.stream.Stream$Builder +java.util.stream.Streams$StreamBuilderImpl +java.util.stream.Streams +java.util.IdentityHashMap$Values +java.lang.System$Logger +sun.util.logging.PlatformLogger$Bridge +sun.util.logging.PlatformLogger$ConfigurableBridge +jdk.internal.logger.BootstrapLogger +jdk.internal.logger.BootstrapLogger$DetectBackend +jdk.internal.logger.BootstrapLogger$DetectBackend$1 +jdk.internal.logger.BootstrapLogger$LoggingBackend +jdk.internal.logger.BootstrapLogger$RedirectedLoggers +jdk.internal.logger.BootstrapLogger$BootstrapExecutors +java.util.logging.LogManager$4 +java.util.logging.Logger$SystemLoggerHelper +java.util.logging.Logger$SystemLoggerHelper$1 +jdk.internal.logger.DefaultLoggerFinder$1 +org.apache.maven.surefire.junitplatform.TestPlanScannerFilter +org.apache.maven.surefire.api.util.DefaultScanResult +jdk.internal.loader.URLClassPath$FileLoader$1 +software.amazon.lambda.powertools.validation.internal.ValidationAspectTest +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder +org.junit.platform.engine.ConfigurationParameters +org.junit.platform.engine.EngineDiscoveryRequest +org.junit.platform.launcher.LauncherDiscoveryRequest +org.junit.platform.engine.reporting.OutputDirectoryProvider +org.junit.platform.engine.DiscoverySelector +org.junit.platform.engine.discovery.DiscoverySelectors +org.junit.platform.commons.util.Preconditions +org.junit.platform.commons.util.StringUtils +org.junit.platform.commons.util.StringUtils$TwoPartSplitResult +java.util.regex.CharPredicates$$Lambda$44/0x00007faab405d900 +org.junit.platform.engine.discovery.ClassSelector +java.lang.invoke.LambdaForm$DMH/0x00007faab401c400 +org.junit.platform.commons.util.Preconditions$$Lambda$45/0x00007faab401a5e0 +org.junit.platform.commons.util.Preconditions$$Lambda$46/0x00007faab401a818 +java.lang.invoke.LambdaForm$DMH/0x00007faab401c800 +java.lang.invoke.DirectMethodHandle$Special +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder$$Lambda$47/0x00007faab401aa50 +org.junit.platform.launcher.core.LauncherConfigurationParameters +org.junit.platform.commons.logging.LoggerFactory +org.junit.platform.commons.logging.Logger +org.junit.platform.commons.logging.LoggerFactory$DelegatingLogger +org.junit.platform.launcher.core.LauncherConfigurationParameters$Builder +org.junit.platform.launcher.core.LauncherConfigurationParameters$Builder$$Lambda$48/0x00007faab401b790 +org.junit.platform.commons.util.CollectionUtils +org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider +org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider$2 +org.junit.platform.commons.util.ClassLoaderUtils +org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider$3 +org.junit.platform.launcher.core.LauncherConfigurationParameters$$Lambda$49/0x00007faab401e498 +org.junit.platform.launcher.core.LauncherConfigurationParameters$$Lambda$50/0x00007faab401e6e0 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners +org.junit.platform.engine.EngineDiscoveryListener +org.junit.platform.launcher.LauncherDiscoveryListener +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$LauncherDiscoveryListenerType +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$LauncherDiscoveryListenerType$$Lambda$51/0x00007faab401f180 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$LauncherDiscoveryListenerType$$Lambda$52/0x00007faab401f3a0 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$$Lambda$53/0x00007faab401f7b8 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$$Lambda$54/0x00007faab401fa10 +org.junit.platform.launcher.listeners.discovery.AbortOnFailureLauncherDiscoveryListener +org.junit.platform.engine.EngineDiscoveryListener$1 +org.junit.platform.launcher.LauncherDiscoveryListener$1 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$$Lambda$55/0x00007faab401d4c0 +org.junit.platform.launcher.core.HierarchicalOutputDirectoryProvider +java.util.regex.Pattern$$Lambda$56/0x00007faab405df20 +java.util.regex.Pattern$CharPredicate$$Lambda$57/0x00007faab405e180 +java.util.regex.Pattern$CharPredicate$$Lambda$21/0x80000002d +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder$$Lambda$59/0x00007faab401d928 +org.junit.platform.launcher.core.DefaultDiscoveryRequest +org.junit.platform.launcher.LauncherSession +org.junit.platform.launcher.core.LauncherFactory +org.junit.platform.launcher.core.LauncherConfig +org.junit.platform.launcher.core.LauncherConfig$Builder +org.junit.platform.launcher.core.DefaultLauncherConfig +org.junit.platform.launcher.core.DefaultLauncherSession +org.junit.platform.launcher.LauncherInterceptor +org.junit.platform.launcher.core.DefaultLauncherSession$1 +org.junit.platform.launcher.core.LauncherConfigurationParameters$$Lambda$60/0x00007faab4020dd0 +org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor +org.junit.platform.launcher.LauncherSessionListener +org.junit.platform.launcher.core.LauncherFactory$$Lambda$61/0x00007faab4021448 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore +org.junit.platform.launcher.core.LauncherFactory$$Lambda$62/0x00007faab4021898 +org.junit.platform.engine.support.store.NamespacedHierarchicalStoreException +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$CloseAction +java.lang.invoke.LambdaForm$DMH/0x00007faab4024000 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$CloseAction$$Lambda$63/0x00007faab4021f40 +java.util.stream.SliceOps +java.util.stream.ReferencePipeline$StatefulOp +java.util.stream.SliceOps$1 +org.junit.platform.launcher.core.DefaultLauncherSession$$Lambda$64/0x00007faab4022160 +java.util.stream.ReduceOps$1 +java.util.stream.ReduceOps$1ReducingSink +java.util.stream.SliceOps$1$1 +org.junit.platform.launcher.LauncherInterceptor$Invocation +java.lang.invoke.LambdaForm$DMH/0x00007faab4024400 +org.junit.platform.launcher.core.DefaultLauncherSession$$Lambda$65/0x00007faab40225a8 +org.junit.platform.launcher.core.ListenerRegistry +org.junit.platform.launcher.listeners.session.LauncherSessionListeners +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$66/0x00007faab4022c08 +org.junit.platform.launcher.core.ServiceLoaderRegistry +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$67/0x00007faab4023050 +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$68/0x00007faab40232a0 +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$69/0x00007faab40234e8 +org.junit.platform.commons.util.ServiceLoaderUtils +java.util.ServiceLoader$ProviderSpliterator +org.junit.platform.commons.util.ServiceLoaderUtils$$Lambda$70/0x00007faab4023948 +org.junit.platform.commons.util.ServiceLoaderUtils$$Lambda$71/0x00007faab4023ba0 +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$72/0x00007faab4026000 +java.lang.invoke.LambdaForm$DMH/0x00007faab4024800 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$73/0x00007faab4026228 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$74/0x00007faab4026460 +org.junit.platform.launcher.LauncherSessionListener$1 +org.junit.platform.launcher.core.DelegatingLauncher +org.junit.platform.launcher.core.InterceptingLauncher +org.junit.platform.launcher.core.DefaultLauncherSession$$Lambda$75/0x00007faab4026db0 +org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry +org.junit.platform.engine.TestEngine +org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry$$Lambda$76/0x00007faab40271d8 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$77/0x00007faab4027400 +org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine +org.junit.jupiter.engine.JupiterTestEngine +org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutorService +org.junit.jupiter.engine.config.JupiterConfiguration +org.junit.platform.engine.TestDescriptor +org.junit.platform.engine.support.hierarchical.EngineExecutionContext +org.junit.platform.launcher.core.LauncherFactory$$Lambda$78/0x00007faab4025400 +org.junit.platform.launcher.core.DefaultLauncher +org.junit.platform.launcher.TestPlan +org.junit.platform.launcher.core.InternalTestPlan +org.junit.platform.launcher.core.LauncherListenerRegistry +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$79/0x00007faab4024c00 +org.junit.platform.launcher.core.CompositeTestExecutionListener +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$80/0x00007faab40282a0 +org.junit.platform.launcher.core.EngineExecutionOrchestrator +org.junit.platform.engine.EngineExecutionListener +org.junit.platform.launcher.TestPlan$Visitor +org.junit.platform.launcher.core.DiscoveryIssueException +org.junit.platform.launcher.core.DefaultLauncher$$Lambda$81/0x00007faab4028d68 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator +org.junit.platform.launcher.core.EngineDiscoveryResultValidator +org.junit.platform.launcher.core.EngineIdValidator +org.junit.platform.launcher.core.EngineIdValidator$$Lambda$82/0x00007faab40295d0 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$83/0x00007faab40297f8 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$84/0x00007faab4029a30 +org.junit.platform.commons.util.ClassNamePatternFilterUtils +org.junit.platform.launcher.core.LauncherFactory$$Lambda$85/0x00007faab4029e70 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$86/0x00007faab402a0b0 +java.lang.invoke.LambdaForm$DMH/0x00007faab402c000 +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$87/0x00007faab402a300 +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$88/0x00007faab402a558 +org.junit.platform.launcher.listeners.UniqueIdTrackingListener +org.junit.platform.launcher.core.LauncherFactory$$Lambda$89/0x00007faab402aa40 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$90/0x00007faab402ac78 +org.junit.platform.launcher.core.InterceptingLauncher$$Lambda$91/0x00007faab402aeb0 +org.junit.platform.launcher.core.LauncherPhase +org.junit.platform.engine.UniqueId +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$92/0x00007faab402b748 +org.junit.platform.launcher.core.DiscoveryIssueCollector +org.junit.platform.engine.TestSource +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener +org.junit.platform.launcher.core.DelegatingLauncherDiscoveryRequest +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$1 +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener$$Lambda$93/0x00007faab402e830 +org.junit.platform.launcher.core.EngineFilterer +org.junit.platform.engine.FilterResult +org.junit.platform.launcher.core.EngineFilterer$$Lambda$94/0x00007faab402eeb0 +java.lang.invoke.LambdaForm$DMH/0x00007faab402c400 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$95/0x00007faab402f0f8 +java.util.stream.MatchOps$MatchKind +java.util.stream.MatchOps +java.util.stream.MatchOps$MatchOp +java.util.stream.MatchOps$BooleanTerminalSink +java.util.stream.MatchOps$$Lambda$96/0x00007faab4060150 +java.util.stream.MatchOps$1MatchSink +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$97/0x00007faab402f348 +org.junit.platform.engine.UniqueIdFormat +java.io.UnsupportedEncodingException +java.util.Formatter +java.util.regex.Pattern$$Lambda$19/0x800000029 +java.util.regex.Pattern$BmpCharPredicate$$Lambda$20/0x80000002b +java.util.Locale$Category +java.util.Formatter$Conversion +java.util.Formatter$FormatString +java.util.Formatter$FormatSpecifier +java.util.Formatter$Flags +java.util.Formatter$FixedString +java.util.Formattable +java.util.regex.Pattern$$Lambda$100/0x00007faab4060cd8 +java.lang.invoke.LambdaForm$DMH/0x00007faab402c800 +org.junit.platform.engine.UniqueIdFormat$$Lambda$101/0x00007faab402f790 +java.net.URLEncoder +java.util.BitSet +java.io.CharArrayWriter +org.junit.platform.engine.UniqueIdFormat$$Lambda$102/0x00007faab402f9d0 +org.junit.platform.engine.UniqueIdFormat$$Lambda$103/0x00007faab402fc10 +org.junit.platform.engine.UniqueIdFormat$$Lambda$104/0x00007faab402d000 +org.junit.platform.engine.UniqueIdFormat$$Lambda$105/0x00007faab402d240 +org.junit.platform.engine.UniqueIdFormat$$Lambda$106/0x00007faab402d480 +org.junit.platform.engine.UniqueId$Segment +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener$$Lambda$107/0x00007faab402d8e0 +org.junit.jupiter.engine.config.CachingJupiterConfiguration +org.junit.jupiter.engine.config.DefaultJupiterConfiguration +org.junit.jupiter.api.parallel.ExecutionMode +org.junit.jupiter.api.TestInstance$Lifecycle +org.junit.jupiter.api.io.CleanupMode +org.junit.jupiter.api.extension.TestInstantiationAwareExtension$ExtensionContextScope +org.junit.jupiter.engine.config.EnumConfigurationParameterConverter +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter +org.junit.jupiter.api.DisplayNameGenerator +org.junit.jupiter.api.MethodOrderer +org.junit.jupiter.api.ClassOrderer +org.junit.jupiter.api.io.TempDirFactory +org.junit.platform.engine.support.hierarchical.Node +org.junit.platform.engine.support.descriptor.AbstractTestDescriptor +org.junit.platform.engine.support.descriptor.EngineDescriptor +org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor +org.junit.jupiter.engine.extension.ExtensionRegistry +org.junit.jupiter.api.extension.ExtensionContext +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver +org.junit.platform.engine.support.discovery.SelectorResolver +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$InitializationContext +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$Builder +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$108/0x00007faab40330b8 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$Builder$$Lambda$109/0x00007faab40332f8 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$110/0x00007faab4033540 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$111/0x00007faab4033780 +org.junit.platform.engine.TestDescriptor$Visitor +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$112/0x00007faab4033bc0 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter +org.junit.platform.engine.DiscoveryIssue +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$$Lambda$113/0x00007faab4034200 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$$Lambda$114/0x00007faab4034448 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$DefaultInitializationContext +org.junit.platform.engine.DiscoveryFilter +org.junit.platform.engine.discovery.ClassNameFilter +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$115/0x00007faab4034d00 +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$116/0x00007faab4034f58 +org.junit.platform.engine.discovery.PackageNameFilter +org.junit.platform.engine.CompositeFilter +org.junit.platform.engine.CompositeFilter$1 +org.junit.platform.engine.CompositeFilter$1$$Lambda$117/0x00007faab4035818 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$$Lambda$118/0x00007faab4035a68 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$$Lambda$119/0x00007faab4035cb0 +java.util.stream.Collectors$$Lambda$120/0x00007faab4061750 +java.util.stream.Collectors$$Lambda$121/0x00007faab4061980 +org.junit.platform.engine.support.discovery.ClassContainerSelectorResolver +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$122/0x00007faab4036400 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$123/0x00007faab4036650 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$124/0x00007faab40368a0 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$125/0x00007faab4036af8 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod +org.junit.jupiter.engine.discovery.predicates.IsTestMethod +org.junit.jupiter.api.Test +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$Condition +org.junit.jupiter.engine.discovery.predicates.IsTestMethod$$Lambda$126/0x00007faab4037620 +org.junit.platform.commons.support.ModifierSupport +java.lang.invoke.LambdaForm$DMH/0x00007faab4038000 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$127/0x00007faab4037a58 +java.lang.invoke.MethodHandle$1 +java.lang.invoke.LambdaForm$DMH/0x00007faab4038400 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$128/0x00007faab4037ca8 +java.lang.invoke.LambdaForm$DMH/0x00007faab4038800 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$$Lambda$129/0x00007faab403c000 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$130/0x00007faab403c258 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$131/0x00007faab403c4a8 +java.lang.invoke.LambdaForm$DMH/0x00007faab4038c00 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$Condition$$Lambda$132/0x00007faab403c6f0 +org.junit.platform.commons.util.ReflectionUtils +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$133/0x00007faab403cb50 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$134/0x00007faab403cda0 +org.junit.jupiter.engine.discovery.predicates.IsTestFactoryMethod +org.junit.jupiter.api.DynamicNode +java.util.regex.MatchResult +java.util.regex.Matcher +java.util.regex.IntHashSet +org.junit.jupiter.api.TestFactory +org.junit.jupiter.engine.discovery.predicates.IsTestFactoryMethod$$Lambda$135/0x00007faab403d670 +org.junit.jupiter.engine.discovery.predicates.IsTestFactoryMethod$$Lambda$136/0x00007faab403d8a0 +org.junit.jupiter.engine.discovery.predicates.IsTestFactoryMethod$$Lambda$137/0x00007faab403daf8 +java.util.function.Predicate$$Lambda$138/0x00007faab4062210 +org.junit.jupiter.engine.discovery.predicates.IsTestTemplateMethod +org.junit.jupiter.api.TestTemplate +org.junit.jupiter.engine.discovery.predicates.IsTestTemplateMethod$$Lambda$139/0x00007faab403e1a8 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$140/0x00007faab403e3d8 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$141/0x00007faab403e628 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$142/0x00007faab403e870 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$143/0x00007faab403eac0 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$144/0x00007faab403ed00 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$145/0x00007faab403ef50 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$146/0x00007faab403f190 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$147/0x00007faab403f3e0 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$148/0x00007faab403f620 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$149/0x00007faab403f870 +org.junit.jupiter.engine.discovery.ClassSelectorResolver +org.junit.jupiter.engine.descriptor.ResourceLockAware +org.junit.jupiter.engine.descriptor.TestClassAware +org.junit.jupiter.engine.descriptor.Validatable +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor +org.junit.jupiter.engine.descriptor.ClassTestDescriptor +org.junit.jupiter.engine.descriptor.NestedClassTestDescriptor +org.junit.jupiter.api.extension.ClassTemplateInvocationContext +org.junit.jupiter.engine.descriptor.Filterable +org.junit.jupiter.engine.descriptor.ClassTemplateTestDescriptor +org.junit.jupiter.engine.discovery.MethodSelectorResolver +org.junit.jupiter.engine.discovery.MethodFinder +java.util.regex.Pattern$$Lambda$150/0x00007faab4062468 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$TestDescriptorFactory +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor +org.junit.jupiter.engine.extension.ExtensionRegistrar +java.lang.invoke.LambdaForm$DMH/0x00007faab4084000 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$151/0x00007faab4080b00 +org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor +org.junit.jupiter.engine.descriptor.DynamicNodeTestDescriptor +org.junit.jupiter.engine.descriptor.DynamicContainerTestDescriptor +org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$152/0x00007faab4082038 +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$153/0x00007faab40827f0 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor +org.junit.jupiter.engine.discovery.ClassOrderingVisitor +org.junit.jupiter.api.ClassOrdererContext +org.junit.platform.commons.util.LruCache +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$154/0x00007faab40836f0 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$155/0x00007faab4083938 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$156/0x00007faab4083b78 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$157/0x00007faab4086000 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$158/0x00007faab4083dc8 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$DescriptorWrapperOrderer +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$MessageGenerator +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$DescriptorWrapperOrderer$$Lambda$159/0x00007faab4086660 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$DescriptorWrapperOrderer$$Lambda$160/0x00007faab4086880 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$161/0x00007faab4086aa0 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$162/0x00007faab4086cf0 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor +org.junit.jupiter.api.MethodOrdererContext +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$163/0x00007faab4087378 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$164/0x00007faab40875c8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$165/0x00007faab4087808 +java.lang.invoke.LambdaForm$MH/0x00007faab4084400 +java.util.Comparator$$Lambda$166/0x00007faab40628c0 +java.util.Collections$ReverseComparator +java.util.Comparators$NaturalOrderComparator +java.util.Collections$ReverseComparator2 +java.util.function.UnaryOperator +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$167/0x00007faab4087a50 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$168/0x00007faab4087cb0 +org.junit.platform.engine.CompositeTestDescriptorVisitor +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution +org.junit.platform.engine.support.discovery.SelectorResolver$Context +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$DefaultContext +org.junit.platform.engine.support.discovery.SelectorResolver$Match +org.junit.platform.engine.support.discovery.SelectorResolver$Match$$Lambda$169/0x00007faab4085ab8 +org.junit.platform.engine.support.discovery.SelectorResolver$Match$Type +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$170/0x00007faab40849f8 +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$171/0x00007faab4084c50 +java.util.ArrayDeque$$Lambda$172/0x00007faab4063970 +org.junit.platform.engine.discovery.UniqueIdSelector +org.junit.platform.engine.support.discovery.SelectorResolver$Resolution +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$173/0x00007faab4088460 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$174/0x00007faab40886a8 +org.junit.platform.engine.discovery.ClasspathResourceSelector +org.junit.platform.engine.discovery.ClasspathRootSelector +org.junit.platform.commons.support.ReflectionSupport +org.junit.platform.commons.util.ClasspathScannerLoader +org.junit.platform.commons.support.scanning.ClasspathScanner +java.util.Spliterators$IteratorSpliterator +jdk.internal.misc.ScopedMemoryAccess$Scope +org.junit.platform.commons.support.scanning.DefaultClasspathScanner +java.nio.file.FileVisitor +org.junit.platform.commons.util.ClasspathScannerLoader$$Lambda$175/0x00007faab40895e8 +org.junit.platform.commons.function.Try +java.lang.invoke.LambdaForm$DMH/0x00007faab408c000 +org.junit.platform.commons.util.ClasspathScannerLoader$$Lambda$176/0x00007faab4089a58 +java.lang.invoke.LambdaForm$DMH/0x00007faab408c400 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$177/0x00007faab4089c88 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$178/0x00007faab4089ec0 +org.junit.platform.commons.function.Try$Failure +org.junit.platform.commons.function.Try$Success +org.junit.platform.commons.function.Try$$Lambda$179/0x00007faab408a598 +java.util.regex.Pattern$1 +org.junit.platform.engine.discovery.ClassSelector$$Lambda$180/0x00007faab408a7c0 +org.junit.jupiter.api.Nested +org.junit.platform.commons.support.AnnotationSupport +org.junit.platform.commons.util.AnnotationUtils +java.lang.annotation.Inherited +sun.reflect.generics.parser.SignatureParser +sun.reflect.generics.tree.Tree +sun.reflect.generics.tree.TypeTree +sun.reflect.generics.tree.TypeArgument +sun.reflect.generics.tree.ReturnType +sun.reflect.generics.tree.TypeSignature +sun.reflect.generics.tree.BaseType +sun.reflect.generics.tree.FieldTypeSignature +sun.reflect.generics.tree.SimpleClassTypeSignature +sun.reflect.generics.tree.ClassTypeSignature +sun.reflect.generics.scope.Scope +sun.reflect.generics.scope.AbstractScope +sun.reflect.generics.scope.ClassScope +sun.reflect.generics.factory.GenericsFactory +sun.reflect.generics.factory.CoreReflectionFactory +sun.reflect.generics.visitor.TypeTreeVisitor +sun.reflect.generics.visitor.Reifier +java.lang.annotation.Target +java.lang.reflect.GenericArrayType +sun.reflect.annotation.AnnotationType +sun.reflect.annotation.AnnotationType$1 +java.lang.annotation.ElementType +java.lang.annotation.Retention +java.lang.annotation.Documented +java.lang.annotation.RetentionPolicy +sun.reflect.annotation.ExceptionProxy +sun.reflect.annotation.AnnotationTypeMismatchExceptionProxy +sun.reflect.annotation.AnnotationParser$1 +java.lang.reflect.InvocationHandler +sun.reflect.annotation.AnnotationInvocationHandler +java.lang.reflect.Proxy +java.lang.ClassValue +java.lang.reflect.Proxy$1 +java.lang.ClassValue$Entry +java.lang.ClassValue$Identity +java.lang.ClassValue$Version +jdk.internal.loader.AbstractClassLoaderValue$Sub +java.lang.reflect.Proxy$$Lambda$181/0x00007faab406bf50 +java.lang.reflect.Proxy$ProxyBuilder +java.lang.PublicMethods +java.util.LinkedHashMap$LinkedValues +java.util.LinkedHashMap$LinkedValueIterator +java.lang.reflect.Proxy$ProxyBuilder$$Lambda$182/0x00007faab406cb68 +java.lang.module.ModuleDescriptor$Modifier +java.lang.module.ModuleDescriptor$Builder +jdk.internal.module.Checks +java.lang.module.ModuleDescriptor$Builder$$Lambda$1/0x800000002 +java.lang.reflect.Proxy$$Lambda$184/0x00007faab406cd98 +java.lang.reflect.ProxyGenerator +java.lang.reflect.ProxyGenerator$ProxyMethod +java.util.StringJoiner +java.lang.reflect.ProxyGenerator$$Lambda$185/0x00007faab406d4e8 +java.lang.reflect.ProxyGenerator$$Lambda$186/0x00007faab406d728 +java.lang.reflect.ProxyGenerator$PrimitiveTypeInfo +jdk.internal.org.objectweb.asm.Edge +jdk.proxy1.$Proxy0 +java.lang.reflect.Proxy$ProxyBuilder$1 +sun.reflect.annotation.AnnotationParser$$Lambda$187/0x00007faab406e218 +java.lang.invoke.LambdaForm$DMH/0x00007faab408c800 +jdk.proxy1.$Proxy1 +jdk.proxy1.$Proxy2 +org.apiguardian.api.API +org.apiguardian.api.API$Status +jdk.proxy2.$Proxy3 +java.lang.reflect.UndeclaredThrowableException +java.lang.Class$AnnotationData +org.junit.platform.commons.util.KotlinReflectionUtils +org.junit.platform.commons.function.Try$Transformer +org.junit.platform.commons.util.KotlinReflectionUtils$$Lambda$188/0x00007faab408bcc8 +org.junit.jupiter.api.ClassTemplate +jdk.proxy1.$Proxy4 +org.junit.platform.commons.annotation.Testable +jdk.proxy2.$Proxy5 +org.junit.platform.commons.util.ReflectionUtils$HierarchyTraversalMode +org.junit.platform.commons.util.ReflectionUtils$$Lambda$189/0x00007faab408ea90 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$190/0x00007faab408ece0 +com.amazonaws.services.lambda.runtime.events.SQSEvent +com.amazonaws.services.lambda.runtime.events.KinesisEvent +com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent +com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPResponse +com.amazonaws.services.lambda.runtime.RequestHandler +software.amazon.lambda.powertools.validation.handlers.SQSWithWrongEnvelopeHandler +org.junit.platform.commons.util.ReflectionUtils$$Lambda$191/0x00007faab408fc88 +java.util.Arrays$LegacyMergeSort +java.util.TimSort +org.junit.jupiter.params.ParameterizedTest +org.junit.jupiter.params.ArgumentCountValidationMode +org.junit.jupiter.api.extension.ExtendWith +jdk.proxy2.$Proxy6 +com.amazonaws.services.lambda.runtime.tests.annotations.Event +org.junit.jupiter.params.provider.ArgumentsSource +jdk.proxy2.$Proxy7 +java.util.LinkedHashMap$LinkedEntrySet +java.util.LinkedHashMap$LinkedEntryIterator +jdk.proxy2.$Proxy8 +java.lang.annotation.Repeatable +sun.reflect.annotation.AnnotationParser$$Lambda$192/0x00007faab406f5a0 +org.junit.jupiter.api.extension.Extension +org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider +org.junit.jupiter.params.ParameterizedInvocationContextProvider +org.junit.jupiter.params.ParameterizedTestExtension +jdk.proxy2.$Proxy9 +jdk.internal.reflect.ClassFileConstants +jdk.internal.reflect.AccessorGenerator +jdk.internal.reflect.MethodAccessorGenerator +jdk.internal.reflect.ByteVectorFactory +jdk.internal.reflect.ByteVector +jdk.internal.reflect.ByteVectorImpl +jdk.internal.reflect.ClassFileAssembler +jdk.internal.reflect.UTF8 +jdk.internal.reflect.Label +jdk.internal.reflect.Label$PatchInfo +jdk.internal.reflect.MethodAccessorGenerator$1 +jdk.internal.reflect.ClassDefiner +jdk.internal.reflect.ClassDefiner$1 +jdk.internal.reflect.GeneratedConstructorAccessor1 +java.lang.Class$1 +jdk.internal.reflect.BootstrapConstructorAccessorImpl +org.junit.jupiter.api.extension.Extensions +jdk.proxy1.$Proxy10 +sun.reflect.annotation.AnnotationInvocationHandler$1 +org.junit.jupiter.params.provider.ArgumentsProvider +org.junit.jupiter.params.support.AnnotationConsumer +com.amazonaws.services.lambda.runtime.tests.EventArgumentsProvider +jdk.proxy2.$Proxy11 +org.junit.jupiter.params.provider.ArgumentsSources +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$193/0x00007faab40919f0 +org.junit.jupiter.api.extension.ExtensionConfigurationException +org.junit.jupiter.api.extension.TestInstanceFactoryContext +org.junit.jupiter.api.extension.TestInstantiationAwareExtension +org.junit.jupiter.api.extension.TestInstantiationException +org.junit.jupiter.engine.execution.ConditionEvaluator +org.junit.jupiter.engine.execution.ConditionEvaluationException +org.junit.jupiter.api.extension.ConditionEvaluationResult +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker +org.junit.jupiter.api.extension.ReflectiveInvocationContext +org.junit.jupiter.api.extension.InvocationInterceptor$Invocation +org.junit.jupiter.engine.execution.InvocationInterceptorChain +org.junit.jupiter.engine.descriptor.DisplayNameUtils +org.junit.jupiter.api.DisplayNameGenerator$Standard +org.junit.jupiter.api.DisplayNameGenerator$Simple +org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores +org.junit.jupiter.api.DisplayNameGenerator$IndicativeSentences +org.junit.jupiter.api.DisplayNameGenerator$IndicativeSentences$$Lambda$194/0x00007faab4096000 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$195/0x00007faab4096250 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$196/0x00007faab4096470 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$197/0x00007faab40966a8 +org.junit.platform.engine.support.descriptor.ClassSource +org.junit.jupiter.api.DisplayName +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$198/0x00007faab4096cf0 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$199/0x00007faab4096f30 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$200/0x00007faab4097180 +org.junit.jupiter.api.DisplayNameGeneration +java.util.AbstractList$Itr +java.util.AbstractList$ListItr +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$201/0x00007faab40975c0 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$202/0x00007faab4097800 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$203/0x00007faab4097a40 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$204/0x00007faab4097c88 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$205/0x00007faab4095000 +org.junit.jupiter.engine.config.DefaultJupiterConfiguration$$Lambda$206/0x00007faab4095248 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$ClassInfo +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$ClassInfo$$Lambda$207/0x00007faab4095678 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$ClassInfo$$Lambda$208/0x00007faab40958a0 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$ClassInfo$$Lambda$209/0x00007faab4095ac8 +org.junit.jupiter.api.Tag +org.junit.jupiter.api.Tags +org.junit.platform.commons.util.AnnotationUtils$$Lambda$210/0x00007faab4094a00 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$211/0x00007faab4094c28 +java.lang.invoke.LambdaForm$DMH/0x00007faab4094400 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$212/0x00007faab4098000 +org.junit.platform.engine.TestTag +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$213/0x00007faab4098468 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$214/0x00007faab40986a8 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$215/0x00007faab40988c8 +java.lang.invoke.LambdaForm$DMH/0x00007faab409c000 +java.util.function.Function$$Lambda$216/0x00007faab40722d0 +org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils +org.junit.jupiter.api.TestInstance +jdk.internal.reflect.GeneratedConstructorAccessor2 +org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils$$Lambda$217/0x00007faab4098f10 +org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils$$Lambda$218/0x00007faab4099150 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$219/0x00007faab4099378 +java.lang.invoke.LambdaForm$DMH/0x00007faab409c800 +org.junit.jupiter.engine.config.EnumConfigurationParameterConverter$$Lambda$220/0x00007faab40997b8 +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$1 +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$DefaultExclusiveResourceCollector +org.junit.jupiter.api.parallel.ResourceLock +jdk.internal.reflect.GeneratedConstructorAccessor3 +org.junit.jupiter.api.parallel.ResourceLocks +jdk.internal.reflect.GeneratedConstructorAccessor4 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$LifecycleMethods +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$$Lambda$221/0x00007faab409a6a0 +java.lang.invoke.LambdaForm$DMH/0x00007faab409d400 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$$Lambda$222/0x00007faab409a8d8 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils +org.junit.jupiter.api.BeforeAll +org.junit.platform.commons.support.HierarchyTraversalMode +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$223/0x00007faab409b368 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$224/0x00007faab409b5b0 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$225/0x00007faab409b800 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$226/0x00007faab409ba48 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$227/0x00007faab409bca0 +java.util.function.IntFunction +org.junit.platform.commons.util.ReflectionUtils$$Lambda$228/0x00007faab409e000 +java.util.stream.Nodes +java.util.stream.Node +java.util.stream.Nodes$EmptyNode +java.util.stream.Nodes$EmptyNode$OfRef +java.util.stream.Node$OfPrimitive +java.util.stream.Node$OfInt +java.util.stream.Nodes$EmptyNode$OfInt +java.util.stream.Node$OfLong +java.util.stream.Nodes$EmptyNode$OfLong +java.util.stream.Node$OfDouble +java.util.stream.Nodes$EmptyNode$OfDouble +java.util.stream.Node$Builder +java.util.stream.AbstractSpinedBuffer +java.util.stream.SpinedBuffer +java.util.stream.Nodes$SpinedNodeBuilder +org.junit.platform.commons.util.ReflectionUtils$$Lambda$229/0x00007faab409e220 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$230/0x00007faab409e478 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$231/0x00007faab409e698 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$232/0x00007faab409e8f0 +java.util.stream.DistinctOps +java.util.stream.DistinctOps$1 +org.junit.platform.commons.util.CollectionUtils$$Lambda$233/0x00007faab409eb10 +java.util.stream.DistinctOps$1$2 +jdk.proxy2.$Proxy12 +org.junit.jupiter.params.provider.MethodSource +jdk.proxy2.$Proxy13 +org.junit.jupiter.params.provider.MethodSources +org.junit.jupiter.params.provider.AnnotationBasedArgumentsProvider +org.junit.jupiter.params.provider.MethodArgumentsProvider +software.amazon.lambda.powertools.validation.internal.ResponseEventsArgumentsProvider +org.junit.jupiter.api.BeforeEach +jdk.proxy2.$Proxy14 +software.amazon.lambda.powertools.validation.internal.HandledResponseEventsArgumentsProvider +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$234/0x00007faab409dc88 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$235/0x00007faab40a0000 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$236/0x00007faab40a0250 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$Condition$$Lambda$237/0x00007faab40a0498 +java.util.stream.ReferencePipeline$15 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$238/0x00007faab40a06d0 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$239/0x00007faab40a0918 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$240/0x00007faab40a0b68 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$Condition$$Lambda$241/0x00007faab40a0db0 +java.util.stream.ReferencePipeline$15$1 +org.junit.jupiter.api.AfterAll +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$242/0x00007faab40a1208 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$243/0x00007faab40a1450 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$244/0x00007faab40a16a0 +org.junit.jupiter.api.AfterEach +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$245/0x00007faab40a1ae8 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$246/0x00007faab40a1d30 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$247/0x00007faab40a1f58 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$248/0x00007faab40a2180 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$249/0x00007faab40a23c8 +org.junit.platform.engine.SelectorResolutionResult +org.junit.platform.engine.SelectorResolutionResult$Status +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener$$Lambda$250/0x00007faab40a2c60 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$251/0x00007faab40a2e98 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$252/0x00007faab40a30e8 +java.util.stream.ForEachOps +java.util.stream.ForEachOps$ForEachOp +java.util.stream.ForEachOps$ForEachOp$OfRef +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$253/0x00007faab40a3320 +org.junit.platform.commons.util.ReflectionUtils$CycleErrorHandling +org.junit.platform.commons.util.ReflectionUtils$CycleErrorHandling$1 +org.junit.platform.commons.util.ReflectionUtils$CycleErrorHandling$2 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$254/0x00007faab40a3e50 +java.lang.invoke.LambdaForm$DMH/0x00007faab40a8000 +java.util.function.Predicate$$Lambda$255/0x00007faab40754b8 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$256/0x00007faab40a4088 +java.util.function.Predicate$$Lambda$257/0x00007faab4075710 +java.util.stream.Streams$ConcatSpliterator +java.util.stream.Streams$ConcatSpliterator$OfRef +java.util.stream.Streams$2 +org.junit.platform.engine.discovery.NestedClassSelector +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$258/0x00007faab40a4530 +java.util.stream.AbstractPipeline$$Lambda$259/0x00007faab40760d8 +java.util.stream.StreamSpliterators$AbstractWrappingSpliterator +java.util.stream.StreamSpliterators$WrappingSpliterator +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$260/0x00007faab40a4778 +java.util.stream.StreamSpliterators +java.util.stream.StreamSpliterators$WrappingSpliterator$$Lambda$261/0x00007faab4076a38 +org.junit.platform.engine.discovery.MethodSelector +org.junit.platform.engine.discovery.MethodSelector$$Lambda$262/0x00007faab40a4c08 +org.junit.platform.commons.util.ClassUtils +org.junit.platform.commons.util.ClassUtils$$Lambda$263/0x00007faab40a5050 +java.util.stream.Collectors$$Lambda$31/0x800000042 +java.util.stream.Collectors$$Lambda$23/0x80000003a +java.util.stream.Collectors$$Lambda$26/0x80000003d +java.util.stream.Collectors$$Lambda$28/0x80000003f +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$268/0x00007faab40a5298 +org.junit.platform.engine.discovery.IterationSelector +org.junit.platform.engine.discovery.DirectorySelector +org.junit.platform.engine.discovery.FileSelector +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$269/0x00007faab40a5ba8 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$270/0x00007faab40a5dd0 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$271/0x00007faab40a6000 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$272/0x00007faab40a6248 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$273/0x00007faab40a6498 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$274/0x00007faab40a66d8 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$275/0x00007faab40a6920 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$276/0x00007faab40a6b48 +org.junit.platform.commons.util.ClassUtils$$Lambda$277/0x00007faab40a6d90 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$278/0x00007faab40a6fd0 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$279/0x00007faab40a71f8 +org.junit.jupiter.api.DisplayNameGenerator$$Lambda$280/0x00007faab40a7430 +org.junit.platform.engine.support.descriptor.MethodSource +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$MethodInfo +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$MethodInfo$$Lambda$281/0x00007faab40a7aa8 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$MethodInfo$$Lambda$282/0x00007faab40a7cd0 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$MethodInfo$$Lambda$283/0x00007faab40ac000 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$284/0x00007faab40ac238 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$285/0x00007faab40ac478 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$286/0x00007faab40ac6c8 +java.util.function.BiPredicate +org.junit.jupiter.engine.descriptor.DynamicDescendantFilter +org.junit.jupiter.engine.descriptor.DynamicDescendantFilter$WithoutIndexFiltering +org.junit.jupiter.engine.descriptor.DynamicDescendantFilter$Mode +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$287/0x00007faab40ad288 +java.util.HashMap$KeySpliterator +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall$VoidMethodInterceptorCall +org.junit.jupiter.api.extension.InvocationInterceptor +java.lang.invoke.LambdaForm$DMH/0x00007faab40a8400 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$288/0x00007faab40ad8b0 +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall$$Lambda$289/0x00007faab40adcd0 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$290/0x00007faab40adef8 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$291/0x00007faab40ae130 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$292/0x00007faab40ae368 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$293/0x00007faab40ae5a8 +org.junit.jupiter.api.ClassDescriptor +org.junit.jupiter.engine.discovery.AbstractAnnotatedDescriptorWrapper +org.junit.jupiter.engine.discovery.DefaultClassDescriptor +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$294/0x00007faab40aee58 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$$Lambda$295/0x00007faab40af098 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$$Lambda$296/0x00007faab40af2f0 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$$Lambda$297/0x00007faab40af538 +org.junit.jupiter.api.Order +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$298/0x00007faab40af970 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$299/0x00007faab40afba8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$300/0x00007faab40aa000 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$301/0x00007faab40aa238 +org.junit.platform.engine.TestDescriptor$$Lambda$302/0x00007faab40aa478 +org.junit.jupiter.api.TestClassOrder +jdk.internal.reflect.GeneratedConstructorAccessor5 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$303/0x00007faab40aa6b0 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$304/0x00007faab40aa8f0 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$305/0x00007faab40aab30 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$306/0x00007faab40aad78 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$307/0x00007faab40aafa0 +org.junit.jupiter.api.TestMethodOrder +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$308/0x00007faab40ab3e0 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$309/0x00007faab40ab620 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$310/0x00007faab40ab860 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$311/0x00007faab40abaa0 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$312/0x00007faab40abcc8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$313/0x00007faab40a9000 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$314/0x00007faab40a9248 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$315/0x00007faab40a9468 +org.junit.jupiter.api.MethodDescriptor +org.junit.jupiter.engine.discovery.DefaultMethodDescriptor +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$316/0x00007faab40a9af8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$317/0x00007faab40a9d38 +org.junit.platform.engine.support.hierarchical.Node$ExecutionMode +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$318/0x00007faab40b0000 +org.junit.jupiter.engine.descriptor.Validatable$$Lambda$319/0x00007faab40b0238 +org.junit.jupiter.api.extension.ClassTemplateInvocationLifecycleMethod +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$320/0x00007faab40b0670 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$321/0x00007faab40b08a8 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$322/0x00007faab40b0ad0 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$323/0x00007faab40b0cf8 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$324/0x00007faab40b0f38 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$325/0x00007faab40b1188 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$326/0x00007faab40b13c0 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$327/0x00007faab40b15e8 +org.junit.platform.launcher.core.EngineDiscoveryResultValidator$$Lambda$328/0x00007faab40b1810 +org.junit.platform.engine.TestDescriptor$Type +org.junit.platform.launcher.core.EngineDiscoveryResultValidator$$Lambda$329/0x00007faab40b1e78 +org.junit.platform.launcher.EngineDiscoveryResult +org.junit.platform.launcher.EngineDiscoveryResult$Status +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener$$Lambda$330/0x00007faab40b2700 +java.util.Collections$UnmodifiableList$1 +java.util.ArrayList$ListItr +org.junit.platform.commons.util.ExceptionUtils +java.io.StringWriter +org.junit.platform.launcher.listeners.discovery.AbortOnFailureLauncherDiscoveryListener$$Lambda$331/0x00007faab40b2b40 +org.junit.platform.launcher.core.DiscoveryIssueNotifier +org.junit.platform.engine.DiscoveryIssue$Severity +org.junit.platform.launcher.core.LauncherDiscoveryResult$EngineResultInfo +org.junit.platform.launcher.core.EngineFilterer$$Lambda$332/0x00007faab40b3420 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$333/0x00007faab40b3660 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$334/0x00007faab40b38b0 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$335/0x00007faab40b3af0 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$336/0x00007faab40b3d30 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$337/0x00007faab40b3f88 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$338/0x00007faab40b41a8 +java.lang.invoke.LambdaForm$DMH/0x00007faab40b8000 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$339/0x00007faab40b43f8 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$340/0x00007faab40b4620 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$341/0x00007faab40b4858 +java.lang.invoke.LambdaForm$DMH/0x00007faab40b8400 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$342/0x00007faab40b4a88 +org.junit.platform.engine.TestDescriptor$$Lambda$343/0x00007faab40b4ca8 +org.junit.platform.launcher.core.LauncherDiscoveryResult +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener$$Lambda$344/0x00007faab40b5150 +org.junit.platform.launcher.core.LauncherPhase$$Lambda$345/0x00007faab40b5388 +org.junit.platform.engine.ConfigurationParameters$$Lambda$346/0x00007faab40b55c8 +org.junit.platform.launcher.core.LauncherDiscoveryResult$$Lambda$347/0x00007faab40b5810 +org.junit.platform.launcher.core.LauncherDiscoveryResult$$Lambda$348/0x00007faab40b5a60 +org.junit.platform.launcher.TestPlan$$Lambda$349/0x00007faab40b5ca0 +org.junit.platform.launcher.TestPlan$$Lambda$350/0x00007faab40b5ec8 +org.junit.platform.launcher.TestIdentifier +org.junit.platform.launcher.TestIdentifier$SerializedForm +java.io.ObjectStreamClass +java.io.ObjectStreamClass$Caches +java.io.ClassCache +java.io.ObjectStreamClass$Caches$1 +java.io.ClassCache$1 +java.io.ObjectStreamClass$Caches$2 +java.lang.ClassValue$ClassValueMap +java.io.Externalizable +java.io.ObjectStreamClass$2 +jdk.internal.reflect.UnsafeFieldAccessorFactory +jdk.internal.reflect.UnsafeQualifiedStaticFieldAccessorImpl +jdk.internal.reflect.UnsafeQualifiedStaticLongFieldAccessorImpl +java.util.ComparableTimSort +jdk.internal.reflect.SerializationConstructorAccessorImpl +jdk.internal.reflect.GeneratedSerializationConstructorAccessor1 +java.io.ObjectOutput +java.io.ObjectStreamConstants +java.io.ObjectOutputStream +java.io.ObjectInput +java.io.ObjectInputStream +java.lang.Class$$Lambda$351/0x00007faab407a758 +java.lang.CloneNotSupportedException +java.io.ClassCache$CacheRef +java.io.ObjectStreamClass$FieldReflectorKey +java.io.ObjectStreamClass$FieldReflector +org.junit.platform.launcher.TestIdentifier$$Lambda$352/0x00007faab40b6528 +org.junit.platform.launcher.TestPlan$$Lambda$353/0x00007faab40b6768 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$354/0x00007faab40b69a8 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$355/0x00007faab40b6be0 +software.amazon.lambda.powertools.validation.ValidationUtilsTest +com.fasterxml.jackson.core.TreeNode +com.fasterxml.jackson.databind.JsonSerializable +com.fasterxml.jackson.databind.JsonSerializable$Base +com.fasterxml.jackson.databind.JsonNode +software.amazon.lambda.powertools.validation.model.Product +software.amazon.lambda.powertools.validation.model.MyCustomEvent +jdk.internal.reflect.GeneratedConstructorAccessor6 +org.apache.maven.surefire.api.util.TestsToRun +org.apache.maven.surefire.api.util.DefaultRunOrderCalculator +java.util.random.RandomGenerator +java.util.Random +org.apache.maven.surefire.api.util.CloseableIterator +org.apache.maven.surefire.api.util.TestsToRun$ClassesIterator +java.util.NoSuchElementException +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$356/0x00007faab40bcbd8 +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder$$Lambda$357/0x00007faab40bce10 +org.junit.platform.launcher.core.InterceptingLauncher$$Lambda$358/0x00007faab40bd048 +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$359/0x00007faab40bd270 +org.junit.platform.launcher.core.CompositeTestExecutionListener$EagerTestExecutionListener +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$360/0x00007faab40bd6a8 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$361/0x00007faab40bd900 +org.junit.platform.engine.reporting.ReportEntry +java.lang.invoke.LambdaForm$DMH/0x00007faab40b9000 +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$362/0x00007faab40bdd58 +org.junit.platform.launcher.core.StreamInterceptingTestExecutionListener +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$363/0x00007faab40be268 +org.junit.platform.engine.EngineExecutionListener$1 +org.junit.platform.launcher.core.IterationOrder +org.junit.platform.launcher.core.IterationOrder$1 +org.junit.platform.launcher.core.IterationOrder$2 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$364/0x00007faab40bf000 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$365/0x00007faab40bf238 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$366/0x00007faab40bf460 +org.junit.platform.launcher.core.CompositeEngineExecutionListener +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$367/0x00007faab40bf918 +org.junit.platform.launcher.core.ExecutionListenerAdapter +org.junit.platform.launcher.core.DelegatingEngineExecutionListener +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$368/0x00007faab40bfdd8 +org.junit.platform.launcher.core.OutcomeDelayingEngineExecutionListener +org.junit.platform.engine.ExecutionRequest +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$369/0x00007faab40ba9d8 +org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService +org.junit.jupiter.engine.execution.JupiterEngineExecutionContext +org.junit.jupiter.engine.descriptor.LauncherStoreFacade +org.junit.jupiter.api.extension.ExtensionContext$Store +org.junit.jupiter.engine.descriptor.LauncherStoreFacade$$Lambda$370/0x00007faab40bb528 +org.junit.jupiter.engine.execution.JupiterEngineExecutionContext$State +org.junit.platform.engine.support.hierarchical.ThrowableCollector$Factory +org.junit.platform.engine.support.hierarchical.ThrowableCollector +org.junit.jupiter.engine.support.JupiterThrowableCollectorFactory +org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector +org.junit.jupiter.engine.JupiterTestEngine$$Lambda$371/0x00007faab40b9a40 +org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor +org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutorService$TestTask +org.junit.platform.engine.support.hierarchical.NodeTreeWalker +org.junit.platform.engine.support.hierarchical.LockManager +org.junit.platform.engine.support.hierarchical.ResourceLock +java.util.concurrent.locks.ReadWriteLock +org.junit.platform.engine.support.hierarchical.SingleLock +org.junit.platform.engine.support.hierarchical.ExclusiveResource +org.junit.platform.engine.support.hierarchical.ExclusiveResource$LockMode +org.junit.platform.engine.support.hierarchical.ExclusiveResource$$Lambda$372/0x00007faab40c0d38 +org.junit.platform.engine.support.hierarchical.ExclusiveResource$$Lambda$373/0x00007faab40c0f78 +java.util.Comparator$$Lambda$374/0x00007faab407b718 +java.lang.invoke.LambdaForm$DMH/0x00007faab40c4000 +java.util.Comparator$$Lambda$375/0x00007faab407b9b8 +org.junit.platform.engine.support.hierarchical.ExclusiveResource$$Lambda$376/0x00007faab40c11b8 +org.junit.platform.engine.support.hierarchical.LockManager$$Lambda$377/0x00007faab40c13f8 +java.util.concurrent.locks.ReentrantReadWriteLock +java.util.concurrent.locks.ReentrantReadWriteLock$Sync +java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync +java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter +java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock +java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock +org.junit.platform.commons.util.CollectionUtils$$Lambda$378/0x00007faab40c1638 +org.junit.platform.engine.support.hierarchical.NodeUtils +org.junit.platform.engine.support.hierarchical.NodeUtils$1 +org.junit.platform.engine.support.hierarchical.NodeExecutionAdvisor +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$379/0x00007faab40c1f68 +org.junit.platform.engine.support.hierarchical.NopLock +org.junit.jupiter.api.parallel.ResourceLocksProvider +org.junit.jupiter.engine.descriptor.ClassTestDescriptor$$Lambda$380/0x00007faab40c2630 +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$381/0x00007faab40c2878 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$382/0x00007faab40c2ab0 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$383/0x00007faab40c2cd8 +org.junit.jupiter.engine.descriptor.ResourceLockAware$1 +org.junit.jupiter.api.parallel.ResourceLockTarget +java.util.ArrayDeque$DeqSpliterator +org.junit.jupiter.engine.descriptor.ResourceLockAware$$Lambda$384/0x00007faab40c35a8 +org.junit.jupiter.engine.descriptor.ResourceLockAware$$Lambda$385/0x00007faab40c37e8 +org.junit.jupiter.engine.descriptor.ResourceLockAware$$Lambda$386/0x00007faab40c3a30 +org.junit.platform.engine.support.hierarchical.NodeTestTaskContext +org.junit.platform.engine.support.hierarchical.NodeTestTask +org.junit.platform.engine.support.hierarchical.Node$DynamicTestExecutor +java.lang.invoke.LambdaForm$DMH/0x00007faab40c4400 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$387/0x00007faab40c6458 +org.opentest4j.IncompleteExecutionException +org.opentest4j.TestAbortedException +org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector$$Lambda$388/0x00007faab40c6b38 +org.junit.platform.commons.util.UnrecoverableExceptions +org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector$$Lambda$389/0x00007faab40c6f98 +org.junit.platform.engine.support.hierarchical.ThrowableCollector$Executable +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$390/0x00007faab40c73b8 +org.junit.jupiter.engine.extension.MutableExtensionRegistry +org.junit.jupiter.engine.extension.MutableExtensionRegistry$Entry +org.junit.jupiter.api.extension.ExecutionCondition +org.junit.jupiter.engine.extension.DisabledCondition +org.junit.jupiter.api.extension.TestInstancePreDestroyCallback +org.junit.jupiter.api.extension.AfterAllCallback +org.junit.jupiter.engine.extension.AutoCloseExtension +org.junit.jupiter.api.extension.BeforeAllCallback +org.junit.jupiter.api.extension.BeforeEachCallback +org.junit.jupiter.engine.extension.TimeoutExtension +org.junit.jupiter.api.Timeout +org.junit.jupiter.api.extension.ExtensionContext$Namespace +org.junit.jupiter.engine.extension.RepeatedTestExtension +org.junit.jupiter.api.extension.TestTemplateInvocationContext +org.junit.jupiter.api.extension.ParameterResolver +org.junit.jupiter.engine.extension.TestInfoParameterResolver +org.junit.jupiter.api.TestInfo +org.junit.jupiter.engine.extension.TestReporterParameterResolver +org.junit.jupiter.api.TestReporter +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$391/0x00007faab40c8cc0 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$392/0x00007faab40c8ef8 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$393/0x00007faab40c9130 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$Entry$$Lambda$394/0x00007faab40c9358 +org.junit.jupiter.engine.extension.TempDirectory +org.junit.jupiter.api.extension.AnnotatedElementContext +org.junit.jupiter.engine.extension.TempDirectory$Scope +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$395/0x00007faab40c9c68 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$396/0x00007faab40c9eb0 +org.junit.jupiter.engine.extension.ExtensionContextInternal +org.junit.jupiter.engine.descriptor.AbstractExtensionContext +org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext +org.junit.jupiter.api.extension.ExecutableInvoker +org.junit.jupiter.engine.execution.DefaultExecutableInvoker +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$397/0x00007faab40cb118 +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$398/0x00007faab40cb358 +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$399/0x00007faab40cb578 +org.junit.jupiter.engine.execution.NamespaceAwareStore +org.junit.jupiter.api.extension.ExtensionContextException +org.junit.platform.engine.support.store.Namespace +java.lang.invoke.LambdaForm$DMH/0x00007faab40cc000 +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$400/0x00007faab40ce000 +org.junit.jupiter.engine.execution.JupiterEngineExecutionContext$Builder +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$401/0x00007faab40ce460 +org.junit.platform.engine.support.hierarchical.Node$SkipResult +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$402/0x00007faab40ce8a8 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$403/0x00007faab40ceae0 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$404/0x00007faab40ced08 +org.junit.platform.launcher.TestPlan$$Lambda$405/0x00007faab40cef40 +org.junit.platform.launcher.TestPlan$$Lambda$406/0x00007faab40cf160 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$407/0x00007faab40cf388 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$408/0x00007faab40cf5c0 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$409/0x00007faab40cf7e8 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$410/0x00007faab40cfa20 +org.junit.platform.engine.UniqueIdFormat$$Lambda$411/0x00007faab40cfc48 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$412/0x00007faab40cd000 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$413/0x00007faab40cd258 +org.junit.platform.engine.support.hierarchical.Node$Invocation +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$414/0x00007faab40cd680 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$415/0x00007faab40cd8a8 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$416/0x00007faab40cdad0 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$417/0x00007faab40cdd18 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor +java.util.concurrent.CancellationException +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$418/0x00007faab40cca50 +org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService$$Lambda$419/0x00007faab40ccc88 +org.junit.jupiter.engine.descriptor.ExtensionUtils +java.util.function.ToIntFunction +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$420/0x00007faab40d0000 +java.util.Comparator$$Lambda$421/0x00007faab407d3d8 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$422/0x00007faab40d0220 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$423/0x00007faab40d0470 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$424/0x00007faab40d06b0 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$LateInitEntry +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$425/0x00007faab40d0b38 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$426/0x00007faab40d0d70 +software.amazon.lambda.powertools.validation.Validation +org.aspectj.lang.Signature +com.amazonaws.services.lambda.runtime.Context +org.aspectj.lang.JoinPoint +org.aspectj.lang.ProceedingJoinPoint +software.amazon.lambda.powertools.validation.internal.ValidationAspect +org.junit.platform.commons.util.ReflectionUtils$$Lambda$427/0x00007faab40d1bd8 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$428/0x00007faab40d1e70 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$429/0x00007faab40d20c0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$430/0x00007faab40d22e0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$431/0x00007faab40d2538 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$432/0x00007faab40d2758 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$433/0x00007faab40d29b0 +java.util.stream.SortedOps +java.util.stream.SortedOps$OfRef +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$434/0x00007faab40d2bd0 +java.util.stream.SortedOps$AbstractRefSortingSink +java.util.stream.SortedOps$RefSortingSink +java.util.stream.SortedOps$RefSortingSink$$Lambda$435/0x00007faab407e2f8 +org.junit.jupiter.api.extension.TestInstanceFactory +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$436/0x00007faab40d3008 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$437/0x00007faab40d3248 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$438/0x00007faab40d34a0 +org.junit.jupiter.engine.extension.ExtensionRegistry$$Lambda$439/0x00007faab40d36e8 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$440/0x00007faab40d3908 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$441/0x00007faab40d3b58 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$442/0x00007faab40d3d78 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$443/0x00007faab40d3fa0 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$444/0x00007faab40d41e8 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$445/0x00007faab40d4428 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$446/0x00007faab40d4660 +org.junit.jupiter.engine.execution.BeforeEachMethodAdapter +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$447/0x00007faab40d4a98 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$448/0x00007faab40d4ce0 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$449/0x00007faab40d4f18 +org.junit.jupiter.engine.execution.AfterEachMethodAdapter +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$450/0x00007faab40d5340 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$451/0x00007faab40d5588 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$452/0x00007faab40d57c0 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$453/0x00007faab40d5a10 +org.junit.jupiter.api.extension.RegisterExtension +org.mockito.Mock +org.mockito.stubbing.Answer +org.mockito.Answers +org.mockito.Mock$Strictness +org.mockito.invocation.InvocationOnMock +org.mockito.internal.stubbing.defaultanswers.GloballyConfiguredAnswer +org.mockito.internal.stubbing.defaultanswers.ReturnsSmartNulls +org.mockito.internal.stubbing.defaultanswers.RetrieveGenericsForDefaultAnswers$AnswerCallback +org.mockito.internal.stubbing.defaultanswers.ReturnsMoreEmptyValues +org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues +org.mockito.internal.stubbing.defaultanswers.ReturnsMocks +org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs +org.mockito.invocation.DescribedInvocation +org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs$ReturnsDeepStubsSerializationFallback +org.mockito.stubbing.ValidableAnswer +org.mockito.internal.stubbing.answers.CallsRealMethods +org.mockito.exceptions.base.MockitoException +org.mockito.internal.stubbing.defaultanswers.TriesToReturnSelf +jdk.proxy2.$Proxy15 +org.junit.jupiter.engine.descriptor.ClassExtensionContext +org.junit.jupiter.engine.execution.TestInstancesProvider +org.junit.jupiter.api.extension.TestInstances +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$454/0x00007faab40d9650 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$455/0x00007faab40d9888 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$456/0x00007faab40d9ad0 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$FilterType +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$457/0x00007faab40da150 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$458/0x00007faab40da3a0 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$459/0x00007faab40da5e0 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$460/0x00007faab40da828 +org.junit.jupiter.engine.execution.ConditionEvaluator$$Lambda$461/0x00007faab40daa78 +org.junit.jupiter.engine.execution.ConditionEvaluator$$Lambda$462/0x00007faab40dacc0 +org.junit.jupiter.api.Disabled +org.junit.jupiter.engine.extension.DisabledCondition$$Lambda$463/0x00007faab40db110 +org.junit.jupiter.engine.execution.ConditionEvaluator$$Lambda$464/0x00007faab40db358 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$465/0x00007faab40db580 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$466/0x00007faab40db7d8 +org.junit.platform.launcher.TestIdentifier$$Lambda$467/0x00007faab40dba30 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$468/0x00007faab40dbc70 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$469/0x00007faab40dbeb8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$470/0x00007faab40dc100 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$471/0x00007faab40dc320 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$472/0x00007faab40dc570 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$473/0x00007faab40dc7b0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$474/0x00007faab40dca08 +org.apache.maven.surefire.api.report.SimpleReportEntry +org.apache.maven.surefire.api.util.internal.ClassMethod +org.apache.maven.surefire.report.ClassMethodIndexer$$Lambda$475/0x00007faab40dd160 +org.apache.maven.surefire.api.util.internal.ImmutableMap +org.apache.maven.surefire.booter.spi.EventChannelEncoder$StackTrace +java.lang.StrictMath +java.nio.StringCharBuffer +org.junit.jupiter.engine.descriptor.CallbackSupport$CallbackInvoker +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$476/0x00007faab40ddd50 +org.junit.jupiter.engine.descriptor.CallbackSupport +org.junit.jupiter.engine.descriptor.CallbackSupport$$Lambda$477/0x00007faab40de178 +org.junit.jupiter.engine.extension.TimeoutDuration +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$478/0x00007faab40de5c8 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$479/0x00007faab40de808 +org.junit.jupiter.api.Timeout$ThreadMode +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$480/0x00007faab40dec88 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$481/0x00007faab40deec8 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$482/0x00007faab40df100 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$483/0x00007faab40df358 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$484/0x00007faab40df590 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$485/0x00007faab40df7e0 +org.junit.jupiter.engine.execution.NamespaceAwareStore$$Lambda$486/0x00007faab40dfa28 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$CompositeKey +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$StoredValue +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$487/0x00007faab40e0210 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$MemoizingSupplier +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$488/0x00007faab40e0688 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$489/0x00007faab40e08b0 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$MemoizingSupplier$Failure +org.junit.jupiter.api.io.TempDir +org.junit.platform.commons.util.AnnotationUtils$$Lambda$490/0x00007faab40e1100 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$491/0x00007faab40e1358 +org.junit.jupiter.engine.descriptor.ClassExtensionContext$$Lambda$492/0x00007faab40e1590 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$493/0x00007faab40e17d0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$494/0x00007faab40e1a10 +java.util.stream.Nodes$ArrayNode +java.util.stream.Nodes$FixedNodeBuilder +org.junit.jupiter.api.extension.TemplateInvocationValidationException +org.junit.jupiter.params.ParameterizedDeclarationContext +org.junit.jupiter.engine.descriptor.TestTemplateExtensionContext +org.junit.jupiter.engine.descriptor.TemplateExecutor +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor$TestTemplateExecutor +java.lang.invoke.LambdaForm$DMH/0x00007faab40e4000 +org.junit.jupiter.engine.descriptor.TemplateExecutor$$Lambda$495/0x00007faab40e2a60 +org.junit.jupiter.api.RepeatedTest +org.junit.jupiter.params.ParameterizedTestContext +org.junit.jupiter.params.ResolverFacade +org.junit.jupiter.params.support.ParameterDeclaration +org.junit.jupiter.params.support.ParameterDeclarations +org.junit.jupiter.params.ResolverFacade$ResolvableParameterDeclaration +org.junit.jupiter.params.support.FieldContext +org.junit.jupiter.params.ResolverFacade$FieldParameterDeclaration +org.junit.jupiter.params.ResolverFacade$Resolver +org.junit.jupiter.api.extension.ParameterResolutionException +org.junit.jupiter.params.ResolverFacade$ExecutableParameterDeclaration +org.junit.jupiter.api.extension.ParameterContext +org.junit.jupiter.params.aggregator.ArgumentsAccessor +org.junit.jupiter.params.aggregator.AggregateWith +java.util.TreeMap$Values +java.util.TreeMap$ValueIterator +org.junit.jupiter.params.ResolverFacade$DefaultParameterDeclarations +org.junit.jupiter.engine.execution.NamespaceAwareStore$$Lambda$496/0x00007faab40e6f48 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$497/0x00007faab40e7170 +org.junit.jupiter.engine.descriptor.TemplateExecutor$$Lambda$498/0x00007faab40e7398 +org.junit.jupiter.engine.execution.NamespaceAwareStore$$Lambda$499/0x00007faab40e75c0 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$500/0x00007faab40e77e8 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$PartialFormatter +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$501/0x00007faab40e5000 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$502/0x00007faab40e5228 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$CachingByArgumentsLengthPartialFormatter +java.lang.invoke.LambdaForm$DMH/0x00007faab40e4400 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$503/0x00007faab40e5698 +java.lang.invoke.LambdaForm$DMH/0x00007faab40e4800 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$ArgumentSetNameFormatter +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$PartialFormatters +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$ArgumentsContext +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$PartialFormatter$$Lambda$504/0x00007faab40e4c00 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$505/0x00007faab40e8000 +java.lang.invoke.LambdaForm$DMH/0x00007faab40ec000 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$506/0x00007faab40e8228 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$507/0x00007faab40e8468 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$PlaceholderPosition +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$508/0x00007faab40e88a0 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$509/0x00007faab40e8cc0 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$510/0x00007faab40e8f00 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$511/0x00007faab40e9148 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$512/0x00007faab40e9390 +org.junit.jupiter.params.provider.Arguments +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$513/0x00007faab40e97d8 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$514/0x00007faab40e9a20 +org.junit.jupiter.engine.descriptor.TemplateExecutor$$Lambda$515/0x00007faab40e9c48 +org.junit.jupiter.params.ParameterizedTestSpiInstantiator +org.junit.jupiter.params.ParameterizedTestSpiInstantiator$$Lambda$516/0x00007faab40ea088 +org.junit.jupiter.engine.execution.ParameterResolutionUtils +org.junit.jupiter.engine.execution.ExtensionContextSupplier +org.junit.jupiter.engine.execution.ParameterResolutionUtils$$Lambda$517/0x00007faab40ea6b8 +org.junit.jupiter.params.support.AnnotationConsumerInitializer +org.junit.jupiter.params.support.AnnotationConsumerInitializer$AnnotationConsumingMethodSignature +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$518/0x00007faab40eaf00 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$519/0x00007faab40eb140 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$520/0x00007faab40eb390 +java.lang.invoke.LambdaForm$DMH/0x00007faab40ec400 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$521/0x00007faab40eb5d8 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$522/0x00007faab40eb830 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$523/0x00007faab40eba70 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$524/0x00007faab40ebcb0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$525/0x00007faab40ee000 +java.lang.reflect.Executable$$Lambda$526/0x00007faab407f5c8 +java.lang.reflect.Executable$$Lambda$527/0x00007faab407f808 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$528/0x00007faab40ee220 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$529/0x00007faab40ee470 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$530/0x00007faab40ee690 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$531/0x00007faab40ee8e8 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$532/0x00007faab40eeb08 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$533/0x00007faab40eed60 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$534/0x00007faab40eefa0 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$535/0x00007faab40ef1e0 +com.amazonaws.services.lambda.runtime.tests.EventLoader +com.amazonaws.services.lambda.runtime.tests.EventLoadingException +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers +com.amazonaws.services.lambda.runtime.serialization.util.ReflectUtil$ReflectException +com.amazonaws.services.lambda.runtime.serialization.PojoSerializer +java.util.AbstractMap$SimpleEntry +com.amazonaws.services.lambda.runtime.serialization.events.serializers.OrgJsonSerializer +com.amazonaws.services.lambda.runtime.serialization.events.serializers.S3EventSerializer +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers$$Lambda$536/0x00007faab40ed4a8 +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers$$Lambda$537/0x00007faab40ed6e8 +java.util.stream.Collectors$$Lambda$538/0x00007faab40f0000 +java.util.stream.Collectors$$Lambda$539/0x00007faab40f0220 +java.util.stream.Collectors$$Lambda$540/0x00007faab40f0458 +com.amazonaws.services.lambda.runtime.serialization.events.mixins.CloudFormationCustomResourceEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.CloudFrontEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.CloudWatchLogsEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.CodeCommitEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.CodeCommitEventMixin$RecordMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.ConnectEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.ConnectEventMixin$DetailsMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.ConnectEventMixin$ContactDataMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.ConnectEventMixin$CustomerEndpointMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.ConnectEventMixin$QueueMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.ConnectEventMixin$SystemEndpointMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.DynamodbEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.DynamodbEventMixin$DynamodbStreamRecordMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.DynamodbEventMixin$StreamRecordMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.DynamodbEventMixin$AttributeValueMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.DynamodbTimeWindowEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.KinesisEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.KinesisEventMixin$RecordMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.KinesisTimeWindowEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.ScheduledEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.SecretsManagerRotationEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.SNSEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.SNSEventMixin$SNSRecordMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.SQSEventMixin +com.amazonaws.services.lambda.runtime.serialization.events.mixins.SQSEventMixin$SQSMessageMixin +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers$$Lambda$541/0x00007faab4102a30 +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers$$Lambda$542/0x00007faab4102c70 +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers$NestedClass +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers$AlternateNestedClass +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers$$Lambda$543/0x00007faab41036d0 +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers$$Lambda$544/0x00007faab4103910 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyNamingStrategy +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyNamingStrategy$PropertyNamingStrategyBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyNamingStrategy$UpperCamelCaseStrategy +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyNamingStrategy$PascalCaseStrategy +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyNamingStrategy$SnakeCaseStrategy +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyNamingStrategy$LowerCaseStrategy +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyNamingStrategy$KebabCaseStrategy +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyNamingStrategy$LowerDotCaseStrategy +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers$$Lambda$545/0x00007faab4104cc8 +com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers$$Lambda$546/0x00007faab4104f08 +com.amazonaws.services.lambda.runtime.serialization.factories.PojoSerializerFactory +com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.Versioned +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.Module +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.module.SimpleModule +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.JavaTimeModule +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.Jdk8Module +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.TokenStreamFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.DataOutputAsStream +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.SerializableString +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.TSFBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonFactoryBuilder +java.io.CharArrayReader +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.base.ParserMinimalBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.base.ParserBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.ReaderBasedJsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.UTF8DataInputJsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.async.NonBlockingInputFeeder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.async.ByteArrayFeeder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.async.NonBlockingJsonParserBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.async.NonBlockingUtf8JsonParserBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.async.NonBlockingJsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.async.ByteBufferFeeder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.async.NonBlockingByteBufferJsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.base.GeneratorBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.JsonGeneratorImpl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.UTF8JsonGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.UTF8Writer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.WriterBasedJsonGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.JacksonFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonFactory$Feature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonParser$Feature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonGenerator$Feature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.PrettyPrinter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.Instantiatable +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.DefaultPrettyPrinter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.DefaultPrettyPrinter$Indenter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.SerializedString +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.JsonStringEncoder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.CharTypes +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.FormatFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.JsonReadFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.JsonWriteFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer$TableInfo +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer$Bucket +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer$TableInfo +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.TreeCodec +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.ObjectCodec +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectMapper +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.json.JsonMapper +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.MappingJsonFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.SubtypeResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.DatabindContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.SerializerProvider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.DefaultSerializerProvider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.DefaultSerializerProvider$Impl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.DeserializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BasicDeserializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.DeserializationContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.DefaultDeserializationContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.DefaultDeserializationContext$Impl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.SerializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BasicSerializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BeanSerializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.AnnotationIntrospector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy$Provider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy$Provider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator +java.text.Format +java.text.DateFormat +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.StdDateFormat +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JacksonException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonProcessingException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.DatabindException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonMappingException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.TreeNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonSerializable +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonSerializable$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.BaseJsonNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.ValueNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.NullNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.Module$SetupContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.TokenBuffer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.ClassIntrospector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.BasicClassIntrospector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.VisibilityChecker +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.TreeTraversingParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.SegmentedStringWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.ByteArrayBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.type.ResolvedType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JavaType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.ArrayType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.CollectionLikeType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.CollectionType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.MapLikeType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.MapType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.MismatchedInputException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.Annotated +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.TypeResolutionContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedClass +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedMember +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.VirtualAnnotatedMember +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.Named +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.BeanProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.ConcreteBeanPropertyBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.PropertyWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BeanPropertyWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedWithParams +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedMethod +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonSerialize +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonView +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFormat +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonTypeInfo +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonRawValue +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonUnwrapped +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonBackReference +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonManagedReference +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonDeserialize +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonMerge +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7Support +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.ClassUtil +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.ClassUtil$Ctor +java.beans.Transient +java.beans.ConstructorProperties +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.LookupCache +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.LRUMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$Builder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap +java.io.ObjectStreamException +java.io.InvalidObjectException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.Linked +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.LinkedDeque +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$2 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$3 +java.util.concurrent.atomic.AtomicLongArray +java.lang.invoke.VarHandleLongs$Array +java.util.concurrent.atomic.AtomicReferenceArray +java.lang.invoke.VarHandleReferences$Array +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.BaseSettings +java.util.TimeZone +sun.util.calendar.ZoneInfo +sun.util.calendar.ZoneInfoFile +sun.util.calendar.ZoneInfoFile$1 +java.io.DataInputStream +sun.util.calendar.ZoneInfoFile$ZoneOffsetTransitionRule +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.SimpleType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.ResolvedRecursiveType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.PlaceholderForType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.ReferenceType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeBindings +java.text.SimpleDateFormat +java.util.Calendar +java.util.GregorianCalendar +java.text.ParseException +java.text.AttributedCharacterIterator$Attribute +java.text.Format$Field +java.text.DateFormat$Field +sun.util.calendar.ZoneInfoFile$Checksum +java.util.spi.LocaleServiceProvider +sun.util.spi.CalendarProvider +sun.util.locale.provider.LocaleProviderAdapter +sun.util.locale.provider.LocaleProviderAdapter$Type +sun.util.locale.provider.LocaleProviderAdapter$1 +sun.util.locale.provider.ResourceBundleBasedAdapter +sun.util.locale.provider.JRELocaleProviderAdapter +sun.util.cldr.CLDRLocaleProviderAdapter +sun.util.locale.provider.LocaleDataMetaInfo +sun.util.cldr.CLDRBaseLocaleDataMetaInfo +sun.util.locale.LanguageTag +sun.util.locale.ParseStatus +sun.util.locale.StringTokenIterator +sun.util.locale.InternalLocaleBuilder +sun.util.locale.InternalLocaleBuilder$CaseInsensitiveChar +sun.util.locale.BaseLocale$Key +sun.util.locale.LocaleObjectCache +sun.util.locale.BaseLocale$Cache +sun.util.locale.LocaleObjectCache$CacheEntry +java.util.Locale$Cache +sun.util.cldr.CLDRLocaleProviderAdapter$$Lambda$57/0x80000005e +jdk.internal.module.ModulePatcher$PatchedModuleReader +sun.net.www.protocol.jrt.Handler +sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$59/0x800000060 +sun.util.locale.provider.AvailableLanguageTags +sun.util.locale.provider.CalendarProviderImpl +java.util.Calendar$Builder +sun.util.calendar.CalendarSystem +sun.util.calendar.CalendarSystem$GregorianHolder +sun.util.calendar.AbstractCalendar +sun.util.calendar.BaseCalendar +sun.util.calendar.Gregorian +sun.util.locale.provider.CalendarDataUtility +java.util.Locale$Builder +java.util.spi.CalendarDataProvider +sun.util.locale.provider.LocaleServiceProviderPool +java.text.spi.BreakIteratorProvider +java.text.spi.CollatorProvider +java.text.spi.DateFormatProvider +java.text.spi.DateFormatSymbolsProvider +java.text.spi.DecimalFormatSymbolsProvider +java.text.spi.NumberFormatProvider +java.util.spi.CurrencyNameProvider +java.util.spi.LocaleNameProvider +java.util.spi.TimeZoneNameProvider +sun.util.locale.provider.LocaleServiceProviderPool$LocalizedObjectGetter +sun.util.locale.provider.CalendarDataUtility$CalendarWeekParameterGetter +java.util.ResourceBundle$Control +java.util.ResourceBundle +java.util.ResourceBundle$Control$CandidateListCache +java.util.ResourceBundle$SingleFormatControl +java.util.ResourceBundle$NoFallbackControl +sun.util.cldr.CLDRLocaleProviderAdapter$$Lambda$58/0x80000005f +sun.util.locale.provider.CalendarDataProviderImpl +sun.util.cldr.CLDRCalendarDataProviderImpl +sun.util.locale.provider.LocaleResources +sun.util.resources.LocaleData +sun.util.resources.LocaleData$1 +sun.util.resources.Bundles$Strategy +sun.util.resources.LocaleData$LocaleDataStrategy +sun.util.resources.Bundles +sun.util.resources.Bundles$1 +jdk.internal.access.JavaUtilResourceBundleAccess +java.util.ResourceBundle$1 +java.util.ResourceBundle$2 +sun.util.resources.Bundles$CacheKey +java.util.ListResourceBundle +sun.util.resources.cldr.CalendarData +java.util.ResourceBundle$ResourceBundleProviderHelper +java.util.ResourceBundle$ResourceBundleProviderHelper$$Lambda$11/0x80000000f +sun.util.resources.Bundles$CacheKeyReference +sun.util.resources.Bundles$BundleReference +sun.util.locale.provider.LocaleResources$ResourceReference +sun.util.calendar.CalendarDate +sun.util.calendar.BaseCalendar$Date +sun.util.calendar.Gregorian$Date +sun.util.calendar.CalendarUtils +java.text.DateFormatSymbols +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$61/0x800000062 +sun.util.locale.provider.DateFormatSymbolsProviderImpl +sun.text.resources.cldr.FormatData +sun.text.resources.cldr.FormatData_en +java.text.NumberFormat +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$63/0x800000064 +sun.util.locale.provider.NumberFormatProviderImpl +java.text.DecimalFormatSymbols +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$62/0x800000063 +sun.util.locale.provider.DecimalFormatSymbolsProviderImpl +java.lang.StringLatin1$CharsSpliterator +java.util.stream.IntStream +java.util.stream.IntPipeline +java.util.stream.IntPipeline$Head +java.util.function.IntPredicate +java.text.DecimalFormatSymbols$$Lambda$7/0x80000000b +java.util.stream.IntPipeline$StatelessOp +java.util.stream.IntPipeline$10 +java.util.function.IntConsumer +java.util.stream.Sink$OfInt +java.util.stream.FindOps$FindSink$OfInt +java.util.OptionalInt +java.util.stream.FindOps$FindSink$OfInt$$Lambda$36/0x800000047 +java.util.stream.FindOps$FindSink$OfInt$$Lambda$34/0x800000045 +java.util.stream.FindOps$FindSink$OfInt$$Lambda$35/0x800000046 +java.util.stream.FindOps$FindSink$OfInt$$Lambda$33/0x800000044 +java.util.stream.Sink$ChainedInt +java.util.stream.IntPipeline$10$1 +java.lang.StringUTF16$CharsSpliterator +java.lang.CharacterData00 +java.text.DecimalFormat +java.text.FieldPosition +java.text.DigitList +java.math.RoundingMode +java.util.Date +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.Base64Variants +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.Base64Variant +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.Base64Variant$PaddingReadBehaviour +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy$RecordNaming +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.MapperBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.json.JsonMapper$Builder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.RootNameLookup +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.ClassIntrospector$MixInResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.SimpleMixInResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.MapperConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.MapperConfigBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.DeserializationConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.BeanDescription +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.BasicBeanDescription +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.SerializationConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedClassResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.Annotations +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationCollector$EmptyCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationCollector$NoAnnotations +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedClass$Creators +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedConstructor +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedParameter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConfigOverrides +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JacksonAnnotationValue +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonInclude$Value +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonInclude$Include +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonSetter$Value +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.Nulls +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.VisibilityChecker$Std +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAutoDetect$Visibility +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.CoercionConfigs +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.LogicalType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.CoercionAction +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.CoercionConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.MutableCoercionConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.CoercionInputShape +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.DefaultBaseTypeLimitingValidator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFormat$Value +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFormat$Shape +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFormat$Features +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConfigOverride +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConfigOverride$Empty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConfigFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.MapperFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.DefaultPrettyPrinter$NopIndenter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.DefaultPrettyPrinter$FixedSpaceIndenter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.DefaultIndenter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.Separators +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.SerializationFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.DatatypeFeatures +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.DatatypeFeatures$DefaultHolder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.DatatypeFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.EnumFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.JsonNodeFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ContextAttributes +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ContextAttributes$Impl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.DeserializationFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.JsonNodeCreator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.JsonNodeFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.MissingNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.BooleanNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.NumericNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.DecimalNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.ShortNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.IntNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.LongNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.DoubleNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.FloatNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.BigIntegerNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.TextNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.BinaryNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.POJONode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsonschema.SchemaAware +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NullSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.FailingSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ToEmptyObjectSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.UnknownSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.ContextualSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.InvalidDefinitionException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.InvalidTypeIdException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.ContainerNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.ObjectNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.ResolvableSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.SerializerCache +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.NullValueProvider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.PropertyBindingException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.InvalidFormatException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.ValueInstantiationException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.UnresolvedForwardReference +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ContextualDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiator$Gettable +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StringArrayDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.EnumSetDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.AbstractDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.CollectionDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ArrayBlockingQueueDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StringCollectionDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ResolvableDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.EnumMapDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.MapDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StringDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.MapEntryDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.TokenBufferDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.EnumDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ReferenceTypeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.AtomicReferenceDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.SettableBeanProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.CreatorProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.ErrorThrowingDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.ObjectIdGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.ObjectIdGenerators$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.ObjectIdGenerators$PropertyGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.MethodProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.FieldProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.SetterlessProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyName +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializerModifier +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.AbstractTypeResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiators +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.KeyDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.KeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$DelegatingKD +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$EnumKD +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringCtorKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringFactoryKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.DeserializerCache +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.JsonValueSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ToStringSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdScalarSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.EnumSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.ContainerSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.MapEntrySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.IteratorSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.IterableSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.MapSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StaticListSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.IndexedStringListSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.StringCollectionSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.CollectionSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ArraySerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.StringArraySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.EnumSetSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ReferenceTypeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.SerializableSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.DateTimeSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.CalendarSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.DateSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ByteBufferSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.InetAddressSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.InetSocketAddressSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.TimeZoneSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.BeanSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BeanSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedField +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StringSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$IntegerSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonParser$NumberType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$LongSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$IntLikeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$ShortSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$DoubleSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$FloatSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.BooleanSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.BooleanSerializer$AsNumber +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializer$BigDecimalAsStringSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdJdkSerializers +java.util.Currency +java.util.UUID +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.UUIDSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicBooleanSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicIntegerSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicLongSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.FileSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ClassSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.TokenBufferSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BeanSerializerModifier +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.JSR310DeserializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.JSR310DateTimeDeserializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.DurationDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.MonthDayDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.OffsetTimeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.YearDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.YearMonthDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.JSR310SerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.DurationSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.MonthDaySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.OffsetDateTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.OffsetTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.YearSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.YearMonthSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.ZoneIdSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.key.ZonedDateTimeKeySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.Jsr310KeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.DurationKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.InstantKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.LocalDateTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.LocalDateKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.LocalTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.MonthDayKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.OffsetDateTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.OffsetTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.PeriodKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.YearKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.YearMonthKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.ZonedDateTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.ZoneIdKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.ZoneOffsetKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.PackageVersion +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.VersionUtil +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.Version +java.time.temporal.TemporalAccessor +java.time.temporal.Temporal +java.time.temporal.TemporalAdjuster +java.time.Instant +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.exc.StreamReadException +java.time.DateTimeException +java.util.regex.Pattern$BnM +java.util.regex.Pattern$Pos +java.time.format.DateTimeFormatter +java.time.format.DateTimeFormatterBuilder +java.time.temporal.TemporalQuery +java.time.ZoneId +java.time.format.DateTimeFormatterBuilder$$Lambda$10/0x80000000e +java.time.temporal.TemporalField +java.time.temporal.ChronoField +java.time.temporal.ValueRange +java.time.temporal.IsoFields +java.time.temporal.IsoFields$Field +java.time.temporal.IsoFields$Field$1 +java.time.temporal.IsoFields$Field$2 +java.time.temporal.IsoFields$Field$3 +java.time.temporal.IsoFields$Field$4 +java.time.temporal.IsoFields$Unit +java.time.temporal.JulianFields +java.time.temporal.JulianFields$Field +java.time.format.SignStyle +java.time.format.DateTimeFormatterBuilder$DateTimePrinterParser +java.time.format.DateTimeFormatterBuilder$NumberPrinterParser +java.time.format.DateTimeFormatterBuilder$CharLiteralPrinterParser +java.time.format.ResolverStyle +java.time.chrono.Chronology +java.time.chrono.AbstractChronology +java.time.chrono.IsoChronology +java.time.format.DateTimeFormatterBuilder$CompositePrinterParser +java.time.format.DecimalStyle +java.time.format.DateTimeFormatterBuilder$SettingsParser +java.time.format.DateTimeFormatterBuilder$OffsetIdPrinterParser +java.time.format.DateTimeFormatterBuilder$FractionPrinterParser +java.time.format.DateTimeFormatterBuilder$ZoneIdPrinterParser +java.time.format.DateTimeFormatterBuilder$StringLiteralPrinterParser +java.time.format.DateTimeFormatterBuilder$InstantPrinterParser +java.time.format.TextStyle +java.time.format.DateTimeTextProvider$LocaleStore +java.util.AbstractMap$SimpleImmutableEntry +java.time.format.DateTimeTextProvider +java.time.format.DateTimeTextProvider$1 +java.time.format.DateTimeFormatterBuilder$1 +java.time.format.DateTimeFormatterBuilder$TextPrinterParser +java.time.chrono.ChronoPeriod +java.time.Period +java.time.format.DateTimeFormatter$$Lambda$8/0x80000000c +java.time.format.DateTimeFormatter$$Lambda$9/0x80000000d +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$562/0x00007faab41634e8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$FromIntegerArguments +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$563/0x00007faab4163938 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$FromDecimalArguments +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$564/0x00007faab4163d88 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$565/0x00007faab4163fc8 +java.time.OffsetDateTime +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$566/0x00007faab41641f8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$567/0x00007faab4164438 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$568/0x00007faab4164678 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$569/0x00007faab41648b8 +java.time.chrono.ChronoZonedDateTime +java.time.ZonedDateTime +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$570/0x00007faab4164ae8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$571/0x00007faab4164d28 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$572/0x00007faab4164f68 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$573/0x00007faab41651a8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.module.SimpleDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.ClassKey +java.time.chrono.ChronoLocalDateTime +java.time.LocalDateTime +java.time.chrono.ChronoLocalDate +java.time.LocalDate +java.time.LocalTime +java.time.MonthDay +java.time.OffsetTime +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.JSR310StringParsableDeserializer +java.time.ZoneOffset +java.time.Year +java.time.YearMonth +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.module.SimpleSerializers +java.util.function.ToLongFunction +java.lang.invoke.LambdaForm$DMH/0x00007faab4168000 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer$$Lambda$574/0x00007faab41665f8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer$$Lambda$575/0x00007faab4166818 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer$$Lambda$576/0x00007faab4166a38 +java.lang.invoke.LambdaForm$DMH/0x00007faab4168400 +java.lang.invoke.LambdaForm$DMH/0x00007faab4168800 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.OffsetDateTimeSerializer$$Lambda$577/0x00007faab4166c58 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.OffsetDateTimeSerializer$$Lambda$578/0x00007faab4166e78 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.OffsetDateTimeSerializer$$Lambda$579/0x00007faab4167098 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer$$Lambda$580/0x00007faab41672b8 +java.lang.invoke.LambdaForm$DMH/0x00007faab4168c00 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer$$Lambda$581/0x00007faab41674d8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer$$Lambda$582/0x00007faab41676f8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.module.SimpleKeyDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectMapper$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.ArrayBuilders +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiators$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.JavaTimeModule$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeModifier +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.Jdk8TypeModifier +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.Jdk8BeanSerializerModifier +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.PackageVersion +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.Jdk8Serializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalIntSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalLongSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalDoubleSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.LongStreamSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.IntStreamSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.DoubleStreamSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.StreamSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.Jdk8Deserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.BaseScalarOptionalDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalIntDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalLongDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalDoubleDeserializer +com.amazonaws.services.lambda.runtime.serialization.util.SerializeUtil +com.amazonaws.services.lambda.runtime.serialization.util.ReflectUtil +java.lang.ExceptionInInitializerError +java.lang.InstantiationException +com.amazonaws.services.lambda.runtime.serialization.util.Functions$R0 +com.amazonaws.services.lambda.runtime.serialization.util.Functions$R1 +com.amazonaws.services.lambda.runtime.serialization.util.Functions$R9 +com.amazonaws.services.lambda.runtime.serialization.util.Functions$R4 +com.amazonaws.services.lambda.runtime.serialization.util.Functions$R3 +com.amazonaws.services.lambda.runtime.serialization.util.Functions$R5 +com.amazonaws.services.lambda.runtime.serialization.util.Functions$R2 +java.lang.ClassFormatError +com.amazonaws.services.lambda.runtime.serialization.util.Functions$V2 +com.amazonaws.services.lambda.runtime.serialization.util.Functions$V1 +com.amazonaws.services.lambda.runtime.events.models.kinesis.Record +com.amazonaws.services.lambda.runtime.events.KinesisEvent$Record +com.amazonaws.services.lambda.runtime.serialization.events.modules.DateModule +com.amazonaws.services.lambda.runtime.serialization.events.modules.DateModule$Serializer +com.amazonaws.services.lambda.runtime.serialization.events.modules.DateModule$Deserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.PackageVersion +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.JodaModule +com.amazonaws.services.lambda.runtime.serialization.events.modules.DateTimeModule +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.JodaDeserializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.DateTimeZoneDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.DurationDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.JodaDateDeserializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.InstantDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.LocalDateTimeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.LocalDateDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.LocalTimeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.PeriodDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.IntervalDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.MonthDayDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.YearMonthDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.JodaSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.JodaDateSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.DateTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.DateTimeZoneSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.DurationSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.InstantSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.LocalDateTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.LocalDateSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.LocalTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.PeriodSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.IntervalSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.MonthDaySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.YearMonthSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.key.JodaKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.key.DateTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.key.LocalTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.key.LocalDateKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.key.LocalDateTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.key.DurationKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.key.PeriodKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.DateMidnightDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.ser.DateMidnightSerializer +com.amazonaws.services.lambda.runtime.serialization.events.modules.DateTimeModule$1 +com.amazonaws.services.lambda.runtime.serialization.events.modules.DateTimeModule$2 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.PackageVersion +com.amazonaws.lambda.thirdparty.org.joda.time.ReadableInstant +com.amazonaws.lambda.thirdparty.org.joda.time.ReadableDateTime +com.amazonaws.lambda.thirdparty.org.joda.time.base.AbstractInstant +com.amazonaws.lambda.thirdparty.org.joda.time.base.AbstractDateTime +com.amazonaws.lambda.thirdparty.org.joda.time.base.BaseDateTime +com.amazonaws.lambda.thirdparty.org.joda.time.DateTime +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.cfg.FormatConfig +com.amazonaws.lambda.thirdparty.org.joda.time.DateTimeZone +com.amazonaws.lambda.thirdparty.org.joda.time.IllegalInstantException +com.amazonaws.lambda.thirdparty.org.joda.time.JodaTimePermission +com.amazonaws.lambda.thirdparty.org.joda.time.tz.NameProvider +com.amazonaws.lambda.thirdparty.org.joda.time.tz.FixedDateTimeZone +com.amazonaws.lambda.thirdparty.org.joda.time.tz.Provider +com.amazonaws.lambda.thirdparty.org.joda.time.UTCDateTimeZone +java.util.SimpleTimeZone +com.amazonaws.lambda.thirdparty.org.joda.time.tz.ZoneInfoProvider +java.lang.ArrayIndexOutOfBoundsException +com.amazonaws.lambda.thirdparty.org.joda.time.tz.ZoneInfoProvider$1 +java.util.Collections$UnmodifiableSortedSet +com.amazonaws.lambda.thirdparty.org.joda.time.tz.DateTimeZoneBuilder +com.amazonaws.lambda.thirdparty.org.joda.time.tz.DateTimeZoneBuilder$PrecalculatedZone +com.amazonaws.lambda.thirdparty.org.joda.time.tz.CachedDateTimeZone +com.amazonaws.lambda.thirdparty.org.joda.time.tz.DateTimeZoneBuilder$DSTZone +com.amazonaws.lambda.thirdparty.org.joda.time.Chronology +com.amazonaws.lambda.thirdparty.org.joda.time.chrono.BaseChronology +com.amazonaws.lambda.thirdparty.org.joda.time.chrono.AssembledChronology +com.amazonaws.lambda.thirdparty.org.joda.time.chrono.ISOChronology +com.amazonaws.lambda.thirdparty.org.joda.time.tz.CachedDateTimeZone$Info +com.amazonaws.lambda.thirdparty.org.joda.time.format.ISODateTimeFormat +com.amazonaws.lambda.thirdparty.org.joda.time.format.ISODateTimeFormat$Constants +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder +com.amazonaws.lambda.thirdparty.org.joda.time.format.InternalPrinter +com.amazonaws.lambda.thirdparty.org.joda.time.format.InternalParser +com.amazonaws.lambda.thirdparty.org.joda.time.DateTimeFieldType +com.amazonaws.lambda.thirdparty.org.joda.time.DateTimeFieldType$StandardDateTimeFieldType +com.amazonaws.lambda.thirdparty.org.joda.time.DurationFieldType +com.amazonaws.lambda.thirdparty.org.joda.time.DurationFieldType$StandardDurationFieldType +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder$NumberFormatter +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder$PaddedNumber +com.amazonaws.lambda.thirdparty.org.joda.time.DateTimeField +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder$Composite +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatter +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder$CharacterLiteral +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder$StringLiteral +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder$UnpaddedNumber +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder$Fraction +com.amazonaws.lambda.thirdparty.org.joda.time.field.BaseDateTimeField +com.amazonaws.lambda.thirdparty.org.joda.time.field.PreciseDurationDateTimeField +com.amazonaws.lambda.thirdparty.org.joda.time.field.PreciseDateTimeField +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder$TimeZoneOffset +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder$FixedNumber +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeParser +com.amazonaws.lambda.thirdparty.org.joda.time.format.InternalParserDateTimeParser +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeParserInternalParser +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimeFormatterBuilder$MatchingParser +com.amazonaws.lambda.thirdparty.org.joda.time.format.DateTimePrinterInternalPrinter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.cfg.JacksonJodaFormatBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.cfg.JacksonJodaDateFormat +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.joda.cfg.JacksonJodaPeriodFormat +com.amazonaws.lambda.thirdparty.org.joda.time.format.ISOPeriodFormat +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodFormatterBuilder +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodPrinter +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodParser +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodFormatterBuilder$PeriodFieldAffix +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodFormatterBuilder$FieldFormatter +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodFormatterBuilder$Literal +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodFormatterBuilder$IgnorableAffix +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodFormatterBuilder$SimpleAffix +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodFormatterBuilder$Separator +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodFormatterBuilder$Composite +com.amazonaws.lambda.thirdparty.org.joda.time.format.PeriodFormatter +com.amazonaws.lambda.thirdparty.org.joda.time.ReadablePeriod +com.amazonaws.lambda.thirdparty.org.joda.time.ReadWritablePeriod +com.amazonaws.lambda.thirdparty.org.joda.time.ReadableDuration +com.amazonaws.lambda.thirdparty.org.joda.time.base.AbstractDuration +com.amazonaws.lambda.thirdparty.org.joda.time.base.BaseDuration +com.amazonaws.lambda.thirdparty.org.joda.time.Duration +com.amazonaws.lambda.thirdparty.org.joda.time.Instant +com.amazonaws.lambda.thirdparty.org.joda.time.ReadablePartial +com.amazonaws.lambda.thirdparty.org.joda.time.base.AbstractPartial +com.amazonaws.lambda.thirdparty.org.joda.time.base.BaseLocal +com.amazonaws.lambda.thirdparty.org.joda.time.LocalDateTime +com.amazonaws.lambda.thirdparty.org.joda.time.LocalDate +com.amazonaws.lambda.thirdparty.org.joda.time.LocalTime +com.amazonaws.lambda.thirdparty.org.joda.time.base.AbstractPeriod +com.amazonaws.lambda.thirdparty.org.joda.time.base.BasePeriod +com.amazonaws.lambda.thirdparty.org.joda.time.Period +com.amazonaws.lambda.thirdparty.org.joda.time.ReadableInterval +com.amazonaws.lambda.thirdparty.org.joda.time.base.AbstractInterval +com.amazonaws.lambda.thirdparty.org.joda.time.base.BaseInterval +com.amazonaws.lambda.thirdparty.org.joda.time.Interval +com.amazonaws.lambda.thirdparty.org.joda.time.base.BasePartial +com.amazonaws.lambda.thirdparty.org.joda.time.MonthDay +com.amazonaws.lambda.thirdparty.org.joda.time.YearMonth +com.amazonaws.lambda.thirdparty.org.joda.time.DateMidnight +org.joda.time.ReadableInstant +org.joda.time.ReadableDateTime +org.joda.time.base.AbstractInstant +org.joda.time.base.AbstractDateTime +org.joda.time.base.BaseDateTime +org.joda.time.DateTime +org.joda.time.Chronology +org.joda.time.chrono.BaseChronology +org.joda.time.chrono.AssembledChronology +org.joda.time.chrono.ISOChronology +com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory$InternalSerializer +com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory$ClassSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.ClassStack +sun.reflect.generics.repository.AbstractRepository +sun.reflect.generics.repository.GenericDeclRepository +sun.reflect.generics.repository.ClassRepository +java.lang.reflect.TypeVariable +sun.reflect.generics.tree.FormalTypeParameter +sun.reflect.generics.tree.Signature +sun.reflect.generics.tree.ClassSignature +java.util.OptionalLong +java.util.OptionalDouble +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$WeightedValue +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$Node +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$AddTask +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectReader +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.filter.TokenFilter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.filter.JsonPointerBasedFilter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.ArrayNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.JsonParserDelegate +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.filter.FilteringParserDelegate +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonParseException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationCollector$OneCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAutoDetect +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIdentityInfo +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.ArrayIterator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.OptionalHandlerFactory +org.w3c.dom.Node +org.w3c.dom.Document +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7Handlers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.NioPathSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.NioPathDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.JdkDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.FromStringDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.UUIDDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.AtomicBooleanDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.AtomicIntegerDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.AtomicLongDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ByteBufferDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NullifyingDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$StringBuilderDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$StringBufferDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$Std +java.net.InetAddress +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.impl.SubTypeValidator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.BeanUtil +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonValueInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiator$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.JsonLocationInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$ArrayListInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$ConstantValueInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$LinkedHashMapInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$HashMapInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonLocation +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConstructorDetector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConstructorDetector$SingleArgConstructor +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.CreatorCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdValueInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.CollectorBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.TypeResolutionContext$Basic +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector$FieldBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonKey +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonValue +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAnyGetter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAnySetter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.InternCache +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonSetter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAutoDetect$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.PropertyAccessor +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIgnore +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$WithMember +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.AnnotationIntrospector$ReferenceProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.AnnotationIntrospector$ReferenceProperty$Type +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$Linked +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedMethodCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.MemberKey +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonProperty$Access +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JacksonAnnotation +jdk.proxy2.$Proxy16 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedMethodCollector$MethodBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationCollector$NCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JacksonAnnotationsInside +jdk.proxy2.$Proxy17 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedMethodMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonGetter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$5 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$6 +java.util.LinkedList$ListItr +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JacksonInject +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonNaming +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonPropertyOrder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonPropertyDescription +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyMetadata +sun.reflect.generics.scope.MethodScope +sun.reflect.generics.repository.ConstructorRepository +sun.reflect.generics.repository.MethodRepository +sun.reflect.generics.tree.VoidDescriptor +sun.reflect.generics.tree.MethodTypeSignature +com.amazonaws.services.lambda.runtime.events.KinesisEvent$KinesisEventRecord +java.lang.reflect.ParameterizedType +sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl +sun.reflect.generics.tree.TypeVariableSignature +sun.reflect.generics.reflectiveObjects.LazyReflectiveObjectGenerator +sun.reflect.generics.reflectiveObjects.TypeVariableImpl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeBindings$TypeParamStash +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeBindings$AsKey +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BasicDeserializerFactory$CreatorCollectionState +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.ObjectIdValueProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIgnoreProperties +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIgnoreProperties$Value +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIncludeProperties +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIncludeProperties$Value +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.IgnorePropertiesUtil +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIgnoreType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonTypeResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.FailingDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.AccessPattern +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$2 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$4 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAlias +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFormat$Feature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.IgnoredPropertyException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.SettableBeanProperty$Delegating +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.ManagedReferenceProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.ObjectIdReferenceProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.MergingSettableBeanProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.InnerClassProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.ReadableObjectId$Referring +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializer$BeanReferring +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.BeanAsArrayDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BasicDeserializerFactory$ContainerDefaultMappings +java.util.concurrent.ConcurrentNavigableMap +java.util.concurrent.ConcurrentSkipListMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.LinkedNode +com.amazonaws.services.lambda.runtime.events.models.kinesis.EncryptionType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$PrimitiveOrWrapperDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BooleanDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$LongDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$DoubleDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$CharacterDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$ByteDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$ShortDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$FloatDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$NumberDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BigDecimalDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BigIntegerDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.DateDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.DateDeserializers$DateBasedDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.DateDeserializers$CalendarDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.DateDeserializers$DateDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.ByteBufferBackedOutputStream +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.MinimalPrettyPrinter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectWriter$GeneratorSettings +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectWriter$Prefetch +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.RuntimeJsonMappingException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.ContentReference +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.IOContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.BufferRecyclers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.BufferRecycler +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.UTF8StreamJsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.MergedStream +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.UTF32Reader +java.io.CharConversionException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonEncoding +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.exc.InputCoercionException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.JsonEOFException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonStreamContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.JsonReadContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.StreamReadCapability +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.JacksonFeatureSet +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.TextBuffer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonToken +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.NumberInput +org.junit.jupiter.params.provider.Arguments$$Lambda$583/0x00007faab41aefd8 +org.junit.jupiter.params.ParameterizedInvocationContext +org.junit.jupiter.params.ParameterizedTestInvocationContext +java.util.function.IntUnaryOperator +java.lang.invoke.LambdaForm$DMH/0x00007faab41b0000 +org.junit.jupiter.params.ParameterizedInvocationContext$$Lambda$584/0x00007faab41af670 +org.junit.jupiter.params.EvaluatedArgumentSet +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$585/0x00007faab41afb00 +java.lang.invoke.LambdaForm$DMH/0x00007faab41b0400 +org.junit.jupiter.params.provider.Arguments$ArgumentSet +org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor +org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor$$Lambda$586/0x00007faab41b45b0 +org.junit.jupiter.api.Named +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$587/0x00007faab41b49d0 +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$588/0x00007faab41b4c10 +java.util.stream.ReferencePipeline$$Lambda$589/0x00007faab40fc2b8 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$MessageFormatPartialFormatter +java.util.stream.Streams$RangeIntSpliterator +java.lang.invoke.LambdaForm$DMH/0x00007faab41b0800 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$590/0x00007faab41b5088 +java.util.stream.IntPipeline$1 +java.util.stream.IntPipeline$1$1 +org.junit.jupiter.params.ResolverFacade$$Lambda$591/0x00007faab41b52b0 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$592/0x00007faab41b54f0 +java.text.MessageFormat +sun.util.locale.provider.TimeZoneNameUtility +sun.util.locale.provider.TimeZoneNameUtility$TimeZoneNameGetter +sun.util.cldr.CLDRLocaleProviderAdapter$$Lambda$593/0x00007faab40fded0 +sun.util.locale.provider.TimeZoneNameProviderImpl +sun.util.cldr.CLDRTimeZoneNameProviderImpl +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$594/0x00007faab40fe578 +sun.util.locale.provider.BaseLocaleDataMetaInfo +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$595/0x00007faab40fe9f8 +sun.util.resources.provider.NonBaseLocaleDataMetaInfo +sun.util.resources.OpenListResourceBundle +sun.util.resources.TimeZoneNamesBundle +sun.util.resources.cldr.TimeZoneNames +sun.util.resources.cldr.TimeZoneNames_en +sun.util.cldr.CLDRBaseLocaleDataMetaInfo$TZCanonicalIDMapHolder +java.time.ZoneRegion +java.time.zone.ZoneRulesProvider +java.time.zone.ZoneRulesProvider$1 +java.time.zone.TzdbZoneRulesProvider +java.time.zone.Ser +java.time.zone.ZoneRules +java.time.zone.ZoneOffsetTransitionRule +java.time.zone.ZoneOffsetTransition +sun.util.resources.TimeZoneNames +sun.util.resources.TimeZoneNames_en +java.text.MessageFormat$Field +org.junit.jupiter.engine.descriptor.TemplateExecutor$$Lambda$596/0x00007faab41b5730 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$597/0x00007faab41b5968 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$598/0x00007faab41b5ba0 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$599/0x00007faab41b5dc8 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$600/0x00007faab41b6000 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor$$Lambda$601/0x00007faab41b6228 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DynamicTaskState +org.junit.platform.engine.support.hierarchical.NodeTestTask$DynamicTaskState$$Lambda$602/0x00007faab41b6650 +org.junit.jupiter.params.ParameterizedInvocationParameterResolver +org.junit.jupiter.params.ParameterizedTestMethodParameterResolver +org.junit.jupiter.params.ResolutionCache +org.junit.jupiter.params.ResolutionCache$$Lambda$603/0x00007faab41b6f10 +org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor$$Lambda$604/0x00007faab41b7130 +org.junit.jupiter.engine.descriptor.MethodExtensionContext +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$605/0x00007faab41b7848 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$606/0x00007faab41b7a70 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$607/0x00007faab41b7c98 +org.junit.jupiter.engine.execution.ExtensionContextSupplier$ScopeBasedExtensionContextSupplier +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$608/0x00007faab41b2428 +org.junit.jupiter.engine.descriptor.DefaultTestInstanceFactoryContext +org.junit.jupiter.api.extension.TestInstancePreConstructCallback +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$609/0x00007faab41b2aa8 +java.lang.invoke.LambdaForm$DMH/0x00007faab41b0c00 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$610/0x00007faab41b2ce0 +org.junit.jupiter.engine.execution.ConstructorInvocation +org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptorCall +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$$Lambda$611/0x00007faab41b3398 +org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation +org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation +org.aspectj.lang.NoAspectBoundException +software.amazon.lambda.powertools.validation.ValidationException +org.slf4j.LoggerFactory +org.slf4j.spi.SLF4JServiceProvider +java.util.ServiceConfigurationError +org.slf4j.event.LoggingEvent +org.slf4j.helpers.SubstituteServiceProvider +org.slf4j.IMarkerFactory +org.slf4j.spi.MDCAdapter +org.slf4j.ILoggerFactory +org.slf4j.helpers.SubstituteLoggerFactory +org.slf4j.Logger +java.util.concurrent.LinkedBlockingQueue +java.util.concurrent.LinkedBlockingQueue$Node +org.slf4j.helpers.BasicMarkerFactory +org.slf4j.Marker +org.slf4j.helpers.BasicMDCAdapter +java.lang.InheritableThreadLocal +org.slf4j.helpers.BasicMDCAdapter$1 +org.slf4j.helpers.ThreadLocalMapOfStacks +org.slf4j.helpers.NOP_FallbackServiceProvider +org.slf4j.helpers.NOPLoggerFactory +org.slf4j.helpers.NOPMDCAdapter +org.slf4j.helpers.Util +org.slf4j.simple.SimpleServiceProvider +org.slf4j.MDC +org.slf4j.simple.SimpleLoggerFactory +org.slf4j.helpers.AbstractLogger +org.slf4j.helpers.LegacyAbstractLogger +org.slf4j.simple.SimpleLogger +org.slf4j.spi.LoggingEventBuilder +org.slf4j.simple.SimpleLoggerConfiguration +org.slf4j.simple.SimpleLoggerConfiguration$$Lambda$612/0x00007faab41bb830 +org.slf4j.simple.OutputChoice +org.slf4j.simple.OutputChoice$OutputChoiceType +org.slf4j.helpers.Reporter +org.slf4j.helpers.Reporter$TargetChoice +org.slf4j.helpers.Reporter$Level +org.slf4j.simple.SimpleLoggerFactory$$Lambda$613/0x00007faab41bcb30 +org.junit.jupiter.engine.execution.DefaultTestInstances +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$614/0x00007faab41bcfd8 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$615/0x00007faab41bd220 +org.junit.jupiter.api.extension.TestInstancePostProcessor +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$616/0x00007faab41bd648 +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$617/0x00007faab41bd880 +org.junit.jupiter.params.ParameterizedInvocationContext$$Lambda$618/0x00007faab41bdac0 +org.junit.jupiter.params.ParameterizedInvocationContext$$Lambda$619/0x00007faab41bdd18 +org.junit.jupiter.api.extension.ExtensionContext$Store$CloseableResource +org.junit.jupiter.params.ParameterizedInvocationContext$CloseableArgument +org.junit.jupiter.params.ParameterizedInvocationContext$$Lambda$620/0x00007faab41be3a8 +org.junit.jupiter.params.ParameterizedInvocationContext$$Lambda$621/0x00007faab41be5e8 +org.junit.jupiter.params.ArgumentCountValidator +org.junit.jupiter.params.ArgumentCountValidator$$Lambda$622/0x00007faab41bea38 +org.junit.jupiter.params.ArgumentCountValidator$1 +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$623/0x00007faab41bee88 +org.junit.jupiter.params.aggregator.DefaultArgumentsAccessor +org.junit.jupiter.params.aggregator.ArgumentAccessException +org.junit.jupiter.params.aggregator.DefaultArgumentsAccessor$$Lambda$624/0x00007faab41bf638 +org.junit.jupiter.params.aggregator.DefaultArgumentsAccessor$$Lambda$625/0x00007faab41bf870 +org.junit.jupiter.params.support.ParameterInfo +org.junit.jupiter.params.DefaultParameterInfo +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$626/0x00007faab4200000 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$627/0x00007faab4200248 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$628/0x00007faab4200498 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$629/0x00007faab42006e0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$630/0x00007faab4200928 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$631/0x00007faab4200b68 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$632/0x00007faab4200db8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$633/0x00007faab4200ff8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$634/0x00007faab4201250 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$635/0x00007faab42014a0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$636/0x00007faab42016e0 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$637/0x00007faab4201930 +org.junit.jupiter.engine.extension.TempDirectory$FailureTracker +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$638/0x00007faab4201d98 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$639/0x00007faab4201fd0 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$640/0x00007faab4202220 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$641/0x00007faab4202448 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$642/0x00007faab4202668 +org.junit.jupiter.engine.execution.MethodInvocation +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$$Lambda$643/0x00007faab4202b28 +org.junit.jupiter.engine.extension.TimeoutExtension$TimeoutProvider +org.junit.jupiter.engine.extension.TimeoutConfiguration +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$644/0x00007faab42031a0 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$645/0x00007faab42033f8 +org.junit.jupiter.engine.extension.TimeoutDurationParser +java.time.format.DateTimeParseException +java.util.regex.Pattern$$Lambda$646/0x00007faab41c2be0 +java.util.regex.Pattern$$Lambda$647/0x00007faab41c2e40 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$648/0x00007faab4203850 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$649/0x00007faab4203a78 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$650/0x00007faab4203cc0 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$651/0x00007faab4203f08 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$652/0x00007faab4204130 +org.mockito.MockitoAnnotations +org.mockito.configuration.IMockitoConfiguration +org.mockito.internal.configuration.GlobalConfiguration +org.mockito.configuration.DefaultMockitoConfiguration +org.mockito.internal.configuration.ClassPathLoader +org.mockito.exceptions.misusing.MockitoConfigurationException +org.mockito.internal.configuration.plugins.Plugins +org.mockito.plugins.MockitoPlugins +org.mockito.internal.configuration.plugins.PluginRegistry +org.mockito.plugins.PluginSwitch +org.mockito.internal.configuration.plugins.PluginLoader +org.mockito.internal.configuration.plugins.DefaultPluginSwitch +org.mockito.internal.configuration.plugins.DefaultMockitoPlugins +org.mockito.plugins.MockMaker +org.mockito.plugins.StackTraceCleanerProvider +org.mockito.plugins.InstantiatorProvider2 +org.mockito.plugins.AnnotationEngine +org.mockito.plugins.MockitoLogger +org.mockito.plugins.MemberAccessor +org.mockito.plugins.DoNotMockEnforcerWithType +org.mockito.internal.configuration.plugins.PluginInitializer +java.lang.invoke.LambdaForm$MH/0x00007faab4208000 +org.mockito.internal.configuration.plugins.PluginFinder +org.mockito.internal.util.collections.Iterables +org.mockito.internal.creation.bytebuddy.ClassCreatingMockMaker +org.mockito.plugins.InlineMockMaker +org.mockito.creation.instance.Instantiator +org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker +org.mockito.exceptions.base.MockitoInitializationException +org.mockito.internal.creation.bytebuddy.BytecodeGenerator +org.mockito.creation.instance.InstantiationException +org.mockito.plugins.MockMaker$TypeMockability +org.mockito.plugins.MockMaker$StaticMockControl +org.mockito.plugins.MockMaker$ConstructionMockControl +org.mockito.internal.PremainAttachAccess +org.mockito.internal.PremainAttach +java.lang.instrument.Instrumentation +net.bytebuddy.agent.Installer +java.io.Console +java.lang.Deprecated +jdk.proxy1.$Proxy18 +net.bytebuddy.ClassFileVersion +net.bytebuddy.ClassFileVersion$VersionLocator$Resolver +net.bytebuddy.ClassFileVersion$VersionLocator +net.bytebuddy.ClassFileVersion$VersionLocator$Resolved +java.lang.Process +net.bytebuddy.agent.ByteBuddyAgent +net.bytebuddy.agent.ByteBuddyAgent$AgentProvider +net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider +net.bytebuddy.agent.ByteBuddyAgent$AttachmentTypeEvaluator$InstallationAction +net.bytebuddy.agent.ByteBuddyAgent$AttachmentTypeEvaluator +java.security.PrivilegedActionException +com.sun.proxy.jdk.proxy1.$Proxy19 +java.security.DomainCombiner +net.bytebuddy.agent.ByteBuddyAgent$AttachmentTypeEvaluator$ForJava9CapableVm +java.lang.ProcessHandle +java.lang.ProcessHandle$Info +java.util.concurrent.CompletionStage +java.util.concurrent.CompletableFuture +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Compound +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Accessor +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$ForModularizedVm +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$ForJ9Vm +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$ForStandardToolsJarVm +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$ForUserDefinedToolsJar +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$ForEmulatedAttachment +net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider$ForCurrentVm +net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider$ForCurrentVm$ForJava9CapableVm +java.lang.reflect.AnnotatedType +java.lang.ProcessHandleImpl +java.lang.ProcessHandleImpl$$Lambda$653/0x00007faab41c5a00 +java.util.concurrent.ThreadLocalRandom +jdk.internal.util.random.RandomSupport +java.lang.invoke.LambdaForm$DMH/0x00007faab4208400 +java.lang.invoke.LambdaForm$DMH/0x00007faab4208800 +java.lang.ProcessHandleImpl$$Lambda$654/0x00007faab41c5c20 +java.lang.invoke.LambdaForm$DMH/0x00007faab4208c00 +java.lang.invoke.LambdaForm$MH/0x00007faab4209000 +java.util.concurrent.SynchronousQueue +java.util.concurrent.SynchronousQueue$Transferer +java.util.concurrent.SynchronousQueue$TransferStack +java.util.concurrent.SynchronousQueue$TransferStack$SNode +net.bytebuddy.agent.ByteBuddyAgent$AgentProvider$ForByteBuddyAgent +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Accessor$Simple +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Accessor$Simple$WithExternalAttachment +com.sun.tools.attach.VirtualMachine +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Accessor$ExternalAttachment +java.util.zip.ZipInputStream +java.util.jar.JarInputStream +java.io.PushbackInputStream +sun.security.util.ManifestEntryVerifier +net.bytebuddy.agent.Attacher +java.lang.ProcessBuilder +java.lang.ProcessImpl +java.lang.ProcessImpl$Platform +java.lang.ProcessImpl$LaunchMechanism +java.lang.ProcessImpl$Platform$$Lambda$655/0x00007faab41c83f0 +java.lang.ProcessImpl$$Lambda$656/0x00007faab41c8618 +java.lang.invoke.LambdaForm$DMH/0x00007faab4210000 +java.lang.invoke.LambdaForm$DMH/0x00007faab4210400 +java.lang.invoke.LambdaForm$MH/0x00007faab4210800 +java.lang.ProcessImpl$1 +java.lang.ProcessImpl$ProcessPipeOutputStream +java.lang.ProcessImpl$ProcessPipeInputStream +java.lang.Process$PipeInputStream +java.lang.ProcessHandleImpl$ExitCompletion +java.util.concurrent.CompletableFuture$AltResult +java.util.concurrent.ForkJoinPool +java.lang.invoke.VarHandleLongs$FieldInstanceReadOnly +java.lang.invoke.VarHandleLongs$FieldInstanceReadWrite +java.lang.invoke.VarHandleInts$FieldStaticReadOnly +java.lang.invoke.VarHandleInts$FieldStaticReadWrite +java.util.concurrent.ForkJoinPool$ForkJoinWorkerThreadFactory +java.util.concurrent.ForkJoinPool$DefaultForkJoinWorkerThreadFactory +java.util.concurrent.ForkJoinPool$1 +java.util.concurrent.ForkJoinPool$DefaultCommonPoolForkJoinWorkerThreadFactory +java.util.concurrent.ForkJoinPool$WorkQueue +java.util.concurrent.CompletableFuture$AsynchronousCompletionTask +java.util.concurrent.ForkJoinTask +java.util.concurrent.CompletableFuture$Completion +java.lang.ProcessHandleImpl$1 +java.lang.ProcessImpl$$Lambda$657/0x00007faab41ca448 +java.util.concurrent.CompletableFuture$UniCompletion +java.util.concurrent.CompletableFuture$UniHandle +java.util.concurrent.ForkJoinTask$Aux +jdk.internal.event.Event +jdk.internal.event.ProcessStartEvent +sun.instrument.InstrumentationImpl +sun.instrument.TransformerManager +sun.instrument.TransformerManager$TransformerInfo +java.lang.ProcessBuilder$NullInputStream +java.io.FileOutputStream$1 +java.lang.ProcessBuilder$NullOutputStream +java.io.File$TempDirectory +java.security.SecureRandom +sun.security.jca.Providers +sun.security.jca.ProviderList +sun.security.jca.ProviderConfig +java.security.Provider +sun.security.jca.ProviderList$3 +sun.security.jca.ProviderList$1 +java.security.Provider$ServiceKey +java.security.Provider$EngineDescription +java.security.SecureRandomParameters +java.security.cert.CertStoreParameters +java.security.Policy$Parameters +javax.security.auth.login.Configuration$Parameters +sun.security.jca.ProviderList$2 +sun.security.provider.Sun +sun.security.util.SecurityConstants +java.net.NetPermission +java.security.SecurityPermission +java.net.SocketPermission +sun.security.provider.SunEntries +sun.security.provider.SunEntries$1 +java.security.SecureRandomSpi +sun.security.provider.NativePRNG +sun.security.provider.NativePRNG$Variant +sun.security.provider.NativePRNG$1 +sun.security.provider.NativePRNG$2 +sun.security.provider.NativePRNG$RandomIO +sun.security.provider.FileInputStreamPool +sun.security.provider.FileInputStreamPool$UnclosableInputStream +sun.security.provider.FileInputStreamPool$StreamRef +java.security.Provider$Service +java.security.Provider$UString +sun.security.provider.NativePRNG$Blocking +sun.security.provider.NativePRNG$NonBlocking +sun.security.util.SecurityProviderConstants +sun.security.util.KnownOIDs +sun.security.util.KnownOIDs$1 +sun.security.util.KnownOIDs$2 +sun.security.util.KnownOIDs$3 +sun.security.util.KnownOIDs$4 +sun.security.util.KnownOIDs$5 +sun.security.util.KnownOIDs$6 +sun.security.util.KnownOIDs$7 +sun.security.util.KnownOIDs$8 +sun.security.util.KnownOIDs$9 +sun.security.util.KnownOIDs$10 +jdk.internal.event.SecurityProviderServiceEvent +sun.security.provider.SecureRandom +java.security.MessageDigestSpi +java.security.MessageDigest +sun.security.jca.GetInstance +sun.security.provider.DigestBase +sun.security.provider.SHA +sun.security.jca.GetInstance$Instance +sun.security.util.MessageDigestSpi2 +java.security.MessageDigest$Delegate +java.security.MessageDigest$Delegate$CloneableDelegate +sun.security.provider.ByteArrayAccess +sun.security.provider.ByteArrayAccess$BE +java.lang.invoke.VarHandleByteArrayAsInts$ByteArrayViewVarHandle +java.lang.invoke.VarHandleByteArrayAsInts$ArrayHandle +java.lang.invoke.VarHandleByteArrayBase +java.lang.invoke.VarHandleByteArrayAsInts +java.lang.invoke.VarHandleByteArrayAsInts$ArrayHandle$$Lambda$658/0x00007faab41d7338 +java.lang.invoke.VarHandleByteArrayAsLongs$ByteArrayViewVarHandle +java.lang.invoke.VarHandleByteArrayAsLongs$ArrayHandle +java.lang.invoke.VarHandleByteArrayAsLongs +java.lang.invoke.VarHandleByteArrayAsLongs$ArrayHandle$$Lambda$659/0x00007faab41d7ca0 +java.lang.invoke.VarHandle$TypesAndInvokers +java.lang.invoke.VarHandle$2 +java.lang.invoke.VarHandle$VarHandleDesc$Kind +java.lang.constant.ConstantDescs +java.lang.constant.ClassDesc +java.lang.constant.ConstantUtils +java.lang.constant.ReferenceClassDescImpl +java.lang.constant.DirectMethodHandleDesc$Kind +java.lang.constant.MethodTypeDesc +java.lang.constant.MethodTypeDescImpl +java.lang.constant.MethodHandleDesc +java.lang.constant.MethodHandleDesc$1 +java.lang.constant.DirectMethodHandleDesc +java.lang.constant.DirectMethodHandleDescImpl +java.lang.constant.DirectMethodHandleDescImpl$1 +java.lang.constant.DirectMethodHandleDesc$1 +java.lang.constant.DynamicConstantDesc +java.lang.constant.PrimitiveClassDescImpl +java.lang.constant.DynamicConstantDesc$AnonymousDynamicConstantDesc +java.io.DeleteOnExitHook +java.io.DeleteOnExitHook$1 +java.util.zip.DeflaterOutputStream +java.util.zip.ZipOutputStream +java.util.jar.JarOutputStream +java.util.zip.Deflater +java.util.zip.Deflater$DeflaterZStreamRef +java.util.zip.ZipOutputStream$XEntry +java.util.Vector$Itr +opened:/tmp/mockitoboot5452617940860437443.jar +org.mockito.internal.creation.bytebuddy.inject.MockMethodDispatcher +org.mockito.internal.util.concurrent.WeakConcurrentMap +org.mockito.internal.util.concurrent.DetachedThreadLocal +org.mockito.internal.util.concurrent.DetachedThreadLocal$1 +org.mockito.internal.util.concurrent.WeakConcurrentMap$WithInlinedExpunction +org.mockito.internal.util.concurrent.DetachedThreadLocal$2 +org.mockito.internal.util.concurrent.DetachedThreadLocal$Cleaner +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$$Lambda$660/0x00007faab4215060 +java.lang.ThreadLocal$SuppliedThreadLocal +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$$Lambda$661/0x00007faab4215280 +org.mockito.internal.creation.bytebuddy.StackWalkerChecker +java.lang.StackWalker$Option +java.lang.invoke.LambdaForm$DMH/0x00007faab4210c00 +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$$Lambda$662/0x00007faab4215708 +org.mockito.internal.creation.bytebuddy.ConstructionCallback +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$$Lambda$663/0x00007faab4215b60 +org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator +net.bytebuddy.matcher.ElementMatcher +net.bytebuddy.TypeCache +net.bytebuddy.TypeCache$WithInlineExpunction +java.lang.instrument.ClassFileTransformer +org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator +net.bytebuddy.implementation.Implementation$Context$Factory +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler +net.bytebuddy.dynamic.scaffold.InstrumentedType$Prepareable +net.bytebuddy.implementation.Implementation +net.bytebuddy.asm.AsmVisitorWrapper +org.mockito.internal.creation.bytebuddy.MockMethodAdvice +java.lang.instrument.UnmodifiableClassException +net.bytebuddy.ByteBuddy +net.bytebuddy.NamingStrategy +net.bytebuddy.implementation.auxiliary.AuxiliaryType$NamingStrategy +net.bytebuddy.matcher.LatentMatcher +net.bytebuddy.utility.AsmClassWriter$Factory +net.bytebuddy.utility.AsmClassReader$Factory +net.bytebuddy.dynamic.VisibilityBridgeStrategy +net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory +net.bytebuddy.implementation.attribute.AnnotationValueFilter$Factory +net.bytebuddy.NamingStrategy$Suffixing$BaseNameResolver +net.bytebuddy.dynamic.DynamicType$Builder +net.bytebuddy.description.NamedElement +net.bytebuddy.description.ModifierReviewable +net.bytebuddy.description.ModifierReviewable$OfByteCodeElement +net.bytebuddy.description.ModifierReviewable$OfAbstraction +net.bytebuddy.description.ModifierReviewable$OfEnumeration +net.bytebuddy.description.ModifierReviewable$ForTypeDefinition +net.bytebuddy.description.type.TypeDefinition +net.bytebuddy.matcher.FilterableList +net.bytebuddy.description.type.TypeList$Generic +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy +net.bytebuddy.description.NamedElement$WithRuntimeName +net.bytebuddy.description.annotation.AnnotationSource +net.bytebuddy.description.type.PackageDescription +net.bytebuddy.description.NamedElement$WithDescriptor +net.bytebuddy.description.DeclaredByType +net.bytebuddy.description.ByteCodeElement +net.bytebuddy.description.TypeVariableSource +net.bytebuddy.description.type.TypeDescription +net.bytebuddy.utility.privilege.GetSystemPropertyAction +net.bytebuddy.dynamic.scaffold.TypeValidation +net.bytebuddy.utility.GraalImageCode +net.bytebuddy.NamingStrategy$AbstractBase +net.bytebuddy.NamingStrategy$Suffixing +net.bytebuddy.NamingStrategy$SuffixingRandom +net.bytebuddy.NamingStrategy$Suffixing$BaseNameResolver$ForUnnamedType +net.bytebuddy.utility.RandomString +net.bytebuddy.implementation.auxiliary.AuxiliaryType$NamingStrategy$SuffixingRandom +net.bytebuddy.implementation.attribute.AnnotationValueFilter +net.bytebuddy.implementation.attribute.AnnotationValueFilter$Default +net.bytebuddy.implementation.attribute.AnnotationValueFilter$Default$1 +net.bytebuddy.implementation.attribute.AnnotationValueFilter$Default$2 +net.bytebuddy.implementation.attribute.AnnotationRetention +net.bytebuddy.implementation.Implementation$Context$Default$Factory +net.bytebuddy.implementation.MethodAccessorFactory +net.bytebuddy.implementation.Implementation$Context +net.bytebuddy.implementation.Implementation$Context$ExtractableView +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$AbstractBase +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default +net.bytebuddy.dynamic.scaffold.MethodGraph +net.bytebuddy.dynamic.scaffold.MethodGraph$Linked +net.bytebuddy.description.type.TypeDescription$Generic$Visitor +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Merger +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Harmonizer +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Harmonizer$ForJavaMethod +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Merger$Directional +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Reifying +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Reifying$1 +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Reifying$2 +net.bytebuddy.description.type.TypeDescription$Generic +net.bytebuddy.matcher.ElementMatchers +net.bytebuddy.matcher.ElementMatcher$Junction +net.bytebuddy.description.ModifierReviewable$ForFieldDescription +net.bytebuddy.description.DeclaredByType$WithMandatoryDeclaration +net.bytebuddy.description.NamedElement$WithGenericName +net.bytebuddy.description.ByteCodeElement$Member +net.bytebuddy.description.ByteCodeElement$TypeDependant +net.bytebuddy.description.field.FieldDescription +net.bytebuddy.description.field.FieldDescription$InDefinedShape +net.bytebuddy.description.ModifierReviewable$ForMethodDescription +net.bytebuddy.description.method.MethodDescription +net.bytebuddy.description.method.MethodDescription$InDefinedShape +net.bytebuddy.matcher.ElementMatcher$Junction$AbstractBase +net.bytebuddy.matcher.BooleanMatcher +net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory$Default +net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory$Default$1 +net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory$Default$2 +net.bytebuddy.implementation.LoadedTypeInitializer +net.bytebuddy.implementation.bytecode.ByteCodeAppender +net.bytebuddy.dynamic.scaffold.TypeInitializer +net.bytebuddy.dynamic.scaffold.InstrumentedType +net.bytebuddy.dynamic.scaffold.InstrumentedType$WithFlexibleName +net.bytebuddy.dynamic.VisibilityBridgeStrategy$Default +net.bytebuddy.dynamic.VisibilityBridgeStrategy$Default$1 +net.bytebuddy.dynamic.VisibilityBridgeStrategy$Default$2 +net.bytebuddy.dynamic.VisibilityBridgeStrategy$Default$3 +net.bytebuddy.utility.AsmClassReader$Factory$Default +net.bytebuddy.utility.AsmClassReader$Factory$Default$1 +net.bytebuddy.utility.AsmClassReader$Factory$Default$2 +net.bytebuddy.utility.AsmClassReader$Factory$Default$3 +net.bytebuddy.utility.AsmClassReader$Factory$Default$4 +net.bytebuddy.utility.AsmClassReader$Factory$Default$5 +net.bytebuddy.utility.AsmClassReader +net.bytebuddy.utility.AsmClassWriter$Factory$Default +net.bytebuddy.utility.AsmClassWriter$Factory$Default$1 +net.bytebuddy.utility.AsmClassWriter$Factory$Default$2 +net.bytebuddy.utility.AsmClassWriter$Factory$Default$3 +net.bytebuddy.utility.AsmClassWriter$Factory$Default$4 +net.bytebuddy.utility.AsmClassWriter$Factory$Default$5 +net.bytebuddy.pool.TypePool +net.bytebuddy.jar.asm.ClassVisitor +net.bytebuddy.jar.asm.ClassWriter +net.bytebuddy.utility.AsmClassWriter$FrameComputingClassWriter +net.bytebuddy.utility.AsmClassWriter +net.bytebuddy.matcher.LatentMatcher$Resolved +net.bytebuddy.matcher.ModifierMatcher$Mode +net.bytebuddy.matcher.ElementMatcher$Junction$ForNonNullValues +net.bytebuddy.matcher.ModifierMatcher +net.bytebuddy.matcher.NameMatcher +net.bytebuddy.matcher.StringMatcher +net.bytebuddy.matcher.StringMatcher$Mode +net.bytebuddy.matcher.StringMatcher$Mode$1 +net.bytebuddy.matcher.StringMatcher$Mode$2 +net.bytebuddy.matcher.StringMatcher$Mode$3 +net.bytebuddy.matcher.StringMatcher$Mode$4 +net.bytebuddy.matcher.StringMatcher$Mode$5 +net.bytebuddy.matcher.StringMatcher$Mode$6 +net.bytebuddy.matcher.StringMatcher$Mode$7 +net.bytebuddy.matcher.StringMatcher$Mode$8 +net.bytebuddy.matcher.StringMatcher$Mode$9 +net.bytebuddy.matcher.MethodParametersMatcher +net.bytebuddy.matcher.CollectionSizeMatcher +net.bytebuddy.matcher.ElementMatcher$Junction$Conjunction +net.bytebuddy.description.ModifierReviewable$ForParameterDescription +net.bytebuddy.description.ModifierReviewable$AbstractBase +net.bytebuddy.description.TypeVariableSource$AbstractBase +net.bytebuddy.description.type.TypeDescription$AbstractBase +net.bytebuddy.description.type.TypeDescription$ForLoadedType +java.lang.reflect.GenericSignatureFormatError +net.bytebuddy.description.annotation.AnnotationList +net.bytebuddy.description.field.FieldList +net.bytebuddy.description.type.RecordComponentList +net.bytebuddy.matcher.FilterableList$Empty +net.bytebuddy.description.type.RecordComponentList$Empty +net.bytebuddy.matcher.FilterableList$AbstractBase +net.bytebuddy.description.type.RecordComponentList$AbstractBase +net.bytebuddy.description.type.RecordComponentList$ForLoadedRecordComponents +net.bytebuddy.description.method.MethodList +net.bytebuddy.description.type.TypeList +net.bytebuddy.description.type.TypeList$Empty +net.bytebuddy.description.type.TypeList$AbstractBase +net.bytebuddy.description.type.TypeList$ForLoadedTypes +net.bytebuddy.description.type.TypeDescription$ForLoadedType$Dispatcher +net.bytebuddy.utility.dispatcher.JavaDispatcher +net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher +net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader$Resolver$CreationAction +net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader$Resolver +net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader$Resolver$ForModuleSystem +net.bytebuddy.utility.dispatcher.JavaDispatcher$InvokerCreationAction +net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader +net.bytebuddy.utility.Invoker +net.bytebuddy.jar.asm.ClassTooLargeException +net.bytebuddy.jar.asm.FieldVisitor +net.bytebuddy.jar.asm.FieldWriter +net.bytebuddy.jar.asm.AnnotationVisitor +net.bytebuddy.jar.asm.AnnotationWriter +net.bytebuddy.jar.asm.MethodVisitor +net.bytebuddy.jar.asm.MethodWriter +net.bytebuddy.jar.asm.ModuleVisitor +net.bytebuddy.jar.asm.ModuleWriter +net.bytebuddy.jar.asm.RecordComponentVisitor +net.bytebuddy.jar.asm.RecordComponentWriter +java.lang.TypeNotPresentException +net.bytebuddy.jar.asm.SymbolTable +net.bytebuddy.jar.asm.Symbol +net.bytebuddy.jar.asm.SymbolTable$Entry +net.bytebuddy.jar.asm.ByteVector +net.bytebuddy.jar.asm.Type +net.bytebuddy.utility.MethodComparator +net.bytebuddy.jar.asm.Frame +net.bytebuddy.jar.asm.CurrentFrame +net.bytebuddy.jar.asm.MethodTooLargeException +net.bytebuddy.jar.asm.Handler +net.bytebuddy.jar.asm.Attribute +net.bytebuddy.utility.Invoker$Dispatcher +net.bytebuddy.utility.dispatcher.JavaDispatcher$Proxied +net.bytebuddy.utility.dispatcher.JavaDispatcher$Defaults +jdk.proxy2.$Proxy20 +jdk.proxy2.$Proxy21 +net.bytebuddy.utility.dispatcher.JavaDispatcher$Instance +net.bytebuddy.utility.dispatcher.JavaDispatcher$Container +net.bytebuddy.utility.dispatcher.JavaDispatcher$IsStatic +net.bytebuddy.utility.dispatcher.JavaDispatcher$IsConstructor +net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher$ForNonStaticMethod +net.bytebuddy.utility.nullability.MaybeNull +jdk.proxy2.$Proxy22 +net.bytebuddy.utility.dispatcher.JavaDispatcher$ProxiedInvocationHandler +net.bytebuddy.description.type.$Proxy23 +net.bytebuddy.dynamic.TargetType +net.bytebuddy.matcher.EqualityMatcher +net.bytebuddy.matcher.ErasureMatcher +net.bytebuddy.matcher.MethodReturnTypeMatcher +net.bytebuddy.matcher.DeclaringTypeMatcher +net.bytebuddy.matcher.ElementMatcher$Junction$Disjunction +net.bytebuddy.implementation.Implementation$Context$Disabled$Factory +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$ForDeclaredMethods +net.bytebuddy.matcher.MethodSortMatcher$Sort +net.bytebuddy.matcher.MethodSortMatcher$Sort$1 +net.bytebuddy.matcher.MethodSortMatcher$Sort$2 +net.bytebuddy.matcher.MethodSortMatcher$Sort$3 +net.bytebuddy.matcher.MethodSortMatcher$Sort$4 +net.bytebuddy.matcher.MethodSortMatcher$Sort$5 +net.bytebuddy.matcher.MethodSortMatcher +net.bytebuddy.matcher.NegatingMatcher +org.mockito.internal.util.concurrent.WeakConcurrentSet +org.mockito.internal.util.concurrent.WeakConcurrentSet$Cleaner +org.mockito.internal.creation.bytebuddy.SubclassBytecodeGenerator +net.bytebuddy.implementation.attribute.MethodAttributeAppender$Factory +net.bytebuddy.dynamic.loading.ClassLoadingStrategy +org.mockito.internal.creation.bytebuddy.ModuleHandler +org.mockito.internal.creation.bytebuddy.ModuleHandler$ModuleSystemFound +org.mockito.internal.creation.bytebuddy.ModuleHandler$1 +org.mockito.internal.creation.bytebuddy.ModuleHandler$NoModuleSystemFound +org.mockito.internal.creation.bytebuddy.ModuleHandler$2 +org.mockito.internal.creation.bytebuddy.ModuleHandler$3 +java.lang.instrument.ClassDefinition +org.mockito.internal.creation.bytebuddy.ModuleHandler$MockitoMockClassLoader +jdk.internal.vm.annotation.ForceInline +com.sun.proxy.jdk.proxy1.$Proxy24 +net.bytebuddy.implementation.Implementation$Composable +net.bytebuddy.implementation.MethodDelegation +net.bytebuddy.implementation.bind.MethodDelegationBinder$TerminationHandler +net.bytebuddy.implementation.bind.MethodDelegationBinder$Record +net.bytebuddy.implementation.bind.MethodDelegationBinder$AmbiguityResolver +net.bytebuddy.implementation.MethodDelegation$WithCustomProperties +net.bytebuddy.implementation.bind.MethodDelegationBinder$BindingResolver +net.bytebuddy.implementation.MethodDelegation$ImplementationDelegate +net.bytebuddy.dynamic.scaffold.FieldLocator$Factory +net.bytebuddy.implementation.bind.MethodDelegationBinder$AmbiguityResolver$Compound +net.bytebuddy.implementation.bind.annotation.BindingPriority$Resolver +net.bytebuddy.implementation.bind.annotation.BindingPriority +net.bytebuddy.description.method.MethodList$AbstractBase +net.bytebuddy.description.method.MethodList$ForLoadedMethods +net.bytebuddy.description.method.MethodDescription$AbstractBase +net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase +net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable +net.bytebuddy.description.method.ParameterDescription$ForLoadedParameter$ParameterAnnotationSource +net.bytebuddy.description.method.MethodDescription$ForLoadedConstructor +net.bytebuddy.description.method.MethodDescription$ForLoadedMethod +net.bytebuddy.utility.ConstructorComparator +net.bytebuddy.description.ByteCodeElement$Token +net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$Executable +net.bytebuddy.description.method.$Proxy25 +net.bytebuddy.implementation.bind.DeclaringTypeResolver +net.bytebuddy.implementation.bind.ArgumentTypeResolver +net.bytebuddy.implementation.bind.MethodNameEqualityResolver +net.bytebuddy.implementation.bind.ParameterLengthResolver +net.bytebuddy.implementation.bind.MethodDelegationBinder$AmbiguityResolver$NoOp +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$ParameterBinder +net.bytebuddy.implementation.bind.annotation.Argument$Binder +net.bytebuddy.implementation.bytecode.StackManipulation +net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding +net.bytebuddy.implementation.bind.annotation.Argument +net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic +net.bytebuddy.description.method.MethodList$Explicit +net.bytebuddy.implementation.bind.annotation.AllArguments$Binder +net.bytebuddy.implementation.bind.annotation.AllArguments +net.bytebuddy.implementation.bind.annotation.AllArguments$Assignment +net.bytebuddy.implementation.bind.annotation.Origin$Binder +net.bytebuddy.implementation.bind.annotation.Origin +net.bytebuddy.implementation.bind.annotation.This$Binder +net.bytebuddy.implementation.bind.annotation.This +net.bytebuddy.implementation.bind.annotation.Super$Binder +net.bytebuddy.implementation.bind.annotation.Super +net.bytebuddy.implementation.bind.annotation.Super$Instantiation +net.bytebuddy.implementation.bind.annotation.Default$Binder +net.bytebuddy.implementation.bind.annotation.Default +net.bytebuddy.implementation.bind.annotation.SuperCall$Binder +net.bytebuddy.implementation.bind.annotation.SuperCall +net.bytebuddy.implementation.bind.annotation.SuperCallHandle$Binder +net.bytebuddy.implementation.bind.annotation.SuperCallHandle +net.bytebuddy.implementation.bind.annotation.DefaultCall$Binder +net.bytebuddy.implementation.bind.annotation.DefaultCall$Binder$DefaultMethodLocator +net.bytebuddy.implementation.bind.annotation.DefaultCall +net.bytebuddy.implementation.bind.annotation.DefaultCallHandle$Binder +net.bytebuddy.implementation.bind.annotation.DefaultCallHandle$Binder$DefaultMethodLocator +net.bytebuddy.implementation.bind.annotation.DefaultCallHandle +net.bytebuddy.implementation.bind.annotation.SuperMethod$Binder +net.bytebuddy.implementation.bind.annotation.SuperMethod +net.bytebuddy.implementation.bind.annotation.SuperMethodHandle$Binder +net.bytebuddy.implementation.bind.annotation.SuperMethodHandle +net.bytebuddy.implementation.bind.annotation.Handle$Binder +net.bytebuddy.utility.ConstantValue +net.bytebuddy.utility.JavaConstant +net.bytebuddy.implementation.bind.annotation.Handle +net.bytebuddy.utility.JavaConstant$MethodHandle$HandleType +net.bytebuddy.implementation.bind.annotation.DynamicConstant$Binder +net.bytebuddy.implementation.bind.annotation.DynamicConstant +net.bytebuddy.implementation.bind.annotation.DefaultMethod$Binder +net.bytebuddy.implementation.bind.annotation.DefaultMethod$Binder$MethodLocator +net.bytebuddy.implementation.bind.annotation.DefaultMethod +net.bytebuddy.implementation.bind.annotation.DefaultMethodHandle$Binder +net.bytebuddy.implementation.bind.annotation.DefaultMethodHandle$Binder$MethodLocator +net.bytebuddy.implementation.bind.annotation.DefaultMethodHandle +net.bytebuddy.implementation.bind.annotation.FieldValue$Binder +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$ParameterBinder$ForFieldBinding +net.bytebuddy.implementation.bind.annotation.FieldValue$Binder$Delegate +net.bytebuddy.dynamic.scaffold.FieldLocator +net.bytebuddy.dynamic.scaffold.FieldLocator$AbstractBase +net.bytebuddy.dynamic.scaffold.FieldLocator$ForClassHierarchy +net.bytebuddy.dynamic.scaffold.FieldLocator$ForExactType +net.bytebuddy.implementation.bind.annotation.FieldValue +net.bytebuddy.implementation.bind.annotation.FieldGetterHandle$Binder +net.bytebuddy.implementation.bind.annotation.FieldGetterHandle$Binder$Delegate +net.bytebuddy.implementation.bind.annotation.FieldGetterHandle +net.bytebuddy.implementation.bind.annotation.FieldSetterHandle$Binder +net.bytebuddy.implementation.bind.annotation.FieldSetterHandle$Binder$Delegate +net.bytebuddy.implementation.bind.annotation.FieldSetterHandle +net.bytebuddy.implementation.bind.annotation.StubValue$Binder +net.bytebuddy.implementation.bind.annotation.Empty$Binder +net.bytebuddy.implementation.bind.MethodDelegationBinder$BindingResolver$Default +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$Identifier +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$ParameterBinder$ForFixedValue +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$ParameterBinder$ForFixedValue$OfConstant +net.bytebuddy.utility.CompoundList +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ForReadObject +org.mockito.internal.creation.bytebuddy.access.MockAccess +net.bytebuddy.implementation.bind.MethodDelegationBinder +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$DelegationProcessor +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$DelegationProcessor$Handler +net.bytebuddy.implementation.bind.annotation.StubValue +net.bytebuddy.implementation.bind.annotation.Empty +net.bytebuddy.implementation.MethodDelegation$ImplementationDelegate$ForStaticMethod +net.bytebuddy.implementation.MethodDelegation$ImplementationDelegate$Compiled +net.bytebuddy.implementation.bind.annotation.IgnoreForBinding$Verifier +net.bytebuddy.description.annotation.AnnotationList$AbstractBase +net.bytebuddy.description.annotation.AnnotationList$ForLoadedAnnotations +net.bytebuddy.description.annotation.AnnotationDescription +net.bytebuddy.implementation.bind.annotation.IgnoreForBinding +net.bytebuddy.description.method.ParameterList +net.bytebuddy.description.method.ParameterList$AbstractBase +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$OfMethod +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$OfLegacyVmMethod +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$OfConstructor +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$OfLegacyVmConstructor +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$Executable +jdk.proxy2.$Proxy26 +net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher$ForInstanceCheck +jdk.internal.reflect.GeneratedConstructorAccessor7 +net.bytebuddy.description.method.$Proxy27 +net.bytebuddy.description.NamedElement$WithOptionalName +net.bytebuddy.description.method.ParameterDescription +net.bytebuddy.description.method.ParameterDescription$InDefinedShape +net.bytebuddy.description.method.ParameterDescription$AbstractBase +net.bytebuddy.description.method.ParameterDescription$InDefinedShape$AbstractBase +net.bytebuddy.description.method.ParameterDescription$ForLoadedParameter +net.bytebuddy.description.method.ParameterDescription$ForLoadedParameter$OfMethod +net.bytebuddy.description.method.ParameterDescription$ForLoadedParameter$Parameter +net.bytebuddy.description.method.$Proxy28 +net.bytebuddy.implementation.bind.annotation.RuntimeType$Verifier +org.mockito.internal.creation.bytebuddy.$Proxy29 +jdk.proxy2.$Proxy30 +net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 +net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 +jdk.proxy2.$Proxy31 +net.bytebuddy.implementation.bind.annotation.RuntimeType +net.bytebuddy.description.annotation.AnnotationDescription$Loadable +net.bytebuddy.description.annotation.AnnotationDescription$AbstractBase +net.bytebuddy.description.annotation.AnnotationDescription$ForLoadedAnnotation +net.bytebuddy.description.annotation.AnnotationValue +net.bytebuddy.description.enumeration.EnumerationDescription +net.bytebuddy.description.type.TypeDefinition$Sort +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader +net.bytebuddy.description.type.TypeDefinition$Sort$AnnotatedType +net.bytebuddy.description.type.$Proxy32 +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$NoOp +net.bytebuddy.description.type.TypeDescription$Generic$AbstractBase +net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType +net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType$ForLoadedType +net.bytebuddy.implementation.bytecode.assign.Assigner$Typing +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$DelegationProcessor$Handler$Unbound +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$DelegationProcessor$Handler$Bound +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$Record +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding +net.bytebuddy.implementation.bind.MethodDelegationBinder$TerminationHandler$Default +net.bytebuddy.implementation.bind.MethodDelegationBinder$TerminationHandler$Default$1 +net.bytebuddy.implementation.bind.MethodDelegationBinder$TerminationHandler$Default$2 +net.bytebuddy.implementation.bytecode.assign.Assigner +net.bytebuddy.implementation.bytecode.assign.primitive.VoidAwareAssigner +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveTypeAwareAssigner +net.bytebuddy.implementation.bytecode.assign.reference.ReferenceTypeAwareAssigner +net.bytebuddy.implementation.bytecode.StackManipulation$Trivial +net.bytebuddy.implementation.bytecode.StackManipulation$Illegal +net.bytebuddy.implementation.bytecode.assign.reference.GenericTypeAwareAssigner +org.mockito.internal.creation.bytebuddy.access.MockMethodInterceptor$DispatcherDefaultingToRealMethod +org.mockito.internal.invocation.RealMethod +org.mockito.internal.creation.bytebuddy.access.MockMethodInterceptor +jdk.proxy2.$Proxy33 +jdk.proxy2.$Proxy34 +jdk.proxy2.$Proxy35 +jdk.proxy2.$Proxy36 +jdk.proxy2.$Proxy37 +jdk.proxy2.$Proxy38 +jdk.proxy2.$Proxy39 +org.mockito.internal.creation.bytebuddy.access.MockMethodInterceptor$ForHashCode +org.mockito.internal.creation.bytebuddy.access.MockMethodInterceptor$ForEquals +org.mockito.internal.creation.bytebuddy.access.MockMethodInterceptor$ForWriteReplace +net.bytebuddy.TypeCache$Sort +net.bytebuddy.TypeCache$Sort$1 +net.bytebuddy.TypeCache$Sort$2 +net.bytebuddy.TypeCache$Sort$3 +org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$TypeCachingLock +net.bytebuddy.asm.AsmVisitorWrapper$ForDeclaredMethods +net.bytebuddy.asm.AsmVisitorWrapper$ForDeclaredMethods$DispatchingVisitor +net.bytebuddy.matcher.CollectionOneToOneMatcher +net.bytebuddy.matcher.CollectionErasureMatcher +net.bytebuddy.matcher.MethodParameterTypesMatcher +net.bytebuddy.matcher.AnnotationTypeMatcher +net.bytebuddy.matcher.DeclaringAnnotationMatcher +net.bytebuddy.matcher.CollectionItemMatcher +net.bytebuddy.asm.AsmVisitorWrapper$ForDeclaredMethods$MethodVisitorWrapper +net.bytebuddy.asm.Advice +net.bytebuddy.asm.Advice$ExceptionHandler +net.bytebuddy.asm.Advice$Dispatcher +net.bytebuddy.asm.Advice$Dispatcher$Unresolved +net.bytebuddy.dynamic.ClassFileLocator +net.bytebuddy.asm.Advice$Delegator$Factory +net.bytebuddy.asm.Advice$PostProcessor$Factory +net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor +net.bytebuddy.utility.visitor.LineNumberPrependingMethodVisitor +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$Relocation +net.bytebuddy.asm.Advice$AdviceVisitor +net.bytebuddy.asm.Advice$AdviceVisitor$WithoutExitAdvice +net.bytebuddy.asm.Advice$AdviceVisitor$WithExitAdvice +net.bytebuddy.asm.Advice$AdviceVisitor$WithExitAdvice$WithoutExceptionHandling +net.bytebuddy.asm.Advice$AdviceVisitor$WithExitAdvice$WithExceptionHandling +net.bytebuddy.asm.Advice$OnMethodEnter +net.bytebuddy.asm.Advice$OnMethodExit +net.bytebuddy.asm.Advice$WithCustomMapping +net.bytebuddy.asm.Advice$OffsetMapping$Factory +net.bytebuddy.asm.Advice$BootstrapArgumentResolver$Factory +net.bytebuddy.asm.Advice$PostProcessor +net.bytebuddy.asm.Advice$PostProcessor$NoOp +net.bytebuddy.asm.Advice$Delegator$ForRegularInvocation$Factory +net.bytebuddy.asm.Advice$Delegator +net.bytebuddy.asm.Advice$OffsetMapping$ForStackManipulation$Factory +net.bytebuddy.asm.Advice$OffsetMapping +net.bytebuddy.utility.ConstantValue$Simple +net.bytebuddy.utility.JavaConstant$Simple +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher +jdk.proxy2.$Proxy40 +net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher$ForContainerCreation +net.bytebuddy.utility.$Proxy41 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfClassDesc +jdk.proxy2.$Proxy42 +net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher$ForStaticMethod +jdk.proxy2.$Proxy43 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfMethodTypeDesc +jdk.proxy2.$Proxy44 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfMethodHandleDesc +jdk.proxy2.$Proxy45 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfDirectMethodHandleDesc +jdk.proxy2.$Proxy46 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfDirectMethodHandleDesc$ForKind +jdk.proxy2.$Proxy47 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfDynamicConstantDesc +jdk.proxy2.$Proxy48 +net.bytebuddy.utility.JavaConstant$Simple$OfTrivialValue +net.bytebuddy.utility.JavaConstant$Simple$OfTrivialValue$ForString +net.bytebuddy.implementation.bytecode.StackManipulation$AbstractBase +net.bytebuddy.implementation.bytecode.constant.TextConstant +net.bytebuddy.dynamic.ClassFileLocator$ForClassLoader +net.bytebuddy.dynamic.ClassFileLocator$Resolution +net.bytebuddy.dynamic.ClassFileLocator$ForClassLoader$BootLoaderProxyCreationAction +net.bytebuddy.asm.Advice$Dispatcher$Resolved +net.bytebuddy.asm.Advice$Dispatcher$Resolved$ForMethodEnter +net.bytebuddy.asm.Advice$Dispatcher$Resolved$ForMethodExit +net.bytebuddy.asm.Advice$Dispatcher$Bound +net.bytebuddy.asm.Advice$Dispatcher$Inactive +net.bytebuddy.asm.Advice$NoExceptionHandler +jdk.proxy2.$Proxy49 +net.bytebuddy.description.annotation.AnnotationValue$AbstractBase +net.bytebuddy.description.annotation.AnnotationValue$ForConstant +net.bytebuddy.description.annotation.AnnotationValue$Loaded +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$1 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$2 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$3 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$4 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$5 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$6 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$7 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$8 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$9 +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithEagerNavigation +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithEagerNavigation$OfAnnotatedElement +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$ForLoadedReturnType +net.bytebuddy.asm.Advice$Dispatcher$Inlining +net.bytebuddy.asm.Advice$Return +jdk.proxy2.$Proxy50 +net.bytebuddy.asm.Advice$Enter +jdk.proxy2.$Proxy51 +net.bytebuddy.asm.Advice$Local +net.bytebuddy.asm.Advice$OnNonDefaultValue +jdk.proxy2.$Proxy52 +net.bytebuddy.asm.Advice$This +jdk.proxy2.$Proxy53 +net.bytebuddy.asm.Advice$Origin +jdk.proxy2.$Proxy54 +net.bytebuddy.asm.Advice$AllArguments +jdk.proxy2.$Proxy55 +net.bytebuddy.dynamic.ClassFileLocator$Resolution$Explicit +net.bytebuddy.utility.StreamDrainer +net.bytebuddy.utility.OpenedClassReader +net.bytebuddy.utility.AsmClassReader$ForAsm +net.bytebuddy.jar.asm.ClassReader +net.bytebuddy.asm.Advice$Dispatcher$Resolved$AbstractBase +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodEnter +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodEnter$WithRetainedEnterType +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodEnter$WithDiscardedEnterType +net.bytebuddy.asm.Advice$ArgumentHandler +net.bytebuddy.asm.Advice$Dispatcher$Inlining$CodeTranslationVisitor +net.bytebuddy.asm.Advice$OffsetMapping$ForArgument$Unresolved$Factory +net.bytebuddy.asm.Advice$Argument +net.bytebuddy.asm.Advice$OffsetMapping$ForAllArguments$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForThisReference$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForField$Unresolved$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForField +net.bytebuddy.asm.Advice$OffsetMapping$ForField$Unresolved +net.bytebuddy.asm.Advice$OffsetMapping$ForField$Unresolved$WithImplicitType +net.bytebuddy.asm.Advice$OffsetMapping$ForField$Unresolved$WithExplicitType +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle$Unresolved$ReaderFactory +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle$Unresolved +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle$Unresolved$WithImplicitType +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle$Unresolved$WithExplicitType +net.bytebuddy.asm.Advice$FieldGetterHandle +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle$Unresolved$WriterFactory +net.bytebuddy.asm.Advice$FieldSetterHandle +net.bytebuddy.asm.Advice$OffsetMapping$ForOrigin$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForSelfCallHandle$Factory +net.bytebuddy.asm.Advice$SelfCallHandle +net.bytebuddy.asm.Advice$OffsetMapping$ForHandle$Factory +net.bytebuddy.asm.Advice$Handle +net.bytebuddy.asm.Advice$OffsetMapping$ForDynamicConstant$Factory +net.bytebuddy.asm.Advice$DynamicConstant +net.bytebuddy.asm.Advice$OffsetMapping$ForUnusedValue$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForStubValue +net.bytebuddy.asm.Advice$OffsetMapping$Target +net.bytebuddy.asm.Advice$OffsetMapping$ForThrowable$Factory +net.bytebuddy.asm.Advice$Thrown +net.bytebuddy.asm.Advice$OffsetMapping$ForExitValue$Factory +net.bytebuddy.asm.Advice$Exit +net.bytebuddy.asm.Advice$OffsetMapping$Factory$Illegal +net.bytebuddy.asm.Advice$OffsetMapping$ForLocalValue$Factory +net.bytebuddy.description.annotation.AnnotationValue$ForTypeDescription +net.bytebuddy.description.annotation.AnnotationValue$ForMismatchedType +net.bytebuddy.asm.Advice$OffsetMapping$Factory$AdviceType +net.bytebuddy.asm.Advice$FieldValue +net.bytebuddy.asm.Advice$Unused +net.bytebuddy.asm.Advice$StubValue +net.bytebuddy.asm.Advice$OffsetMapping$ForStackManipulation +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$OfMethodParameter +net.bytebuddy.description.type.TypeList$Generic$AbstractBase +net.bytebuddy.description.type.TypeList$Generic$Explicit +net.bytebuddy.description.type.TypeList$Explicit +net.bytebuddy.implementation.bytecode.StackSize +net.bytebuddy.asm.Advice$OffsetMapping$ForThisReference +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForDefaultValue +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForDefaultValue$ReadOnly +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForDefaultValue$ReadWrite +net.bytebuddy.description.enumeration.EnumerationDescription$AbstractBase +net.bytebuddy.description.enumeration.EnumerationDescription$ForLoadedEnumeration +net.bytebuddy.description.annotation.AnnotationValue$ForEnumerationDescription +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod$1 +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod$2 +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod$3 +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod$4 +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod$5 +sun.reflect.generics.tree.ArrayTypeSignature +sun.reflect.generics.tree.BottomSignature +sun.reflect.generics.tree.Wildcard +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedExecutableParameterType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedExecutableParameterType$Dispatcher +jdk.internal.reflect.GeneratedMethodAccessor1 +net.bytebuddy.description.type.$Proxy56 +net.bytebuddy.asm.Advice$OffsetMapping$ForAllArguments +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$Chained +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForComponentType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForComponentType$AnnotatedParameterizedType +java.lang.reflect.AnnotatedArrayType +net.bytebuddy.description.type.$Proxy57 +net.bytebuddy.asm.Advice$Dispatcher$SuppressionHandler +net.bytebuddy.asm.Advice$Dispatcher$SuppressionHandler$Suppressing +net.bytebuddy.asm.Advice$Dispatcher$SuppressionHandler$Bound +net.bytebuddy.asm.Advice$Dispatcher$SuppressionHandler$NoOp +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForType +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$Bound +net.bytebuddy.asm.Advice$OnDefaultValue +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$1 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$2 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$3 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$4 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$5 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$6 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$7 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$8 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$9 +java.lang.reflect.WildcardType +sun.reflect.generics.reflectiveObjects.WildcardTypeImpl +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedMethodReturnType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedMethodReturnType$Dispatcher +net.bytebuddy.description.type.$Proxy58 +net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType +net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType$ForLoadedType +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$OfNonDefault +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodExit +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodExit$WithoutExceptionHandler +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodExit$WithExceptionHandler +net.bytebuddy.asm.Advice$OffsetMapping$ForEnterValue$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForReturnValue$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForReturnValue +net.bytebuddy.asm.Advice$OffsetMapping$ForEnterValue +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$Disabled +net.bytebuddy.asm.Advice$ExceptionHandler$Default +net.bytebuddy.asm.Advice$ExceptionHandler$Default$1 +net.bytebuddy.asm.Advice$ExceptionHandler$Default$2 +net.bytebuddy.asm.Advice$ExceptionHandler$Default$3 +net.bytebuddy.implementation.SuperMethodCall +net.bytebuddy.asm.AsmVisitorWrapper$ForDeclaredMethods$Entry +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ForStatic +jdk.internal.reflect.GeneratedMethodAccessor2 +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedType +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ConstructorShortcut +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ConstructorShortcut$1 +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ForHashCode +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ForEquals +jdk.proxy2.$Proxy59 +net.bytebuddy.asm.Advice$OffsetMapping$ForArgument +net.bytebuddy.asm.Advice$OffsetMapping$ForArgument$Unresolved +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$SelfCallInfo +org.mockito.internal.util.reflection.ModuleMemberAccessor +org.mockito.internal.util.reflection.InstrumentationMemberAccessor +net.bytebuddy.dynamic.loading.InjectionClassLoader +net.bytebuddy.dynamic.loading.ByteArrayClassLoader +net.bytebuddy.implementation.MethodCall +net.bytebuddy.implementation.MethodCall$WithoutSpecifiedTarget +net.bytebuddy.dynamic.loading.ClassFilePostProcessor +net.bytebuddy.dynamic.loading.PackageDefinitionStrategy +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PackageLookupStrategy$CreationAction +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PackageLookupStrategy +net.bytebuddy.utility.JavaModule +net.bytebuddy.utility.JavaModule$Resolver +net.bytebuddy.utility.$Proxy60 +net.bytebuddy.utility.JavaModule$Module +net.bytebuddy.utility.$Proxy61 +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PackageLookupStrategy$ForJava9CapableVm +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$SynchronizationStrategy$CreationAction +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$SynchronizationStrategy$Initializable +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$SynchronizationStrategy +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$SynchronizationStrategy$ForJava8CapableVm +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PersistenceHandler +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PersistenceHandler$1 +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PersistenceHandler$2 +net.bytebuddy.dynamic.loading.PackageDefinitionStrategy$Trivial +net.bytebuddy.dynamic.loading.PackageDefinitionStrategy$Definition +net.bytebuddy.dynamic.loading.ClassFilePostProcessor$NoOp +org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$1 +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$2 +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$3 +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$4 +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$5 +net.bytebuddy.dynamic.scaffold.MethodRegistry$Handler +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$UsingTypeWriter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter +net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder +net.bytebuddy.dynamic.TypeResolutionStrategy +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ImplementationDefinition +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$TypeVariableDefinition +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ExceptionDefinition +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Optional +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Valuable +net.bytebuddy.implementation.attribute.TypeAttributeAppender +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator +net.bytebuddy.dynamic.DynamicType$Builder$InnerTypeDefinition +net.bytebuddy.dynamic.DynamicType$Builder$InnerTypeDefinition$ForType +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$InnerTypeDefinitionForTypeAdapter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$InnerTypeDefinitionForMethodAdapter +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ImplementationDefinition$Optional +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Simple +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Initial +net.bytebuddy.dynamic.DynamicType$Builder$TypeVariableDefinition +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Optional$Valuable +net.bytebuddy.dynamic.DynamicType$Builder$RecordComponentDefinition +net.bytebuddy.dynamic.DynamicType$Builder$RecordComponentDefinition$Optional +net.bytebuddy.dynamic.scaffold.RecordComponentRegistry +net.bytebuddy.dynamic.scaffold.MethodRegistry +net.bytebuddy.dynamic.scaffold.FieldRegistry +net.bytebuddy.implementation.Implementation$Target$Factory +net.bytebuddy.dynamic.scaffold.TypeWriter$RecordComponentPool +net.bytebuddy.dynamic.scaffold.TypeWriter$FieldPool +net.bytebuddy.description.modifier.ModifierContributor +net.bytebuddy.description.modifier.ModifierContributor$ForType +net.bytebuddy.description.modifier.ModifierContributor$ForMethod +net.bytebuddy.description.modifier.ModifierContributor$ForField +net.bytebuddy.description.modifier.Visibility +net.bytebuddy.description.modifier.TypeManifestation +net.bytebuddy.description.modifier.ModifierContributor$Resolver +net.bytebuddy.description.type.TypeDescription$AbstractBase$OfSimpleType +net.bytebuddy.dynamic.scaffold.InstrumentedType$Default +net.bytebuddy.dynamic.scaffold.TypeInitializer$None +net.bytebuddy.implementation.LoadedTypeInitializer$NoOp +net.bytebuddy.description.type.TypeDescription$LazyProxy +net.bytebuddy.description.modifier.Ownership +net.bytebuddy.description.modifier.ModifierContributor$ForParameter +net.bytebuddy.description.modifier.SyntheticState +net.bytebuddy.description.modifier.EnumerationState +net.bytebuddy.description.TypeVariableSource$Visitor +jdk.proxy2.$Proxy62 +net.bytebuddy.description.type.TypeList$Generic$ForLoadedTypes +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$ForDetachment +net.bytebuddy.dynamic.scaffold.FieldRegistry$Default +net.bytebuddy.dynamic.scaffold.FieldRegistry$Compiled +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default +net.bytebuddy.dynamic.scaffold.MethodRegistry$Prepared +net.bytebuddy.dynamic.scaffold.RecordComponentRegistry$Default +net.bytebuddy.dynamic.scaffold.RecordComponentRegistry$Compiled +net.bytebuddy.implementation.attribute.TypeAttributeAppender$ForInstrumentedType +net.bytebuddy.implementation.attribute.AnnotationAppender$Target +net.bytebuddy.implementation.attribute.AnnotationAppender +net.bytebuddy.asm.AsmVisitorWrapper$NoOp +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ImplementationDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$MethodMatchAdapter +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ReceiverTypeDefinition +net.bytebuddy.implementation.MethodCall$MethodLocator$Factory +net.bytebuddy.implementation.MethodCall$TerminationHandler$Factory +net.bytebuddy.implementation.MethodCall$MethodInvoker$Factory +net.bytebuddy.implementation.MethodCall$TargetHandler$Factory +net.bytebuddy.implementation.MethodCall$ArgumentLoader$Factory +net.bytebuddy.implementation.MethodCall$MethodLocator +net.bytebuddy.implementation.MethodCall$MethodLocator$ForExplicitMethod +net.bytebuddy.implementation.MethodCall$TargetHandler$ForField$Location +net.bytebuddy.implementation.MethodCall$TargetHandler$ForSelfOrStaticInvocation$Factory +net.bytebuddy.implementation.MethodCall$TargetHandler +net.bytebuddy.implementation.MethodCall$MethodInvoker$ForContextualInvocation$Factory +net.bytebuddy.implementation.MethodCall$MethodInvoker +net.bytebuddy.implementation.MethodCall$TerminationHandler +net.bytebuddy.implementation.MethodCall$TerminationHandler$Simple +net.bytebuddy.implementation.MethodCall$TerminationHandler$Simple$1 +net.bytebuddy.implementation.MethodCall$TerminationHandler$Simple$2 +net.bytebuddy.implementation.MethodCall$TerminationHandler$Simple$3 +net.bytebuddy.dynamic.scaffold.MethodRegistry$Handler$ForImplementation +net.bytebuddy.dynamic.scaffold.MethodRegistry$Handler$Compiled +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ReceiverTypeDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$AbstractBase$Adapter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$MethodMatchAdapter$AnnotationAdapter +net.bytebuddy.dynamic.Transformer +net.bytebuddy.implementation.attribute.MethodAttributeAppender +net.bytebuddy.implementation.attribute.MethodAttributeAppender$NoOp +net.bytebuddy.dynamic.Transformer$NoOp +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Entry +net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodCall$Factory +net.bytebuddy.implementation.MethodCall$MethodInvoker$ForVirtualInvocation$WithImplicitType +net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodParameter +net.bytebuddy.implementation.MethodCall$TargetHandler$Resolved +net.bytebuddy.implementation.MethodCall$ArgumentLoader$ArgumentProvider +net.bytebuddy.implementation.MethodCall$ArgumentLoader$ForMethodParameter$Factory +net.bytebuddy.dynamic.TypeResolutionStrategy$Resolved +net.bytebuddy.dynamic.TypeResolutionStrategy$Passive +net.bytebuddy.pool.TypePool$AbstractBase +net.bytebuddy.pool.TypePool$AbstractBase$Hierarchical +net.bytebuddy.pool.TypePool$ClassLoading +net.bytebuddy.pool.TypePool$Resolution +net.bytebuddy.pool.TypePool$CacheProvider +net.bytebuddy.pool.TypePool$Empty +net.bytebuddy.pool.TypePool$CacheProvider$Simple +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithResolvedErasure +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$ForAttachment +net.bytebuddy.description.method.MethodList$TypeSubstituting +net.bytebuddy.description.method.MethodDescription$InGenericShape +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$ForRawType +net.bytebuddy.matcher.VisibilityMatcher +net.bytebuddy.description.method.MethodDescription$TypeSubstituting +net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType$ForGenerifiedErasure +net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType$ForErasure +net.bytebuddy.description.type.TypeList$Generic$ForLoadedTypes$OfTypeVariables +net.bytebuddy.description.method.MethodDescription$Token +net.bytebuddy.matcher.TypeSortMatcher +net.bytebuddy.description.ByteCodeElement$Token$TokenList +net.bytebuddy.description.method.ParameterList$TypeSubstituting +net.bytebuddy.description.method.ParameterDescription$InGenericShape +net.bytebuddy.description.type.TypeList$Generic$ForDetachedTypes +net.bytebuddy.description.type.TypeList$Generic$OfConstructorExceptionTypes +jdk.internal.vm.annotation.IntrinsicCandidate +com.sun.proxy.jdk.proxy1.$Proxy63 +net.bytebuddy.description.annotation.AnnotationList$Explicit +net.bytebuddy.description.type.TypeDescription$Generic$LazyProxy +jdk.proxy2.$Proxy64 +net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder$InstrumentableMatcher +net.bytebuddy.description.method.MethodList$ForTokens +net.bytebuddy.description.method.MethodDescription$Latent +net.bytebuddy.description.method.ParameterList$ForTokens +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithLazyNavigation +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithLazyNavigation$OfAnnotatedElement +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$ForLoadedSuperClass +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store$Entry +net.bytebuddy.description.type.TypeList$Generic$ForDetachedTypes$WithResolvedErasure +net.bytebuddy.description.type.TypeList$Generic$OfLoadedInterfaceTypes +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Harmonized +net.bytebuddy.description.method.MethodDescription$TypeToken +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Harmonizer$ForJavaMethod$Token +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store$Entry$Initial +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store$Entry$Resolved +net.bytebuddy.dynamic.scaffold.MethodGraph$Node +net.bytebuddy.description.method.ParameterDescription$TypeSubstituting +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store$Entry$Resolved$Node +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Detached +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store$Graph +net.bytebuddy.dynamic.scaffold.MethodGraph$Linked$Delegation +net.bytebuddy.matcher.MethodParameterTypeMatcher +net.bytebuddy.matcher.FailSafeMatcher +net.bytebuddy.dynamic.scaffold.MethodGraph$NodeList +net.bytebuddy.dynamic.scaffold.MethodGraph$Node$Sort +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Prepared$Entry +net.bytebuddy.description.method.MethodDescription$Latent$TypeInitializer +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Prepared +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool +net.bytebuddy.dynamic.scaffold.MethodRegistry$Compiled +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Validator +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Validator$1 +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Validator$2 +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Validator$3 +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Validator$ForTypeAnnotations +net.bytebuddy.description.annotation.AnnotationList$Empty +net.bytebuddy.description.type.TypeList$Generic$ForDetachedTypes$OfTypeVariables +net.bytebuddy.description.type.PackageDescription$AbstractBase +net.bytebuddy.description.type.PackageDescription$Simple +net.bytebuddy.description.field.FieldList$AbstractBase +net.bytebuddy.description.field.FieldList$ForTokens +net.bytebuddy.description.method.MethodDescription$SignatureToken +net.bytebuddy.description.annotation.AnnotationValue$ForDescriptionArray +net.bytebuddy.description.annotation.AnnotationValue$Sort +net.bytebuddy.description.annotation.AnnotationValue$State +net.bytebuddy.dynamic.scaffold.subclass.SubclassImplementationTarget$Factory +net.bytebuddy.implementation.Implementation$Target +net.bytebuddy.dynamic.scaffold.subclass.SubclassImplementationTarget$OriginTypeResolver +net.bytebuddy.dynamic.scaffold.subclass.SubclassImplementationTarget$OriginTypeResolver$1 +net.bytebuddy.dynamic.scaffold.subclass.SubclassImplementationTarget$OriginTypeResolver$2 +net.bytebuddy.implementation.Implementation$Target$AbstractBase +net.bytebuddy.dynamic.scaffold.subclass.SubclassImplementationTarget +net.bytebuddy.implementation.Implementation$SpecialMethodInvocation +net.bytebuddy.implementation.Implementation$Target$AbstractBase$DefaultMethodInvocation +net.bytebuddy.implementation.Implementation$Target$AbstractBase$DefaultMethodInvocation$1 +net.bytebuddy.implementation.Implementation$Target$AbstractBase$DefaultMethodInvocation$2 +net.bytebuddy.dynamic.scaffold.MethodRegistry$Handler$ForImplementation$Compiled +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record +net.bytebuddy.implementation.MethodCall$Appender +net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodCall +net.bytebuddy.implementation.MethodCall$MethodInvoker$ForContextualInvocation +net.bytebuddy.implementation.MethodCall$TargetHandler$ForSelfOrStaticInvocation +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Compiled$Entry +net.bytebuddy.implementation.SuperMethodCall$Appender +net.bytebuddy.implementation.SuperMethodCall$Appender$TerminationHandler +net.bytebuddy.implementation.SuperMethodCall$Appender$TerminationHandler$1 +net.bytebuddy.implementation.SuperMethodCall$Appender$TerminationHandler$2 +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Compiled +net.bytebuddy.dynamic.scaffold.FieldRegistry$Default$Compiled +net.bytebuddy.dynamic.scaffold.TypeWriter$FieldPool$Record +net.bytebuddy.dynamic.scaffold.RecordComponentRegistry$Default$Compiled +net.bytebuddy.dynamic.scaffold.TypeWriter$RecordComponentPool$Record +net.bytebuddy.pool.TypePool$Explicit +net.bytebuddy.pool.TypePool$CacheProvider$NoOp +net.bytebuddy.dynamic.scaffold.TypeWriter +net.bytebuddy.dynamic.scaffold.TypeWriter$Default +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ClassDumpAction$Dispatcher +net.bytebuddy.dynamic.scaffold.inline.MethodRebaseResolver +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation +net.bytebuddy.utility.visitor.MetadataAwareClassVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation$CreationClassVisitor +net.bytebuddy.utility.visitor.ContextClassVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation$ImplementationContextClassVisitor +net.bytebuddy.dynamic.scaffold.TypeInitializer$Drain +net.bytebuddy.description.type.RecordComponentList$ForTokens +net.bytebuddy.description.type.RecordComponentDescription +net.bytebuddy.description.type.RecordComponentDescription$InDefinedShape +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ClassDumpAction$Dispatcher$Disabled +net.bytebuddy.utility.AsmClassWriter$Factory$Default$EmptyAsmClassReader +net.bytebuddy.utility.AsmClassWriter$ForAsm +net.bytebuddy.implementation.Implementation$Context$FrameGeneration +net.bytebuddy.implementation.Implementation$Context$FrameGeneration$1 +net.bytebuddy.implementation.Implementation$Context$FrameGeneration$2 +net.bytebuddy.implementation.Implementation$Context$FrameGeneration$3 +net.bytebuddy.implementation.Implementation$Context$ExtractableView$AbstractBase +net.bytebuddy.implementation.Implementation$Context$Default +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod +net.bytebuddy.implementation.Implementation$Context$Default$DelegationRecord +net.bytebuddy.implementation.Implementation$Context$Default$AccessorMethodDelegation +net.bytebuddy.implementation.Implementation$Context$Default$FieldGetterDelegation +net.bytebuddy.implementation.Implementation$Context$Default$FieldSetterDelegation +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$Constraint +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$ValidatingFieldVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$ValidatingMethodVisitor +net.bytebuddy.jar.asm.signature.SignatureVisitor +net.bytebuddy.jar.asm.signature.SignatureWriter +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$ForSignatureVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$Constraint$ForClassFileVersion +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$Constraint$ForClass +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$Constraint$Compound +net.bytebuddy.implementation.attribute.AnnotationAppender$Default +net.bytebuddy.implementation.attribute.AnnotationAppender$Target$OnType +net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations +java.util.AbstractList$SubList +net.bytebuddy.jar.asm.TypeReference +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$AccessBridgeWrapper +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$Sort +net.bytebuddy.description.modifier.Visibility$1 +net.bytebuddy.description.type.TypeList$Generic$OfMethodExceptionTypes +net.bytebuddy.implementation.MethodCall$TargetHandler$ForSelfOrStaticInvocation$Resolved +net.bytebuddy.implementation.bytecode.Duplication +net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodCall$Resolved +net.bytebuddy.implementation.bytecode.ByteCodeAppender$Size +net.bytebuddy.implementation.bytecode.StackManipulation$Compound +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess$MethodLoading$TypeCastingHandler +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess$OffsetLoading +net.bytebuddy.implementation.bytecode.member.MethodInvocation +net.bytebuddy.implementation.bytecode.member.MethodInvocation$WithImplicitInvocationTargetType +net.bytebuddy.implementation.bytecode.member.MethodInvocation$Invocation +net.bytebuddy.implementation.bytecode.member.MethodReturn +net.bytebuddy.implementation.bytecode.StackManipulation$Size +net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodParameter$Resolved +net.bytebuddy.implementation.MethodCall$ArgumentLoader +net.bytebuddy.implementation.MethodCall$ArgumentLoader$ForMethodParameter +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveWideningDelegate +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveWideningDelegate$WideningStackManipulation +net.bytebuddy.description.type.TypeList$Generic$OfMethodExceptionTypes$TypeProjection +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedExecutableExceptionType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedExecutableExceptionType$Dispatcher +net.bytebuddy.description.type.$Proxy65 +net.bytebuddy.matcher.SignatureTokenMatcher +net.bytebuddy.implementation.Implementation$SpecialMethodInvocation$AbstractBase +net.bytebuddy.implementation.Implementation$SpecialMethodInvocation$Simple +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess$MethodLoading +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess$MethodLoading$TypeCastingHandler$NoOp +net.bytebuddy.dynamic.scaffold.TypeInitializer$Drain$Default +net.bytebuddy.description.method.ParameterList$Empty +net.bytebuddy.description.type.TypeList$Generic$Empty +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForNonImplementedMethod +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$UnresolvedType +net.bytebuddy.dynamic.DynamicType +net.bytebuddy.dynamic.DynamicType$Unloaded +net.bytebuddy.dynamic.DynamicType$AbstractBase +net.bytebuddy.dynamic.DynamicType$Default +net.bytebuddy.dynamic.DynamicType$Default$Unloaded +net.bytebuddy.dynamic.DynamicType$Loaded +net.bytebuddy.dynamic.loading.InjectionClassLoader$Strategy +net.bytebuddy.dynamic.DynamicType$Default$Loaded +java.lang.invoke.LambdaForm$MH/0x00007faab42dc000 +java.lang.invoke.MethodHandleImpl$WrappedMember +java.lang.invoke.MethodHandleImpl$CasesHolder +java.lang.invoke.MethodHandleImpl$LoopClauses +java.lang.invoke.MethodHandleImpl$ArrayAccess +java.lang.invoke.MethodHandleImpl$2 +java.lang.invoke.MethodHandleImpl$ArrayAccessor +java.lang.invoke.MethodHandleImpl$ArrayAccessor$1 +java.lang.invoke.LambdaForm$DMH/0x00007faab42dc400 +java.lang.invoke.LambdaForm$DMH/0x00007faab42dc800 +java.lang.invoke.LambdaForm$MH/0x00007faab42dcc00 +java.lang.invoke.LambdaForm$MH/0x00007faab42dd000 +java.lang.invoke.BoundMethodHandle$Species_LLL +java.lang.invoke.LambdaForm$MH/0x00007faab42dd400 +java.lang.invoke.LambdaForm$MH/0x00007faab42dd800 +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$ClassDefinitionAction +net.bytebuddy.dynamic.loading.PackageDefinitionStrategy$Definition$Trivial +org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$csVRoV61 +java.lang.invoke.LambdaForm$DMH/0x00007faab42de000 +org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleanerProvider +org.mockito.internal.configuration.InjectingAnnotationEngine +org.mockito.internal.configuration.IndependentAnnotationEngine +org.mockito.internal.configuration.FieldAnnotationProcessor +org.mockito.internal.configuration.MockAnnotationProcessor +org.mockito.Captor +org.mockito.internal.configuration.CaptorAnnotationProcessor +org.mockito.internal.configuration.SpyAnnotationEngine +org.mockito.internal.util.ConsoleMockitoLogger +org.mockito.plugins.MockResolver +org.mockito.plugins.DoNotMockEnforcer +org.mockito.internal.configuration.DefaultDoNotMockEnforcer +org.mockito.internal.creation.instance.DefaultInstantiatorProvider +org.mockito.internal.creation.instance.ObjenesisInstantiator +org.objenesis.Objenesis +org.objenesis.ObjenesisBase +org.objenesis.ObjenesisStd +org.objenesis.strategy.InstantiatorStrategy +org.objenesis.strategy.BaseInstantiatorStrategy +org.objenesis.strategy.StdInstantiatorStrategy +org.objenesis.instantiator.ObjectInstantiator +org.mockito.internal.util.Supplier +org.mockito.internal.configuration.MockAnnotationProcessor$$Lambda$664/0x00007faab42e0650 +org.mockito.ArgumentMatchers +org.mockito.Mockito +org.mockito.ArgumentMatcher +org.mockito.verification.VerificationMode +org.mockito.verification.VerificationAfterDelay +org.mockito.verification.VerificationWithTimeout +org.mockito.MockitoFramework +org.mockito.session.MockitoSessionBuilder +org.mockito.internal.MockitoCore +org.mockito.stubbing.BaseStubber +org.mockito.stubbing.LenientStubber +org.mockito.ScopedMock +org.mockito.MockedStatic +org.mockito.MockedConstruction +org.mockito.MockingDetails +org.mockito.exceptions.misusing.NotAMockException +org.mockito.internal.verification.api.VerificationData +org.mockito.stubbing.Stubber +org.mockito.InOrder +org.mockito.exceptions.misusing.DoNotMockException +org.mockito.internal.verification.api.VerificationDataInOrder +org.mockito.MockSettings +org.mockito.mock.MockCreationSettings +org.mockito.internal.creation.settings.CreationSettings +org.mockito.internal.creation.MockSettingsImpl +org.mockito.mock.MockName +org.mockito.mock.SerializableMode +org.mockito.internal.util.MockCreationValidator +org.mockito.internal.util.MockUtil +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$1 +org.mockito.mock.MockType +org.mockito.internal.util.MockNameImpl +org.mockito.plugins.DoNotMockEnforcer$Cache +org.mockito.internal.handler.MockHandlerFactory +org.mockito.invocation.MockHandler +org.mockito.internal.handler.MockHandlerImpl +org.mockito.invocation.MatchableInvocation +org.mockito.stubbing.OngoingStubbing +org.mockito.stubbing.Stubbing +org.mockito.invocation.InvocationContainer +org.mockito.internal.invocation.MatchersBinder +org.mockito.internal.stubbing.InvocationContainerImpl +org.mockito.invocation.StubInfo +org.mockito.internal.verification.RegisteredInvocations +org.mockito.internal.verification.DefaultRegisteredInvocations +org.mockito.internal.stubbing.DoAnswerStyleStubbing +org.mockito.internal.handler.NullResultGuardian +org.mockito.internal.handler.InvocationNotifierHandler +org.mockito.listeners.MethodInvocationReport +org.mockito.internal.creation.bytebuddy.MockFeatures +net.bytebuddy.TypeCache$SimpleKey +org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$MockitoMockKey +org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$$Lambda$665/0x00007faab42e8000 +net.bytebuddy.TypeCache$LookupKey +org.mockito.internal.creation.bytebuddy.TypeSupport +org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator$$Lambda$666/0x00007faab42e8650 +org.mockito.internal.util.concurrent.WeakConcurrentMap$WeakKey +org.mockito.internal.util.concurrent.WeakConcurrentMap$LatentKey +sun.instrument.InstrumentationImpl$$Lambda$667/0x00007faab41e0010 +sun.instrument.InstrumentationImpl$$Lambda$668/0x00007faab41e0248 +net.bytebuddy.dynamic.ClassFileLocator$Simple +net.bytebuddy.dynamic.scaffold.inline.AbstractInliningDynamicTypeBuilder +net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder +net.bytebuddy.description.type.TypeList$Generic$OfLoadedInterfaceTypes$TypeProjection +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedInterface +net.bytebuddy.description.field.FieldList$ForLoadedFields +net.bytebuddy.utility.FieldComparator +com.networknt.schema.SpecVersion$VersionFlag +sun.reflect.annotation.TypeAnnotation$TypeAnnotationTarget +sun.reflect.annotation.TypeAnnotationParser +sun.reflect.annotation.TypeAnnotation +sun.reflect.annotation.TypeAnnotation$LocationInfo +sun.reflect.annotation.TypeAnnotation$LocationInfo$Location +sun.reflect.annotation.AnnotatedTypeFactory +sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$Simple +net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType$Latent +java.lang.Class$EnclosingMethodInfo +net.bytebuddy.description.type.RecordComponentDescription$Token +net.bytebuddy.implementation.attribute.TypeAttributeAppender$ForInstrumentedType$Differentiating +net.bytebuddy.asm.AsmVisitorWrapper$AbstractBase +org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator$ParameterWritingVisitorWrapper +org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator$ParameterWritingVisitorWrapper$ParameterAddingClassVisitor +net.bytebuddy.asm.AsmVisitorWrapper$Compound +net.bytebuddy.pool.TypePool$Default +net.bytebuddy.pool.TypePool$Default$TypeExtractor +net.bytebuddy.pool.TypePool$Default$ReaderMode +net.bytebuddy.dynamic.scaffold.inline.InliningImplementationMatcher +net.bytebuddy.dynamic.scaffold.MethodGraph$Node$Simple +net.bytebuddy.dynamic.scaffold.MethodGraph$Simple +net.bytebuddy.dynamic.scaffold.MethodGraph$Empty +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$RegistryContextClassVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor +net.bytebuddy.jar.asm.commons.Remapper +net.bytebuddy.jar.asm.commons.SimpleRemapper +net.bytebuddy.jar.asm.commons.ClassRemapper +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$OpenedClassRemapper +net.bytebuddy.dynamic.scaffold.inline.MethodRebaseResolver$Disabled +net.bytebuddy.dynamic.scaffold.inline.MethodRebaseResolver$Resolution +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$ContextRegistry +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$InitializationHandler +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor$AttributeObtainingRecordComponentVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor$AttributeObtainingFieldVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor$AttributeObtainingMethodVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor$CodePreservingMethodVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor$DeduplicatingClassVisitor +net.bytebuddy.jar.asm.Context +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$InitializationHandler$Creating +net.bytebuddy.implementation.Implementation$Context$Disabled +org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator$ParameterWritingVisitorWrapper$MethodParameterStrippingMethodVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$SignatureKey +net.bytebuddy.matcher.DescriptorMatcher +software.amazon.lambda.powertools.validation.Validation +net.bytebuddy.description.method.ParameterDescription$Token +net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType$ForLoadedType$ParameterArgumentTypeList +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeArgument +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeArgument$AnnotatedParameterizedType +java.lang.reflect.AnnotatedParameterizedType +net.bytebuddy.description.type.$Proxy66 +net.bytebuddy.description.type.TypeDescription$Generic$OfWildcardType +net.bytebuddy.description.type.TypeDescription$Generic$OfWildcardType$ForLoadedType +net.bytebuddy.description.type.TypeDescription$Generic$OfWildcardType$Latent +net.bytebuddy.description.type.TypeDescription$Generic$OfWildcardType$ForLoadedType$WildcardUpperBoundTypeList +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForWildcardUpperBoundType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForWildcardUpperBoundType$AnnotatedWildcardType +java.lang.reflect.AnnotatedWildcardType +net.bytebuddy.description.type.$Proxy67 +net.bytebuddy.description.type.TypeDescription$Generic$OfWildcardType$ForLoadedType$WildcardLowerBoundTypeList +net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType$Latent +net.bytebuddy.description.method.ParameterDescription$Latent +java.lang.annotation.Annotation +net.bytebuddy.dynamic.loading.MultipleParentClassLoader$Builder +net.bytebuddy.dynamic.loading.MultipleParentClassLoader +jdk.internal.reflect.GeneratedMethodAccessor3 +net.bytebuddy.matcher.LatentMatcher$Disjunction +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$OptionalMethodMatchAdapter +net.bytebuddy.description.modifier.SynchronizationState +net.bytebuddy.dynamic.Transformer$ForMethod +net.bytebuddy.dynamic.Transformer$ForMethod$MethodModifierTransformer +net.bytebuddy.dynamic.Transformer$Compound +net.bytebuddy.implementation.attribute.MethodAttributeAppender$ForInstrumentedMethod +net.bytebuddy.implementation.attribute.MethodAttributeAppender$ForInstrumentedMethod$1 +net.bytebuddy.implementation.attribute.MethodAttributeAppender$ForInstrumentedMethod$2 +net.bytebuddy.implementation.attribute.MethodAttributeAppender$Factory$Compound +net.bytebuddy.description.modifier.FieldManifestation +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Optional$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Optional$Valuable$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Optional$Valuable$AbstractBase$Adapter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$FieldDefinitionAdapter +net.bytebuddy.implementation.attribute.FieldAttributeAppender$Factory +net.bytebuddy.description.field.FieldDescription$Token +net.bytebuddy.implementation.attribute.FieldAttributeAppender +net.bytebuddy.implementation.attribute.FieldAttributeAppender$ForInstrumentedField +net.bytebuddy.matcher.LatentMatcher$ForFieldToken +net.bytebuddy.dynamic.scaffold.FieldRegistry$Default$Entry +net.bytebuddy.implementation.FieldAccessor +net.bytebuddy.implementation.FieldAccessor$FieldLocation +net.bytebuddy.implementation.FieldAccessor$PropertyConfigurable +net.bytebuddy.implementation.FieldAccessor$AssignerConfigurable +net.bytebuddy.implementation.FieldAccessor$OwnerTypeLocatable +net.bytebuddy.implementation.FieldAccessor$FieldNameExtractor +net.bytebuddy.implementation.FieldAccessor$FieldNameExtractor$ForBeanProperty +net.bytebuddy.implementation.FieldAccessor$FieldNameExtractor$ForBeanProperty$1 +net.bytebuddy.implementation.FieldAccessor$FieldNameExtractor$ForBeanProperty$2 +net.bytebuddy.implementation.FieldAccessor$ForImplicitProperty +net.bytebuddy.implementation.FieldAccessor$FieldLocation$Relative +net.bytebuddy.implementation.FieldAccessor$FieldLocation$Prepared +net.bytebuddy.dynamic.scaffold.FieldLocator$ForClassHierarchy$Factory +net.bytebuddy.matcher.SuperTypeMatcher +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$TypeVariableDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ExceptionDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Initial$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$MethodDefinitionAdapter +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$TypeVariableDefinition$Annotatable +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Annotatable +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Simple$Annotatable +net.bytebuddy.description.method.ParameterDescription$Token$TypeList +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Simple$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Simple$Annotatable$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Simple$Annotatable$AbstractBase$Adapter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$MethodDefinitionAdapter$SimpleParameterAnnotationAdapter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$MethodDefinitionAdapter$AnnotationAdapter +net.bytebuddy.dynamic.loading.ClassLoadingStrategy$UsingLookup +net.bytebuddy.dynamic.loading.ClassInjector +net.bytebuddy.dynamic.loading.ClassInjector$AbstractBase +net.bytebuddy.dynamic.loading.ClassInjector$UsingLookup +net.bytebuddy.dynamic.loading.ClassInjector$UsingLookup$MethodHandles +net.bytebuddy.dynamic.loading.$Proxy68 +net.bytebuddy.dynamic.loading.ClassInjector$UsingLookup$MethodHandles$Lookup +jdk.proxy2.$Proxy69 +net.bytebuddy.utility.JavaType +net.bytebuddy.description.type.TypeDescription$Latent +net.bytebuddy.utility.JavaType$LatentTypeWithSimpleName +net.bytebuddy.matcher.LatentMatcher$ForMethodToken +net.bytebuddy.matcher.LatentMatcher$ForMethodToken$ResolvedMatcher +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Reducing +net.bytebuddy.dynamic.Transformer$ForMethod$TransformedMethod +jdk.internal.reflect.GeneratedMethodAccessor4 +net.bytebuddy.implementation.MethodDelegation$ImplementationDelegate$Compiled$ForStaticCall +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodInvoker +net.bytebuddy.implementation.MethodDelegation$Appender +net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor +net.bytebuddy.implementation.attribute.MethodAttributeAppender$Compound +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$WithoutTypeSubstitution +net.bytebuddy.dynamic.Transformer$ForMethod$TransformedMethod$AttachmentVisitor +net.bytebuddy.dynamic.Transformer$ForMethod$TransformedMethod$TransformedParameterList +net.bytebuddy.implementation.FieldAccessor$ForImplicitProperty$Appender +net.bytebuddy.implementation.FieldAccessor$FieldLocation$Relative$Prepared +net.bytebuddy.dynamic.scaffold.FieldLocator$Resolution +net.bytebuddy.dynamic.scaffold.FieldRegistry$Default$Compiled$Entry +net.bytebuddy.matcher.LatentMatcher$ForFieldToken$ResolvedMatcher +net.bytebuddy.description.field.FieldDescription$SignatureToken +net.bytebuddy.description.type.TypeVariableToken +net.bytebuddy.implementation.attribute.AnnotationAppender$1 +net.bytebuddy.description.annotation.AnnotationValue$Loaded$AbstractBase +net.bytebuddy.description.annotation.AnnotationValue$ForEnumerationDescription$Loaded +net.bytebuddy.description.field.FieldDescription$AbstractBase +net.bytebuddy.description.field.FieldDescription$InDefinedShape$AbstractBase +net.bytebuddy.description.field.FieldDescription$Latent +net.bytebuddy.dynamic.scaffold.TypeWriter$FieldPool$Record$ForExplicitField +net.bytebuddy.implementation.attribute.AnnotationAppender$Target$OnField +net.bytebuddy.implementation.attribute.AnnotationAppender$Target$OnMethod +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodInvoker$Simple +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Builder +net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding$Anonymous +net.bytebuddy.description.type.TypeDefinition$SuperClassIterator +net.bytebuddy.description.field.FieldList$Explicit +net.bytebuddy.dynamic.scaffold.FieldLocator$Resolution$Simple +net.bytebuddy.implementation.bytecode.member.FieldAccess +net.bytebuddy.implementation.bytecode.member.FieldAccess$Defined +net.bytebuddy.implementation.bytecode.member.FieldAccess$AccessDispatcher +net.bytebuddy.implementation.bytecode.member.FieldAccess$AccessDispatcher$AbstractFieldInstruction +net.bytebuddy.implementation.bytecode.member.FieldAccess$AccessDispatcher$FieldGetInstruction +net.bytebuddy.implementation.bytecode.constant.MethodConstant +net.bytebuddy.implementation.bytecode.constant.MethodConstant$CanCache +net.bytebuddy.implementation.bytecode.constant.MethodConstant$ForMethod +net.bytebuddy.implementation.bytecode.constant.MethodConstant$CachedMethod +net.bytebuddy.implementation.bytecode.collection.CollectionFactory +net.bytebuddy.implementation.bytecode.collection.ArrayFactory +net.bytebuddy.implementation.bytecode.collection.ArrayFactory$ArrayCreator +net.bytebuddy.implementation.bytecode.collection.ArrayFactory$ArrayCreator$ForReferenceType +net.bytebuddy.implementation.bytecode.collection.ArrayFactory$ArrayStackManipulation +net.bytebuddy.implementation.auxiliary.MethodCallProxy$AssignableSignatureCall +net.bytebuddy.implementation.auxiliary.AuxiliaryType +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Builder$Build +net.bytebuddy.implementation.bytecode.constant.DefaultValue +net.bytebuddy.implementation.bytecode.constant.IntegerConstant +net.bytebuddy.implementation.bytecode.constant.LongConstant +net.bytebuddy.implementation.bytecode.constant.FloatConstant +net.bytebuddy.implementation.bytecode.constant.DoubleConstant +net.bytebuddy.implementation.bytecode.constant.NullConstant +net.bytebuddy.implementation.bind.MethodDelegationBinder$1 +net.bytebuddy.implementation.bind.MethodDelegationBinder$AmbiguityResolver$Resolution +net.bytebuddy.implementation.Implementation$Context$Default$FieldCacheEntry +net.bytebuddy.implementation.Implementation$Context$Default$CacheValueField +net.bytebuddy.implementation.auxiliary.MethodCallProxy +net.bytebuddy.implementation.MethodAccessorFactory$AccessType +net.bytebuddy.implementation.Implementation$Context$Default$AbstractPropertyAccessorMethod +net.bytebuddy.implementation.Implementation$Context$Default$AccessorMethod +net.bytebuddy.description.method.ParameterList$Explicit$ForTypes +net.bytebuddy.implementation.auxiliary.MethodCallProxy$PrecomputedMethodGraph +net.bytebuddy.implementation.auxiliary.MethodCallProxy$MethodCall +net.bytebuddy.implementation.auxiliary.MethodCallProxy$ConstructorCall +net.bytebuddy.implementation.auxiliary.MethodCallProxy$MethodCall$Appender +net.bytebuddy.implementation.auxiliary.MethodCallProxy$ConstructorCall$Appender +net.bytebuddy.implementation.bytecode.Removal +net.bytebuddy.implementation.bytecode.Removal$1 +net.bytebuddy.implementation.bytecode.Removal$2 +net.bytebuddy.implementation.attribute.AnnotationAppender$Target$OnMethodParameter +net.bytebuddy.implementation.bytecode.member.FieldAccess$AccessDispatcher$FieldPutInstruction +net.bytebuddy.implementation.bytecode.TypeCreation +net.bytebuddy.implementation.bytecode.Duplication$1 +net.bytebuddy.implementation.bytecode.Duplication$2 +net.bytebuddy.implementation.bytecode.Duplication$3 +net.bytebuddy.implementation.bind.ArgumentTypeResolver$ParameterIndexToken +net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding$Unique +net.bytebuddy.implementation.bytecode.assign.TypeCasting +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$ForSignatureVisitor$OfTypeArgument +sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedParameterizedTypeImpl +sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedWildcardTypeImpl +net.bytebuddy.dynamic.scaffold.MethodGraph$Node$Unresolved +net.bytebuddy.implementation.Implementation$SpecialMethodInvocation$Illegal +net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding$Illegal +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Illegal +com.networknt.schema.SpecVersion +jdk.internal.reflect.GeneratedMethodAccessor5 +jdk.internal.reflect.GeneratedMethodAccessor6 +jdk.internal.reflect.GeneratedMethodAccessor7 +jdk.internal.reflect.GeneratedMethodAccessor8 +jdk.internal.reflect.GeneratedMethodAccessor9 +jdk.internal.reflect.GeneratedMethodAccessor10 +net.bytebuddy.dynamic.scaffold.FieldLocator$Resolution$Illegal +net.bytebuddy.implementation.bytecode.ByteCodeAppender$Simple +net.bytebuddy.dynamic.scaffold.TypeInitializer$Simple +net.bytebuddy.implementation.bytecode.ByteCodeAppender$Compound +net.bytebuddy.implementation.bytecode.constant.ClassConstant +net.bytebuddy.implementation.bytecode.constant.ClassConstant$ForReferenceType +net.bytebuddy.description.type.PackageDescription$ForLoadedPackage +software.amazon.lambda.powertools.validation.Validation$MockitoMock$r3AWkvyb +software.amazon.lambda.powertools.validation.Validation$MockitoMock$r3AWkvyb$auxiliary$a0EM2a2n +software.amazon.lambda.powertools.validation.Validation$MockitoMock$r3AWkvyb$auxiliary$RFyMI1P9 +net.bytebuddy.TypeCache$StorageKey +org.mockito.plugins.MemberAccessor$OnConstruction +org.mockito.plugins.MemberAccessor$ConstructionDispatcher +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$$Lambda$669/0x00007faab431f9a8 +java.lang.invoke.LambdaForm$MH/0x00007faab431d800 +java.lang.invoke.LambdaForm$MH/0x00007faab431dc00 +java.lang.invoke.LambdaForm$MH/0x00007faab4320000 +java.lang.invoke.LambdaForm$MH/0x00007faab4320400 +sun.invoke.util.ValueConversions$WrapperCache +java.lang.invoke.LambdaForm$MH/0x00007faab4320800 +java.lang.invoke.LambdaForm$MH/0x00007faab4320c00 +java.lang.invoke.BoundMethodHandle$Species_LLLL +java.lang.invoke.LambdaForm$MH/0x00007faab4321000 +java.lang.invoke.LambdaForm$MH/0x00007faab4321400 +java.lang.invoke.LambdaForm$MH/0x00007faab4321800 +org.mockito.internal.util.reflection.InstrumentationMemberAccessor$$Lambda$670/0x00007faab431fbd0 +org.mockito.invocation.Invocation +org.mockito.internal.creation.bytebuddy.ByteBuddyCrossClassLoaderSerializationSupport +org.mockito.exceptions.base.MockitoSerializationIssue +org.mockito.internal.progress.ThreadSafeMockingProgress +org.mockito.internal.progress.ThreadSafeMockingProgress$1 +org.mockito.internal.progress.MockingProgress +org.mockito.internal.progress.MockingProgressImpl +org.mockito.internal.progress.ArgumentMatcherStorage +org.mockito.verification.VerificationStrategy +org.mockito.internal.progress.ArgumentMatcherStorageImpl +java.util.Stack +org.mockito.internal.progress.MockingProgressImpl$1 +java.lang.invoke.LambdaForm$MH/0x00007faab4321c00 +java.lang.invoke.LambdaForm$MH/0x00007faab4322000 +java.lang.invoke.LambdaForm$MH/0x00007faab4322400 +jdk.internal.reflect.GeneratedMethodAccessor11 +org.aspectj.lang.Signature +jdk.internal.reflect.GeneratedMethodAccessor12 +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveUnboxingDelegate +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveUnboxingDelegate$UnboxingResponsible +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveUnboxingDelegate$ImplicitlyTypedUnboxingResponsible +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveBoxingDelegate +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveBoxingDelegate$BoxingStackManipulation +jdk.internal.reflect.GeneratedMethodAccessor13 +jdk.internal.reflect.GeneratedMethodAccessor14 +org.aspectj.lang.Signature$MockitoMock$F8wJJwod +org.aspectj.lang.Signature$MockitoMock$F8wJJwod$auxiliary$TN3rx6QT +org.aspectj.lang.Signature$MockitoMock$F8wJJwod$auxiliary$MUj6Pxo6 +com.amazonaws.services.lambda.runtime.LambdaLogger +com.amazonaws.services.lambda.runtime.CognitoIdentity +com.amazonaws.services.lambda.runtime.ClientContext +net.bytebuddy.jar.asm.Label +net.bytebuddy.utility.visitor.StackAwareMethodVisitor +net.bytebuddy.asm.Advice$ArgumentHandler$Factory +net.bytebuddy.asm.Advice$ArgumentHandler$Factory$1 +net.bytebuddy.asm.Advice$ArgumentHandler$Factory$2 +net.bytebuddy.asm.Advice$ArgumentHandler$ForInstrumentedMethod +net.bytebuddy.asm.Advice$ArgumentHandler$ForInstrumentedMethod$Default +net.bytebuddy.asm.Advice$ArgumentHandler$ForInstrumentedMethod$Default$Copying +net.bytebuddy.asm.Advice$ArgumentHandler$ForAdvice +net.bytebuddy.asm.Advice$MethodSizeHandler +net.bytebuddy.asm.Advice$MethodSizeHandler$ForInstrumentedMethod +net.bytebuddy.asm.Advice$MethodSizeHandler$Default +net.bytebuddy.asm.Advice$MethodSizeHandler$ForAdvice +net.bytebuddy.asm.Advice$MethodSizeHandler$Default$WithCopiedArguments +net.bytebuddy.asm.Advice$StackMapFrameHandler +net.bytebuddy.asm.Advice$StackMapFrameHandler$ForInstrumentedMethod +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default +net.bytebuddy.asm.Advice$StackMapFrameHandler$ForPostProcessor +net.bytebuddy.asm.Advice$StackMapFrameHandler$ForAdvice +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default$WithPreservedArguments +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default$WithPreservedArguments$WithArgumentCopy +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$AdviceMethodInliner +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$AdviceMethodInliner$ExceptionTableExtractor +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$AdviceMethodInliner$ExceptionTableSubstitutor +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$Bound +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$Relocation$ForLabel +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$AdviceMethodInliner$ExceptionTableCollector +java.util.TreeMap$EntrySet +java.util.TreeMap$EntryIterator +net.bytebuddy.asm.Advice$ArgumentHandler$ForAdvice$Default +net.bytebuddy.asm.Advice$ArgumentHandler$ForAdvice$Default$ForMethodEnter +net.bytebuddy.asm.Advice$MethodSizeHandler$Default$ForAdvice +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default$ForAdvice +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default$TranslationMode +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default$TranslationMode$1 +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default$TranslationMode$2 +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default$TranslationMode$3 +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default$Initialization +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default$Initialization$1 +net.bytebuddy.asm.Advice$StackMapFrameHandler$Default$Initialization$2 +net.bytebuddy.asm.Advice$OffsetMapping$Sort +net.bytebuddy.asm.Advice$OffsetMapping$Sort$1 +net.bytebuddy.asm.Advice$OffsetMapping$Sort$2 +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForStackManipulation +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForVariable +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForVariable$ReadOnly +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForArray +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForArray$ReadOnly +net.bytebuddy.jar.asm.Opcodes +net.bytebuddy.asm.Advice$ArgumentHandler$ForAdvice$Default$ForMethodExit +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForVariable$ReadWrite +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess$OffsetWriting +com.amazonaws.services.lambda.runtime.Context +jdk.internal.reflect.GeneratedMethodAccessor15 +com.amazonaws.services.lambda.runtime.Context$MockitoMock$MawJ5Xou +com.amazonaws.services.lambda.runtime.Context$MockitoMock$MawJ5Xou$auxiliary$QIVtpjYT +com.amazonaws.services.lambda.runtime.Context$MockitoMock$MawJ5Xou$auxiliary$xgUr4uvo +org.aspectj.runtime.internal.AroundClosure +net.bytebuddy.description.type.TypeDescription$Generic$OfGenericArray +net.bytebuddy.description.type.TypeDescription$Generic$OfGenericArray$Latent +jdk.internal.reflect.GeneratedMethodAccessor16 +jdk.internal.reflect.GeneratedMethodAccessor17 +net.bytebuddy.description.type.TypeDescription$ArrayProjection +net.bytebuddy.implementation.bytecode.StackSize$1 +org.aspectj.lang.ProceedingJoinPoint +net.bytebuddy.description.field.FieldDescription$ForLoadedField +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$ForLoadedFieldType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedField +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedField$Dispatcher +net.bytebuddy.description.type.$Proxy70 +org.aspectj.lang.reflect.SourceLocation +org.aspectj.lang.JoinPoint$StaticPart +org.aspectj.lang.JoinPoint$EnclosingStaticPart +net.bytebuddy.dynamic.scaffold.TypeWriter$FieldPool$Record$ForImplicitField +org.aspectj.lang.JoinPoint +jdk.internal.reflect.GeneratedMethodAccessor18 +net.bytebuddy.dynamic.Transformer$ForMethod$TransformedMethod$TransformedParameter +sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedArrayTypeImpl +org.aspectj.lang.ProceedingJoinPoint$MockitoMock$alXgCaDh +org.aspectj.lang.ProceedingJoinPoint$MockitoMock$alXgCaDh$auxiliary$XCx5KE2h +org.aspectj.lang.ProceedingJoinPoint$MockitoMock$alXgCaDh$auxiliary$GAQiDCJf +java.lang.invoke.LambdaForm$DMH/0x00007faab4331000 +org.mockito.internal.configuration.IndependentAnnotationEngine$$Lambda$671/0x00007faab4337dc8 +org.mockito.Spy +org.mockito.plugins.AnnotationEngine$NoAction +org.mockito.internal.util.collections.Sets +org.mockito.internal.util.collections.HashCodeAndEqualsSafeSet +org.mockito.internal.configuration.injection.scanner.InjectMocksScanner +org.mockito.InjectMocks +org.mockito.internal.configuration.injection.scanner.MockScanner +org.mockito.internal.util.reflection.FieldReader +org.mockito.internal.util.collections.HashCodeAndEqualsMockWrapper +java.lang.invoke.LambdaForm$MH/0x00007faab4331400 +org.mockito.internal.util.Checks +org.mockito.internal.util.collections.HashCodeAndEqualsSafeSet$1 +org.mockito.internal.configuration.DefaultInjectionEngine +org.mockito.internal.configuration.injection.MockInjection +org.mockito.internal.configuration.injection.MockInjection$OngoingMockInjection +org.mockito.internal.configuration.injection.MockInjectionStrategy +org.mockito.internal.configuration.injection.ConstructorInjection +org.mockito.internal.configuration.injection.PropertyAndSetterInjection +org.mockito.internal.configuration.injection.SpyOnInjectedFieldsHandler +org.mockito.internal.configuration.injection.MockInjectionStrategy$1 +org.mockito.internal.util.reflection.FieldInitializer$ConstructorArgumentResolver +org.mockito.internal.configuration.injection.filter.MockCandidateFilter +org.mockito.internal.configuration.injection.filter.TypeBasedCandidateFilter +org.mockito.internal.configuration.injection.filter.NameBasedCandidateFilter +org.mockito.internal.configuration.injection.filter.TerminalMockCandidateFilter +org.mockito.internal.configuration.InjectingAnnotationEngine$$Lambda$672/0x00007faab4339998 +org.mockito.internal.configuration.InjectingAnnotationEngine$$Lambda$673/0x00007faab4339bc0 +org.junit.jupiter.api.extension.BeforeTestExecutionCallback +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$674/0x00007faab4339fe8 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$675/0x00007faab433a208 +org.junit.jupiter.engine.descriptor.MethodExtensionContext$$Lambda$676/0x00007faab433a430 +org.junit.jupiter.engine.execution.DefaultParameterContext +org.junit.jupiter.engine.execution.ParameterResolutionUtils$$Lambda$677/0x00007faab433a940 +org.junit.jupiter.params.ResolverFacade$$Lambda$678/0x00007faab433ab98 +org.junit.jupiter.params.ResolverFacade$$Lambda$679/0x00007faab433adb8 +java.lang.invoke.LambdaForm$DMH/0x00007faab433c000 +org.junit.jupiter.params.ResolverFacade$$Lambda$680/0x00007faab433afd8 +java.lang.invoke.LambdaForm$DMH/0x00007faab433c400 +java.lang.invoke.LambdaForm$DMH/0x00007faab433c800 +java.lang.invoke.LambdaForm$MH/0x00007faab433cc00 +org.junit.jupiter.params.ResolverFacade$$Lambda$681/0x00007faab433b200 +org.junit.jupiter.params.converter.ConvertWith +org.junit.jupiter.params.ResolverFacade$$Lambda$682/0x00007faab433b648 +org.junit.jupiter.params.converter.ArgumentConverter +org.junit.jupiter.params.ResolverFacade$$Lambda$683/0x00007faab433ba88 +org.junit.jupiter.params.ResolverFacade$$Lambda$684/0x00007faab433bcd0 +org.junit.jupiter.params.ResolverFacade$Converter +org.junit.jupiter.params.ResolverFacade$$Lambda$685/0x00007faab433e240 +org.junit.jupiter.params.ResolverFacade$$Lambda$686/0x00007faab433e480 +org.junit.jupiter.params.converter.DefaultArgumentConverter +org.junit.platform.commons.support.conversion.ConversionException +org.junit.jupiter.params.converter.ArgumentConversionException +org.junit.jupiter.params.converter.DefaultArgumentConverter$LocaleConversionFormat +org.junit.jupiter.params.converter.DefaultArgumentConverter$$Lambda$687/0x00007faab433efe8 +org.junit.jupiter.params.ResolverFacade$ExecutableParameterDeclaration$$Lambda$688/0x00007faab433f228 +org.junit.jupiter.params.ResolverFacade$ExecutableParameterDeclaration$$Lambda$689/0x00007faab433f480 +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$690/0x00007faab433f6a8 +org.junit.jupiter.engine.execution.ParameterResolutionUtils$$Lambda$691/0x00007faab433f8e8 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$692/0x00007faab433fb10 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$693/0x00007faab433fd68 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$694/0x00007faab433d000 +software.amazon.lambda.powertools.validation.handlers.GenericSchemaV7StringHandler +software.amazon.lambda.powertools.validation.handlers.GenericSchemaV7StringHandler$AjcClosure1 +org.aspectj.runtime.reflect.Factory +org.aspectj.lang.reflect.MemberSignature +org.aspectj.lang.reflect.CodeSignature +org.aspectj.lang.reflect.MethodSignature +org.aspectj.lang.reflect.ConstructorSignature +org.aspectj.lang.reflect.FieldSignature +org.aspectj.lang.reflect.AdviceSignature +org.aspectj.lang.reflect.InitializerSignature +org.aspectj.lang.reflect.CatchClauseSignature +org.aspectj.lang.reflect.LockSignature +org.aspectj.lang.reflect.UnlockSignature +org.aspectj.runtime.reflect.SignatureImpl +org.aspectj.runtime.reflect.MemberSignatureImpl +org.aspectj.runtime.reflect.CodeSignatureImpl +org.aspectj.runtime.reflect.MethodSignatureImpl +org.aspectj.runtime.reflect.SignatureImpl$Cache +org.aspectj.runtime.reflect.JoinPointImpl$StaticPartImpl +org.aspectj.runtime.reflect.SourceLocationImpl +org.aspectj.runtime.reflect.JoinPointImpl +jdk.proxy2.$Proxy71 +software.amazon.lambda.powertools.validation.ValidationConfig +software.amazon.lambda.powertools.validation.ValidationConfig$ConfigHolder +com.networknt.schema.JsonSchemaFactory +com.networknt.schema.resource.SchemaLoader +com.networknt.schema.JsonSchemaException +com.networknt.schema.JsonSchemaVersion +com.networknt.schema.resource.SchemaLoaders +com.networknt.schema.resource.SchemaLoaders$Builder +com.networknt.schema.resource.SchemaMappers +com.networknt.schema.resource.SchemaMappers$Builder +com.networknt.schema.JsonSchemaFactory$1 +com.networknt.schema.Version7 +com.networknt.schema.Version7$Holder +com.networknt.schema.JsonMetaSchema +com.networknt.schema.JsonMetaSchema$Builder +com.networknt.schema.InvalidSchemaException +com.networknt.schema.Formats +com.networknt.schema.Format +com.networknt.schema.format.PatternFormat +java.util.regex.Pattern$Loop +java.util.regex.Pattern$Prolog +com.networknt.schema.format.IPv6Format +java.util.regex.CharPredicates$$Lambda$695/0x00007faab41e3c78 +java.util.regex.CharPredicates$$Lambda$696/0x00007faab41e3f00 +com.networknt.schema.format.DateFormat +com.networknt.schema.format.DateTimeFormat +com.networknt.schema.utils.Classes +com.ethlo.time.ITU +com.networknt.schema.format.DateTimeFormat$Ethlo +com.ethlo.time.LeapSecondException +com.networknt.schema.format.DateTimeFormat$$Lambda$697/0x00007faab4346870 +com.networknt.schema.format.EmailFormat +com.networknt.org.apache.commons.validator.routines.EmailValidator +com.networknt.schema.format.IPv6AwareEmailValidator +com.networknt.org.apache.commons.validator.routines.DomainValidator +com.networknt.org.apache.commons.validator.routines.DomainValidator$LazyHolder +com.networknt.org.apache.commons.validator.routines.RegexValidator +com.networknt.schema.format.IdnEmailFormat +com.networknt.schema.format.IdnHostnameFormat +com.networknt.schema.format.AbstractRFC3986Format +com.networknt.schema.format.IriFormat +com.networknt.schema.format.IriReferenceFormat +com.networknt.schema.format.RegexFormat +com.networknt.schema.format.TimeFormat +com.networknt.schema.format.UriFormat +com.networknt.schema.format.UriReferenceFormat +com.networknt.schema.format.DurationFormat +java.util.regex.Pattern$$Lambda$698/0x00007faab41e4380 +java.util.regex.Pattern$Bound +com.networknt.schema.Keyword +com.networknt.schema.ErrorMessageType +com.networknt.schema.ValidatorTypeCode +com.networknt.schema.ValidatorTypeCode$1 +com.networknt.schema.ValidatorFactory +com.networknt.schema.SchemaLocation +com.networknt.schema.JsonNodePath +com.networknt.schema.walk.JsonSchemaWalker +com.networknt.schema.JsonValidator +com.networknt.schema.ValidationMessageHandler +com.networknt.schema.BaseJsonValidator +com.networknt.schema.JsonSchema +com.networknt.schema.ValidationContext +com.networknt.schema.AdditionalPropertiesValidator +com.networknt.schema.FailFastAssertionException +com.networknt.schema.ValidatorTypeCode$$Lambda$699/0x00007faab434b900 +com.networknt.schema.VersionCode +com.networknt.schema.AllOfValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$700/0x00007faab434c288 +com.networknt.schema.AnyOfValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$701/0x00007faab434c7e0 +com.networknt.schema.ConstValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$702/0x00007faab434cd20 +com.networknt.schema.ContainsValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$703/0x00007faab434d260 +com.networknt.schema.ContentEncodingValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$704/0x00007faab434d7a0 +com.networknt.schema.ContentMediaTypeValidator +com.fasterxml.jackson.core.JacksonException +com.fasterxml.jackson.core.JsonProcessingException +com.networknt.schema.ValidatorTypeCode$$Lambda$705/0x00007faab434e1e0 +com.networknt.schema.DependenciesValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$706/0x00007faab434e720 +com.networknt.schema.DependentRequired +com.networknt.schema.ValidatorTypeCode$$Lambda$707/0x00007faab434ec60 +com.networknt.schema.DependentSchemas +com.networknt.schema.ValidatorTypeCode$$Lambda$708/0x00007faab434f1a8 +com.networknt.schema.DiscriminatorValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$709/0x00007faab434f6f8 +com.networknt.schema.DynamicRefValidator +com.networknt.schema.InvalidSchemaRefException +com.networknt.schema.ValidatorTypeCode$$Lambda$710/0x00007faab4350000 +com.networknt.schema.EnumValidator +com.fasterxml.jackson.databind.node.JsonNodeCreator +com.fasterxml.jackson.databind.node.BaseJsonNode +com.fasterxml.jackson.databind.node.ContainerNode +com.fasterxml.jackson.databind.node.ArrayNode +com.fasterxml.jackson.databind.node.ValueNode +com.fasterxml.jackson.databind.node.NumericNode +com.fasterxml.jackson.databind.node.DecimalNode +com.networknt.schema.ValidatorTypeCode$$Lambda$711/0x00007faab4353210 +com.networknt.schema.ExclusiveMaximumValidator +com.networknt.schema.ThresholdMixin +com.networknt.schema.ValidatorTypeCode$$Lambda$712/0x00007faab4353950 +com.networknt.schema.ExclusiveMinimumValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$713/0x00007faab4353e90 +com.networknt.schema.FalseValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$714/0x00007faab43543d0 +com.networknt.schema.IfValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$715/0x00007faab4354910 +com.networknt.schema.ItemsValidator202012 +com.networknt.schema.ValidatorTypeCode$$Lambda$716/0x00007faab4354e60 +com.networknt.schema.ItemsValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$717/0x00007faab43553b0 +com.networknt.schema.MinMaxContainsValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$718/0x00007faab43558f0 +com.networknt.schema.MaxItemsValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$719/0x00007faab4355e30 +com.networknt.schema.MaxLengthValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$720/0x00007faab4356370 +com.networknt.schema.MaxPropertiesValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$721/0x00007faab43568b0 +com.networknt.schema.MaximumValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$722/0x00007faab4356df0 +com.networknt.schema.ValidatorTypeCode$$Lambda$723/0x00007faab4357010 +com.networknt.schema.MinItemsValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$724/0x00007faab4357550 +com.networknt.schema.MinLengthValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$725/0x00007faab4357a90 +com.networknt.schema.MinPropertiesValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$726/0x00007faab4358000 +com.networknt.schema.MinimumValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$727/0x00007faab4358540 +com.networknt.schema.MultipleOfValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$728/0x00007faab4358a90 +com.networknt.schema.NotAllowedValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$729/0x00007faab4358fd0 +com.networknt.schema.NotValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$730/0x00007faab4359518 +com.networknt.schema.OneOfValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$731/0x00007faab4359a70 +com.networknt.schema.PatternPropertiesValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$732/0x00007faab4359fb0 +com.networknt.schema.PatternValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$733/0x00007faab435a4f0 +com.networknt.schema.PrefixItemsValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$734/0x00007faab435aa38 +com.networknt.schema.PropertiesValidator +com.fasterxml.jackson.databind.node.MissingNode +com.networknt.schema.ValidatorTypeCode$$Lambda$735/0x00007faab435b5c8 +com.networknt.schema.PropertyNamesValidator +com.fasterxml.jackson.databind.node.TextNode +com.networknt.schema.ValidatorTypeCode$$Lambda$736/0x00007faab435c158 +com.networknt.schema.ReadOnlyValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$737/0x00007faab435c698 +com.networknt.schema.RecursiveRefValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$738/0x00007faab435cbe0 +com.networknt.schema.RefValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$739/0x00007faab435d128 +com.networknt.schema.RequiredValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$740/0x00007faab435d668 +com.networknt.schema.TrueValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$741/0x00007faab435dba8 +com.networknt.schema.TypeValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$742/0x00007faab435e0f8 +com.networknt.schema.UnevaluatedItemsValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$743/0x00007faab435e638 +com.networknt.schema.UnevaluatedPropertiesValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$744/0x00007faab435eb78 +com.networknt.schema.UnionTypeValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$745/0x00007faab435f0b8 +com.networknt.schema.UniqueItemsValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$746/0x00007faab435f5f8 +com.networknt.schema.WriteOnlyValidator +com.networknt.schema.ValidatorTypeCode$$Lambda$747/0x00007faab435fb38 +com.networknt.schema.AbstractKeyword +com.networknt.schema.NonValidationKeyword +com.networknt.schema.AnnotationKeyword +com.networknt.schema.FormatKeyword +com.networknt.schema.utils.StringUtils +com.networknt.schema.JsonSchemaFactory$Builder +com.networknt.schema.resource.DefaultSchemaLoader +com.networknt.schema.resource.SchemaMapper +com.networknt.schema.resource.MetaSchemaMapper +com.networknt.schema.resource.ClasspathSchemaLoader +com.networknt.schema.resource.ClasspathSchemaLoader$$Lambda$748/0x00007faab4361c00 +com.networknt.schema.resource.UriSchemaLoader +software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor +software.amazon.lambda.powertools.common.internal.SystemWrapper +software.amazon.lambda.powertools.validation.ValidationUtils +software.amazon.lambda.powertools.validation.ValidationUtils$$Lambda$749/0x00007faab4362678 +com.networknt.schema.SchemaValidatorsConfig +com.networknt.schema.regex.RegularExpressionFactory +com.networknt.schema.walk.WalkListenerRunner +com.networknt.schema.SchemaValidatorsConfig$Builder +com.networknt.schema.SchemaValidatorsConfig$ImmutableSchemaValidatorsConfig +com.networknt.schema.ApplyDefaultsStrategy +com.networknt.schema.PathType +com.networknt.schema.PathType$$Lambda$750/0x00007faab4363d08 +com.networknt.schema.PathType$$Lambda$751/0x00007faab4363f38 +com.networknt.schema.PathType$$Lambda$752/0x00007faab4364168 +com.networknt.schema.PathType$$Lambda$753/0x00007faab4364398 +com.networknt.schema.PathType$$Lambda$754/0x00007faab43645c8 +com.networknt.schema.PathType$$Lambda$755/0x00007faab43647f8 +com.networknt.schema.PathType$$Lambda$756/0x00007faab4364a28 +com.networknt.schema.PathType$$Lambda$757/0x00007faab4364c58 +com.networknt.schema.regex.JDKRegularExpressionFactory +com.networknt.schema.regex.RegularExpression +com.networknt.schema.JsonSchemaIdValidator +com.networknt.schema.JsonSchemaIdValidator$DefaultJsonSchemaIdValidator +com.networknt.schema.walk.AbstractWalkListenerRunner +com.networknt.schema.walk.DefaultItemWalkListenerRunner +com.networknt.schema.walk.DefaultKeywordWalkListenerRunner +com.networknt.schema.walk.DefaultPropertyWalkListenerRunner +com.networknt.schema.AbsoluteIri +com.networknt.schema.resource.InputStreamSource +com.networknt.schema.resource.ClasspathSchemaLoader$$Lambda$758/0x00007faab4366670 +com.networknt.schema.InputFormat +com.networknt.schema.serialization.JsonMapperFactory +com.networknt.schema.serialization.JsonMapperFactory$Holder +com.fasterxml.jackson.core.Versioned +com.fasterxml.jackson.core.TreeCodec +com.fasterxml.jackson.core.ObjectCodec +com.fasterxml.jackson.databind.ObjectMapper +com.fasterxml.jackson.databind.json.JsonMapper +com.fasterxml.jackson.core.TokenStreamFactory +com.fasterxml.jackson.core.JsonFactory +com.fasterxml.jackson.databind.MappingJsonFactory +com.fasterxml.jackson.databind.jsontype.SubtypeResolver +com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver +com.fasterxml.jackson.databind.DatabindContext +com.fasterxml.jackson.databind.SerializerProvider +com.fasterxml.jackson.databind.ser.DefaultSerializerProvider +com.fasterxml.jackson.databind.ser.DefaultSerializerProvider$Impl +com.fasterxml.jackson.databind.deser.DeserializerFactory +com.fasterxml.jackson.databind.deser.BasicDeserializerFactory +com.fasterxml.jackson.databind.deser.BeanDeserializerFactory +com.fasterxml.jackson.databind.DeserializationContext +com.fasterxml.jackson.databind.deser.DefaultDeserializationContext +com.fasterxml.jackson.databind.deser.DefaultDeserializationContext$Impl +com.fasterxml.jackson.databind.ser.SerializerFactory +com.fasterxml.jackson.databind.ser.BasicSerializerFactory +com.fasterxml.jackson.databind.ser.BeanSerializerFactory +com.fasterxml.jackson.databind.AnnotationIntrospector +com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector +com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy$Provider +com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy$Provider +com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator +com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator$Base +com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator +com.fasterxml.jackson.databind.util.StdDateFormat +com.fasterxml.jackson.databind.DatabindException +com.fasterxml.jackson.databind.JsonMappingException +com.fasterxml.jackson.databind.node.NullNode +com.fasterxml.jackson.databind.Module$SetupContext +com.fasterxml.jackson.core.JsonGenerator +com.fasterxml.jackson.databind.util.TokenBuffer +com.fasterxml.jackson.databind.introspect.ClassIntrospector +com.fasterxml.jackson.databind.introspect.BasicClassIntrospector +com.fasterxml.jackson.databind.introspect.VisibilityChecker +com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder +com.fasterxml.jackson.core.JsonParser +com.fasterxml.jackson.core.base.ParserMinimalBase +com.fasterxml.jackson.databind.node.TreeTraversingParser +com.fasterxml.jackson.core.util.BufferRecycler$Gettable +com.fasterxml.jackson.core.io.SegmentedStringWriter +com.fasterxml.jackson.core.util.ByteArrayBuilder +com.fasterxml.jackson.core.type.ResolvedType +com.fasterxml.jackson.databind.JavaType +com.fasterxml.jackson.databind.type.TypeBase +com.fasterxml.jackson.databind.type.ArrayType +com.fasterxml.jackson.databind.type.CollectionLikeType +com.fasterxml.jackson.databind.type.CollectionType +com.fasterxml.jackson.databind.type.MapLikeType +com.fasterxml.jackson.databind.type.MapType +com.fasterxml.jackson.databind.exc.MismatchedInputException +com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair +com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector +com.fasterxml.jackson.databind.introspect.Annotated +com.fasterxml.jackson.databind.introspect.TypeResolutionContext +com.fasterxml.jackson.databind.introspect.AnnotatedClass +com.fasterxml.jackson.databind.introspect.AnnotatedMember +com.fasterxml.jackson.databind.introspect.VirtualAnnotatedMember +com.fasterxml.jackson.databind.util.Named +com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition +com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition +com.fasterxml.jackson.databind.BeanProperty +com.fasterxml.jackson.databind.introspect.ConcreteBeanPropertyBase +com.fasterxml.jackson.databind.ser.PropertyWriter +com.fasterxml.jackson.databind.ser.BeanPropertyWriter +com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter +com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter +com.fasterxml.jackson.databind.introspect.AnnotatedWithParams +com.fasterxml.jackson.databind.introspect.AnnotatedMethod +com.fasterxml.jackson.databind.annotation.JsonSerialize +com.fasterxml.jackson.annotation.JsonView +com.fasterxml.jackson.annotation.JsonFormat +com.fasterxml.jackson.annotation.JsonTypeInfo +com.fasterxml.jackson.annotation.JsonRawValue +com.fasterxml.jackson.annotation.JsonUnwrapped +com.fasterxml.jackson.annotation.JsonBackReference +com.fasterxml.jackson.annotation.JsonManagedReference +com.fasterxml.jackson.databind.annotation.JsonDeserialize +com.fasterxml.jackson.annotation.JsonMerge +com.fasterxml.jackson.databind.ext.Java7Support +java.lang.IllegalAccessError +com.fasterxml.jackson.databind.ext.Java7SupportImpl +com.fasterxml.jackson.databind.util.ClassUtil +com.fasterxml.jackson.databind.util.ClassUtil$Ctor +com.fasterxml.jackson.databind.util.LookupCache +com.fasterxml.jackson.databind.util.LRUMap +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$Builder +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap +com.fasterxml.jackson.databind.util.internal.Linked +com.fasterxml.jackson.databind.util.internal.LinkedDeque +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$1 +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$2 +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$3 +com.fasterxml.jackson.databind.cfg.BaseSettings +com.fasterxml.jackson.databind.type.TypeFactory +com.fasterxml.jackson.databind.type.SimpleType +com.fasterxml.jackson.databind.type.IdentityEqualityType +com.fasterxml.jackson.databind.type.ResolvedRecursiveType +com.fasterxml.jackson.databind.type.PlaceholderForType +com.fasterxml.jackson.databind.type.ReferenceType +com.fasterxml.jackson.databind.type.IterationType +com.fasterxml.jackson.databind.type.TypeParser +com.fasterxml.jackson.databind.type.TypeBindings +com.fasterxml.jackson.core.Base64Variants +com.fasterxml.jackson.core.Base64Variant +com.fasterxml.jackson.core.Base64Variant$PaddingReadBehaviour +com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy +com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy +com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy$RecordNaming +com.fasterxml.jackson.databind.cfg.CacheProvider +com.fasterxml.jackson.databind.cfg.DefaultCacheProvider +com.fasterxml.jackson.databind.cfg.MapperBuilder +com.fasterxml.jackson.databind.json.JsonMapper$Builder +com.fasterxml.jackson.core.io.DataOutputAsStream +com.fasterxml.jackson.core.SerializableString +com.fasterxml.jackson.core.TSFBuilder +com.fasterxml.jackson.core.JsonFactoryBuilder +com.fasterxml.jackson.core.base.ParserBase +com.fasterxml.jackson.core.json.JsonParserBase +com.fasterxml.jackson.core.json.UTF8DataInputJsonParser +com.fasterxml.jackson.core.json.ReaderBasedJsonParser +com.fasterxml.jackson.core.async.NonBlockingInputFeeder +com.fasterxml.jackson.core.async.ByteArrayFeeder +com.fasterxml.jackson.core.json.async.NonBlockingJsonParserBase +com.fasterxml.jackson.core.json.async.NonBlockingUtf8JsonParserBase +com.fasterxml.jackson.core.json.async.NonBlockingJsonParser +com.fasterxml.jackson.core.async.ByteBufferFeeder +com.fasterxml.jackson.core.json.async.NonBlockingByteBufferJsonParser +com.fasterxml.jackson.core.base.GeneratorBase +com.fasterxml.jackson.core.json.JsonGeneratorImpl +com.fasterxml.jackson.core.json.UTF8JsonGenerator +com.fasterxml.jackson.core.io.UTF8Writer +com.fasterxml.jackson.core.json.WriterBasedJsonGenerator +com.fasterxml.jackson.core.util.JacksonFeature +com.fasterxml.jackson.core.JsonFactory$Feature +com.fasterxml.jackson.core.JsonParser$Feature +com.fasterxml.jackson.core.JsonGenerator$Feature +com.fasterxml.jackson.core.io.SerializedString +com.fasterxml.jackson.core.io.JsonStringEncoder +com.fasterxml.jackson.core.io.CharTypes +com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer +com.fasterxml.jackson.core.exc.StreamConstraintsException +com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer$TableInfo +com.fasterxml.jackson.core.util.JsonRecyclerPools +com.fasterxml.jackson.core.util.RecyclerPool +com.fasterxml.jackson.core.util.RecyclerPool$ThreadLocalPoolBase +com.fasterxml.jackson.core.util.JsonRecyclerPools$ThreadLocalPool +com.fasterxml.jackson.core.util.RecyclerPool$WithPool +com.fasterxml.jackson.core.StreamReadConstraints +com.fasterxml.jackson.core.StreamWriteConstraints +com.fasterxml.jackson.core.ErrorReportConfiguration +com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer +com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer$TableInfo +com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer$Bucket +com.fasterxml.jackson.databind.util.RootNameLookup +com.fasterxml.jackson.databind.introspect.ClassIntrospector$MixInResolver +com.fasterxml.jackson.databind.introspect.SimpleMixInResolver +com.fasterxml.jackson.databind.BeanDescription +com.fasterxml.jackson.databind.introspect.BasicBeanDescription +com.fasterxml.jackson.databind.cfg.MapperConfig +com.fasterxml.jackson.databind.cfg.MapperConfigBase +com.fasterxml.jackson.databind.DeserializationConfig +com.fasterxml.jackson.databind.SerializationConfig +com.fasterxml.jackson.databind.introspect.AnnotatedClassResolver +com.fasterxml.jackson.databind.introspect.AnnotationCollector +com.fasterxml.jackson.databind.util.Annotations +com.fasterxml.jackson.databind.introspect.AnnotationCollector$EmptyCollector +com.fasterxml.jackson.databind.introspect.AnnotationCollector$NoAnnotations +com.fasterxml.jackson.databind.introspect.AnnotatedClass$Creators +com.fasterxml.jackson.databind.introspect.AnnotatedConstructor +com.fasterxml.jackson.databind.cfg.ConfigOverrides +com.fasterxml.jackson.annotation.JacksonAnnotationValue +com.fasterxml.jackson.annotation.JsonInclude$Value +com.fasterxml.jackson.annotation.JsonInclude$Include +com.fasterxml.jackson.annotation.JsonSetter$Value +com.fasterxml.jackson.annotation.Nulls +com.fasterxml.jackson.databind.introspect.VisibilityChecker$Std +com.fasterxml.jackson.annotation.JsonAutoDetect$Visibility +com.fasterxml.jackson.databind.cfg.CoercionConfigs +com.fasterxml.jackson.databind.type.LogicalType +com.fasterxml.jackson.databind.cfg.CoercionAction +com.fasterxml.jackson.databind.cfg.CoercionConfig +com.fasterxml.jackson.databind.cfg.MutableCoercionConfig +com.fasterxml.jackson.databind.cfg.CoercionInputShape +com.fasterxml.jackson.databind.jsontype.DefaultBaseTypeLimitingValidator +com.fasterxml.jackson.core.PrettyPrinter +com.fasterxml.jackson.annotation.JsonFormat$Value +com.fasterxml.jackson.annotation.JsonFormat$Shape +com.fasterxml.jackson.annotation.JsonFormat$Features +com.fasterxml.jackson.databind.cfg.ConfigOverride +com.fasterxml.jackson.databind.cfg.ConfigOverride$Empty +com.fasterxml.jackson.databind.cfg.ConfigFeature +com.fasterxml.jackson.databind.MapperFeature +com.fasterxml.jackson.core.util.Instantiatable +com.fasterxml.jackson.core.util.DefaultPrettyPrinter +com.fasterxml.jackson.core.util.DefaultPrettyPrinter$Indenter +com.fasterxml.jackson.core.util.Separators +com.fasterxml.jackson.core.util.Separators$Spacing +com.fasterxml.jackson.core.util.DefaultPrettyPrinter$NopIndenter +com.fasterxml.jackson.core.util.DefaultPrettyPrinter$FixedSpaceIndenter +com.fasterxml.jackson.core.util.DefaultIndenter +com.fasterxml.jackson.databind.SerializationFeature +com.fasterxml.jackson.databind.cfg.DatatypeFeatures +com.fasterxml.jackson.databind.cfg.DatatypeFeatures$DefaultHolder +com.fasterxml.jackson.databind.cfg.DatatypeFeature +com.fasterxml.jackson.databind.cfg.EnumFeature +com.fasterxml.jackson.databind.cfg.JsonNodeFeature +com.fasterxml.jackson.databind.cfg.ContextAttributes +com.fasterxml.jackson.databind.cfg.ContextAttributes$Impl +com.fasterxml.jackson.databind.DeserializationFeature +com.fasterxml.jackson.databind.node.JsonNodeFactory +com.fasterxml.jackson.databind.node.BooleanNode +com.fasterxml.jackson.databind.node.DoubleNode +com.fasterxml.jackson.databind.node.ShortNode +com.fasterxml.jackson.databind.node.IntNode +com.fasterxml.jackson.databind.node.LongNode +com.fasterxml.jackson.databind.node.FloatNode +com.fasterxml.jackson.databind.node.BigIntegerNode +com.fasterxml.jackson.databind.node.BinaryNode +com.fasterxml.jackson.databind.node.POJONode +com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable +com.fasterxml.jackson.databind.JsonSerializer +com.fasterxml.jackson.databind.jsonschema.SchemaAware +com.fasterxml.jackson.databind.ser.std.StdSerializer +com.fasterxml.jackson.databind.ser.std.NullSerializer +com.fasterxml.jackson.databind.ser.impl.FailingSerializer +com.fasterxml.jackson.databind.ser.std.ToEmptyObjectSerializer +com.fasterxml.jackson.databind.ser.impl.UnknownSerializer +com.fasterxml.jackson.databind.ser.ContextualSerializer +com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer +com.fasterxml.jackson.databind.exc.InvalidDefinitionException +com.fasterxml.jackson.databind.exc.InvalidTypeIdException +com.fasterxml.jackson.databind.node.ObjectNode +com.fasterxml.jackson.databind.ser.ResolvableSerializer +com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer +com.fasterxml.jackson.databind.ser.SerializerCache +com.fasterxml.jackson.databind.deser.NullValueProvider +com.fasterxml.jackson.databind.JsonDeserializer +com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer +com.fasterxml.jackson.databind.exc.PropertyBindingException +com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException +com.fasterxml.jackson.databind.exc.InvalidFormatException +com.fasterxml.jackson.databind.exc.ValueInstantiationException +com.fasterxml.jackson.databind.deser.UnresolvedForwardReference +com.fasterxml.jackson.databind.deser.ContextualDeserializer +com.fasterxml.jackson.databind.deser.ValueInstantiator$Gettable +com.fasterxml.jackson.databind.deser.std.StdDeserializer +com.fasterxml.jackson.databind.deser.std.StringArrayDeserializer +com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase +com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer +com.fasterxml.jackson.databind.deser.std.EnumSetDeserializer +com.fasterxml.jackson.databind.deser.std.CollectionDeserializer +com.fasterxml.jackson.databind.deser.std.ArrayBlockingQueueDeserializer +com.fasterxml.jackson.databind.deser.std.StringCollectionDeserializer +com.fasterxml.jackson.databind.deser.ResolvableDeserializer +com.fasterxml.jackson.databind.deser.std.EnumMapDeserializer +com.fasterxml.jackson.databind.deser.std.MapDeserializer +com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer +com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer +com.fasterxml.jackson.databind.deser.std.StringDeserializer +com.fasterxml.jackson.databind.deser.std.MapEntryDeserializer +com.fasterxml.jackson.databind.deser.std.TokenBufferDeserializer +com.fasterxml.jackson.databind.deser.AbstractDeserializer +com.fasterxml.jackson.databind.deser.std.EnumDeserializer +com.fasterxml.jackson.databind.deser.std.ReferenceTypeDeserializer +com.fasterxml.jackson.databind.deser.std.AtomicReferenceDeserializer +com.fasterxml.jackson.databind.introspect.AnnotatedParameter +com.fasterxml.jackson.databind.deser.SettableBeanProperty +com.fasterxml.jackson.databind.deser.CreatorProperty +com.fasterxml.jackson.databind.deser.impl.ErrorThrowingDeserializer +com.fasterxml.jackson.annotation.ObjectIdGenerator +com.fasterxml.jackson.annotation.ObjectIdGenerators$Base +com.fasterxml.jackson.annotation.ObjectIdGenerators$PropertyGenerator +com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator +com.fasterxml.jackson.databind.deser.impl.MethodProperty +com.fasterxml.jackson.databind.deser.impl.FieldProperty +com.fasterxml.jackson.databind.deser.impl.SetterlessProperty +com.fasterxml.jackson.databind.deser.BeanDeserializerBase +com.fasterxml.jackson.databind.deser.BeanDeserializer +com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer +com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer +com.fasterxml.jackson.databind.deser.Deserializers +com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig +com.fasterxml.jackson.databind.deser.BeanDeserializerModifier +com.fasterxml.jackson.databind.AbstractTypeResolver +com.fasterxml.jackson.databind.deser.ValueInstantiators +com.fasterxml.jackson.databind.deser.KeyDeserializers +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializers +com.fasterxml.jackson.databind.KeyDeserializer +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$DelegatingKD +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$EnumKD +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringCtorKeyDeserializer +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringFactoryKeyDeserializer +com.fasterxml.jackson.databind.deser.DeserializerCache +com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer +com.fasterxml.jackson.databind.ser.std.JsonValueSerializer +com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase +com.fasterxml.jackson.databind.ser.std.ToStringSerializer +com.fasterxml.jackson.databind.ser.std.StdScalarSerializer +com.fasterxml.jackson.databind.ser.std.EnumSerializer +com.fasterxml.jackson.databind.ser.ContainerSerializer +com.fasterxml.jackson.databind.ser.impl.MapEntrySerializer +com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase +com.fasterxml.jackson.databind.ser.impl.IteratorSerializer +com.fasterxml.jackson.databind.ser.std.IterableSerializer +com.fasterxml.jackson.databind.ser.std.MapSerializer +com.fasterxml.jackson.databind.ser.std.StaticListSerializerBase +com.fasterxml.jackson.databind.ser.impl.IndexedStringListSerializer +com.fasterxml.jackson.databind.ser.impl.StringCollectionSerializer +com.fasterxml.jackson.databind.ser.std.CollectionSerializer +com.fasterxml.jackson.databind.ser.std.ArraySerializerBase +com.fasterxml.jackson.databind.ser.impl.StringArraySerializer +com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer +com.fasterxml.jackson.databind.ser.std.EnumSetSerializer +com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer +com.fasterxml.jackson.databind.ser.std.ReferenceTypeSerializer +com.fasterxml.jackson.databind.ser.std.SerializableSerializer +com.fasterxml.jackson.databind.ser.std.DateTimeSerializerBase +com.fasterxml.jackson.databind.ser.std.CalendarSerializer +com.fasterxml.jackson.databind.ser.std.DateSerializer +com.fasterxml.jackson.databind.ser.std.ByteBufferSerializer +com.fasterxml.jackson.databind.ser.std.InetAddressSerializer +com.fasterxml.jackson.databind.ser.std.InetSocketAddressSerializer +com.fasterxml.jackson.databind.ser.std.TimeZoneSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializer +com.fasterxml.jackson.databind.ser.impl.MapEntryAsPOJOSerializer +com.fasterxml.jackson.databind.ser.std.BeanSerializerBase +com.fasterxml.jackson.databind.ser.BeanSerializer +com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer +com.fasterxml.jackson.databind.introspect.AnnotatedField +com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator +com.fasterxml.jackson.databind.ser.std.StringSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers +com.fasterxml.jackson.databind.ser.std.NumberSerializers$Base +com.fasterxml.jackson.databind.ser.std.NumberSerializers$IntegerSerializer +com.fasterxml.jackson.core.JsonParser$NumberType +com.fasterxml.jackson.databind.ser.std.NumberSerializers$LongSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$IntLikeSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$ShortSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$DoubleSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$FloatSerializer +com.fasterxml.jackson.databind.ser.std.BooleanSerializer +com.fasterxml.jackson.databind.ser.std.BooleanSerializer$AsNumber +com.fasterxml.jackson.databind.ser.std.NumberSerializer$BigDecimalAsStringSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers +com.fasterxml.jackson.databind.ser.std.UUIDSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicBooleanSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicIntegerSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicLongSerializer +com.fasterxml.jackson.databind.ser.std.FileSerializer +com.fasterxml.jackson.databind.ser.std.ClassSerializer +com.fasterxml.jackson.databind.ser.std.TokenBufferSerializer +com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig +com.fasterxml.jackson.databind.ser.Serializers +com.fasterxml.jackson.databind.ser.BeanSerializerModifier +com.fasterxml.jackson.core.io.ContentReference +com.fasterxml.jackson.core.util.BufferRecyclers +com.fasterxml.jackson.core.util.BufferRecycler +com.fasterxml.jackson.core.io.IOContext +com.fasterxml.jackson.core.util.TextBuffer +com.fasterxml.jackson.core.util.ReadConstrainedTextBuffer +com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper +com.fasterxml.jackson.core.json.UTF8StreamJsonParser +com.fasterxml.jackson.core.io.MergedStream +com.fasterxml.jackson.core.io.UTF32Reader +com.fasterxml.jackson.core.JsonEncoding +com.fasterxml.jackson.core.util.InternCache +com.fasterxml.jackson.core.exc.StreamReadException +com.fasterxml.jackson.core.exc.InputCoercionException +com.fasterxml.jackson.core.JsonParseException +com.fasterxml.jackson.core.io.JsonEOFException +com.fasterxml.jackson.core.JsonStreamContext +com.fasterxml.jackson.core.json.JsonReadContext +com.fasterxml.jackson.core.StreamReadCapability +com.fasterxml.jackson.core.util.JacksonFeatureSet +com.fasterxml.jackson.core.JsonToken +com.fasterxml.jackson.databind.util.ArrayIterator +com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer +com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer +com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer$ObjectDeserializer +com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer$ArrayDeserializer +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$WeightedValue +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$Node +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$AddTask +com.fasterxml.jackson.databind.util.LinkedNode +com.fasterxml.jackson.databind.annotation.JsonTypeResolver +com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer$ContainerStack +com.fasterxml.jackson.core.io.NumberInput +com.fasterxml.jackson.core.JsonParser$NumberTypeFP +com.fasterxml.jackson.core.StreamReadFeature +com.fasterxml.jackson.databind.node.JsonNodeType +com.networknt.schema.JsonSchemaFactory$$Lambda$759/0x00007faab43c1cc0 +com.networknt.schema.JsonSchemaFactory$$Lambda$760/0x00007faab43c1f08 +com.networknt.schema.OutputFormat +java.lang.invoke.LambdaForm$DMH/0x00007faab43c4000 +com.networknt.schema.JsonSchema$$Lambda$761/0x00007faab43c2350 +com.networknt.schema.i18n.DefaultMessageSource +com.networknt.schema.i18n.DefaultMessageSource$Holder +com.networknt.schema.i18n.MessageSource +com.networknt.schema.i18n.ResourceBundleMessageSource +java.util.MissingResourceException +com.networknt.schema.AbstractJsonValidator +com.networknt.schema.NonValidationKeyword$Validator +com.networknt.schema.TypeFactory +com.networknt.schema.JsonType +com.networknt.schema.AnnotationKeyword$Validator +com.networknt.schema.SchemaLocation$Fragment +com.fasterxml.jackson.core.io.NumberOutput +com.networknt.schema.ExclusiveMinimumValidator$2 +com.networknt.schema.JsonSchemaRef +com.networknt.schema.RefValidator$$Lambda$762/0x00007faab43c6660 +com.networknt.schema.CachedSupplier +com.networknt.schema.JsonSchema$$Lambda$763/0x00007faab43c6ab8 +com.networknt.schema.MinimumValidator$1 +com.networknt.schema.RefValidator$$Lambda$764/0x00007faab43c6f40 +com.fasterxml.jackson.databind.node.InternalNodeMapper +com.fasterxml.jackson.databind.ObjectWriter +com.fasterxml.jackson.core.util.MinimalPrettyPrinter +com.fasterxml.jackson.databind.ObjectWriter$GeneratorSettings +com.fasterxml.jackson.databind.ObjectWriter$Prefetch +com.fasterxml.jackson.databind.RuntimeJsonMappingException +com.fasterxml.jackson.databind.ObjectReader +com.fasterxml.jackson.core.filter.TokenFilter +com.fasterxml.jackson.core.filter.JsonPointerBasedFilter +com.fasterxml.jackson.core.util.JsonParserDelegate +com.fasterxml.jackson.core.filter.FilteringParserDelegate +com.fasterxml.jackson.databind.node.InternalNodeMapper$WrapperForSerializer +com.fasterxml.jackson.core.exc.StreamWriteException +com.fasterxml.jackson.core.JsonGenerationException +com.fasterxml.jackson.core.json.JsonWriteContext +com.fasterxml.jackson.core.StreamWriteCapability +com.fasterxml.jackson.core.FormatFeature +com.fasterxml.jackson.core.json.JsonWriteFeature +com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap +com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap$Bucket +com.fasterxml.jackson.databind.util.TypeKey +com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap$$Lambda$765/0x00007faab43ca5c0 +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$EntrySet +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$EntryIterator +com.fasterxml.jackson.databind.type.ClassStack +com.fasterxml.jackson.databind.introspect.AnnotationCollector$OneCollector +com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector +com.fasterxml.jackson.annotation.JsonAutoDetect +com.fasterxml.jackson.annotation.JsonIdentityInfo +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$WriteThroughEntry +com.networknt.schema.format.BaseFormatJsonValidator +com.networknt.schema.FormatValidator +java.util.regex.PatternSyntaxException +com.networknt.schema.OutputFormat$Default +com.networknt.schema.OutputFormat$Boolean +com.networknt.schema.OutputFormat$Flag +com.networknt.schema.OutputFormat$List +com.networknt.schema.output.OutputUnitData +com.networknt.schema.ValidationMessage +com.networknt.schema.OutputFormat$List$$Lambda$766/0x00007faab43cd088 +com.networknt.schema.OutputFormat$Hierarchical +com.networknt.schema.OutputFormat$Hierarchical$$Lambda$767/0x00007faab43cd510 +com.networknt.schema.OutputFormat$Result +com.networknt.schema.ExecutionConfig +com.networknt.schema.ExecutionConfig$$Lambda$768/0x00007faab43cdc00 +com.networknt.schema.ExecutionContext +com.networknt.schema.BaseJsonValidator$JsonNodePathJsonPointer +com.networknt.schema.utils.JsonNodeUtil +com.networknt.schema.TypeFactory$1 +com.networknt.schema.ValidationMessage$BuilderSupport +com.networknt.schema.MessageSourceValidationMessage$BuilderSupport +com.networknt.schema.MessageSourceValidationMessage$Builder +com.networknt.schema.FormatValidator$$Lambda$769/0x00007faab43cf038 +com.networknt.schema.format.UriReferenceFormat$$Lambda$770/0x00007faab43cf260 +java.util.stream.MatchOps$$Lambda$771/0x00007faab41e4f78 +java.util.stream.MatchOps$2MatchSink +com.networknt.schema.format.UriFormat$$Lambda$772/0x00007faab43cf4b0 +com.networknt.schema.utils.SetView +com.networknt.schema.ValidationMessageHandler$$Lambda$773/0x00007faab43cfb18 +com.networknt.schema.MessageSourceValidationMessage +com.networknt.schema.i18n.MessageFormatter +com.networknt.schema.MessageSourceValidationMessage$BuilderSupport$$Lambda$774/0x00007faab43d0000 +com.networknt.schema.utils.CachingSupplier +com.networknt.schema.ValidationMessage$BuilderSupport$$Lambda$775/0x00007faab43d0458 +com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent +com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent +com.amazonaws.services.lambda.runtime.events.SNSEvent +com.amazonaws.services.lambda.runtime.events.ScheduledEvent +com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent +com.amazonaws.services.lambda.runtime.events.CloudWatchLogsEvent +com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent +com.amazonaws.services.lambda.runtime.events.StreamsEventResponse +com.amazonaws.services.lambda.runtime.events.StreamsEventResponse$StreamsEventResponseBuilder +io.burt.jmespath.function.Function +io.burt.jmespath.function.BaseFunction +software.amazon.lambda.powertools.utilities.jmespath.Base64Function +io.burt.jmespath.JmesPathException +io.burt.jmespath.function.FunctionConfigurationException +sun.nio.cs.ThreadLocalCoders +sun.nio.cs.ThreadLocalCoders$Cache +sun.nio.cs.ThreadLocalCoders$1 +sun.nio.cs.ThreadLocalCoders$2 +software.amazon.lambda.powertools.utilities.JsonConfig +io.burt.jmespath.JmesPath +software.amazon.lambda.powertools.utilities.JsonConfig$$Lambda$776/0x00007faab43d2b30 +software.amazon.lambda.powertools.utilities.JsonConfig$ConfigHolder +io.burt.jmespath.function.FunctionRegistry +io.burt.jmespath.function.MathFunction +io.burt.jmespath.function.AbsFunction +io.burt.jmespath.JmesPathType +io.burt.jmespath.function.ArgumentConstraints +io.burt.jmespath.function.ArgumentConstraint +io.burt.jmespath.function.ArgumentConstraints$BaseArgumentConstraint +io.burt.jmespath.function.ArgumentConstraints$TypeCheck +io.burt.jmespath.function.ArgumentConstraints$TypeOf +io.burt.jmespath.function.ArrayMathFunction +io.burt.jmespath.function.AvgFunction +io.burt.jmespath.function.ArgumentConstraints$ArrayOf +io.burt.jmespath.function.ArgumentError +io.burt.jmespath.function.ArgumentError$ArgumentTypeError +io.burt.jmespath.function.ContainsFunction +io.burt.jmespath.function.ArgumentConstraints$TypeOfEither +io.burt.jmespath.function.ArgumentConstraints$AnyValue +io.burt.jmespath.function.ArgumentConstraints$HeterogeneousListOf +io.burt.jmespath.function.CeilFunction +io.burt.jmespath.function.EndsWithFunction +io.burt.jmespath.function.FloorFunction +io.burt.jmespath.function.JoinFunction +io.burt.jmespath.function.KeysFunction +io.burt.jmespath.function.LengthFunction +io.burt.jmespath.function.MapFunction +io.burt.jmespath.function.ArgumentConstraints$Expression +io.burt.jmespath.function.CompareFunction +io.burt.jmespath.function.MaxFunction +io.burt.jmespath.function.TransformByFunction +io.burt.jmespath.function.CompareByFunction +io.burt.jmespath.function.MaxByFunction +io.burt.jmespath.function.TransformByFunction$Aggregator +io.burt.jmespath.function.CompareByFunction$ComparingAggregator +io.burt.jmespath.function.MergeFunction +io.burt.jmespath.function.ArgumentConstraints$HomogeneousListOf +io.burt.jmespath.function.MinFunction +io.burt.jmespath.function.MinByFunction +io.burt.jmespath.function.NotNullFunction +io.burt.jmespath.function.ReverseFunction +io.burt.jmespath.function.SortFunction +io.burt.jmespath.function.SortByFunction +io.burt.jmespath.function.SortByFunction$SortingAggregator +io.burt.jmespath.function.StartsWithFunction +io.burt.jmespath.function.SumFunction +io.burt.jmespath.function.ToArrayFunction +io.burt.jmespath.function.ToStringFunction +io.burt.jmespath.function.ToNumberFunction +io.burt.jmespath.function.TypeFunction +io.burt.jmespath.function.ValuesFunction +software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunction +java.util.zip.GZIPInputStream +software.amazon.lambda.powertools.utilities.jmespath.JsonFunction +io.burt.jmespath.RuntimeConfiguration$Builder +io.burt.jmespath.RuntimeConfiguration +io.burt.jmespath.Adapter +io.burt.jmespath.BaseRuntime +io.burt.jmespath.jackson.JacksonRuntime +io.burt.jmespath.node.NodeFactory +io.burt.jmespath.function.FunctionCallException +io.burt.jmespath.function.ArgumentTypeException +io.burt.jmespath.node.StandardNodeFactory +io.burt.jmespath.Expression +io.burt.jmespath.node.Node +io.burt.jmespath.node.StringNode +io.burt.jmespath.node.CurrentNode +io.burt.jmespath.node.PropertyNode +io.burt.jmespath.node.IndexNode +io.burt.jmespath.node.SliceNode +io.burt.jmespath.node.ProjectionNode +io.burt.jmespath.node.FlattenArrayNode +io.burt.jmespath.node.FlattenObjectNode +io.burt.jmespath.node.SelectionNode +io.burt.jmespath.node.OperatorNode +io.burt.jmespath.node.OrNode +io.burt.jmespath.node.AndNode +io.burt.jmespath.node.FunctionCallNode +io.burt.jmespath.node.ExpressionReferenceNode +io.burt.jmespath.node.NegateNode +io.burt.jmespath.node.CreateObjectNode +io.burt.jmespath.node.CreateArrayNode +io.burt.jmespath.node.JsonLiteralNode +io.burt.jmespath.node.SequenceNode +java.math.MathContext +com.amazonaws.services.lambda.runtime.events.SQSBatchResponse +org.assertj.core.api.InstanceOfAssertFactories +org.assertj.core.api.Assertions +org.assertj.core.api.NumberAssert +org.assertj.core.api.ComparableAssert +org.assertj.core.api.Descriptable +org.assertj.core.api.ExtensionPoints +org.assertj.core.api.Assert +org.assertj.core.api.AbstractAssert +org.assertj.core.api.AbstractObjectAssert +org.assertj.core.api.AbstractComparableAssert +org.assertj.core.api.AbstractBigIntegerAssert +org.assertj.core.api.BigIntegerAssert +org.assertj.core.data.TemporalOffset +org.assertj.core.data.TemporalUnitOffset +org.assertj.core.data.TemporalUnitWithinOffset +org.assertj.core.data.TemporalUnitLessThanOffset +org.assertj.core.configuration.ConfigurationProvider +org.assertj.core.api.AssertionsForClassTypes +org.assertj.core.api.AbstractTemporalAssert +org.assertj.core.api.AbstractInstantAssert +org.assertj.core.api.InstantAssert +org.assertj.core.api.AbstractYearMonthAssert +org.assertj.core.api.YearMonthAssert +org.assertj.core.api.AbstractLocalDateAssert +org.assertj.core.api.LocalDateAssert +org.assertj.core.api.AbstractLocalTimeAssert +org.assertj.core.api.LocalTimeAssert +org.assertj.core.api.ArraySortedAssert +org.assertj.core.api.EnumerableAssert +org.assertj.core.api.AbstractEnumerableAssert +org.assertj.core.api.AbstractArrayAssert +org.assertj.core.api.AbstractByteArrayAssert +org.assertj.core.api.ByteArrayAssert +org.assertj.core.api.AbstractThrowableAssert +org.assertj.core.api.ThrowableAssert +org.assertj.core.api.AbstractPeriodAssert +org.assertj.core.api.PeriodAssert +org.assertj.core.api.AbstractDurationAssert +org.assertj.core.api.DurationAssert +org.assertj.core.api.AbstractDateAssert +org.assertj.core.api.DateAssert +org.assertj.core.api.AbstractCharSequenceAssert +org.assertj.core.api.AbstractStringAssert +org.assertj.core.api.StringAssert +org.assertj.core.api.CharSequenceAssert +org.assertj.core.api.AbstractOffsetTimeAssert +org.assertj.core.api.OffsetTimeAssert +org.assertj.core.api.AbstractOffsetDateTimeAssert +org.assertj.core.api.OffsetDateTimeAssert +org.assertj.core.api.AbstractLocalDateTimeAssert +org.assertj.core.api.LocalDateTimeAssert +org.assertj.core.api.AbstractZonedDateTimeAssert +org.assertj.core.api.ZonedDateTimeAssert +org.assertj.core.api.AbstractBigDecimalAssert +org.assertj.core.api.BigDecimalAssert +org.assertj.core.api.AbstractUriAssert +org.assertj.core.api.UriAssert +org.assertj.core.api.AbstractBooleanArrayAssert +org.assertj.core.api.BooleanArrayAssert +org.assertj.core.api.AbstractByteAssert +org.assertj.core.api.ByteAssert +org.assertj.core.api.AbstractBooleanAssert +org.assertj.core.api.BooleanAssert +org.assertj.core.api.AbstractUrlAssert +org.assertj.core.api.UrlAssert +org.assertj.core.api.AbstractInputStreamAssert +org.assertj.core.api.InputStreamAssert +org.assertj.core.api.AbstractFileAssert +org.assertj.core.api.FileAssert +org.assertj.core.api.AbstractDoubleArrayAssert +org.assertj.core.api.DoubleArrayAssert +org.assertj.core.api.AbstractFloatArrayAssert +org.assertj.core.api.FloatArrayAssert +org.assertj.core.api.FloatingPointNumberAssert +org.assertj.core.api.AbstractFloatAssert +org.assertj.core.api.FloatAssert +org.assertj.core.api.AbstractCharacterAssert +org.assertj.core.api.CharacterAssert +org.assertj.core.api.AbstractCharArrayAssert +org.assertj.core.api.CharArrayAssert +org.assertj.core.api.AbstractDoubleAssert +org.assertj.core.api.DoubleAssert +org.assertj.core.api.AbstractLongArrayAssert +org.assertj.core.api.LongArrayAssert +org.assertj.core.api.AbstractLongAssert +org.assertj.core.api.LongAssert +org.assertj.core.api.AbstractShortAssert +org.assertj.core.api.ShortAssert +org.assertj.core.api.AbstractIntegerAssert +org.assertj.core.api.IntegerAssert +org.assertj.core.api.AbstractShortArrayAssert +org.assertj.core.api.ShortArrayAssert +org.assertj.core.api.AbstractIntArrayAssert +org.assertj.core.api.IntArrayAssert +org.assertj.core.description.Description +org.assertj.core.description.LazyTextDescription +org.assertj.core.description.TextDescription +org.assertj.core.api.AssertionInfo +org.assertj.core.internal.ComparisonStrategy +org.assertj.core.api.ObjectEnumerableAssert +org.assertj.core.api.IndexedObjectEnumerableAssert +org.assertj.core.api.AbstractIterableAssert +org.assertj.core.api.AbstractCollectionAssert +org.assertj.core.api.AbstractListAssert +org.assertj.core.api.FactoryBasedNavigableListAssert +org.assertj.core.api.ListAssert +org.assertj.core.internal.Objects +org.assertj.core.error.ErrorMessageFactory +org.assertj.core.util.introspection.IntrospectionError +org.assertj.core.internal.AbstractComparisonStrategy +org.assertj.core.internal.StandardComparisonStrategy +org.assertj.core.util.introspection.PropertySupport +org.assertj.core.internal.Failures +org.assertj.core.error.AssertionErrorCreator +org.assertj.core.util.Arrays +org.assertj.core.error.ConstructorInvoker +org.assertj.core.util.introspection.FieldSupport +org.assertj.core.error.GroupTypeDescription +org.assertj.core.internal.Conditions +org.assertj.core.api.WritableAssertionInfo +org.assertj.core.presentation.Representation +org.assertj.core.configuration.Configuration +org.assertj.core.configuration.PreferredAssumptionException +org.assertj.core.configuration.PreferredAssumptionException$1 +org.assertj.core.configuration.Services +org.assertj.core.util.Lists +org.assertj.core.util.Streams +org.assertj.core.util.Lists$$Lambda$777/0x00007faab441c950 +org.assertj.core.presentation.CompositeRepresentation +java.lang.invoke.LambdaForm$DMH/0x00007faab4420000 +org.assertj.core.presentation.CompositeRepresentation$$Lambda$778/0x00007faab441cdc8 +java.util.stream.SortedOps$SizedRefSortingSink +org.assertj.core.presentation.StandardRepresentation +java.nio.file.DirectoryStream +org.assertj.core.internal.Strings +org.assertj.core.internal.Comparables +org.junit.jupiter.api.extension.AfterTestExecutionCallback +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$779/0x00007faab441dc38 +org.junit.jupiter.engine.descriptor.CallbackSupport$$Lambda$780/0x00007faab441de58 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$781/0x00007faab441e090 +org.junit.jupiter.api.extension.AfterEachCallback +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$782/0x00007faab441e4b8 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$783/0x00007faab441e6d8 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$784/0x00007faab441e900 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$785/0x00007faab441eb28 +org.junit.jupiter.engine.descriptor.MethodExtensionContext$$Lambda$786/0x00007faab441ed50 +org.junit.jupiter.engine.descriptor.TestTemplateExtensionContext$$Lambda$787/0x00007faab441ef90 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$788/0x00007faab441f1d0 +org.junit.jupiter.engine.descriptor.CallbackSupport$$Lambda$789/0x00007faab441f3f0 +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$790/0x00007faab441f618 +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$791/0x00007faab441f868 +org.junit.jupiter.api.extension.TestInstancePreDestroyCallback$$Lambda$792/0x00007faab441faa0 +org.junit.jupiter.api.extension.TestInstancePreDestroyCallback$$Lambda$793/0x00007faab441fce0 +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$794/0x00007faab4424000 +org.junit.jupiter.api.AutoClose +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$795/0x00007faab4424450 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$796/0x00007faab4424688 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$797/0x00007faab44248b0 +java.util.concurrent.ConcurrentHashMap$EntrySpliterator +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$EvaluatedValue +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$798/0x00007faab4424d10 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$799/0x00007faab4424f50 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$EvaluatedValue$$Lambda$800/0x00007faab44251a0 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$801/0x00007faab44253e0 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$802/0x00007faab4425618 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$803/0x00007faab4425840 +org.junit.platform.engine.TestExecutionResult +org.junit.platform.engine.TestExecutionResult$Status +org.junit.jupiter.api.extension.TestWatcher +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$804/0x00007faab44262e8 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$805/0x00007faab4426520 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$806/0x00007faab4426758 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$807/0x00007faab4426998 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$808/0x00007faab4426be8 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$809/0x00007faab4426e28 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$810/0x00007faab4427068 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$811/0x00007faab44272b8 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$812/0x00007faab44274f0 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$813/0x00007faab4427718 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$814/0x00007faab4427950 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$815/0x00007faab4427b78 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$816/0x00007faab4427db0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$817/0x00007faab4422000 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$1 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor$$Lambda$818/0x00007faab4422460 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$819/0x00007faab4422698 +com.amazonaws.services.lambda.runtime.events.SQSEvent$SQSMessage +com.amazonaws.services.lambda.runtime.events.SQSEvent$MessageAttribute +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringKD +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ContextualKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JacksonStdImpl +jdk.proxy2.$Proxy72 +software.amazon.lambda.powertools.validation.handlers.StandardSQSHandler +software.amazon.lambda.powertools.validation.handlers.StandardSQSHandler$AjcClosure1 +com.amazonaws.services.lambda.runtime.events.SQSBatchResponse$SQSBatchResponseBuilder +com.networknt.schema.result.JsonNodeResults +com.networknt.schema.result.JsonNodeResult +com.networknt.schema.result.JsonNodeResults$$Lambda$820/0x00007faab4421230 +software.amazon.lambda.powertools.validation.ValidationUtils$ValidationErrors +com.fasterxml.jackson.databind.introspect.PotentialCreators +com.fasterxml.jackson.databind.introspect.CollectorBase +com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector +com.fasterxml.jackson.databind.introspect.AnnotationMap +com.fasterxml.jackson.databind.introspect.TypeResolutionContext$Basic +com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector$FieldBuilder +com.fasterxml.jackson.annotation.JsonKey +com.fasterxml.jackson.annotation.JsonValue +com.fasterxml.jackson.annotation.JsonAnyGetter +com.fasterxml.jackson.annotation.JsonAnySetter +com.fasterxml.jackson.databind.PropertyName +com.fasterxml.jackson.annotation.JsonGetter +com.fasterxml.jackson.annotation.JsonProperty +com.fasterxml.jackson.annotation.JsonAutoDetect$1 +com.fasterxml.jackson.annotation.PropertyAccessor +com.fasterxml.jackson.annotation.JsonIgnore +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$WithMember +com.fasterxml.jackson.databind.AnnotationIntrospector$ReferenceProperty +com.fasterxml.jackson.databind.AnnotationIntrospector$ReferenceProperty$Type +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$Linked +com.fasterxml.jackson.databind.introspect.AnnotatedMethodCollector +com.fasterxml.jackson.databind.introspect.MemberKey +com.fasterxml.jackson.databind.introspect.AnnotatedMethodCollector$MethodBuilder +com.fasterxml.jackson.databind.introspect.AnnotatedMethodMap +com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector +com.fasterxml.jackson.annotation.JsonCreator +com.fasterxml.jackson.databind.introspect.PotentialCreator +com.fasterxml.jackson.annotation.JsonCreator$Mode +com.fasterxml.jackson.databind.cfg.ConstructorDetector +com.fasterxml.jackson.databind.cfg.ConstructorDetector$SingleArgConstructor +sun.reflect.generics.scope.ConstructorScope +com.fasterxml.jackson.databind.type.TypeBindings$TypeParamStash +com.fasterxml.jackson.databind.type.TypeBindings$AsKey +com.fasterxml.jackson.annotation.JsonSetter +com.fasterxml.jackson.annotation.JacksonInject +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$5 +com.fasterxml.jackson.annotation.JsonProperty$Access +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$6 +com.fasterxml.jackson.databind.annotation.JsonNaming +com.fasterxml.jackson.annotation.JsonPropertyOrder +com.fasterxml.jackson.annotation.JsonPropertyDescription +com.fasterxml.jackson.databind.PropertyMetadata +com.fasterxml.jackson.databind.ext.OptionalHandlerFactory +com.fasterxml.jackson.databind.ext.Java7Handlers +com.fasterxml.jackson.databind.ext.Java7HandlersImpl +com.fasterxml.jackson.databind.ext.NioPathSerializer +com.fasterxml.jackson.databind.ext.NioPathDeserializer +com.fasterxml.jackson.databind.util.BeanUtil +com.fasterxml.jackson.databind.ser.BeanSerializerBuilder +com.fasterxml.jackson.annotation.JsonIgnoreType +com.fasterxml.jackson.databind.ser.PropertyBuilder +com.fasterxml.jackson.annotation.JsonInclude +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$3 +com.fasterxml.jackson.annotation.JsonTypeId +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$2 +com.fasterxml.jackson.databind.BeanProperty$Std +com.fasterxml.jackson.annotation.JsonIgnoreProperties +com.fasterxml.jackson.annotation.JacksonAnnotation +jdk.proxy2.$Proxy73 +jdk.proxy2.$Proxy74 +jdk.proxy2.$Proxy75 +com.fasterxml.jackson.databind.introspect.AnnotationCollector$NCollector +com.fasterxml.jackson.annotation.JacksonAnnotationsInside +jdk.proxy2.$Proxy76 +com.fasterxml.jackson.databind.ser.PropertyBuilder$1 +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$1 +com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Empty +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Single +com.fasterxml.jackson.databind.annotation.JsonAppend +com.fasterxml.jackson.annotation.JsonIgnoreProperties$Value +com.fasterxml.jackson.annotation.JsonIncludeProperties +com.fasterxml.jackson.annotation.JsonIncludeProperties$Value +com.fasterxml.jackson.annotation.JsonFilter +com.fasterxml.jackson.databind.ser.impl.BeanAsArraySerializer +com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer +com.fasterxml.jackson.databind.ser.AnyGetterWriter +java.util.stream.DoubleStream +java.util.stream.LongStream +com.fasterxml.jackson.annotation.JsonFormat$Feature +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$SerializerAndMapResult +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Double +com.networknt.schema.utils.SetView$SetViewIterator +com.fasterxml.jackson.databind.annotation.JsonSerialize$Inclusion +com.fasterxml.jackson.databind.annotation.JsonSerialize$Typing +com.fasterxml.jackson.databind.util.Converter +com.fasterxml.jackson.databind.util.Converter$None +com.fasterxml.jackson.databind.JsonSerializer$None +jdk.proxy2.$Proxy77 +com.networknt.schema.ValidationMessage$Builder +com.fasterxml.jackson.databind.introspect.MethodGenericTypeResolver +com.fasterxml.jackson.databind.annotation.NoClass +com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector$1 +com.fasterxml.jackson.databind.util.IgnorePropertiesUtil +com.fasterxml.jackson.databind.ser.std.StdArraySerializers +com.fasterxml.jackson.databind.ser.std.StdArraySerializers$BooleanArraySerializer +com.fasterxml.jackson.databind.ser.std.ByteArraySerializer +com.fasterxml.jackson.databind.ser.std.StdArraySerializers$CharArraySerializer +com.fasterxml.jackson.databind.ser.std.StdArraySerializers$TypedPrimitiveArraySerializer +com.fasterxml.jackson.databind.ser.std.StdArraySerializers$ShortArraySerializer +com.fasterxml.jackson.databind.ser.std.StdArraySerializers$IntArraySerializer +com.fasterxml.jackson.databind.ser.std.StdArraySerializers$LongArraySerializer +com.fasterxml.jackson.databind.ser.std.StdArraySerializers$FloatArraySerializer +com.fasterxml.jackson.databind.ser.std.StdArraySerializers$DoubleArraySerializer +com.networknt.schema.i18n.ResourceBundleMessageSource$$Lambda$821/0x00007faab4437d00 +com.networknt.schema.i18n.ResourceBundleMessageSource$$Lambda$822/0x00007faab4439a70 +com.networknt.schema.i18n.ResourceBundleMessageSource$$Lambda$823/0x00007faab4439cb8 +com.networknt.schema.i18n.ResourceBundleMessageSource$$Lambda$824/0x00007faab4439f00 +com.networknt.schema.i18n.ResourceBundleMessageSource$$Lambda$825/0x00007faab443a150 +com.networknt.schema.i18n.ResourceBundleMessageSource$$Lambda$826/0x00007faab443a398 +com.networknt.schema.i18n.ResourceBundleMessageSource$$Lambda$827/0x00007faab443a5e8 +com.networknt.schema.i18n.ResourceBundleMessageSource$$Lambda$828/0x00007faab443a828 +java.util.ResourceBundle$ResourceBundleControlProviderHolder +java.util.ResourceBundle$ResourceBundleControlProviderHolder$$Lambda$829/0x00007faab41e71c0 +java.util.spi.ResourceBundleControlProvider +java.util.ResourceBundle$ResourceBundleControlProviderHolder$$Lambda$830/0x00007faab41e75e0 +java.util.ImmutableCollections$Access +jdk.internal.access.JavaUtilCollectionAccess +java.util.ImmutableCollections$Access$1 +java.util.ResourceBundle$CacheKey +java.util.ResourceBundle$CacheKeyReference +java.util.ResourceBundle$KeyElementReference +java.util.ResourceBundle$$Lambda$831/0x00007faab41e84e0 +java.util.ResourceBundle$Control$2 +java.util.PropertyResourceBundle +sun.util.PropertyResourceBundleCharset +sun.util.PropertyResourceBundleCharset$PropertiesFileDecoder +java.util.ResourceBundle$BundleReference +com.networknt.schema.i18n.ResourceBundleMessageSource$$Lambda$832/0x00007faab443aa70 +com.networknt.schema.i18n.ResourceBundleMessageSource$$Lambda$833/0x00007faab443acb0 +java.text.Format$FieldDelegate +java.text.FieldPosition$Delegate +java.text.NumberFormat$Field +com.fasterxml.jackson.databind.ser.std.NumberSerializers$1 +org.slf4j.event.Level +org.slf4j.helpers.MessageFormatter +org.slf4j.helpers.FormattingTuple +org.apache.maven.surefire.api.report.TestOutputReportEntry +com.amazonaws.services.lambda.runtime.events.SQSBatchResponse$BatchItemFailure +com.amazonaws.services.lambda.runtime.events.SQSBatchResponse$BatchItemFailure$BatchItemFailureBuilder +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Multi +org.assertj.core.api.AssertionsForInterfaceTypes +org.assertj.core.api.GenericComparableAssert +org.assertj.core.api.AbstractUniversalComparableAssert +org.assertj.core.api.UniversalComparableAssert +org.assertj.core.api.AbstractIterableSizeAssert +org.assertj.core.api.IterableSizeAssert +org.assertj.core.api.AssertFactory +org.assertj.core.api.ObjectAssert +org.assertj.core.api.ListAssert$$Lambda$834/0x00007faab443f898 +org.assertj.core.internal.Iterables +org.assertj.core.internal.Predicates +org.assertj.core.internal.Lists +org.assertj.core.util.IterableUtil +org.assertj.core.internal.CommonValidations +software.amazon.lambda.powertools.validation.internal.ValidationAspectTest$$Lambda$835/0x00007faab4441120 +org.assertj.core.internal.Iterables$$Lambda$836/0x00007faab4441360 +org.assertj.core.internal.Iterables$$Lambda$837/0x00007faab44415b8 +org.assertj.core.internal.StandardComparisonStrategy$$Lambda$838/0x00007faab44417d8 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$839/0x00007faab4441a30 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$840/0x00007faab4441c88 +software.amazon.lambda.powertools.validation.handlers.ValidationInboundAPIGatewayV2HTTPEventHandler +software.amazon.lambda.powertools.validation.handlers.ValidationInboundAPIGatewayV2HTTPEventHandler$AjcClosure1 +org.assertj.core.internal.WholeNumbers +org.assertj.core.internal.Numbers +org.assertj.core.internal.Integers +org.mockito.internal.invocation.RealMethod$IsIllegal +org.mockito.internal.debugging.LocationFactory +org.mockito.internal.debugging.LocationFactory$Factory +org.mockito.internal.util.Platform +org.mockito.internal.debugging.LocationFactory$DefaultLocationFactory +org.mockito.invocation.Location +org.mockito.internal.debugging.LocationImpl +org.mockito.exceptions.stacktrace.StackTraceCleaner +org.mockito.exceptions.stacktrace.StackTraceCleaner$StackFrameMetadata +org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleaner +org.mockito.internal.debugging.LocationImpl$$Lambda$841/0x00007faab4444500 +org.mockito.internal.debugging.LocationImpl$$Lambda$842/0x00007faab4444740 +org.mockito.internal.debugging.LocationImpl$$Lambda$843/0x00007faab4444998 +java.lang.StackStreamFactory +java.lang.StackWalker$ExtendedOption +java.lang.StackStreamFactory$StackFrameTraverser +java.lang.StackStreamFactory$WalkerState +java.lang.StackStreamFactory$1 +java.lang.StackStreamFactory$FrameBuffer +java.lang.StackStreamFactory$StackFrameTraverser$StackFrameBuffer +org.mockito.internal.debugging.LocationImpl$$Lambda$844/0x00007faab4444bd8 +org.mockito.internal.debugging.LocationImpl$MetadataShim +org.mockito.internal.debugging.LocationImpl$$Lambda$845/0x00007faab4445058 +org.mockito.internal.debugging.LocationImpl$$Lambda$846/0x00007faab4445298 +org.mockito.invocation.InvocationFactory +org.mockito.internal.invocation.DefaultInvocationFactory +org.mockito.internal.invocation.mockref.MockReference +org.mockito.internal.invocation.AbstractAwareMethod +org.mockito.internal.invocation.MockitoMethod +org.mockito.internal.exceptions.VerificationAwareInvocation +org.mockito.internal.invocation.InterceptedInvocation +org.mockito.internal.invocation.InterceptedInvocation$1 +org.mockito.internal.invocation.mockref.MockWeakReference +org.mockito.internal.creation.DelegatingMethod +org.mockito.internal.creation.SuspendMethod +org.mockito.internal.progress.SequenceNumber +org.mockito.internal.invocation.ArgumentsProcessor +org.mockito.internal.invocation.InvocationMatcher +org.mockito.internal.invocation.ArgumentMatcherAction +org.mockito.internal.stubbing.BaseStubbing +org.mockito.internal.stubbing.OngoingStubbingImpl +org.mockito.internal.listeners.StubbingLookupNotifier +org.mockito.listeners.StubbingLookupEvent +org.mockito.internal.util.ObjectMethodsGuru +org.mockito.internal.util.Primitives +org.mockito.internal.stubbing.answers.DefaultAnswerValidator +org.mockito.internal.stubbing.answers.InvocationInfo +org.mockito.internal.stubbing.answers.Returns +org.mockito.internal.util.reflection.GenericMetadataSupport +org.mockito.internal.util.reflection.GenericMetadataSupport$GenericArrayReturnType +org.mockito.internal.util.reflection.GenericMetadataSupport$FromClassGenericMetadataSupport +org.mockito.internal.util.reflection.GenericMetadataSupport$FromParameterizedTypeGenericMetadataSupport +org.mockito.internal.util.reflection.GenericMetadataSupport$BoundedType +org.mockito.internal.util.reflection.GenericMetadataSupport$NotGenericReturnTypeSupport +org.mockito.internal.util.reflection.GenericMetadataSupport$ParameterizedReturnType +org.mockito.internal.util.reflection.GenericMetadataSupport$TypeVariableReturnType +org.mockito.internal.stubbing.StubbedInvocationMatcher +org.mockito.internal.stubbing.ConsecutiveStubbing +org.mockito.internal.invocation.MatcherApplicationStrategy +org.mockito.internal.invocation.TypeSafeMatching +org.mockito.internal.invocation.StubInfoImpl +org.mockito.internal.invocation.InvocationMatcher$1 +org.mockito.internal.util.KotlinInlineClassUtil +org.mockito.internal.matchers.ContainsExtraTypeInfo +org.mockito.internal.matchers.Equals +org.mockito.internal.matchers.ArrayEquals +org.assertj.core.api.NotThrownAssert +org.assertj.core.api.ThrowableAssert$ThrowingCallable +software.amazon.lambda.powertools.validation.internal.ValidationAspectTest$$Lambda$847/0x00007faab444b9b0 +org.mockito.internal.invocation.TypeSafeMatching$$Lambda$848/0x00007faab444bbd8 +org.mockito.internal.matchers.CapturesArguments +org.assertj.core.internal.Throwables +org.assertj.core.description.EmptyTextDescription +software.amazon.lambda.powertools.validation.handlers.KinesisHandlerWithError +software.amazon.lambda.powertools.validation.handlers.KinesisHandlerWithError$AjcClosure1 +com.amazonaws.services.lambda.runtime.events.StreamsEventResponse$BatchItemFailure +com.amazonaws.services.lambda.runtime.events.StreamsEventResponse$BatchItemFailure$BatchItemFailureBuilder +software.amazon.lambda.powertools.validation.internal.ValidationAspectTest$$Lambda$849/0x00007faab444cdd0 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$850/0x00007faab444d010 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$851/0x00007faab444d260 +org.junit.jupiter.params.provider.AnnotationBasedArgumentsProvider$$Lambda$852/0x00007faab444d4b0 +org.junit.jupiter.engine.descriptor.TestTemplateExtensionContext$$Lambda$853/0x00007faab444d6f8 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$854/0x00007faab444d938 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$855/0x00007faab444db80 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$856/0x00007faab444ddc8 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$857/0x00007faab444e010 +org.junit.jupiter.params.provider.ArgumentsUtils +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$858/0x00007faab444e458 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$859/0x00007faab444e698 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$860/0x00007faab444e8c0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$861/0x00007faab444eb08 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$862/0x00007faab444ed60 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$863/0x00007faab444ef88 +com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent +com.amazonaws.services.lambda.runtime.events.KafkaEvent +com.amazonaws.services.lambda.runtime.events.ActiveMQEvent +com.amazonaws.services.lambda.runtime.events.RabbitMQEvent +com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsFirehoseInputPreprocessingEvent +com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsStreamsInputPreprocessingEvent +com.fasterxml.jackson.databind.deser.std.JdkDeserializers +com.fasterxml.jackson.databind.deser.std.FromStringDeserializer +com.fasterxml.jackson.databind.deser.std.UUIDDeserializer +com.fasterxml.jackson.databind.deser.std.AtomicBooleanDeserializer +com.fasterxml.jackson.databind.deser.std.AtomicIntegerDeserializer +com.fasterxml.jackson.databind.deser.std.AtomicLongDeserializer +com.fasterxml.jackson.databind.deser.std.ByteBufferDeserializer +com.fasterxml.jackson.databind.deser.std.NullifyingDeserializer +com.fasterxml.jackson.databind.deser.std.StdNodeBasedDeserializer +com.fasterxml.jackson.databind.deser.std.ThreadGroupDeserializer +com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$StringBuilderDeserializer +com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$StringBufferDeserializer +com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$Std +com.fasterxml.jackson.databind.jsontype.impl.SubTypeValidator +com.fasterxml.jackson.databind.annotation.JsonValueInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators +com.fasterxml.jackson.databind.deser.ValueInstantiator +com.fasterxml.jackson.databind.deser.ValueInstantiator$Base +com.fasterxml.jackson.databind.deser.std.JsonLocationInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$JDKValueInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$ArrayListInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$HashSetInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$LinkedListInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$TreeSetInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$ConstantValueInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$LinkedHashMapInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$HashMapInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$ConcurrentHashMapInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$TreeMapInstantiator +com.fasterxml.jackson.core.JsonLocation +com.amazonaws.services.lambda.runtime.events.SNSEvent$SNSRecord +com.fasterxml.jackson.databind.deser.impl.CreatorCollector +com.fasterxml.jackson.databind.deser.std.StdValueInstantiator +com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder +com.fasterxml.jackson.databind.deser.impl.ObjectIdValueProperty +com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer +com.fasterxml.jackson.databind.deser.impl.FailingDeserializer +com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider +com.fasterxml.jackson.databind.util.AccessPattern +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$4 +com.fasterxml.jackson.annotation.JsonAlias +com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap +com.fasterxml.jackson.databind.exc.IgnoredPropertyException +com.fasterxml.jackson.databind.deser.SettableBeanProperty$Delegating +com.fasterxml.jackson.databind.deser.impl.ManagedReferenceProperty +com.fasterxml.jackson.databind.deser.impl.ObjectIdReferenceProperty +com.fasterxml.jackson.databind.deser.impl.MergingSettableBeanProperty +com.fasterxml.jackson.databind.deser.impl.InnerClassProperty +com.fasterxml.jackson.databind.deser.impl.ReadableObjectId$Referring +com.fasterxml.jackson.databind.deser.BeanDeserializer$BeanReferring +com.fasterxml.jackson.databind.deser.impl.BeanAsArrayDeserializer +com.fasterxml.jackson.databind.deser.BasicDeserializerFactory$ContainerDefaultMappings +com.amazonaws.services.lambda.runtime.events.SNSEvent$SNS +com.amazonaws.services.lambda.runtime.events.SNSEvent$MessageAttribute +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringKD +com.fasterxml.jackson.databind.deser.ContextualKeyDeserializer +com.fasterxml.jackson.databind.annotation.JacksonStdImpl +jdk.proxy2.$Proxy78 +com.fasterxml.jackson.core.util.InternalJacksonUtil +software.amazon.lambda.powertools.validation.internal.ValidationAspect$$Lambda$864/0x00007faab445d7b0 +com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializerNR +com.fasterxml.jackson.databind.deser.std.NumberDeserializers +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$PrimitiveOrWrapperDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BooleanDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$LongDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$DoubleDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$CharacterDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$ByteDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$ShortDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$FloatDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$NumberDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BigDecimalDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BigIntegerDeserializer +com.fasterxml.jackson.databind.util.TokenBuffer$Parser +com.fasterxml.jackson.databind.util.TokenBuffer$Segment +com.fasterxml.jackson.databind.ser.std.MapProperty +com.fasterxml.jackson.databind.ser.BasicSerializerFactory$1 +com.fasterxml.jackson.databind.ser.std.StdKeySerializers +com.fasterxml.jackson.databind.ser.std.StdKeySerializer +com.fasterxml.jackson.databind.ser.std.StdKeySerializers$StringKeySerializer +com.fasterxml.jackson.databind.ser.std.StdKeySerializers$Dynamic +com.fasterxml.jackson.databind.ser.std.StdKeySerializers$Default +com.fasterxml.jackson.databind.ser.std.StdKeySerializers$EnumKeySerializer +com.fasterxml.jackson.databind.ser.std.MapSerializer$1 +com.fasterxml.jackson.databind.util.TokenBufferReadContext +com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent$RequestContext +com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent$Elb +com.amazonaws.services.lambda.runtime.events.CloudWatchLogsEvent$AWSLogs +java.util.Base64 +java.util.Base64$Decoder +java.util.Base64$Encoder +java.lang.invoke.LambdaForm$MH/0x00007faab4468000 +java.lang.invoke.LambdaForm$MH/0x00007faab4468400 +com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent$CloudFormationCustomResourceEventBuilder +com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent$Record +com.fasterxml.jackson.databind.deser.std.DateDeserializers +com.fasterxml.jackson.databind.deser.std.DateDeserializers$DateBasedDeserializer +com.fasterxml.jackson.databind.deser.std.DateDeserializers$CalendarDeserializer +com.fasterxml.jackson.databind.deser.std.DateDeserializers$DateDeserializer +com.fasterxml.jackson.databind.util.ByteBufferBackedOutputStream +software.amazon.lambda.powertools.validation.internal.ValidationAspect$$Lambda$865/0x00007faab4465ee8 +com.amazonaws.services.lambda.runtime.events.KafkaEvent$KafkaEventBuilder +com.amazonaws.services.lambda.runtime.events.KafkaEvent$KafkaEventRecord +com.amazonaws.services.lambda.runtime.events.KafkaEvent$SchemaMetadata +com.amazonaws.services.lambda.runtime.events.KafkaEvent$KafkaEventRecord$KafkaEventRecordBuilder +sun.reflect.generics.tree.IntSignature +sun.reflect.generics.tree.LongSignature +sun.reflect.generics.tree.ByteSignature +com.amazonaws.services.lambda.runtime.events.KafkaEvent$SchemaMetadata$SchemaMetadataBuilder +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$IntDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$LongDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$ByteDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$ShortDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$FloatDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$DoubleDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$BooleanDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$CharDeser +com.fasterxml.jackson.databind.exc.InvalidNullException +software.amazon.lambda.powertools.validation.internal.ValidationAspect$$Lambda$866/0x00007faab446de00 +software.amazon.lambda.powertools.validation.internal.ValidationAspect$$Lambda$867/0x00007faab446e038 +com.amazonaws.services.lambda.runtime.events.ActiveMQEvent$ActiveMQEventBuilder +com.amazonaws.services.lambda.runtime.events.ActiveMQEvent$ActiveMQMessage +com.amazonaws.services.lambda.runtime.events.ActiveMQEvent$Destination +com.amazonaws.services.lambda.runtime.events.ActiveMQEvent$ActiveMQMessage$ActiveMQMessageBuilder +sun.reflect.generics.tree.BooleanSignature +com.amazonaws.services.lambda.runtime.events.ActiveMQEvent$Destination$DestinationBuilder +com.fasterxml.jackson.databind.cfg.CoercionConfigs$1 +software.amazon.lambda.powertools.validation.internal.ValidationAspect$$Lambda$868/0x00007faab446f088 +com.amazonaws.services.lambda.runtime.events.RabbitMQEvent$RabbitMQEventBuilder +com.amazonaws.services.lambda.runtime.events.RabbitMQEvent$RabbitMessage +com.amazonaws.services.lambda.runtime.events.RabbitMQEvent$BasicProperties +com.amazonaws.services.lambda.runtime.events.RabbitMQEvent$RabbitMessage$RabbitMessageBuilder +com.amazonaws.services.lambda.runtime.events.RabbitMQEvent$BasicProperties$BasicPropertiesBuilder +com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializerNR$Scope +software.amazon.lambda.powertools.validation.internal.ValidationAspect$$Lambda$869/0x00007faab446a210 +software.amazon.lambda.powertools.validation.internal.ValidationAspect$$Lambda$870/0x00007faab446a448 +com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsFirehoseInputPreprocessingEvent$Record +com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsFirehoseInputPreprocessingEvent$Record$KinesisFirehoseRecordMetadata +software.amazon.lambda.powertools.validation.internal.ValidationAspect$$Lambda$871/0x00007faab446aae0 +jdk.internal.reflect.GeneratedConstructorAccessor8 +jdk.internal.reflect.GeneratedMethodAccessor19 +com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsStreamsInputPreprocessingEvent$Record +com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsStreamsInputPreprocessingEvent$Record$KinesisStreamRecordMetadata +software.amazon.lambda.powertools.validation.internal.ValidationAspect$$Lambda$872/0x00007faab446b1a8 +software.amazon.lambda.powertools.validation.model.Basket +com.amazonaws.services.lambda.runtime.events.APIGatewayV2WebSocketResponse +com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerResponseEvent +com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsInputPreprocessingResponse +com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsInputPreprocessingResponse$Record +com.amazonaws.services.lambda.runtime.events.KinesisAnalyticsInputPreprocessingResponse$Result +software.amazon.lambda.powertools.validation.internal.ResponseEventsArgumentsProvider$$Lambda$873/0x00007faab4469440 +org.assertj.core.api.ThrowableTypeAssert +software.amazon.lambda.powertools.validation.internal.ValidationAspectTest$$Lambda$874/0x00007faab4469920 +org.assertj.core.api.ThrowableAssertAlternative +software.amazon.lambda.powertools.validation.internal.ValidationAspect$$Lambda$875/0x00007faab4469b48 +software.amazon.lambda.powertools.validation.handlers.SQSHandlerWithError +software.amazon.lambda.powertools.validation.handlers.SQSHandlerWithError$AjcClosure1 +software.amazon.lambda.powertools.validation.internal.ValidationAspectTest$$Lambda$876/0x00007faab4470bc0 +software.amazon.lambda.powertools.validation.handlers.GenericSchemaV7APIGatewayProxyRequestEventHandler +software.amazon.lambda.powertools.validation.handlers.GenericSchemaV7APIGatewayProxyRequestEventHandler$AjcClosure1 +org.assertj.core.api.AbstractCharSequenceAssert$$Lambda$877/0x00007faab4471280 +org.assertj.core.api.AbstractMapAssert +org.assertj.core.api.MapAssert +org.assertj.core.api.AbstractMapSizeAssert +org.assertj.core.api.MapSizeAssert +org.assertj.core.internal.Maps +software.amazon.lambda.powertools.validation.internal.HandledResponseEventsArgumentsProvider$$Lambda$878/0x00007faab4474720 +org.assertj.core.util.Preconditions +org.assertj.core.internal.ComparatorBasedComparisonStrategy +java.util.concurrent.atomic.Striped64 +java.util.concurrent.atomic.LongAdder +java.util.concurrent.atomic.AtomicMarkableReference +java.util.concurrent.atomic.AtomicStampedReference +java.util.concurrent.atomic.AtomicIntegerFieldUpdater +java.util.concurrent.atomic.AtomicLongFieldUpdater +java.util.concurrent.atomic.AtomicReferenceFieldUpdater +org.assertj.core.presentation.PredicateDescription +org.assertj.core.presentation.TransformingList +org.assertj.core.presentation.StandardRepresentation$$Lambda$879/0x00007faab4475580 +java.lang.invoke.LambdaForm$DMH/0x00007faab4478000 +java.lang.invoke.LambdaForm$MH/0x00007faab4478400 +software.amazon.lambda.powertools.validation.internal.ValidationAspectTest$$Lambda$880/0x00007faab44757c8 +org.assertj.core.data.MapEntry +org.assertj.core.internal.ErrorMessages +software.amazon.lambda.powertools.validation.internal.ValidationAspectTest$$Lambda$881/0x00007faab4476048 +software.amazon.lambda.powertools.validation.handlers.StandardKinesisHandler +software.amazon.lambda.powertools.validation.handlers.StandardKinesisHandler$AjcClosure1 +software.amazon.lambda.powertools.validation.internal.ValidationAspectTest$$Lambda$882/0x00007faab4476700 +software.amazon.lambda.powertools.validation.handlers.SQSWithCustomEnvelopeHandler +software.amazon.lambda.powertools.validation.handlers.SQSWithCustomEnvelopeHandler$AjcClosure1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.exc.StreamWriteException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonGenerationException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.JsonWriteContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.StreamWriteCapability +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap$Bucket +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.TypeKey +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap$$Lambda$883/0x00007faab447c420 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$EntrySet +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$EntryIterator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BeanSerializerBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.PropertyBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonInclude +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$3 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonTypeId +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.BeanProperty$Std +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.PropertyBuilder$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Empty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Single +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonAppend +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFilter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.BeanAsArraySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$SerializerAndMapResult +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Double +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.MapProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BasicSerializerFactory$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdKeySerializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdKeySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdKeySerializers$StringKeySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdKeySerializers$Dynamic +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdKeySerializers$Default +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdKeySerializers$EnumKeySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.MapSerializer$1 +io.burt.jmespath.antlr.v4.runtime.tree.ParseTreeVisitor +io.burt.jmespath.parser.JmesPathVisitor +io.burt.jmespath.antlr.v4.runtime.tree.AbstractParseTreeVisitor +io.burt.jmespath.parser.JmesPathBaseVisitor +io.burt.jmespath.parser.ExpressionParser +io.burt.jmespath.antlr.v4.runtime.tree.Tree +io.burt.jmespath.antlr.v4.runtime.tree.SyntaxTree +io.burt.jmespath.antlr.v4.runtime.tree.ParseTree +io.burt.jmespath.antlr.v4.runtime.tree.RuleNode +io.burt.jmespath.antlr.v4.runtime.ANTLRErrorListener +io.burt.jmespath.parser.ParseException +io.burt.jmespath.util.StringEscapeHelper +io.burt.jmespath.antlr.v4.runtime.BaseErrorListener +io.burt.jmespath.parser.ParseErrorAccumulator +io.burt.jmespath.util.AntlrHelper +io.burt.jmespath.antlr.v4.runtime.TokenSource +io.burt.jmespath.antlr.v4.runtime.IntStream +io.burt.jmespath.antlr.v4.runtime.TokenStream +io.burt.jmespath.antlr.v4.runtime.CharStream +io.burt.jmespath.antlr.v4.runtime.Recognizer +io.burt.jmespath.antlr.v4.runtime.Lexer +io.burt.jmespath.parser.JmesPathLexer +io.burt.jmespath.antlr.v4.runtime.RecognitionException +io.burt.jmespath.antlr.v4.runtime.LexerNoViableAltException +java.util.EmptyStackException +io.burt.jmespath.antlr.v4.runtime.atn.ATNSimulator +io.burt.jmespath.antlr.v4.runtime.atn.LexerATNSimulator +io.burt.jmespath.antlr.v4.runtime.Vocabulary +io.burt.jmespath.antlr.v4.runtime.RuntimeMetaData +io.burt.jmespath.antlr.v4.runtime.atn.PredictionContextCache +io.burt.jmespath.antlr.v4.runtime.atn.PredictionContext +io.burt.jmespath.antlr.v4.runtime.atn.SingletonPredictionContext +io.burt.jmespath.antlr.v4.runtime.atn.EmptyPredictionContext +io.burt.jmespath.antlr.v4.runtime.VocabularyImpl +io.burt.jmespath.antlr.v4.runtime.atn.ATNDeserializer +java.io.InvalidClassException +io.burt.jmespath.antlr.v4.runtime.atn.Transition +io.burt.jmespath.antlr.v4.runtime.atn.EpsilonTransition +io.burt.jmespath.antlr.v4.runtime.atn.ActionTransition +io.burt.jmespath.antlr.v4.runtime.atn.ATNState +io.burt.jmespath.antlr.v4.runtime.atn.DecisionState +io.burt.jmespath.antlr.v4.runtime.atn.BlockStartState +io.burt.jmespath.antlr.v4.runtime.atn.BasicBlockStartState +io.burt.jmespath.antlr.v4.runtime.atn.BlockEndState +io.burt.jmespath.antlr.v4.runtime.atn.RuleStopState +io.burt.jmespath.antlr.v4.runtime.atn.BasicState +io.burt.jmespath.antlr.v4.runtime.atn.AtomTransition +io.burt.jmespath.antlr.v4.runtime.atn.RangeTransition +io.burt.jmespath.antlr.v4.runtime.atn.RuleTransition +io.burt.jmespath.antlr.v4.runtime.atn.AbstractPredicateTransition +io.burt.jmespath.antlr.v4.runtime.atn.PredicateTransition +io.burt.jmespath.antlr.v4.runtime.atn.PrecedencePredicateTransition +io.burt.jmespath.antlr.v4.runtime.atn.SetTransition +io.burt.jmespath.antlr.v4.runtime.atn.NotSetTransition +io.burt.jmespath.antlr.v4.runtime.atn.WildcardTransition +io.burt.jmespath.antlr.v4.runtime.atn.RuleStartState +io.burt.jmespath.antlr.v4.runtime.atn.PlusBlockStartState +io.burt.jmespath.antlr.v4.runtime.atn.StarBlockStartState +io.burt.jmespath.antlr.v4.runtime.atn.TokensStartState +io.burt.jmespath.antlr.v4.runtime.atn.StarLoopbackState +io.burt.jmespath.antlr.v4.runtime.atn.StarLoopEntryState +io.burt.jmespath.antlr.v4.runtime.atn.PlusLoopbackState +io.burt.jmespath.antlr.v4.runtime.atn.LoopEndState +io.burt.jmespath.antlr.v4.runtime.atn.ATNDeserializer$UnicodeDeserializer +io.burt.jmespath.antlr.v4.runtime.atn.LexerAction +io.burt.jmespath.antlr.v4.runtime.atn.ATNDeserializationOptions +io.burt.jmespath.antlr.v4.runtime.atn.ATNType +io.burt.jmespath.antlr.v4.runtime.atn.ATN +io.burt.jmespath.antlr.v4.runtime.misc.IntSet +io.burt.jmespath.antlr.v4.runtime.misc.Pair +io.burt.jmespath.antlr.v4.runtime.atn.ATNDeserializer$UnicodeDeserializingMode +io.burt.jmespath.antlr.v4.runtime.atn.ATNDeserializer$1 +io.burt.jmespath.antlr.v4.runtime.misc.IntervalSet +io.burt.jmespath.antlr.v4.runtime.misc.Interval +io.burt.jmespath.antlr.v4.runtime.atn.ATNDeserializer$2 +io.burt.jmespath.antlr.v4.runtime.atn.Transition$1 +io.burt.jmespath.antlr.v4.runtime.atn.LexerActionType +io.burt.jmespath.antlr.v4.runtime.atn.ATNDeserializer$3 +io.burt.jmespath.antlr.v4.runtime.atn.LexerSkipAction +io.burt.jmespath.antlr.v4.runtime.dfa.DFA +io.burt.jmespath.antlr.v4.runtime.dfa.DFASerializer +io.burt.jmespath.antlr.v4.runtime.dfa.LexerDFASerializer +io.burt.jmespath.antlr.v4.runtime.CharStreams +io.burt.jmespath.antlr.v4.runtime.CodePointBuffer +io.burt.jmespath.antlr.v4.runtime.CodePointBuffer$Builder +io.burt.jmespath.antlr.v4.runtime.CodePointBuffer$Type +io.burt.jmespath.antlr.v4.runtime.CodePointBuffer$1 +io.burt.jmespath.antlr.v4.runtime.CodePointCharStream +io.burt.jmespath.antlr.v4.runtime.CodePointCharStream$CodePoint8BitCharStream +io.burt.jmespath.antlr.v4.runtime.CodePointCharStream$CodePoint16BitCharStream +io.burt.jmespath.antlr.v4.runtime.CodePointCharStream$CodePoint32BitCharStream +io.burt.jmespath.antlr.v4.runtime.CodePointCharStream$1 +io.burt.jmespath.antlr.v4.runtime.Recognizer$1 +io.burt.jmespath.antlr.v4.runtime.ConsoleErrorListener +io.burt.jmespath.antlr.v4.runtime.TokenFactory +io.burt.jmespath.antlr.v4.runtime.CommonTokenFactory +io.burt.jmespath.antlr.v4.runtime.Token +io.burt.jmespath.antlr.v4.runtime.misc.IntegerList +io.burt.jmespath.antlr.v4.runtime.misc.IntegerStack +io.burt.jmespath.antlr.v4.runtime.atn.ATNConfig +io.burt.jmespath.antlr.v4.runtime.atn.LexerATNConfig +io.burt.jmespath.antlr.v4.runtime.atn.ATNConfigSet +io.burt.jmespath.antlr.v4.runtime.atn.OrderedATNConfigSet +io.burt.jmespath.antlr.v4.runtime.dfa.DFAState +io.burt.jmespath.antlr.v4.runtime.misc.Array2DHashSet +io.burt.jmespath.antlr.v4.runtime.atn.ATNConfigSet$AbstractConfigHashSet +io.burt.jmespath.antlr.v4.runtime.atn.ATNConfigSet$ConfigHashSet +io.burt.jmespath.antlr.v4.runtime.misc.EqualityComparator +io.burt.jmespath.antlr.v4.runtime.misc.AbstractEqualityComparator +io.burt.jmespath.antlr.v4.runtime.misc.ObjectEqualityComparator +io.burt.jmespath.antlr.v4.runtime.atn.ATNConfigSet$ConfigEqualityComparator +io.burt.jmespath.antlr.v4.runtime.atn.LexerATNSimulator$SimState +io.burt.jmespath.antlr.v4.runtime.BufferedTokenStream +io.burt.jmespath.antlr.v4.runtime.CommonTokenStream +io.burt.jmespath.antlr.v4.runtime.Parser +io.burt.jmespath.parser.JmesPathParser +io.burt.jmespath.antlr.v4.runtime.ANTLRErrorStrategy +io.burt.jmespath.antlr.v4.runtime.RuleContext +io.burt.jmespath.antlr.v4.runtime.ParserRuleContext +io.burt.jmespath.antlr.v4.runtime.tree.ParseTreeListener +io.burt.jmespath.antlr.v4.runtime.tree.TerminalNode +io.burt.jmespath.antlr.v4.runtime.tree.ErrorNode +io.burt.jmespath.antlr.v4.runtime.atn.ParserATNSimulator +io.burt.jmespath.antlr.v4.runtime.atn.ProfilingATNSimulator +io.burt.jmespath.parser.JmesPathParser$SliceContext +io.burt.jmespath.parser.JmesPathParser$WildcardContext +io.burt.jmespath.parser.JmesPathParser$LiteralContext +io.burt.jmespath.parser.JmesPathParser$ExpressionContext +io.burt.jmespath.parser.JmesPathParser$BracketExpressionContext +io.burt.jmespath.parser.JmesPathParser$NotExpressionContext +io.burt.jmespath.parser.JmesPathParser$IdentifierExpressionContext +io.burt.jmespath.parser.JmesPathParser$ParenExpressionContext +io.burt.jmespath.parser.JmesPathParser$WildcardExpressionContext +io.burt.jmespath.parser.JmesPathParser$MultiSelectListExpressionContext +io.burt.jmespath.parser.JmesPathParser$MultiSelectHashExpressionContext +io.burt.jmespath.parser.JmesPathParser$LiteralExpressionContext +io.burt.jmespath.parser.JmesPathParser$FunctionCallExpressionContext +io.burt.jmespath.parser.JmesPathParser$RawStringExpressionContext +io.burt.jmespath.parser.JmesPathParser$CurrentNodeExpressionContext +io.burt.jmespath.parser.JmesPathParser$ComparisonExpressionContext +io.burt.jmespath.antlr.v4.runtime.FailedPredicateException +io.burt.jmespath.parser.JmesPathParser$AndExpressionContext +io.burt.jmespath.parser.JmesPathParser$OrExpressionContext +io.burt.jmespath.parser.JmesPathParser$PipeExpressionContext +io.burt.jmespath.parser.JmesPathParser$ChainExpressionContext +io.burt.jmespath.parser.JmesPathParser$BracketedExpressionContext +io.burt.jmespath.parser.JmesPathParser$IdentifierContext +io.burt.jmespath.parser.JmesPathParser$JsonObjectContext +io.burt.jmespath.parser.JmesPathParser$CurrentNodeContext +io.burt.jmespath.parser.JmesPathParser$JmesPathExpressionContext +io.burt.jmespath.parser.JmesPathParser$BracketSpecifierContext +io.burt.jmespath.parser.JmesPathParser$BracketIndexContext +io.burt.jmespath.parser.JmesPathParser$BracketStarContext +io.burt.jmespath.parser.JmesPathParser$BracketSliceContext +io.burt.jmespath.parser.JmesPathParser$BracketFlattenContext +io.burt.jmespath.parser.JmesPathParser$SelectContext +io.burt.jmespath.parser.JmesPathParser$ChainedExpressionContext +io.burt.jmespath.parser.JmesPathParser$KeyvalExprContext +io.burt.jmespath.parser.JmesPathParser$FunctionArgContext +io.burt.jmespath.antlr.v4.runtime.NoViableAltException +io.burt.jmespath.parser.JmesPathParser$JsonValueContext +io.burt.jmespath.parser.JmesPathParser$JsonStringValueContext +io.burt.jmespath.parser.JmesPathParser$JsonNumberValueContext +io.burt.jmespath.parser.JmesPathParser$JsonObjectValueContext +io.burt.jmespath.parser.JmesPathParser$JsonArrayValueContext +io.burt.jmespath.parser.JmesPathParser$JsonConstantValueContext +io.burt.jmespath.parser.JmesPathParser$MultiSelectListContext +io.burt.jmespath.parser.JmesPathParser$MultiSelectHashContext +io.burt.jmespath.parser.JmesPathParser$FunctionExpressionContext +io.burt.jmespath.parser.JmesPathParser$ExpressionTypeContext +io.burt.jmespath.parser.JmesPathParser$JsonObjectPairContext +io.burt.jmespath.parser.JmesPathParser$JsonArrayContext +io.burt.jmespath.antlr.v4.runtime.DefaultErrorStrategy +io.burt.jmespath.antlr.v4.runtime.InputMismatchException +io.burt.jmespath.antlr.v4.runtime.atn.SemanticContext +io.burt.jmespath.antlr.v4.runtime.atn.SemanticContext$PrecedencePredicate +io.burt.jmespath.antlr.v4.runtime.atn.SemanticContext$Predicate +io.burt.jmespath.antlr.v4.runtime.atn.PredictionMode +io.burt.jmespath.antlr.v4.runtime.atn.ArrayPredictionContext +io.burt.jmespath.antlr.v4.runtime.misc.MurmurHash +io.burt.jmespath.antlr.v4.runtime.atn.OrderedATNConfigSet$LexerConfigHashSet +io.burt.jmespath.antlr.v4.runtime.atn.SemanticContext$Operator +io.burt.jmespath.antlr.v4.runtime.atn.SemanticContext$OR +io.burt.jmespath.antlr.v4.runtime.atn.SemanticContext$AND +io.burt.jmespath.antlr.v4.runtime.WritableToken +io.burt.jmespath.antlr.v4.runtime.CommonToken +io.burt.jmespath.antlr.v4.runtime.atn.LL1Analyzer +io.burt.jmespath.antlr.v4.runtime.misc.DoubleKeyMap +io.burt.jmespath.antlr.v4.runtime.misc.FlexibleHashMap +io.burt.jmespath.antlr.v4.runtime.atn.PredictionMode$AltAndContextMap +io.burt.jmespath.antlr.v4.runtime.atn.PredictionMode$AltAndContextConfigEqualityComparator +io.burt.jmespath.antlr.v4.runtime.misc.FlexibleHashMap$Entry +io.burt.jmespath.antlr.v4.runtime.tree.TerminalNodeImpl +io.burt.jmespath.antlr.v4.runtime.dfa.DFAState$PredPrediction +io.burt.jmespath.jackson.JacksonRuntime$1 +io.burt.jmespath.jackson.JacksonRuntime$ArrayNodeListWrapper +io.burt.jmespath.function.FunctionArgument +io.burt.jmespath.function.FunctionArgument$V +io.burt.jmespath.function.FunctionArgument$E +software.amazon.lambda.powertools.validation.ValidationUtils$$Lambda$884/0x00007faab44a4e30 +software.amazon.lambda.powertools.validation.handlers.SQSWithWrongEnvelopeHandler$AjcClosure1 +software.amazon.lambda.powertools.validation.internal.ValidationAspectTest$$Lambda$885/0x00007faab44a52b8 +java.lang.invoke.LambdaForm$DMH/0x00007faab44a8000 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$886/0x00007faab44a54e0 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$887/0x00007faab44a5718 +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$888/0x00007faab44a5938 +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$889/0x00007faab44a5b88 +org.apache.maven.surefire.api.util.internal.ObjectUtils +org.apache.maven.surefire.api.util.internal.ImmutableMap$Node +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$890/0x00007faab44a6228 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$891/0x00007faab44a6450 +com.fasterxml.jackson.databind.util.NativeImageUtil +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$892/0x00007faab44a6880 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$893/0x00007faab44a6aa8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonCreator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonCreator$Mode +java.util.concurrent.ConcurrentHashMap$TreeNode +java.util.concurrent.ConcurrentHashMap$TreeBin +com.networknt.schema.Version201909 +com.networknt.schema.Version201909$Holder +com.networknt.schema.Vocabularies +com.networknt.schema.Vocabulary +java.lang.invoke.LambdaForm$DMH/0x00007faab44a8400 +com.networknt.schema.RefValidator$$Lambda$894/0x00007faab44a7b68 +java.lang.invoke.LambdaForm$DMH/0x00007faab44a8800 +java.lang.invoke.LambdaForm$DMH/0x00007faab44a8c00 +java.lang.invoke.LambdaForm$MH/0x00007faab44a9000 +com.networknt.schema.RecursiveRefValidator$$Lambda$895/0x00007faab44a7d90 +com.networknt.schema.utils.JsonNodes +com.networknt.schema.PatternValidator$$Lambda$896/0x00007faab44ac208 +com.networknt.schema.PatternValidator$$Lambda$897/0x00007faab44ac458 +com.networknt.schema.regex.JDKRegularExpression +com.networknt.schema.Version202012 +com.networknt.schema.Version202012$Holder +com.networknt.schema.DynamicRefValidator$$Lambda$898/0x00007faab44accf8 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$899/0x00007faab44acf20 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$WriteThroughEntry +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$900/0x00007faab44ad3a8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.NumberOutput +io.burt.jmespath.antlr.v4.runtime.ProxyErrorListener +io.burt.jmespath.parser.ParseError +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$901/0x00007faab44ade60 +com.networknt.schema.Version4 +com.networknt.schema.Version4$Holder +com.networknt.schema.MinimumValidator$2 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$902/0x00007faab44ae6f0 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$903/0x00007faab44ae910 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$904/0x00007faab44aeb38 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$905/0x00007faab44aed60 +jdk.internal.reflect.GeneratedConstructorAccessor9 +jdk.internal.reflect.GeneratedMethodAccessor20 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$906/0x00007faab44aef88 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$907/0x00007faab44af1b0 +java.lang.Throwable$PrintStreamOrWriter +java.lang.Throwable$WrappedPrintStream +java.lang.StackTraceElement$HashedModules +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$908/0x00007faab44af3d0 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$909/0x00007faab44af5f8 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$910/0x00007faab44af820 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$911/0x00007faab44afa48 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$912/0x00007faab44afc70 +com.fasterxml.jackson.databind.JsonMappingException$Reference +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$913/0x00007faab44aa250 +jdk.internal.reflect.GeneratedMethodAccessor21 +jdk.internal.reflect.GeneratedMethodAccessor22 +jdk.internal.reflect.GeneratedMethodAccessor23 +jdk.internal.reflect.GeneratedMethodAccessor24 +jdk.internal.reflect.GeneratedMethodAccessor25 +jdk.internal.reflect.GeneratedMethodAccessor26 +jdk.internal.reflect.GeneratedMethodAccessor27 +jdk.internal.reflect.GeneratedMethodAccessor28 +jdk.internal.reflect.GeneratedMethodAccessor29 +jdk.internal.reflect.GeneratedMethodAccessor30 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$914/0x00007faab44aa478 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$915/0x00007faab44aa6a0 +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$TypeAndSerializer +jdk.internal.reflect.GeneratedMethodAccessor31 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$916/0x00007faab44aacd0 +software.amazon.lambda.powertools.validation.ValidationUtilsTest$$Lambda$917/0x00007faab44aaef8 +com.networknt.schema.Version6 +com.networknt.schema.Version6$Holder +org.junit.platform.launcher.core.OutcomeDelayingEngineExecutionListener$Outcome +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$918/0x00007faab44ab990 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$919/0x00007faab44abbc8 +java.lang.invoke.LambdaForm$DMH/0x00007faab44b2800 +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$920/0x00007faab44b4000 +org.junit.platform.launcher.core.DefaultLauncherSession$ClosedLauncher +org.apache.maven.surefire.api.suite.RunResult +org.apache.maven.surefire.booter.ForkedBooter$6 +org.apache.maven.surefire.booter.ForkedBooter$7 +java.util.concurrent.locks.AbstractQueuedSynchronizer$SharedNode +java.util.concurrent.locks.AbstractQueuedSynchronizer$ExclusiveNode +org.apache.maven.surefire.booter.ForkedBooter$1 +org.apache.maven.surefire.booter.spi.AbstractMasterProcessChannelProcessorFactory$2 +java.util.IdentityHashMap$IdentityHashMapIterator +java.util.IdentityHashMap$KeyIterator diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationConfigTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationConfigTest.java new file mode 100644 index 000000000..bde195271 --- /dev/null +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/ValidationConfigTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.validation; + +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.mockito.Mockito.mock; + +import org.crac.Context; +import org.crac.Resource; +import org.junit.jupiter.api.Test; + +class ValidationConfigTest { + + ValidationConfig config = ValidationConfig.get(); + Context<Resource> context = mock(Context.class); + + @Test + void testBeforeCheckpointDoesNotThrowException() { + assertThatNoException().isThrownBy(() -> config.beforeCheckpoint(context)); + } + + @Test + void testAfterRestoreDoesNotThrowException() { + assertThatNoException().isThrownBy(() -> config.afterRestore(context)); + } +} diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index 9a42ebf16..35aed5e26 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -191,6 +191,11 @@ </And> </Or> </Match> + <Match> + <Bug pattern="RV_RETURN_VALUE_IGNORED_NO_SIDE_EFFECT"/> + <Class name="software.amazon.lambda.powertools.validation.ValidationConfig"/> + <Method name="beforeCheckpoint"/> + </Match> <!--Functionally needed--> <Match> <Bug pattern="MS_SHOULD_BE_FINAL"/> From a7785b30cedfdb2ec8bed6da78d153f5ea52290e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 10:54:05 -0300 Subject: [PATCH 391/577] chore: bump actions/dependency-review-action from 4.7.2 to 4.7.3 (#2092) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.2 to 4.7.3. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/bc41886e18ea39df68b1b1245f4184881938e050...595b5aeba73380359d98a5e087f648dbb0edce1b) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.7.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ana Falcão <anafalcao@poli.ufrj.br> --- .github/workflows/security-dependencies-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml index 3e0ca168c..903b96af9 100644 --- a/.github/workflows/security-dependencies-check.yml +++ b/.github/workflows/security-dependencies-check.yml @@ -26,6 +26,6 @@ jobs: - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Verify Contents - uses: actions/dependency-review-action@bc41886e18ea39df68b1b1245f4184881938e050 # v4.7.2 + uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # v4.7.3 with: config-file: './.github/dependency-review-config.yml' From 11da7254bff8f61ecd04524c21b11e056f642771 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 11:04:29 -0300 Subject: [PATCH 392/577] chore: bump aws.sdk.version from 2.32.30 to 2.32.31 (#2093) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps `aws.sdk.version` from 2.32.30 to 2.32.31. Updates `software.amazon.awssdk:bom` from 2.32.30 to 2.32.31 Updates `software.amazon.awssdk:http-client-spi` from 2.32.30 to 2.32.31 Updates `software.amazon.awssdk:url-connection-client` from 2.32.26 to 2.32.31 Updates `software.amazon.awssdk:dynamodb` from 2.32.30 to 2.32.31 Updates `software.amazon.awssdk:s3` from 2.32.26 to 2.32.31 Updates `software.amazon.awssdk:lambda` from 2.32.30 to 2.32.31 Updates `software.amazon.awssdk:kinesis` from 2.32.26 to 2.32.31 Updates `software.amazon.awssdk:cloudwatch` from 2.32.30 to 2.32.31 Updates `software.amazon.awssdk:xray` from 2.32.30 to 2.32.31 Updates `software.amazon.awssdk:sqs` from 2.32.26 to 2.32.31 Updates `software.amazon.awssdk:cloudformation` from 2.32.30 to 2.32.31 Updates `software.amazon.awssdk:sts` from 2.32.30 to 2.32.31 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.32.31 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.32.31 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ana Falcão <anafalcao@poli.ufrj.br> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index b92f458b0..45dffb792 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.30</aws.sdk.version> + <aws.sdk.version>2.32.31</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index c63e78d7e..7e287d4e5 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.19.2</jackson.version> - <aws.sdk.version>2.32.30</aws.sdk.version> + <aws.sdk.version>2.32.31</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 8cc580958..d7ac21335 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -20,7 +20,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.13.1</aspectj.plugin.version> <maven.compiler.version>3.11.0</maven.compiler.version> - <aws.sdk.version>2.32.30</aws.sdk.version> + <aws.sdk.version>2.32.31</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> From 58107194c1545115ebc500a198a47c1875ef75a6 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 28 Aug 2025 19:18:05 +0200 Subject: [PATCH 393/577] feat(graalvm): GraalVM support for powertools-cloudformation (#2090) --- .github/workflows/check-build.yml | 38 +- GraalVM.md | 26 ++ .../Makefile | 5 + .../infra/sam-graalvm/Dockerfile | 14 + .../infra/sam-graalvm/README.md | 52 +++ .../infra/sam-graalvm/template.yaml | 49 ++ .../pom.xml | 184 +++++--- .../src/main/config/bootstrap | 4 + .../aws-lambda-java-core/reflect-config.json | 13 + .../reflect-config.json | 35 ++ .../jni-config.json | 11 + .../native-image.properties | 1 + .../reflect-config.json | 34 ++ .../resource-config.json | 19 + .../reflect-config.json | 25 + .../helloworld/native-image.properties | 1 + .../helloworld/reflect-config.json | 11 + .../helloworld/resource-config.json | 7 + .../s3/reflect-config.json | 27 ++ powertools-cloudformation/pom.xml | 87 ++++ .../CloudFormationResponse.java | 2 +- .../reflect-config.json | 432 ++++++++++++++++++ .../resource-config.json | 41 ++ .../AbstractCustomResourceHandlerTest.java | 180 ++------ .../CloudFormationIntegrationTest.java | 155 ++----- .../CloudFormationResponseTest.java | 88 ++-- .../ExceptionThrowingHandler.java | 31 ++ .../ExpectedStatusResourceHandler.java | 56 +++ .../ExplicitSuccessResponseHandler.java | 31 ++ .../FailToSendResponseHandler.java | 41 ++ .../cloudformation/FailedResponseHandler.java | 31 ++ .../cloudformation/FailedSendHandler.java | 25 + .../NoOpCustomResourceHandler.java | 34 ++ .../NullCustomResourceHandler.java | 47 ++ .../cloudformation/ResponseTest.java | 8 +- .../SuccessResponseHandler.java | 31 ++ .../cloudformation/SuccessfulSendHandler.java | 25 + .../NoPhysicalResourceIdSetHandler.java | 1 + .../PhysicalResourceIdSetHandler.java | 1 + .../RuntimeExceptionThrownHandler.java | 1 + .../test/resources/simplelogger.properties | 7 + 41 files changed, 1511 insertions(+), 400 deletions(-) create mode 100644 examples/powertools-examples-cloudformation/Makefile create mode 100644 examples/powertools-examples-cloudformation/infra/sam-graalvm/Dockerfile create mode 100644 examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md create mode 100644 examples/powertools-examples-cloudformation/infra/sam-graalvm/template.yaml create mode 100755 examples/powertools-examples-cloudformation/src/main/config/bootstrap create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/native-image.properties create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/reflect-config.json create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/resource-config.json create mode 100644 examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/software.amazon.awssdk/s3/reflect-config.json create mode 100644 powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json create mode 100644 powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExceptionThrowingHandler.java create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExpectedStatusResourceHandler.java create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExplicitSuccessResponseHandler.java create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailToSendResponseHandler.java create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailedResponseHandler.java create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailedSendHandler.java create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/NoOpCustomResourceHandler.java create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/NullCustomResourceHandler.java create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/SuccessResponseHandler.java create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/SuccessfulSendHandler.java create mode 100644 powertools-cloudformation/src/test/resources/simplelogger.properties diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 3abb1440c..3a34188f9 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -92,6 +92,14 @@ jobs: - id: checkout name: Checkout repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + fetch-depth: 0 + - name: Get changed files + id: changed-files + uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5 + with: + files: | + powertools-*/** - name: Setup GraalVM uses: graalvm/setup-graalvm@7f488cf82a3629ee755e4e97342c01d6bed318fa # v1.3.5 with: @@ -100,18 +108,36 @@ jobs: cache: maven - id: graalvm-native-test name: GraalVM Native Test + if: steps.changed-files.outputs.any_changed == 'true' + env: + CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} run: | # Build the entire project first to ensure test-jar dependencies are available + echo "::group::Building project dependencies" mvn -B -q install -DskipTests + echo "::endgroup::" + + echo "Changes detected in powertools modules: $CHANGED_FILES" - # Find modules with graalvm-native profile and run tests recursively. - # This will make sure to discover new GraalVM supported modules automatically in the future. + # Find modules with graalvm-native profile and run tests find . -name "pom.xml" -path "./powertools-*" | while read module; do if grep -q "<id>graalvm-native</id>" "$module"; then module_dir=$(dirname "$module") - echo "Regenerating GraalVM metadata for $module_dir" - mvn -B -q -f "$module" -Pgenerate-graalvm-files clean test - echo "Running GraalVM native tests for $module_dir" - mvn -B -q -f "$module" -Pgraalvm-native test + module_name=$(basename "$module_dir") + + # Check if this specific module or common dependencies changed + if echo "$CHANGED_FILES" | grep -q "$module_name/" || \ + echo " $CHANGED_FILES " | grep -q " pom.xml " || \ + echo "$CHANGED_FILES" | grep -q "powertools-common/"; then + echo "::group::Building $module_name with GraalVM" + echo "Changes detected in $module_name - running GraalVM tests" + echo "Regenerating GraalVM metadata for $module_dir" + mvn -B -q -f "$module" -Pgenerate-graalvm-files clean test + echo "Running GraalVM native tests for $module_dir" + mvn -B -q -f "$module" -Pgraalvm-native test + echo "::endgroup::" + else + echo "No changes detected in $module_name - skipping GraalVM tests" + fi fi done diff --git a/GraalVM.md b/GraalVM.md index 56c72d96f..bbddb5e3b 100644 --- a/GraalVM.md +++ b/GraalVM.md @@ -56,5 +56,31 @@ java.lang.InternalError: com.oracle.svm.core.jdk.UnsupportedFeatureError: Defini ``` - This has been [fixed](https://github.com/apache/logging-log4j2/discussions/2364#discussioncomment-8950077) in Log4j 2.24.x. PT has been updated to use this version of Log4j +3. **Test Class Organization** + - **Issue**: Anonymous inner classes and lambda expressions in Mockito matchers cause `NoSuchMethodError` in GraalVM native tests + - **Solution**: + - Extract static inner test classes to separate concrete classes in the same package as the class under test + - Replace lambda expressions in `ArgumentMatcher` with concrete implementations + - Use `mockito-subclass` dependency in GraalVM profiles + - **Example**: Replace `argThat(resp -> resp.getStatus() != expectedStatus)` with: + ```java + argThat(new ArgumentMatcher<Response>() { + @Override + public boolean matches(Response resp) { + return resp != null && resp.getStatus() != expectedStatus; + } + }) + ``` + +4. **Package Visibility Issues** + - **Issue**: Test handler classes cannot access package-private methods when placed in subpackages + - **Solution**: Place test handler classes in the same package as the class under test, not in subpackages like `handlers/` + - **Example**: Use `software.amazon.lambda.powertools.cloudformation` instead of `software.amazon.lambda.powertools.cloudformation.handlers` + +5. **Test Stubs Best Practice** + - **Best Practice**: Avoid mocking where possible and use concrete test stubs provided by `powertools-common` package + - **Solution**: Use `TestLambdaContext` and other test stubs from `powertools-common` test-jar instead of Mockito mocks + - **Implementation**: Add `powertools-common` test-jar dependency and replace `mock(Context.class)` with `new TestLambdaContext()` + ## Reference Implementation Working example is available in the [examples](examples/powertools-examples-core-utilities/sam-graalvm). diff --git a/examples/powertools-examples-cloudformation/Makefile b/examples/powertools-examples-cloudformation/Makefile new file mode 100644 index 000000000..b916d823c --- /dev/null +++ b/examples/powertools-examples-cloudformation/Makefile @@ -0,0 +1,5 @@ +build-HelloWorldFunction: + chmod +x target/hello-world + cp target/hello-world $(ARTIFACTS_DIR) # (ARTIFACTS_DIR --> https://github.com/aws/aws-lambda-builders/blob/develop/aws_lambda_builders/workflows/custom_make/DESIGN.md#implementation) + chmod +x src/main/config/bootstrap + cp src/main/config/bootstrap $(ARTIFACTS_DIR) diff --git a/examples/powertools-examples-cloudformation/infra/sam-graalvm/Dockerfile b/examples/powertools-examples-cloudformation/infra/sam-graalvm/Dockerfile new file mode 100644 index 000000000..dac9390e5 --- /dev/null +++ b/examples/powertools-examples-cloudformation/infra/sam-graalvm/Dockerfile @@ -0,0 +1,14 @@ +# Use the official AWS SAM base image for Java 21 +FROM public.ecr.aws/sam/build-java21@sha256:a5554d68374e19450c6c88448516ac95a9acedc779f318040f5c230134b4e461 + +# Install GraalVM dependencies +RUN curl -4 -L curl https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz +RUN mv graalvm-jdk-21.* /usr/lib/graalvm + +# Make native image and mvn available on CLI +RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image +RUN ln -s /usr/lib/maven/bin/mvn /usr/bin/mvn + +# Set GraalVM as default +ENV JAVA_HOME=/usr/lib/graalvm +ENV PATH=/usr/lib/graalvm/bin:$PATH diff --git a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md new file mode 100644 index 000000000..e8deeb8fd --- /dev/null +++ b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md @@ -0,0 +1,52 @@ +# Powertools for AWS Lambda (Java) - CloudFormation Custom Resource Example with SAM on GraalVM + +This project contains an example of a Lambda function using the CloudFormation module of Powertools for AWS Lambda (Java). For more information on this module, please refer to the [documentation](https://docs.powertools.aws.dev/lambda-java/utilities/custom_resources/). + +In this example you pass in a bucket name as a parameter and upon CloudFormation events a call is made to a lambda. That lambda attempts to create the bucket on CREATE events, create a new bucket if the name changes with an UPDATE event and delete the bucket upon DELETE events. + +Have a look at [App.java](../../src/main/java/helloworld/App.java) for the full details. + +## Build the sample application + +> [!NOTE] +> Building AWS Lambda packages on macOS (ARM64/Intel) for deployment on AWS Lambda (Linux x86_64 or ARM64) will result in incompatible binary dependencies that cause import errors at runtime. + +Choose the appropriate build method based on your operating system: + +### Build locally using Docker + +Recommended for macOS and Windows users: Cross-compile using Docker to match target platform of Lambda: + +```shell +docker build --platform linux/amd64 . -t powertools-examples-cloudformation-sam-graalvm +docker run --platform linux/amd64 -it -v `pwd`/../..:`pwd`/../.. -w `pwd`/../.. -v ~/.m2:/root/.m2 powertools-examples-cloudformation-sam-graalvm mvn clean -Pnative-image package -DskipTests +sam build --use-container --build-image powertools-examples-cloudformation-sam-graalvm +``` + +**Note**: The Docker run command mounts your local Maven cache (`~/.m2`) and builds the native binary with SNAPSHOT support, then SAM packages the pre-built binary. + +### Build on native OS + +For Linux users with GraalVM installed: + +```shell +export JAVA_HOME=<path to GraalVM> +cd ../.. +mvn clean -Pnative-image package -DskipTests +cd infra/sam-graalvm +sam build +``` + +## Deploy the sample application + +```shell +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.3.0718 +``` + +This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting started with SAM in [the examples directory](../../../README.md) + +## Test the application + +The CloudFormation custom resource will be triggered automatically during stack deployment. You can monitor the Lambda function execution in CloudWatch Logs to see the custom resource handling CREATE, UPDATE, and DELETE events for the S3 bucket. + +Check out [App.java](../../src/main/java/helloworld/App.java) to see how it works! \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/infra/sam-graalvm/template.yaml b/examples/powertools-examples-cloudformation/infra/sam-graalvm/template.yaml new file mode 100644 index 000000000..4249aaed1 --- /dev/null +++ b/examples/powertools-examples-cloudformation/infra/sam-graalvm/template.yaml @@ -0,0 +1,49 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + powertools-examples-cloudformation-graalvm + + Sample SAM Template for powertools-examples-cloudformation with GraalVM native image + +Globals: + Function: + Timeout: 20 + +Parameters: + BucketNameParam: + Type: String + +Resources: + HelloWorldCustomResource: + Type: AWS::CloudFormation::CustomResource + Properties: + ServiceToken: !GetAtt HelloWorldFunction.Arn + BucketName: !Ref BucketNameParam + + HelloWorldFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: ../../ + Handler: helloworld.App::handleRequest + Runtime: provided.al2023 + Architectures: + - x86_64 + MemorySize: 512 + Policies: + - Statement: + - Sid: bucketaccess1 + Effect: Allow + Action: + - s3:GetLifecycleConfiguration + - s3:PutLifecycleConfiguration + - s3:CreateBucket + - s3:ListBucket + - s3:DeleteBucket + Resource: '*' + Metadata: + BuildMethod: makefile + +Outputs: + HelloWorldFunction: + Description: "Hello World Lambda Function ARN" + Value: !GetAtt HelloWorldFunction.Arn \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 45dffb792..5dbb73489 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -37,9 +37,9 @@ <version>${lambda.core.version}</version> </dependency> <dependency> - <groupId>com.amazonaws</groupId> - <artifactId>aws-lambda-java-events</artifactId> - <version>${lambda.events.version}</version> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-events</artifactId> + <version>${lambda.events.version}</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> @@ -73,82 +73,114 @@ <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>apache-client</artifactId> - <exclusions> - <exclusion> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - </exclusion> - </exclusions> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + <version>2.8.3</version> </dependency> </dependencies> <build> - <plugins> - <plugin> - <groupId>dev.aspectj</groupId> - <artifactId>aspectj-maven-plugin</artifactId> - <version>1.14.1</version> - <configuration> - <source>${maven.compiler.source}</source> - <target>${maven.compiler.target}</target> - <complianceLevel>${maven.compiler.target}</complianceLevel> - <aspectLibraries> - <aspectLibrary> - <groupId>software.amazon.lambda</groupId> - <artifactId>powertools-logging</artifactId> - </aspectLibrary> - </aspectLibraries> - </configuration> - <executions> - <execution> - <goals> - <goal>compile</goal> - </goals> - </execution> - </executions> - <dependencies> - <dependency> - <groupId>org.aspectj</groupId> - <artifactId>aspectjtools</artifactId> - <version>${aspectj.version}</version> - </dependency> - </dependencies> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> - <executions> - <execution> - <phase>package</phase> - <goals> - <goal>shade</goal> - </goals> - <configuration> - <createDependencyReducedPom>false</createDependencyReducedPom> - <transformers> - <transformer implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer"/> - </transformers> - </configuration> - </execution> - </executions> - <dependencies> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.2.0</version> - </dependency> - </dependencies> - </plugin> - <!-- Don't deploy the example --> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-deploy-plugin</artifactId> - <version>3.1.4</version> - <configuration> - <skip>true</skip> - </configuration> - </plugin> - </plugins> + <plugins> + <plugin> + <groupId>dev.aspectj</groupId> + <artifactId>aspectj-maven-plugin</artifactId> + <version>1.14.1</version> + <configuration> + <source>${maven.compiler.source}</source> + <target>${maven.compiler.target}</target> + <complianceLevel>${maven.compiler.target}</complianceLevel> + <aspectLibraries> + <aspectLibrary> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging</artifactId> + </aspectLibrary> + </aspectLibraries> + </configuration> + <executions> + <execution> + <goals> + <goal>compile</goal> + </goals> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjtools</artifactId> + <version>${aspectj.version}</version> + </dependency> + </dependencies> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>3.6.0</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <createDependencyReducedPom>false</createDependencyReducedPom> + <transformers> + <transformer + implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer" /> + </transformers> + </configuration> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> + <version>0.2.0</version> + </dependency> + </dependencies> + </plugin> + <!-- Don't deploy the example --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-deploy-plugin</artifactId> + <version>3.1.4</version> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + </plugins> </build> + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + <version>0.11.0</version> + <extensions>true</extensions> + <executions> + <execution> + <id>build-native</id> + <goals> + <goal>build</goal> + </goals> + <phase>package</phase> + </execution> + </executions> + <configuration> + <imageName>hello-world</imageName> + <mainClass>com.amazonaws.services.lambda.runtime.api.client.AWSLambda</mainClass> + <buildArgs> + <arg>--enable-url-protocols=http</arg> + <arg>--add-opens java.base/java.util=ALL-UNNAMED</arg> + </buildArgs> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> </project> diff --git a/examples/powertools-examples-cloudformation/src/main/config/bootstrap b/examples/powertools-examples-cloudformation/src/main/config/bootstrap new file mode 100755 index 000000000..8e7928cd3 --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/config/bootstrap @@ -0,0 +1,4 @@ +#!/bin/bash +set -e + +./hello-world $_HANDLER \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..10152cc64 --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,34 @@ +[ + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"<init>","parameterTypes":[] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields":[{"name":"logger"}] + }, + { + "name":"java.lang.Void", + "methods":[{"name":"<init>","parameterTypes":[] }] + }, + { + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] + }, + { + "name":"jdk.internal.module.IllegalAccessLogger", + "fields":[{"name":"logger"}] + }, + { + "name":"sun.misc.Unsafe", + "fields":[{"name":"theUnsafe"}] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/native-image.properties b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/native-image.properties new file mode 100644 index 000000000..db5ebaa55 --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/native-image.properties @@ -0,0 +1 @@ +Args = --enable-url-protocols=http,https \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/reflect-config.json b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/reflect-config.json new file mode 100644 index 000000000..06ea9ce2f --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/reflect-config.json @@ -0,0 +1,11 @@ +[ + { + "name": "helloworld.App", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/resource-config.json b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/helloworld/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/software.amazon.awssdk/s3/reflect-config.json b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/software.amazon.awssdk/s3/reflect-config.json new file mode 100644 index 000000000..d685b7e20 --- /dev/null +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/software.amazon.awssdk/s3/reflect-config.json @@ -0,0 +1,27 @@ +[ + { + "name": "software.amazon.awssdk.services.s3.model.CreateBucketRequest", + "allPublicMethods": true, + "allPublicConstructors": true + }, + { + "name": "software.amazon.awssdk.services.s3.model.DeleteBucketRequest", + "allPublicMethods": true, + "allPublicConstructors": true + }, + { + "name": "software.amazon.awssdk.services.s3.model.HeadBucketRequest", + "allPublicMethods": true, + "allPublicConstructors": true + }, + { + "name": "software.amazon.awssdk.services.s3.model.HeadBucketResponse", + "allPublicMethods": true, + "allPublicConstructors": true + }, + { + "name": "software.amazon.awssdk.services.s3.model.NoSuchBucketException", + "allPublicMethods": true, + "allPublicConstructors": true + } +] \ No newline at end of file diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 355e8a3ed..862f5832e 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -95,5 +95,92 @@ <artifactId>wiremock</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> </dependencies> + + <profiles> + <profile> + <id>generate-graalvm-files</id> + <dependencies> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-subclass</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine> + -Dorg.graalvm.nativeimage.imagecode=agent + -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation,experimental-class-define-support + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + </argLine> + </configuration> + </plugin> + </plugins> + </build> + </profile> + <profile> + <id>graalvm-native</id> + <dependencies> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-subclass</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + <version>0.11.0</version> + <extensions>true</extensions> + <executions> + <execution> + <id>test-native</id> + <goals> + <goal>test</goal> + </goals> + <phase>test</phase> + </execution> + </executions> + <configuration> + <imageName>powertools-cloudformation</imageName> + <buildArgs> + <buildArg>--add-opens java.base/java.util=ALL-UNNAMED</buildArg> + <buildArg>--add-opens java.base/java.lang=ALL-UNNAMED</buildArg> + <buildArg>--enable-url-protocols=http</buildArg> + <buildArg>--no-fallback</buildArg> + <buildArg>--verbose</buildArg> + <buildArg>--native-image-info</buildArg> + <buildArg>-H:+UnlockExperimentalVMOptions</buildArg> + <buildArg>-H:+ReportExceptionStackTraces</buildArg> + </buildArgs> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> + + <build> + <resources> + <!-- GraalVM Native Image Configuration Files --> + <resource> + <directory>src/main/resources</directory> + </resource> + </resources> + </build> </project> diff --git a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java index 404137802..cf6fad827 100644 --- a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java +++ b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponse.java @@ -46,7 +46,7 @@ * <p> * This class is thread-safe provided the SdkHttpClient instance used is also thread-safe. */ -class CloudFormationResponse { +public class CloudFormationResponse { private static final Logger LOG = LoggerFactory.getLogger(CloudFormationResponse.class); private final SdkHttpClient client; diff --git a/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json new file mode 100644 index 000000000..218382888 --- /dev/null +++ b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json @@ -0,0 +1,432 @@ +[ +{ + "name":"[Lcom.fasterxml.jackson.databind.deser.BeanDeserializerModifier;" +}, +{ + "name":"[Lcom.fasterxml.jackson.databind.deser.Deserializers;" +}, +{ + "name":"[Lcom.fasterxml.jackson.databind.deser.KeyDeserializers;" +}, +{ + "name":"[Lcom.fasterxml.jackson.databind.deser.ValueInstantiators;" +}, +{ + "name":"[Lcom.fasterxml.jackson.databind.ser.BeanSerializerModifier;" +}, +{ + "name":"[Lcom.fasterxml.jackson.databind.ser.Serializers;" +}, +{ + "name":"com.amazonaws.services.lambda.runtime.RequestHandler", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"canEqual","parameterTypes":["java.lang.Object"] }, {"name":"getLogicalResourceId","parameterTypes":[] }, {"name":"getOldResourceProperties","parameterTypes":[] }, {"name":"getPhysicalResourceId","parameterTypes":[] }, {"name":"getRequestId","parameterTypes":[] }, {"name":"getRequestType","parameterTypes":[] }, {"name":"getResourceProperties","parameterTypes":[] }, {"name":"getResourceType","parameterTypes":[] }, {"name":"getResponseUrl","parameterTypes":[] }, {"name":"getServiceToken","parameterTypes":[] }, {"name":"getStackId","parameterTypes":[] }, {"name":"setLogicalResourceId","parameterTypes":["java.lang.String"] }, {"name":"setOldResourceProperties","parameterTypes":["java.util.Map"] }, {"name":"setPhysicalResourceId","parameterTypes":["java.lang.String"] }, {"name":"setRequestId","parameterTypes":["java.lang.String"] }, {"name":"setRequestType","parameterTypes":["java.lang.String"] }, {"name":"setResourceProperties","parameterTypes":["java.util.Map"] }, {"name":"setResourceType","parameterTypes":["java.lang.String"] }, {"name":"setResponseUrl","parameterTypes":["java.lang.String"] }, {"name":"setServiceToken","parameterTypes":["java.lang.String"] }, {"name":"setStackId","parameterTypes":["java.lang.String"] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.jayway.jsonpath.spi.cache.CacheProvider", + "fields":[{"name":"cache"}] +}, +{ + "name":"com.sun.crypto.provider.AESCipher$General", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ARCFOURCipher", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESCipher", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.DESedeCipher", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"com.sun.tools.attach.VirtualMachine" +}, +{ + "name":"java.io.FileNotFoundException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.io.Serializable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.AutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Boolean", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Byte", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPackageName","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] +}, +{ + "name":"java.lang.ClassLoader", + "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] +}, +{ + "name":"java.lang.Cloneable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.Double", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Float", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Integer", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Long", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Module", + "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addOpens","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] +}, +{ + "name":"java.lang.Object", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime", + "methods":[{"name":"version","parameterTypes":[] }] +}, +{ + "name":"java.lang.Runtime$Version", + "methods":[{"name":"feature","parameterTypes":[] }] +}, +{ + "name":"java.lang.Short", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.StackWalker" +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getSecurityManager","parameterTypes":[] }] +}, +{ + "name":"java.lang.Thread", + "fields":[{"name":"threadLocalRandomProbe"}], + "methods":[{"name":"isVirtual","parameterTypes":[] }] +}, +{ + "name":"java.lang.annotation.Retention", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.annotation.Target", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.lang.invoke.MethodHandle", + "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles", + "methods":[{"name":"lookup","parameterTypes":[] }, {"name":"privateLookupIn","parameterTypes":["java.lang.Class","java.lang.invoke.MethodHandles$Lookup"] }] +}, +{ + "name":"java.lang.invoke.MethodHandles$Lookup", + "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] +}, +{ + "name":"java.lang.invoke.MethodType", + "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] +}, +{ + "name":"java.lang.management.ManagementFactory", + "methods":[{"name":"getRuntimeMXBean","parameterTypes":[] }] +}, +{ + "name":"java.lang.management.RuntimeMXBean", + "methods":[{"name":"getInputArguments","parameterTypes":[] }, {"name":"getUptime","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AccessibleObject", + "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] +}, +{ + "name":"java.lang.reflect.AnnotatedArrayType", + "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedParameterizedType", + "methods":[{"name":"getAnnotatedActualTypeArguments","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.AnnotatedType", + "methods":[{"name":"getType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Executable", + "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Method", + "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] +}, +{ + "name":"java.lang.reflect.Parameter", + "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] +}, +{ + "name":"java.security.AccessController", + "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] +}, +{ + "name":"java.security.AlgorithmParametersSpi" +}, +{ + "name":"java.security.KeyStoreSpi" +}, +{ + "name":"java.security.SecureRandomParameters" +}, +{ + "name":"java.util.HashSet", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"java.util.concurrent.Callable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, +{ + "name":"java.util.concurrent.Executors", + "methods":[{"name":"newVirtualThreadPerTaskExecutor","parameterTypes":[] }] +}, +{ + "name":"java.util.concurrent.ForkJoinTask", + "fields":[{"name":"aux"}, {"name":"status"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.Striped64", + "fields":[{"name":"base"}, {"name":"cellsBusy"}] +}, +{ + "name":"java.util.function.Consumer", + "queryAllPublicMethods":true +}, +{ + "name":"javax.security.auth.x500.X500Principal", + "fields":[{"name":"thisX500Name"}], + "methods":[{"name":"<init>","parameterTypes":["sun.security.x509.X500Name"] }] +}, +{ + "name":"jdk.internal.misc.Unsafe" +}, +{ + "name":"kotlin.Metadata" +}, +{ + "name":"kotlin.jvm.JvmInline" +}, +{ + "name":"org.apiguardian.api.API", + "queryAllPublicMethods":true +}, +{ + "name":"org.eclipse.jetty.http.pathmap.PathSpecSet", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"org.eclipse.jetty.servlets.CrossOriginFilter", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"org.eclipse.jetty.util.AsciiLowerCaseSet", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"org.eclipse.jetty.util.TypeUtil", + "methods":[{"name":"getClassLoaderLocation","parameterTypes":["java.lang.Class"] }, {"name":"getCodeSourceLocation","parameterTypes":["java.lang.Class"] }, {"name":"getModuleLocation","parameterTypes":["java.lang.Class"] }, {"name":"getSystemClassLoaderLocation","parameterTypes":["java.lang.Class"] }] +}, +{ + "name":"software.amazon.awssdk.http.Abortable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"abort","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.http.ExecutableHttpRequest", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"call","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.http.HttpExecuteResponse", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"httpResponse","parameterTypes":[] }, {"name":"responseBody","parameterTypes":[] }] +}, +{ + "name":"software.amazon.awssdk.http.SdkHttpClient", + "queryAllDeclaredMethods":true, + "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"clientName","parameterTypes":[] }, {"name":"prepareRequest","parameterTypes":["software.amazon.awssdk.http.HttpExecuteRequest"] }] +}, +{ + "name":"software.amazon.awssdk.utils.SdkAutoCloseable", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"close","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.cloudformation.AbstractCustomResourceHandler", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"onSendFailure","parameterTypes":["com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent","com.amazonaws.services.lambda.runtime.Context","software.amazon.lambda.powertools.cloudformation.Response","java.lang.Exception"] }] +}, +{ + "name":"software.amazon.lambda.powertools.cloudformation.CloudFormationResponse", + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"headers","parameterTypes":["int"] }, {"name":"send","parameterTypes":["com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent","com.amazonaws.services.lambda.runtime.Context"] }, {"name":"send","parameterTypes":["com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent","com.amazonaws.services.lambda.runtime.Context","software.amazon.lambda.powertools.cloudformation.Response"] }] +}, +{ + "name":"software.amazon.lambda.powertools.cloudformation.CloudFormationResponse$ResponseBody", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"getLogicalResourceId","parameterTypes":[] }, {"name":"getPhysicalResourceId","parameterTypes":[] }, {"name":"getReason","parameterTypes":[] }, {"name":"getRequestId","parameterTypes":[] }, {"name":"getStackId","parameterTypes":[] }, {"name":"getStatus","parameterTypes":[] }, {"name":"isNoEcho","parameterTypes":[] }] +}, +{ + "name":"sun.misc.SharedSecrets" +}, +{ + "name":"sun.reflect.ReflectionFactory", + "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.NativePRNG", + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"<init>","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.X509Factory", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.rsa.RSAKeyFactory$Legacy", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.SSLContextImpl$TLSContext", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory", + "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"sun.security.x509.AuthorityInfoAccessExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.AuthorityKeyIdentifierExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.BasicConstraintsExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CRLDistributionPointsExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.CertificatePoliciesExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.ExtendedKeyUsageExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.KeyUsageExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.NetscapeCertTypeExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.PrivateKeyUsageExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"sun.security.x509.SubjectKeyIdentifierExtension", + "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +} +] diff --git a/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json new file mode 100644 index 000000000..f3b58337b --- /dev/null +++ b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json @@ -0,0 +1,41 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.InetAddressResolverProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.nio.channels.spi.SelectorProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.util.spi.ResourceBundleControlProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qassets/swagger-ui/index.html\\E" + }, { + "pattern":"\\Qassets\\E" + }, { + "pattern":"\\Qhelpers.nashorn.js\\E" + }, { + "pattern":"\\Qkeystore\\E" + }, { + "pattern":"\\Qorg/apache/hc/client5/version.properties\\E" + }, { + "pattern":"\\Qorg/eclipse/jetty/http/encoding.properties\\E" + }, { + "pattern":"\\Qorg/eclipse/jetty/http/mime.properties\\E" + }, { + "pattern":"\\Qorg/eclipse/jetty/version/build.properties\\E" + }, { + "pattern":"\\Qorg/publicsuffix/list/effective_tld_names.dat\\E" + }]}, + "bundles":[{ + "name":"jakarta.servlet.LocalStrings", + "locales":[""] + }, { + "name":"jakarta.servlet.http.LocalStrings", + "locales":[""] + }] +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandlerTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandlerTest.java index 1e399ef6f..9d0669d43 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandlerTest.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/AbstractCustomResourceHandlerTest.java @@ -16,7 +16,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.mock; @@ -25,14 +24,17 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; import java.io.IOException; + import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + import software.amazon.awssdk.http.SdkHttpClient; -import software.amazon.lambda.powertools.cloudformation.Response.Status; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; public class AbstractCustomResourceHandlerTest { @@ -68,11 +70,11 @@ void defaultAndCustomSdkHttpClients() { } @ParameterizedTest - @CsvSource(value = {"Create,1,0,0", "Update,0,1,0", "Delete,0,0,1"}, delimiter = ',') + @CsvSource(value = { "Create,1,0,0", "Update,0,1,0", "Delete,0,0,1" }, delimiter = ',') void eventsDelegateToCorrectHandlerMethod(String eventType, int createCount, int updateCount, int deleteCount) { AbstractCustomResourceHandler handler = spy(new NoOpCustomResourceHandler()); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); handler.handleRequest(eventOfType(eventType), context); verify(handler, times(createCount)).create(any(), eq(context)); @@ -84,7 +86,7 @@ void eventsDelegateToCorrectHandlerMethod(String eventType, int createCount, int void eventOfUnknownRequestTypeSendEmptySuccess() { AbstractCustomResourceHandler handler = spy(new NoOpCustomResourceHandler()); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); CloudFormationCustomResourceEvent event = eventOfType("UNKNOWN"); handler.handleRequest(event, context); @@ -96,16 +98,9 @@ void eventOfUnknownRequestTypeSendEmptySuccess() { @Test void defaultStatusResponseSendsSuccess() { - ExpectedStatusResourceHandler handler = spy(new ExpectedStatusResourceHandler(Status.SUCCESS) { - @Override - protected Response create(CloudFormationCustomResourceEvent event, Context context) { - return Response.builder() - .value("whatever") - .build(); - } - }); - - Context context = mock(Context.class); + SuccessResponseHandler handler = spy(new SuccessResponseHandler()); + + Context context = new TestLambdaContext(); CloudFormationCustomResourceEvent event = eventOfType("Create"); Response response = handler.handleRequest(event, context); @@ -116,17 +111,9 @@ protected Response create(CloudFormationCustomResourceEvent event, Context conte @Test void explicitResponseWithStatusSuccessSendsSuccess() { - ExpectedStatusResourceHandler handler = spy(new ExpectedStatusResourceHandler(Status.SUCCESS) { - @Override - protected Response create(CloudFormationCustomResourceEvent event, Context context) { - return Response.builder() - .value("whatever") - .status(Status.SUCCESS) - .build(); - } - }); - - Context context = mock(Context.class); + ExplicitSuccessResponseHandler handler = spy(new ExplicitSuccessResponseHandler()); + + Context context = new TestLambdaContext(); CloudFormationCustomResourceEvent event = eventOfType("Create"); Response response = handler.handleRequest(event, context); @@ -137,17 +124,9 @@ protected Response create(CloudFormationCustomResourceEvent event, Context conte @Test void explicitResponseWithStatusFailedSendsFailure() { - ExpectedStatusResourceHandler handler = spy(new ExpectedStatusResourceHandler(Status.FAILED) { - @Override - protected Response create(CloudFormationCustomResourceEvent event, Context context) { - return Response.builder() - .value("whatever") - .status(Status.FAILED) - .build(); - } - }); - - Context context = mock(Context.class); + FailedResponseHandler handler = spy(new FailedResponseHandler()); + + Context context = new TestLambdaContext(); CloudFormationCustomResourceEvent event = eventOfType("Create"); Response response = handler.handleRequest(event, context); @@ -158,14 +137,9 @@ protected Response create(CloudFormationCustomResourceEvent event, Context conte @Test void exceptionWhenGeneratingResponseSendsFailure() { - ExpectedStatusResourceHandler handler = spy(new ExpectedStatusResourceHandler(Status.FAILED) { - @Override - protected Response create(CloudFormationCustomResourceEvent event, Context context) { - throw new RuntimeException("This exception is intentional for testing"); - } - }); - - Context context = mock(Context.class); + ExceptionThrowingHandler handler = spy(new ExceptionThrowingHandler()); + + Context context = new TestLambdaContext(); CloudFormationCustomResourceEvent event = eventOfType("Create"); Response response = handler.handleRequest(event, context); @@ -178,14 +152,9 @@ protected Response create(CloudFormationCustomResourceEvent event, Context conte @Test void exceptionWhenSendingResponseInvokesOnSendFailure() { // a custom handler that builds response successfully but fails to send it - FailToSendResponseHandler handler = spy(new FailToSendResponseHandler() { - @Override - protected Response create(CloudFormationCustomResourceEvent event, Context context) { - return Response.builder().value("Failure happens on send").build(); - } - }); - - Context context = mock(Context.class); + SuccessfulSendHandler handler = spy(new SuccessfulSendHandler()); + + Context context = new TestLambdaContext(); CloudFormationCustomResourceEvent event = eventOfType("Create"); Response response = handler.handleRequest(event, context); @@ -197,15 +166,11 @@ protected Response create(CloudFormationCustomResourceEvent event, Context conte @Test void bothResponseGenerationAndSendFail() { - // a custom handler that fails to build response _and_ fails to send a FAILED response - FailToSendResponseHandler handler = spy(new FailToSendResponseHandler() { - @Override - protected Response create(CloudFormationCustomResourceEvent event, Context context) { - throw new RuntimeException("This exception is intentional for testing"); - } - }); - - Context context = mock(Context.class); + // a custom handler that fails to build response _and_ fails to send a FAILED + // response + FailedSendHandler handler = spy(new FailedSendHandler()); + + Context context = new TestLambdaContext(); CloudFormationCustomResourceEvent event = eventOfType("Create"); Response response = handler.handleRequest(event, context); @@ -214,91 +179,4 @@ protected Response create(CloudFormationCustomResourceEvent event, Context conte .onSendFailure(eq(event), eq(context), isNull(), any(IOException.class)); } - /** - * Bare-bones implementation that returns null for abstract methods. - */ - static class NullCustomResourceHandler extends AbstractCustomResourceHandler { - NullCustomResourceHandler() { - } - - NullCustomResourceHandler(SdkHttpClient client) { - super(client); - } - - @Override - protected Response create(CloudFormationCustomResourceEvent event, Context context) { - return null; - } - - @Override - protected Response update(CloudFormationCustomResourceEvent event, Context context) { - return null; - } - - @Override - protected Response delete(CloudFormationCustomResourceEvent event, Context context) { - return null; - } - } - - /** - * Uses a mocked CloudFormationResponse to avoid sending actual HTTP requests. - */ - static class NoOpCustomResourceHandler extends NullCustomResourceHandler { - - NoOpCustomResourceHandler() { - super(mock(SdkHttpClient.class)); - } - - @Override - protected CloudFormationResponse buildResponseClient() { - return mock(CloudFormationResponse.class); - } - } - - /** - * Creates a handler that will expect the Response to be sent with an expected status. Will throw an AssertionError - * if the method is sent with an unexpected status. - */ - static class ExpectedStatusResourceHandler extends NoOpCustomResourceHandler { - private final Status expectedStatus; - - ExpectedStatusResourceHandler(Status expectedStatus) { - this.expectedStatus = expectedStatus; - } - - @Override - protected CloudFormationResponse buildResponseClient() { - // create a CloudFormationResponse that fails if invoked with unexpected status - CloudFormationResponse cfnResponse = mock(CloudFormationResponse.class); - try { - when(cfnResponse.send(any(), any(), argThat(resp -> resp.getStatus() != expectedStatus))) - .thenThrow(new AssertionError("Expected response's status to be " + expectedStatus)); - } catch (IOException | CustomResourceResponseException e) { - // this should never happen - throw new RuntimeException("Unexpected mocking exception", e); - } - return cfnResponse; - } - } - - /** - * Always fails to send the response - */ - static class FailToSendResponseHandler extends NoOpCustomResourceHandler { - @Override - protected CloudFormationResponse buildResponseClient() { - CloudFormationResponse cfnResponse = mock(CloudFormationResponse.class); - try { - when(cfnResponse.send(any(), any())) - .thenThrow(new IOException("Intentional send failure")); - when(cfnResponse.send(any(), any(), any())) - .thenThrow(new IOException("Intentional send failure")); - } catch (IOException | CustomResourceResponseException e) { - // this should never happen - throw new RuntimeException("Unexpected mocking exception", e); - } - return cfnResponse; - } - } } diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationIntegrationTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationIntegrationTest.java index ce45d3afc..316913bf2 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationIntegrationTest.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationIntegrationTest.java @@ -23,62 +23,40 @@ import static com.github.tomakehurst.wiremock.client.WireMock.verify; import static org.assertj.core.api.Assertions.assertThat; -import com.amazonaws.services.lambda.runtime.ClientContext; -import com.amazonaws.services.lambda.runtime.CognitoIdentity; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.LambdaLogger; -import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; -import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; -import com.github.tomakehurst.wiremock.junit5.WireMockTest; import java.util.UUID; + import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; + +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; + import software.amazon.lambda.powertools.cloudformation.handlers.NoPhysicalResourceIdSetHandler; import software.amazon.lambda.powertools.cloudformation.handlers.PhysicalResourceIdSetHandler; import software.amazon.lambda.powertools.cloudformation.handlers.RuntimeExceptionThrownHandler; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; @WireMockTest public class CloudFormationIntegrationTest { public static final String PHYSICAL_RESOURCE_ID = UUID.randomUUID().toString(); - public static final String LOG_STREAM_NAME = "FakeLogStreamName"; - - private static CloudFormationCustomResourceEvent updateEventWithPhysicalResourceId(int httpPort, - String physicalResourceId) { - CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder builder = baseEvent(httpPort); - - builder.withPhysicalResourceId(physicalResourceId); - builder.withRequestType("Update"); - - return builder.build(); - } - - private static CloudFormationCustomResourceEvent deleteEventWithPhysicalResourceId(int httpPort, - String physicalResourceId) { - CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder builder = baseEvent(httpPort); - - builder.withPhysicalResourceId(physicalResourceId); - builder.withRequestType("Delete"); - - return builder.build(); - } + public static final String LOG_STREAM_NAME = "test-log-stream"; private static CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder baseEvent(int httpPort) { - CloudFormationCustomResourceEvent.CloudFormationCustomResourceEventBuilder builder = - CloudFormationCustomResourceEvent.builder() - .withResponseUrl("http://localhost:" + httpPort + "/") - .withStackId("123") - .withRequestId("234") - .withLogicalResourceId("345"); - - return builder; + return CloudFormationCustomResourceEvent + .builder() + .withResponseUrl("http://localhost:" + httpPort + "/") + .withStackId("123") + .withRequestId("234") + .withLogicalResourceId("345"); } @ParameterizedTest - @ValueSource(strings = {"Update", "Delete"}) + @ValueSource(strings = { "Update", "Delete" }) void physicalResourceIdTakenFromRequestForUpdateOrDeleteWhenUserSpecifiesNull(String requestType, - WireMockRuntimeInfo wmRuntimeInfo) { + WireMockRuntimeInfo wmRuntimeInfo) { stubFor(put("/").willReturn(ok())); NoPhysicalResourceIdSetHandler handler = new NoPhysicalResourceIdSetHandler(); @@ -89,18 +67,17 @@ void physicalResourceIdTakenFromRequestForUpdateOrDeleteWhenUserSpecifiesNull(St .withRequestType(requestType) .build(); - handler.handleRequest(event, new FakeContext()); + handler.handleRequest(event, new TestLambdaContext()); verify(putRequestedFor(urlPathMatching("/")) .withRequestBody(matchingJsonPath("[?(@.Status == 'SUCCESS')]")) - .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + PHYSICAL_RESOURCE_ID + "')]")) - ); + .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + PHYSICAL_RESOURCE_ID + "')]"))); } @ParameterizedTest - @ValueSource(strings = {"Update", "Delete"}) + @ValueSource(strings = { "Update", "Delete" }) void physicalResourceIdDoesNotChangeWhenRuntimeExceptionThrownWhenUpdatingOrDeleting(String requestType, - WireMockRuntimeInfo wmRuntimeInfo) { + WireMockRuntimeInfo wmRuntimeInfo) { stubFor(put("/").willReturn(ok())); RuntimeExceptionThrownHandler handler = new RuntimeExceptionThrownHandler(); @@ -111,12 +88,11 @@ void physicalResourceIdDoesNotChangeWhenRuntimeExceptionThrownWhenUpdatingOrDele .withRequestType(requestType) .build(); - handler.handleRequest(event, new FakeContext()); + handler.handleRequest(event, new TestLambdaContext()); verify(putRequestedFor(urlPathMatching("/")) .withRequestBody(matchingJsonPath("[?(@.Status == 'FAILED')]")) - .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + PHYSICAL_RESOURCE_ID + "')]")) - ); + .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + PHYSICAL_RESOURCE_ID + "')]"))); } @Test @@ -127,16 +103,15 @@ void runtimeExceptionThrownOnCreateSendsLogStreamNameAsPhysicalResourceId(WireMo CloudFormationCustomResourceEvent createEvent = baseEvent(wmRuntimeInfo.getHttpPort()) .withRequestType("Create") .build(); - handler.handleRequest(createEvent, new FakeContext()); + handler.handleRequest(createEvent, new TestLambdaContext()); verify(putRequestedFor(urlPathMatching("/")) .withRequestBody(matchingJsonPath("[?(@.Status == 'FAILED')]")) - .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + LOG_STREAM_NAME + "')]")) - ); + .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + LOG_STREAM_NAME + "')]"))); } @ParameterizedTest - @ValueSource(strings = {"Update", "Delete"}) + @ValueSource(strings = { "Update", "Delete" }) void physicalResourceIdSetFromRequestOnUpdateOrDeleteWhenCustomerDoesntProvideAPhysicalResourceId( String requestType, WireMockRuntimeInfo wmRuntimeInfo) { stubFor(put("/").willReturn(ok())); @@ -149,13 +124,12 @@ void physicalResourceIdSetFromRequestOnUpdateOrDeleteWhenCustomerDoesntProvideAP .withRequestType(requestType) .build(); - Response response = handler.handleRequest(event, new FakeContext()); + Response response = handler.handleRequest(event, new TestLambdaContext()); assertThat(response).isNotNull(); verify(putRequestedFor(urlPathMatching("/")) .withRequestBody(matchingJsonPath("[?(@.Status == 'SUCCESS')]")) - .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + PHYSICAL_RESOURCE_ID + "')]")) - ); + .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + PHYSICAL_RESOURCE_ID + "')]"))); } @Test @@ -166,17 +140,16 @@ void createNewResourceBecausePhysicalResourceIdNotSetByCustomerOnCreate(WireMock CloudFormationCustomResourceEvent createEvent = baseEvent(wmRuntimeInfo.getHttpPort()) .withRequestType("Create") .build(); - Response response = handler.handleRequest(createEvent, new FakeContext()); + Response response = handler.handleRequest(createEvent, new TestLambdaContext()); assertThat(response).isNotNull(); verify(putRequestedFor(urlPathMatching("/")) .withRequestBody(matchingJsonPath("[?(@.Status == 'SUCCESS')]")) - .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + LOG_STREAM_NAME + "')]")) - ); + .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + LOG_STREAM_NAME + "')]"))); } @ParameterizedTest - @ValueSource(strings = {"Create", "Update", "Delete"}) + @ValueSource(strings = { "Create", "Update", "Delete" }) void physicalResourceIdReturnedFromSuccessToCloudformation(String requestType, WireMockRuntimeInfo wmRuntimeInfo) { String physicalResourceId = UUID.randomUUID().toString(); @@ -185,17 +158,16 @@ void physicalResourceIdReturnedFromSuccessToCloudformation(String requestType, W CloudFormationCustomResourceEvent createEvent = baseEvent(wmRuntimeInfo.getHttpPort()) .withRequestType(requestType) .build(); - Response response = handler.handleRequest(createEvent, new FakeContext()); + Response response = handler.handleRequest(createEvent, new TestLambdaContext()); assertThat(response).isNotNull(); verify(putRequestedFor(urlPathMatching("/")) .withRequestBody(matchingJsonPath("[?(@.Status == 'SUCCESS')]")) - .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + physicalResourceId + "')]")) - ); + .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + physicalResourceId + "')]"))); } @ParameterizedTest - @ValueSource(strings = {"Create", "Update", "Delete"}) + @ValueSource(strings = { "Create", "Update", "Delete" }) void physicalResourceIdReturnedFromFailedToCloudformation(String requestType, WireMockRuntimeInfo wmRuntimeInfo) { String physicalResourceId = UUID.randomUUID().toString(); @@ -204,69 +176,12 @@ void physicalResourceIdReturnedFromFailedToCloudformation(String requestType, Wi CloudFormationCustomResourceEvent createEvent = baseEvent(wmRuntimeInfo.getHttpPort()) .withRequestType(requestType) .build(); - Response response = handler.handleRequest(createEvent, new FakeContext()); + Response response = handler.handleRequest(createEvent, new TestLambdaContext()); assertThat(response).isNotNull(); verify(putRequestedFor(urlPathMatching("/")) .withRequestBody(matchingJsonPath("[?(@.Status == 'FAILED')]")) - .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + physicalResourceId + "')]")) - ); + .withRequestBody(matchingJsonPath("[?(@.PhysicalResourceId == '" + physicalResourceId + "')]"))); } - private static class FakeContext implements Context { - @Override - public String getAwsRequestId() { - return null; - } - - @Override - public String getLogGroupName() { - return null; - } - - @Override - public String getLogStreamName() { - return LOG_STREAM_NAME; - } - - @Override - public String getFunctionName() { - return null; - } - - @Override - public String getFunctionVersion() { - return null; - } - - @Override - public String getInvokedFunctionArn() { - return null; - } - - @Override - public CognitoIdentity getIdentity() { - return null; - } - - @Override - public ClientContext getClientContext() { - return null; - } - - @Override - public int getRemainingTimeInMillis() { - return 0; - } - - @Override - public int getMemoryLimitInMB() { - return 0; - } - - @Override - public LambdaLogger getLogger() { - return null; - } - } } diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java index 9da18790c..0cc65f884 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/CloudFormationResponseTest.java @@ -20,15 +20,18 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; -import com.fasterxml.jackson.databind.node.ObjectNode; import java.io.IOException; import java.io.InputStream; import java.util.LinkedHashMap; import java.util.Map; import java.util.Optional; + import org.junit.jupiter.api.Test; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; +import com.fasterxml.jackson.databind.node.ObjectNode; + import software.amazon.awssdk.http.AbortableInputStream; import software.amazon.awssdk.http.ExecutableHttpRequest; import software.amazon.awssdk.http.HttpExecuteRequest; @@ -37,11 +40,13 @@ import software.amazon.awssdk.utils.IoUtils; import software.amazon.awssdk.utils.StringInputStream; import software.amazon.lambda.powertools.cloudformation.CloudFormationResponse.ResponseBody; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; class CloudFormationResponseTest { /** - * Creates a mock CloudFormationCustomResourceEvent with a non-null response URL. + * Creates a mock CloudFormationCustomResourceEvent with a non-null response + * URL. */ static CloudFormationCustomResourceEvent mockCloudFormationCustomResourceEvent() { CloudFormationCustomResourceEvent event = mock(CloudFormationCustomResourceEvent.class); @@ -50,15 +55,15 @@ static CloudFormationCustomResourceEvent mockCloudFormationCustomResourceEvent() } /** - * Creates a CloudFormationResponse that does not make actual HTTP requests. The HTTP response body is the request + * Creates a CloudFormationResponse that does not make actual HTTP requests. The + * HTTP response body is the request * body. */ static CloudFormationResponse testableCloudFormationResponse() { SdkHttpClient client = mock(SdkHttpClient.class); ExecutableHttpRequest executableRequest = mock(ExecutableHttpRequest.class); - when(client.prepareRequest(any(HttpExecuteRequest.class))).thenAnswer(args -> - { + when(client.prepareRequest(any(HttpExecuteRequest.class))).thenAnswer(args -> { HttpExecuteRequest request = args.getArgument(0, HttpExecuteRequest.class); assertThat(request.contentStreamProvider()).isPresent(); @@ -89,7 +94,7 @@ void eventRequiredToSend() { SdkHttpClient client = mock(SdkHttpClient.class); CloudFormationResponse response = new CloudFormationResponse(client); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); assertThatThrownBy(() -> response.send(null, context)) .isInstanceOf(CustomResourceResponseException.class); } @@ -99,7 +104,7 @@ void contextRequiredToSend() { SdkHttpClient client = mock(SdkHttpClient.class); CloudFormationResponse response = new CloudFormationResponse(client); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); assertThatThrownBy(() -> response.send(null, context)) .isInstanceOf(CustomResourceResponseException.class); } @@ -110,8 +115,9 @@ void eventResponseUrlRequiredToSend() { CloudFormationResponse response = new CloudFormationResponse(client); CloudFormationCustomResourceEvent event = mock(CloudFormationCustomResourceEvent.class); - Context context = mock(Context.class); - // not a CustomResourceResponseException since the URL is not part of the response but + Context context = new TestLambdaContext(); + // not a CustomResourceResponseException since the URL is not part of the + // response but // rather the location the response is sent to assertThatThrownBy(() -> response.send(event, context)) .isInstanceOf(RuntimeException.class); @@ -122,8 +128,7 @@ void customPhysicalResponseId() { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); when(event.getPhysicalResourceId()).thenReturn("This-Is-Ignored"); - Context context = mock(Context.class); - when(context.getLogStreamName()).thenReturn("My-Log-Stream-Name"); + Context context = new TestLambdaContext(); String customPhysicalResourceId = "Custom-Physical-Resource-ID"; ResponseBody body = new ResponseBody( @@ -135,7 +140,7 @@ void customPhysicalResponseId() { @Test void responseBodyWithNullDataNode() { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); ResponseBody responseBody = new ResponseBody(event, Response.Status.FAILED, null, true, "See the details in CloudWatch Log Stream: " + context.getLogStreamName()); @@ -143,7 +148,7 @@ void responseBodyWithNullDataNode() { String expectedJson = "{" + "\"Status\":\"FAILED\"," + - "\"Reason\":\"See the details in CloudWatch Log Stream: null\"," + + "\"Reason\":\"See the details in CloudWatch Log Stream: test-log-stream\"," + "\"PhysicalResourceId\":null," + "\"StackId\":null," + "\"RequestId\":null," + @@ -157,7 +162,7 @@ void responseBodyWithNullDataNode() { @Test void responseBodyWithNonNullDataNode() { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); ObjectNode dataNode = ResponseBody.MAPPER.createObjectNode(); dataNode.put("foo", "bar"); dataNode.put("baz", 10); @@ -168,7 +173,7 @@ void responseBodyWithNonNullDataNode() { String expectedJson = "{" + "\"Status\":\"FAILED\"," + - "\"Reason\":\"See the details in CloudWatch Log Stream: null\"," + + "\"Reason\":\"See the details in CloudWatch Log Stream: test-log-stream\"," + "\"PhysicalResourceId\":null," + "\"StackId\":null," + "\"RequestId\":null," + @@ -182,7 +187,7 @@ void responseBodyWithNonNullDataNode() { @Test void defaultStatusIsSuccess() { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); ResponseBody body = new ResponseBody( event, null, null, false, "See the details in CloudWatch Log Stream: " + context.getLogStreamName()); @@ -192,7 +197,7 @@ void defaultStatusIsSuccess() { @Test void customStatus() { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); ResponseBody body = new ResponseBody( event, Response.Status.FAILED, null, false, @@ -203,21 +208,18 @@ void customStatus() { @Test void reasonIncludesLogStreamName() { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - - String logStreamName = "My-Log-Stream-Name"; - Context context = mock(Context.class); - when(context.getLogStreamName()).thenReturn(logStreamName); + Context context = new TestLambdaContext(); ResponseBody body = new ResponseBody( event, Response.Status.SUCCESS, null, false, "See the details in CloudWatch Log Stream: " + context.getLogStreamName()); - assertThat(body.getReason()).contains(logStreamName); + assertThat(body.getReason()).contains(context.getLogStreamName()); } @Test void sendWithNoResponseData() throws Exception { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); CloudFormationResponse cfnResponse = testableCloudFormationResponse(); HttpExecuteResponse response = cfnResponse.send(event, context); @@ -225,8 +227,8 @@ void sendWithNoResponseData() throws Exception { String actualJson = responseAsString(response); String expectedJson = "{" + "\"Status\":\"SUCCESS\"," + - "\"Reason\":\"See the details in CloudWatch Log Stream: null\"," + - "\"PhysicalResourceId\":null," + + "\"Reason\":\"See the details in CloudWatch Log Stream: test-log-stream\"," + + "\"PhysicalResourceId\":\"test-log-stream\"," + "\"StackId\":null," + "\"RequestId\":null," + "\"LogicalResourceId\":null," + @@ -239,7 +241,7 @@ void sendWithNoResponseData() throws Exception { @Test void sendWithNonNullResponseData() throws Exception { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); CloudFormationResponse cfnResponse = testableCloudFormationResponse(); Map<String, String> responseData = new LinkedHashMap<>(); @@ -251,8 +253,8 @@ void sendWithNonNullResponseData() throws Exception { String actualJson = responseAsString(response); String expectedJson = "{" + "\"Status\":\"SUCCESS\"," + - "\"Reason\":\"See the details in CloudWatch Log Stream: null\"," + - "\"PhysicalResourceId\":null," + + "\"Reason\":\"See the details in CloudWatch Log Stream: test-log-stream\"," + + "\"PhysicalResourceId\":\"test-log-stream\"," + "\"StackId\":null," + "\"RequestId\":null," + "\"LogicalResourceId\":null," + @@ -265,15 +267,15 @@ void sendWithNonNullResponseData() throws Exception { @Test void responseBodyStreamNullResponseDefaultsToSuccessStatus() throws Exception { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); CloudFormationResponse cfnResponse = testableCloudFormationResponse(); StringInputStream stream = cfnResponse.responseBodyStream(event, context, null); String expectedJson = "{" + "\"Status\":\"SUCCESS\"," + - "\"Reason\":\"See the details in CloudWatch Log Stream: null\"," + - "\"PhysicalResourceId\":null," + + "\"Reason\":\"See the details in CloudWatch Log Stream: test-log-stream\"," + + "\"PhysicalResourceId\":\"test-log-stream\"," + "\"StackId\":null," + "\"RequestId\":null," + "\"LogicalResourceId\":null," + @@ -286,15 +288,15 @@ void responseBodyStreamNullResponseDefaultsToSuccessStatus() throws Exception { @Test void responseBodyStreamSuccessResponse() throws Exception { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); CloudFormationResponse cfnResponse = testableCloudFormationResponse(); StringInputStream stream = cfnResponse.responseBodyStream(event, context, Response.success(null)); String expectedJson = "{" + "\"Status\":\"SUCCESS\"," + - "\"Reason\":\"See the details in CloudWatch Log Stream: null\"," + - "\"PhysicalResourceId\":null," + + "\"Reason\":\"See the details in CloudWatch Log Stream: test-log-stream\"," + + "\"PhysicalResourceId\":\"test-log-stream\"," + "\"StackId\":null," + "\"RequestId\":null," + "\"LogicalResourceId\":null," + @@ -307,15 +309,15 @@ void responseBodyStreamSuccessResponse() throws Exception { @Test void responseBodyStreamFailedResponse() throws Exception { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); CloudFormationResponse cfnResponse = testableCloudFormationResponse(); StringInputStream stream = cfnResponse.responseBodyStream(event, context, Response.failed(null)); String expectedJson = "{" + "\"Status\":\"FAILED\"," + - "\"Reason\":\"See the details in CloudWatch Log Stream: null\"," + - "\"PhysicalResourceId\":null," + + "\"Reason\":\"See the details in CloudWatch Log Stream: test-log-stream\"," + + "\"PhysicalResourceId\":\"test-log-stream\"," + "\"StackId\":null," + "\"RequestId\":null," + "\"LogicalResourceId\":null," + @@ -328,17 +330,17 @@ void responseBodyStreamFailedResponse() throws Exception { @Test void responseBodyStreamFailedResponseWithReason() throws Exception { CloudFormationCustomResourceEvent event = mockCloudFormationCustomResourceEvent(); - Context context = mock(Context.class); + Context context = new TestLambdaContext(); CloudFormationResponse cfnResponse = testableCloudFormationResponse(); String failureReason = "Failed test reason"; - Response failedResponseWithReason = Response.builder(). - status(Response.Status.FAILED).reason(failureReason).build(); + Response failedResponseWithReason = Response.builder().status(Response.Status.FAILED).reason(failureReason) + .build(); StringInputStream stream = cfnResponse.responseBodyStream(event, context, failedResponseWithReason); String expectedJson = "{" + "\"Status\":\"FAILED\"," + "\"Reason\":\"" + failureReason + "\"," + - "\"PhysicalResourceId\":null," + + "\"PhysicalResourceId\":\"test-log-stream\"," + "\"StackId\":null," + "\"RequestId\":null," + "\"LogicalResourceId\":null," + diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExceptionThrowingHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExceptionThrowingHandler.java new file mode 100644 index 000000000..dd2d1c853 --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExceptionThrowingHandler.java @@ -0,0 +1,31 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.cloudformation; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + +import software.amazon.lambda.powertools.cloudformation.Response.Status; + +public class ExceptionThrowingHandler extends ExpectedStatusResourceHandler { + public ExceptionThrowingHandler() { + super(Status.FAILED); + } + + @Override + protected Response create(CloudFormationCustomResourceEvent event, Context context) { + throw new RuntimeException("This exception is intentional for testing"); + } +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExpectedStatusResourceHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExpectedStatusResourceHandler.java new file mode 100644 index 000000000..7992c712c --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExpectedStatusResourceHandler.java @@ -0,0 +1,56 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.cloudformation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import org.mockito.ArgumentMatcher; + +import software.amazon.lambda.powertools.cloudformation.Response.Status; + +/** + * Creates a handler that will expect the Response to be sent with an expected + * status. Will throw an AssertionError + * if the method is sent with an unexpected status. + */ +public class ExpectedStatusResourceHandler extends NoOpCustomResourceHandler { + private final Status expectedStatus; + + public ExpectedStatusResourceHandler(Status expectedStatus) { + this.expectedStatus = expectedStatus; + } + + @Override + CloudFormationResponse buildResponseClient() { + // create a CloudFormationResponse that fails if invoked with unexpected status + CloudFormationResponse cfnResponse = mock(CloudFormationResponse.class); + try { + when(cfnResponse.send(any(), any(), org.mockito.ArgumentMatchers.argThat(new ArgumentMatcher<Response>() { + @Override + public boolean matches(Response resp) { + return resp != null && resp.getStatus() != expectedStatus; + } + }))).thenThrow(new AssertionError("Expected response's status to be " + expectedStatus)); + } catch (IOException | CustomResourceResponseException e) { + // this should never happen + throw new RuntimeException("Unexpected mocking exception", e); + } + return cfnResponse; + } +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExplicitSuccessResponseHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExplicitSuccessResponseHandler.java new file mode 100644 index 000000000..2b11f8020 --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ExplicitSuccessResponseHandler.java @@ -0,0 +1,31 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.cloudformation; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + +import software.amazon.lambda.powertools.cloudformation.Response.Status; + +public class ExplicitSuccessResponseHandler extends ExpectedStatusResourceHandler { + public ExplicitSuccessResponseHandler() { + super(Status.SUCCESS); + } + + @Override + protected Response create(CloudFormationCustomResourceEvent event, Context context) { + return Response.builder().value("whatever").status(Status.SUCCESS).build(); + } +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailToSendResponseHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailToSendResponseHandler.java new file mode 100644 index 000000000..218994c56 --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailToSendResponseHandler.java @@ -0,0 +1,41 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.cloudformation; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +/** + * Always fails to send the response + */ +public class FailToSendResponseHandler extends NoOpCustomResourceHandler { + @Override + CloudFormationResponse buildResponseClient() { + CloudFormationResponse cfnResponse = mock(CloudFormationResponse.class); + try { + when(cfnResponse.send(any(), any())) + .thenThrow(new IOException("Intentional send failure")); + when(cfnResponse.send(any(), any(), any())) + .thenThrow(new IOException("Intentional send failure")); + } catch (IOException | CustomResourceResponseException e) { + // this should never happen + throw new RuntimeException("Unexpected mocking exception", e); + } + return cfnResponse; + } +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailedResponseHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailedResponseHandler.java new file mode 100644 index 000000000..787713535 --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailedResponseHandler.java @@ -0,0 +1,31 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.cloudformation; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + +import software.amazon.lambda.powertools.cloudformation.Response.Status; + +public class FailedResponseHandler extends ExpectedStatusResourceHandler { + public FailedResponseHandler() { + super(Status.FAILED); + } + + @Override + protected Response create(CloudFormationCustomResourceEvent event, Context context) { + return Response.builder().value("whatever").status(Status.FAILED).build(); + } +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailedSendHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailedSendHandler.java new file mode 100644 index 000000000..fe88d8895 --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/FailedSendHandler.java @@ -0,0 +1,25 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.cloudformation; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + +public class FailedSendHandler extends FailToSendResponseHandler { + @Override + protected Response create(CloudFormationCustomResourceEvent event, Context context) { + throw new RuntimeException("This exception is intentional for testing"); + } +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/NoOpCustomResourceHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/NoOpCustomResourceHandler.java new file mode 100644 index 000000000..0271c36f5 --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/NoOpCustomResourceHandler.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.cloudformation; + +import static org.mockito.Mockito.mock; + +import software.amazon.awssdk.http.SdkHttpClient; + +/** + * Uses a mocked CloudFormationResponse to avoid sending actual HTTP requests. + */ +public class NoOpCustomResourceHandler extends NullCustomResourceHandler { + + public NoOpCustomResourceHandler() { + super(mock(SdkHttpClient.class)); + } + + @Override + CloudFormationResponse buildResponseClient() { + return mock(CloudFormationResponse.class); + } +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/NullCustomResourceHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/NullCustomResourceHandler.java new file mode 100644 index 000000000..a44e2d57e --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/NullCustomResourceHandler.java @@ -0,0 +1,47 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.cloudformation; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + +import software.amazon.awssdk.http.SdkHttpClient; + +/** + * Bare-bones implementation that returns null for abstract methods. + */ +public class NullCustomResourceHandler extends AbstractCustomResourceHandler { + public NullCustomResourceHandler() { + } + + public NullCustomResourceHandler(SdkHttpClient client) { + super(client); + } + + @Override + protected Response create(CloudFormationCustomResourceEvent event, Context context) { + return null; + } + + @Override + protected Response update(CloudFormationCustomResourceEvent event, Context context) { + return null; + } + + @Override + protected Response delete(CloudFormationCustomResourceEvent event, Context context) { + return null; + } +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java index 3e2930541..726bcbeee 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/ResponseTest.java @@ -16,12 +16,14 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; import java.util.HashMap; import java.util.Map; + import org.junit.jupiter.api.Test; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; + class ResponseTest { @Test @@ -81,7 +83,7 @@ void explicitReasonWithDefaultValues() { assertThat(response.toString()).contains("Status = SUCCESS"); assertThat(response.toString()).contains("PhysicalResourceId = null"); assertThat(response.toString()).contains("NoEcho = false"); - assertThat(response.toString()).contains("Reason = "+reason); + assertThat(response.toString()).contains("Reason = " + reason); } @Test diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/SuccessResponseHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/SuccessResponseHandler.java new file mode 100644 index 000000000..18538bc9d --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/SuccessResponseHandler.java @@ -0,0 +1,31 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.cloudformation; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + +import software.amazon.lambda.powertools.cloudformation.Response.Status; + +public class SuccessResponseHandler extends ExpectedStatusResourceHandler { + public SuccessResponseHandler() { + super(Status.SUCCESS); + } + + @Override + protected Response create(CloudFormationCustomResourceEvent event, Context context) { + return Response.builder().value("whatever").build(); + } +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/SuccessfulSendHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/SuccessfulSendHandler.java new file mode 100644 index 000000000..074d1499e --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/SuccessfulSendHandler.java @@ -0,0 +1,25 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.cloudformation; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + +public class SuccessfulSendHandler extends FailToSendResponseHandler { + @Override + protected Response create(CloudFormationCustomResourceEvent event, Context context) { + return Response.builder().value("Failure happens on send").build(); + } +} diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java index e55abca03..4fb14110c 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/NoPhysicalResourceIdSetHandler.java @@ -16,6 +16,7 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + import software.amazon.lambda.powertools.cloudformation.AbstractCustomResourceHandler; import software.amazon.lambda.powertools.cloudformation.Response; diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/PhysicalResourceIdSetHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/PhysicalResourceIdSetHandler.java index c6bd56b76..a01319342 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/PhysicalResourceIdSetHandler.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/PhysicalResourceIdSetHandler.java @@ -16,6 +16,7 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + import software.amazon.lambda.powertools.cloudformation.AbstractCustomResourceHandler; import software.amazon.lambda.powertools.cloudformation.Response; diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/RuntimeExceptionThrownHandler.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/RuntimeExceptionThrownHandler.java index d5a11e895..10e3801c2 100644 --- a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/RuntimeExceptionThrownHandler.java +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/handlers/RuntimeExceptionThrownHandler.java @@ -16,6 +16,7 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.events.CloudFormationCustomResourceEvent; + import software.amazon.lambda.powertools.cloudformation.AbstractCustomResourceHandler; import software.amazon.lambda.powertools.cloudformation.Response; diff --git a/powertools-cloudformation/src/test/resources/simplelogger.properties b/powertools-cloudformation/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..e8ba3a5fa --- /dev/null +++ b/powertools-cloudformation/src/test/resources/simplelogger.properties @@ -0,0 +1,7 @@ +org.slf4j.simpleLogger.logFile=target/cloudformation-test.log +org.slf4j.simpleLogger.defaultLogLevel=warn +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS +org.slf4j.simpleLogger.showThreadName=false +org.slf4j.simpleLogger.showLogName=true +org.slf4j.simpleLogger.showShortLogName=false From c2d2d51ec8133304830f9353cb94c9bc702ebc39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:21:51 -0300 Subject: [PATCH 394/577] chore: bump sam/build-java21 (#2083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps sam/build-java21 from `6ad1664` to `853ac90`. --- updated-dependencies: - dependency-name: sam/build-java21 dependency-version: 853ac90b359be42f95fe913fde43517ed5f3ed086aa93a6c0bd4b2d8fe07df9d dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ana Falcão <anafalcao@poli.ufrj.br> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index a4cacd9cb..4ce9ad1ed 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:6ad16645a48cbc9aa6ab9b707350d1976804f410bb47dd0f87bf106cd69ff36a +FROM public.ecr.aws/sam/build-java21@sha256:853ac90b359be42f95fe913fde43517ed5f3ed086aa93a6c0bd4b2d8fe07df9d # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From b1cfa3e6702156a5b748f4bc75bdd01ffdf0a5b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 16:48:18 -0300 Subject: [PATCH 395/577] chore: bump com.github.spotbugs:spotbugs-maven-plugin (#2084) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) from 4.9.3.2 to 4.9.4.0. - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.9.3.2...spotbugs-maven-plugin-4.9.4.0) --- updated-dependencies: - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-version: 4.9.4.0 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ana Falcão <anafalcao@poli.ufrj.br> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 7e287d4e5..fffccb89a 100644 --- a/pom.xml +++ b/pom.xml @@ -611,7 +611,7 @@ <plugin> <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> - <version>4.9.3.2</version> + <version>4.9.4.0</version> <executions> <execution> <id>test</id> From 8998bc9c20c5a7a318771ca91c96aa8087e76f33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 17:59:38 -0300 Subject: [PATCH 396/577] chore: bump io.github.ascopes:protobuf-maven-plugin from 3.8.0 to 3.8.1 (#2085) Bumps [io.github.ascopes:protobuf-maven-plugin](https://github.com/ascopes/protobuf-maven-plugin) from 3.8.0 to 3.8.1. - [Release notes](https://github.com/ascopes/protobuf-maven-plugin/releases) - [Commits](https://github.com/ascopes/protobuf-maven-plugin/compare/v3.8.0...v3.8.1) --- updated-dependencies: - dependency-name: io.github.ascopes:protobuf-maven-plugin dependency-version: 3.8.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 956ca7d8d..85798000f 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -141,7 +141,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.8.0</version> + <version>3.8.1</version> <executions> <execution> <goals> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 75167ff92..5faa929b7 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -181,7 +181,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.8.0</version> + <version>3.8.1</version> <executions> <execution> <id>generate-test-sources</id> From 19f4ff08bfe1e843acda7d72b32afaa3c38a08a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:10:24 -0300 Subject: [PATCH 397/577] chore: bump org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions (#2088) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions from 0.1.0 to 0.2.0. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions dependency-version: 0.2.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ana Falcão <anafalcao@poli.ufrj.br> --- powertools-e2e-tests/handlers/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index d7ac21335..ffe44eb8e 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -148,7 +148,7 @@ <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-transform-maven-shade-plugin-extensions</artifactId> - <version>0.1.0</version> + <version>0.2.0</version> </dependency> </dependencies> </plugin> From b8c5ec7f4b18cd7626fb263690dc8fb8a41695e8 Mon Sep 17 00:00:00 2001 From: Connor Kirkpatrick <17845406+ConnorKirk@users.noreply.github.com> Date: Tue, 2 Sep 2025 14:02:27 +0100 Subject: [PATCH 398/577] docs: Update docs introduction --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 17f3b397b..9c5c803cb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,7 +3,7 @@ title: Homepage description: Powertools for AWS Lambda (Java) --- -Powertools for AWS Lambda (Java) is a suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier. +Powertools for AWS Lambda (Java) is a developer toolkit to implement Serverless best practices and increase developer velocity. ???+ tip Powertools for AWS Lambda is also available for [Python](https://docs.powertools.aws.dev/lambda/python/latest/){target="_blank"}, [TypeScript](https://docs.powertools.aws.dev/lambda/typescript/latest/){target="_blank"}, and [.NET](https://docs.powertools.aws.dev/lambda/dotnet/){target="_blank"} From e502583de3d2c6661494487da575084b39a470b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:03:10 +0200 Subject: [PATCH 399/577] chore: bump actions/checkout from 4.2.2 to 5.0.0 (#2087) Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 5.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.2.2...08c6903cd8c0fde910a37f88322edcfb5dd907a8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 3a34188f9..f254b67d3 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -91,7 +91,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: fetch-depth: 0 - name: Get changed files From 62d09392941f9f3f006d6db7156fcd68dc208bb0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:03:27 +0200 Subject: [PATCH 400/577] chore: bump org.apache.maven.plugins:maven-compiler-plugin (#2094) Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.11.0 to 3.14.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.11.0...maven-compiler-plugin-3.14.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-version: 3.14.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/handlers/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index ffe44eb8e..3d81e6d1b 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <lambda.java.events>3.16.1</lambda.java.events> <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.13.1</aspectj.plugin.version> - <maven.compiler.version>3.11.0</maven.compiler.version> + <maven.compiler.version>3.14.0</maven.compiler.version> <aws.sdk.version>2.32.31</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> From e33f28d74b7b76fcc7f2563dc58858650fdce4b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:07:47 +0200 Subject: [PATCH 401/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.212.0 to 2.213.0 (#2100) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.212.0 to 2.213.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.212.0...v2.213.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.213.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index bac4f78ff..db4857448 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.3.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.212.0</cdk.version> + <cdk.version>2.213.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.13.4</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 4094bfb20..babfaf7a2 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.2</constructs.version> - <cdk.version>2.212.0</cdk.version> + <cdk.version>2.213.0</cdk.version> </properties> <dependencies> From 20bf95285c3932381636bceeaea8f00dd53c6a89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:08:10 +0200 Subject: [PATCH 402/577] chore: bump github/codeql-action from 3.29.11 to 3.30.0 (#2106) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.11 to 3.30.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/3c3833e0f8c1c83d449a7478aa59c036a9165498...2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 4047f0da2..dfa0b2121 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.5 + uses: github/codeql-action/upload-sarif@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.29.5 with: sarif_file: results.sarif From 2c3e7a6076c9b1fc8adeb303c301fd876486f336 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:08:35 +0200 Subject: [PATCH 403/577] chore: bump aws.sdk.version from 2.32.26 to 2.32.31 (#2098) Bumps `aws.sdk.version` from 2.32.26 to 2.32.31. Updates `software.amazon.awssdk:url-connection-client` from 2.32.26 to 2.32.31 Updates `software.amazon.awssdk:sdk-core` from 2.32.26 to 2.32.31 Updates `software.amazon.awssdk:s3` from 2.32.26 to 2.32.31 Updates `software.amazon.awssdk:kinesis` from 2.32.26 to 2.32.31 Updates `software.amazon.awssdk:sqs` from 2.32.26 to 2.32.31 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.32.26 to 2.32.31 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.32.31 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.32.31 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.32.31 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index c456ace5a..9857aa717 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.32.26</sdk.version> + <sdk.version>2.32.31</sdk.version> </properties> <dependencies> From 90387569e51639dc45852053fe16025ba53831e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 17:21:18 +0200 Subject: [PATCH 404/577] chore: bump dev.aspectj:aspectj-maven-plugin from 1.13.1 to 1.14.1 (#2099) Bumps [dev.aspectj:aspectj-maven-plugin](https://github.com/dev-aspectj/aspectj-maven-plugin) from 1.13.1 to 1.14.1. - [Release notes](https://github.com/dev-aspectj/aspectj-maven-plugin/releases) - [Commits](https://github.com/dev-aspectj/aspectj-maven-plugin/compare/aspectj-maven-plugin-1.13.1...aspectj-maven-plugin-1.14.1) --- updated-dependencies: - dependency-name: dev.aspectj:aspectj-maven-plugin dependency-version: 1.14.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/handlers/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 3d81e6d1b..7b8718671 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -18,7 +18,7 @@ <lambda.java.serialization>1.1.6</lambda.java.serialization> <lambda.java.events>3.16.1</lambda.java.events> <maven.shade.version>3.6.0</maven.shade.version> - <aspectj.plugin.version>1.13.1</aspectj.plugin.version> + <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.0</maven.compiler.version> <aws.sdk.version>2.32.31</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> From de9ba8b32cf344b4536515e583b368ae0bb0423a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 19:00:55 +0200 Subject: [PATCH 405/577] chore: bump jackson.version from 2.19.2 to 2.20 (#2097) * chore: bump jackson.version from 2.19.2 to 2.20 Bumps `jackson.version` from 2.19.2 to 2.20. Updates `com.fasterxml.jackson.core:jackson-databind` from 2.19.2 to 2.20 Updates `com.fasterxml.jackson.core:jackson-core` from 2.19.2 to 2.20 Updates `com.fasterxml.jackson.core:jackson-annotations` from 2.19.2 to 2.20 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.19.2 to 2.20 --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-version: '2.20' dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-version: '2.20' dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-version: '2.20' dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-version: '2.20' dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Migrate to Jackson BOM for managing different Jackson module versions. * Fix issue where root pom file change does not re-trigger graalvm unit tests. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> Co-authored-by: Philipp Page <pagejep@amazon.com> --- .github/workflows/check-build.yml | 1 + pom.xml | 23 +++++------------------ 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index f254b67d3..b84db997b 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -100,6 +100,7 @@ jobs: with: files: | powertools-*/** + pom.xml - name: Setup GraalVM uses: graalvm/setup-graalvm@7f488cf82a3629ee755e4e97342c01d6bed318fa # v1.3.5 with: diff --git a/pom.xml b/pom.xml index fffccb89a..c1fd3b9c4 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <maven.deploy.plugin.version>3.1.2</maven.deploy.plugin.version> <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> - <jackson.version>2.19.2</jackson.version> + <jackson.version>2.20.0</jackson.version> <aws.sdk.version>2.32.31</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> @@ -231,24 +231,11 @@ <version>${aspectj.version}</version> </dependency> <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-databind</artifactId> - <version>${jackson.version}</version> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-core</artifactId> - <version>${jackson.version}</version> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.core</groupId> - <artifactId>jackson-annotations</artifactId> - <version>${jackson.version}</version> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.datatype</groupId> - <artifactId>jackson-datatype-jsr310</artifactId> + <groupId>com.fasterxml.jackson</groupId> + <artifactId>jackson-bom</artifactId> <version>${jackson.version}</version> + <scope>import</scope> + <type>pom</type> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> From 22ea06aacd7a0e80310796b90529b4685d141b05 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 4 Sep 2025 10:42:02 +0200 Subject: [PATCH 406/577] test(metrics): Improve testability of `@FlushMetrics` annotation (#2112) * Clarify how to mock the Lambda context in unit tests for Metrics utility. * Revert when() mocking in documentation. * Avoid metrics from raising an exception when using plain mocked Lambda context. * Reset outputstream in unit test docs. * Make stdout stream field static and final. * Fix issue when function name is not set. * Fix hl_lines in docs. * Fix hl_lines in docs. * Remove java8 from sam templates. --- docs/core/metrics.md | 64 ++++++--- docs/core/tracing.md | 4 +- powertools-metrics/pom.xml | 19 +++ .../metrics/internal/EmfMetricsLogger.java | 2 +- .../metrics/internal/LambdaMetricsAspect.java | 10 +- .../metrics/RequestHandlerTest.java | 126 ++++++++++++++++++ 6 files changed, 203 insertions(+), 22 deletions(-) create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 31079a76e..61d4c38f0 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -140,7 +140,7 @@ For most use-cases, we recommend using Environment variables and only overwrite Type: AWS::Serverless::Function Properties: ... - Runtime: java8 + Runtime: java11 Environment: Variables: POWERTOOLS_SERVICE_NAME: payment @@ -558,9 +558,24 @@ If you would like to suppress metrics output during your unit tests, you can use When unit testing your code, you can run assertions against the output generated by the `Metrics` Singleton. For the `EmfMetricsLogger`, you can assert the generated JSON blob following the [CloudWatch EMF specification](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format.html) against your expected output. +Make sure to set a test metrics namespace and service name to run assertions against metrics. For example, by setting the following environment variables in your tests: + +```xml +<plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <environmentVariables> + <POWERTOOLS_SERVICE_NAME>TestService</POWERTOOLS_SERVICE_NAME> + <POWERTOOLS_METRICS_NAMESPACE>TestNamespace</POWERTOOLS_METRICS_NAMESPACE> + </environmentVariables> + </configuration> +</plugin> +``` + Consider the following example where we redirect the standard output to a custom `PrintStream`. We use the Jackson library to parse the EMF output into a `JsonNode` and run assertions against that. -```java hl_lines="23 28 33 50-55" +```java hl_lines="35 40 56-72" import static org.assertj.core.api.Assertions.assertThat; import java.io.ByteArrayOutputStream; @@ -571,6 +586,9 @@ import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; @@ -578,21 +596,25 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import software.amazon.lambda.powertools.metrics.model.MetricUnit; -import software.amazon.lambda.powertools.metrics.testutils.TestContext; +@ExtendWith(MockitoExtension.class) class MetricsTestExample { + @Mock + Context lambdaContext; + private final PrintStream standardOut = System.out; - private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); + private ByteArrayOutputStream outputStreamCaptor; private final ObjectMapper objectMapper = new ObjectMapper(); @BeforeEach void setUp() { + outputStreamCaptor = new ByteArrayOutputStream(); System.setOut(new PrintStream(outputStreamCaptor)); } @AfterEach - void tearDown() { + void tearDown() throws Exception { System.setOut(standardOut); } @@ -600,27 +622,37 @@ class MetricsTestExample { void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { // Given RequestHandler<Map<String, Object>, String> handler = new HandlerWithMetricsAnnotation(); - Context context = new TestContext(); Map<String, Object> input = new HashMap<>(); // When - handler.handleRequest(input, context); + handler.handleRequest(input, lambdaContext); // Then String emfOutput = outputStreamCaptor.toString().trim(); - JsonNode rootNode = objectMapper.readTree(emfOutput); - - assertThat(rootNode.has("test-metric")).isTrue(); - assertThat(rootNode.get("test-metric").asDouble()).isEqualTo(100.0); - assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) - .isEqualTo("CustomNamespace"); - assertThat(rootNode.has("Service")).isTrue(); - assertThat(rootNode.get("Service").asText()).isEqualTo("CustomService"); + String[] jsonLines = emfOutput.split("\n"); + + // First JSON object should be the cold start metric + JsonNode coldStartNode = objectMapper.readTree(jsonLines[0]); + assertThat(coldStartNode.has("ColdStart")).isTrue(); + assertThat(coldStartNode.get("ColdStart").asDouble()).isEqualTo(1.0); + assertThat(coldStartNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("TestNamespace"); + assertThat(coldStartNode.has("Service")).isTrue(); + assertThat(coldStartNode.get("Service").asText()).isEqualTo("TestService"); + + // Second JSON object should be the regular metric + JsonNode regularNode = objectMapper.readTree(jsonLines[1]); + assertThat(regularNode.has("test-metric")).isTrue(); + assertThat(regularNode.get("test-metric").asDouble()).isEqualTo(100.0); + assertThat(regularNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("TestNamespace"); + assertThat(regularNode.has("Service")).isTrue(); + assertThat(regularNode.get("Service").asText()).isEqualTo("TestService"); } static class HandlerWithMetricsAnnotation implements RequestHandler<Map<String, Object>, String> { @Override - @FlushMetrics(namespace = "CustomNamespace", service = "CustomService") + @FlushMetrics(captureColdStart = true) public String handleRequest(Map<String, Object> input, Context context) { Metrics metrics = MetricsFactory.getMetricsInstance(); metrics.addMetric("test-metric", 100, MetricUnit.COUNT); diff --git a/docs/core/tracing.md b/docs/core/tracing.md index 883f8db86..8129d45ba 100644 --- a/docs/core/tracing.md +++ b/docs/core/tracing.md @@ -105,7 +105,7 @@ Before your use this utility, your AWS Lambda function [must have permissions](h Type: AWS::Serverless::Function Properties: ... - Runtime: java8 + Runtime: java11 Tracing: Active Environment: @@ -191,7 +191,7 @@ different supported `captureMode` to record response, exception or both. Type: AWS::Serverless::Function Properties: ... - Runtime: java8 + Runtime: java11 Tracing: Active Environment: diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 4bccab505..b90506c25 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -105,6 +105,11 @@ <artifactId>assertj-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-common</artifactId> @@ -135,6 +140,13 @@ </profile> <profile> <id>generate-graalvm-files</id> + <dependencies> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-subclass</artifactId> + <scope>test</scope> + </dependency> + </dependencies> <build> <plugins> <plugin> @@ -154,6 +166,13 @@ </profile> <profile> <id>graalvm-native</id> + <dependencies> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-subclass</artifactId> + <scope>test</scope> + </dependency> + </dependencies> <build> <plugins> <plugin> diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java index 2f6f9e689..c9651585f 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java @@ -204,7 +204,7 @@ public void captureColdStartMetric(Context context, } // Add request ID from context if available - if (context != null) { + if (context != null && context.getAwsRequestId() != null) { coldStartLogger.putProperty(REQUEST_ID_PROPERTY, context.getAwsRequestId()); } diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java index b214d7c52..32824e24f 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java @@ -113,7 +113,10 @@ private void captureColdStartMetricIfEnabled(Context extractedContext, FlushMetr } Metrics metricsInstance = MetricsFactory.getMetricsInstance(); - metricsInstance.addMetadata(REQUEST_ID_PROPERTY, extractedContext.getAwsRequestId()); + // This can be null e.g. during unit tests when mocking the Lambda context + if (extractedContext.getAwsRequestId() != null) { + metricsInstance.addMetadata(REQUEST_ID_PROPERTY, extractedContext.getAwsRequestId()); + } // Only capture cold start metrics if enabled on annotation if (metrics.captureColdStart()) { @@ -133,8 +136,9 @@ private void captureColdStartMetricIfEnabled(Context extractedContext, FlushMetr } // Add function name - coldStartDimensions.addDimension("FunctionName", - funcName != null ? funcName : extractedContext.getFunctionName()); + if (funcName != null) { + coldStartDimensions.addDimension("FunctionName", funcName); + } metricsInstance.captureColdStartMetric(extractedContext, coldStartDimensions); } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java new file mode 100644 index 000000000..d94a6bbe8 --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java @@ -0,0 +1,126 @@ +package software.amazon.lambda.powertools.metrics; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junitpioneer.jupiter.SetEnvironmentVariable; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; + +@ExtendWith(MockitoExtension.class) +class RequestHandlerTest { + + // For developer convenience, no exceptions should be thrown when using a plain Lambda Context mock + @Mock + Context lambdaContext; + + private static final PrintStream STDOUT = System.out; + private ByteArrayOutputStream outputStreamCaptor; + private final ObjectMapper objectMapper = new ObjectMapper(); + + @BeforeEach + void setUp() throws Exception { + outputStreamCaptor = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outputStreamCaptor)); + + // Reset LambdaHandlerProcessor's SERVICE_NAME + Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); + resetServiceName.setAccessible(true); + resetServiceName.invoke(null); + + // Reset IS_COLD_START + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + coldStartField.setAccessible(true); + coldStartField.set(null, null); + } + + @AfterEach + void tearDown() throws Exception { + System.setOut(STDOUT); + + // Reset the singleton state between tests + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + field.setAccessible(true); + field.set(null, null); + + field = MetricsFactory.class.getDeclaredField("provider"); + field.setAccessible(true); + field.set(null, new software.amazon.lambda.powertools.metrics.provider.EmfMetricsProvider()); + } + + @Test + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_NAMESPACE", value = "TestNamespace") + @SetEnvironmentVariable(key = "POWERTOOLS_SERVICE_NAME", value = "TestService") + void shouldCaptureMetricsFromAnnotatedHandler() throws Exception { + // Given + RequestHandler<Map<String, Object>, String> handler = new HandlerWithMetricsAnnotation(); + Map<String, Object> input = new HashMap<>(); + + // When + handler.handleRequest(input, lambdaContext); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + String[] jsonLines = emfOutput.split("\n"); + + // First JSON object should be the cold start metric + JsonNode coldStartNode = objectMapper.readTree(jsonLines[0]); + assertThat(coldStartNode.has("ColdStart")).isTrue(); + assertThat(coldStartNode.get("ColdStart").asDouble()).isEqualTo(1.0); + assertThat(coldStartNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("TestNamespace"); + assertThat(coldStartNode.has("Service")).isTrue(); + assertThat(coldStartNode.get("Service").asText()).isEqualTo("TestService"); + + // Second JSON object should be the regular metric + JsonNode regularNode = objectMapper.readTree(jsonLines[1]); + assertThat(regularNode.has("test-metric")).isTrue(); + assertThat(regularNode.get("test-metric").asDouble()).isEqualTo(100.0); + assertThat(regularNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("TestNamespace"); + assertThat(regularNode.has("Service")).isTrue(); + assertThat(regularNode.get("Service").asText()).isEqualTo("TestService"); + } + + @SetEnvironmentVariable(key = "POWERTOOLS_METRICS_DISABLED", value = "true") + @Test + void shouldNotCaptureMetricsWhenDisabled() { + // Given + RequestHandler<Map<String, Object>, String> handler = new HandlerWithMetricsAnnotation(); + Map<String, Object> input = new HashMap<>(); + + // When + handler.handleRequest(input, lambdaContext); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + assertThat(emfOutput).isEmpty(); + } + + static class HandlerWithMetricsAnnotation implements RequestHandler<Map<String, Object>, String> { + @Override + @FlushMetrics(captureColdStart = true) + public String handleRequest(Map<String, Object> input, Context context) { + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.addMetric("test-metric", 100, MetricUnit.COUNT); + return "OK"; + } + } +} From be3f37fda54a1f897850efd3b1b5eaf4cc59100c Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 4 Sep 2025 13:57:39 +0200 Subject: [PATCH 407/577] docs: Add AWS copyright footer. (#2119) --- mkdocs.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 45ea8e64b..ea7617353 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -79,7 +79,14 @@ markdown_extensions: toc_depth: 4 - attr_list -copyright: Copyright © 2021 Amazon Web Services +copyright: | + <div id="awsdocs-legal-zone-copyright"> + <a href="https://aws.amazon.com/privacy" target="_blank" rel="nofollow">Privacy</a> | + <a href="https://aws.amazon.com/terms/" target="_blank" rel="nofollow">Site terms</a> | + <span class="copyright"> + © 2025, Amazon Web Services, Inc. or its affiliates. All rights reserved. + </span> + </div> plugins: - git-revision-date From 53b29bdd694f84651775aef7bafb8e2bbde1a232 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 4 Sep 2025 15:50:44 +0200 Subject: [PATCH 408/577] feat(logging): Log buffering support for Logj42 and Logback (#2103) * Log buffer PoC with log4j2 appender implementation. * Add buffer cleaning to avoid memory leak and flushBufferOnUncaughtError option to Logging aspect. * Call appenders with logevent directly from BufferingAppender. * Extract buffer management logic into KeyBuffer class and keep log4j appender minimal. * Unit tests for BufferingAppender * Rename to Log4jConstants. * Make Appender detection independent of plugin name. * Add assertions in unit test to test multiple appenders. * Make assertion stronger to assert that each message appears twice because we configured two appenders as proxies. * Add logback implementation. Decouple KeyBuffer and BufferingAppender to avoid circular dependency when flushing buffer on error. * Log error in AppStream example. * Update Logging E2E test to use log buffering. * Prepare Logging E2E test to support paramaterized versions by logging backend. * Add Logging E2E tests for both logback and log4j2. * Debug not found appender on Linux. * Isolate log4j context loading in unit tests. * Avoid logging config leakage in log4j unit test. * Avoid config leaking in logback unit tests. * Update Graal metadata for powertools-logging. * Update Graal metadata for powertools-logging-log4j. * Update Graal metadata for powertools-logging-logback. * Address Sonar findings. * Address pmd findings. * Set allowCommentedBlocks=true in pmd rules. * Fix thread-safety issue in double-checked singleton instance creation. * Increase scope of thread-safety tests in KeyBuffer. * Try to satisfy pmd executor service closing. * Try to satisfy pmd executor service closing. * Add PMD suppressions with reason where appropriate. * Add PMD suppressions with reason where appropriate. * Restore original example. * Enable log sampling again. * Restore formatting in pmd ruleset. * Update Javadoc of BufferingAppenders. * Remove unncessary cleanup. * Remove duplicated infrastructure clearnup in LoggingE2E. * Make javadoc for Keybuffer more concise. * Add comment for large event rejection. * Fix grammer in error message. * Remove redundant tests in PowertoolsLoggingTest. * Add developer documentation. * Fix sonar finding. * Clarify log buffering log level configuration with upper and lower bound example. * Update docs/core/logging.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/core/logging.md Co-authored-by: Stefano Vozza <svozza@gmail.com> --------- Co-authored-by: Stefano Vozza <svozza@gmail.com> --- .github/pmd-ruleset.xml | 5 +- docs/core/logging.md | 378 +++++++++++++++- .../sam/src/main/java/helloworld/App.java | 5 - .../src/main/java/helloworld/AppStream.java | 41 +- .../sam/src/main/resources/log4j2.xml | 12 +- .../sam/template.yaml | 4 +- .../{logging => logging-log4j}/pom.xml | 9 +- .../lambda/powertools/e2e/Function.java | 12 +- .../amazon/lambda/powertools/e2e/Input.java | 3 - .../aws-lambda-java-core/reflect-config.json | 0 .../reflect-config.json | 0 .../jni-config.json | 0 .../native-image.properties | 0 .../reflect-config.json | 0 .../resource-config.json | 0 .../reflect-config.json | 0 .../reflect-config.json | 0 .../resource-config.json | 0 .../src/main/resources/log4j2.xml | 11 +- .../handlers/logging-logback/pom.xml | 82 ++++ .../lambda/powertools/e2e/Function.java | 40 ++ .../amazon/lambda/powertools/e2e/Input.java | 38 ++ .../aws-lambda-java-core/reflect-config.json | 13 + .../reflect-config.json | 35 ++ .../jni-config.json | 11 + .../native-image.properties | 1 + .../reflect-config.json | 61 +++ .../resource-config.json | 19 + .../reflect-config.json | 25 ++ .../reflect-config.json | 20 + .../resource-config.json | 7 + .../src/main/resources/logback.xml | 16 + .../amazon/lambda/powertools/e2e/Input.java | 3 - powertools-e2e-tests/handlers/pom.xml | 8 +- .../amazon/lambda/powertools/e2e/Input.java | 3 - powertools-e2e-tests/pom.xml | 5 + .../amazon/lambda/powertools/LoggingE2ET.java | 32 +- .../logging/log4j/BufferingAppender.java | 201 +++++++++ .../internal/Log4jLoggingManager.java | 38 +- .../powertools-logging-log4j/jni-config.json | 16 - .../reflect-config.json | 258 +++-------- .../resource-config.json | 56 --- ...powertools.logging.internal.LoggingManager | 2 +- .../internal/Log4jLoggingManagerTest.java | 51 --- .../internal/handler/PowertoolsArguments.java | 2 +- .../handler/PowertoolsLogEnabled.java | 8 +- .../logging/log4j/BufferingAppenderTest.java | 141 ++++++ .../internal/Log4jLoggingManagerTest.java | 118 +++++ .../resources/log4j2-multiple-buffering.xml | 26 ++ .../src/test/resources/log4j2.xml | 11 +- .../powertools-logging-logback/pom.xml | 5 + .../logging/logback/BufferingAppender.java | 196 +++++++++ .../internal/LogbackLoggingManager.java | 51 ++- .../jni-config.json | 12 - .../reflect-config.json | 85 ++-- .../resource-config.json | 4 - .../logging/LogbackLoggingManagerTest.java | 58 ++- .../logback/BufferingAppenderTest.java | 150 +++++++ .../test/resources/logback-buffering-test.xml | 21 + .../resources/logback-multiple-buffering.xml | 28 ++ .../lambda/powertools/logging/Logging.java | 8 +- .../powertools/logging/PowertoolsLogging.java | 55 +++ .../logging/internal/BufferManager.java | 33 ++ ...anager.java => DefaultLoggingManager.java} | 2 +- .../logging/internal/KeyBuffer.java | 95 ++++ .../logging/internal/LambdaLoggingAspect.java | 186 ++++---- .../internal/LoggingManagerRegistry.java | 99 +++++ .../powertools-logging/jni-config.json | 16 - .../powertools-logging/reflect-config.json | 415 +----------------- .../powertools-logging/resource-config.json | 6 - .../logging/PowertoolsLoggingTest.java | 53 +++ .../handlers/PowertoolsLogErrorNoFlush.java | 15 + .../logging/internal/KeyBufferTest.java | 356 +++++++++++++++ .../internal/LambdaLoggingAspectTest.java | 145 ++++-- .../internal/LoggingManagerRegistryTest.java | 141 ++++++ .../logging/internal/TestLoggingManager.java | 33 +- 76 files changed, 3052 insertions(+), 1043 deletions(-) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/pom.xml (90%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/java/software/amazon/lambda/powertools/e2e/Function.java (86%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/java/software/amazon/lambda/powertools/e2e/Input.java (97%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json (100%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json (100%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json (100%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties (100%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json (100%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json (100%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json (100%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json (100%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json (100%) rename powertools-e2e-tests/handlers/{logging => logging-log4j}/src/main/resources/log4j2.xml (52%) create mode 100644 powertools-e2e-tests/handlers/logging-logback/pom.xml create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/java/software/amazon/lambda/powertools/e2e/Function.java create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/java/software/amazon/lambda/powertools/e2e/Input.java create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json create mode 100644 powertools-e2e-tests/handlers/logging-logback/src/main/resources/logback.xml create mode 100644 powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppender.java rename powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/{log4 => log4j}/internal/Log4jLoggingManager.java (54%) delete mode 100644 powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/Log4jLoggingManagerTest.java create mode 100644 powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppenderTest.java create mode 100644 powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jLoggingManagerTest.java create mode 100644 powertools-logging/powertools-logging-log4j/src/test/resources/log4j2-multiple-buffering.xml create mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/BufferingAppender.java create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/BufferingAppenderTest.java create mode 100644 powertools-logging/powertools-logging-logback/src/test/resources/logback-buffering-test.xml create mode 100644 powertools-logging/powertools-logging-logback/src/test/resources/logback-multiple-buffering.xml create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/PowertoolsLogging.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/BufferManager.java rename powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/{DefautlLoggingManager.java => DefaultLoggingManager.java} (94%) create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/KeyBuffer.java create mode 100644 powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingManagerRegistry.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/PowertoolsLoggingTest.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogErrorNoFlush.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/KeyBufferTest.java create mode 100644 powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LoggingManagerRegistryTest.java diff --git a/.github/pmd-ruleset.xml b/.github/pmd-ruleset.xml index b93fa19b8..1bc5f3020 100644 --- a/.github/pmd-ruleset.xml +++ b/.github/pmd-ruleset.xml @@ -350,6 +350,9 @@ </rule> <rule ref="category/java/errorprone.xml/EmptyCatchBlock"> <priority>1</priority> + <properties> + <property name="allowCommentedBlocks" value="true" /> + </properties> </rule> <!-- <rule ref="category/java/errorprone.xml/EmptyFinalizer" /> --> <!-- <rule ref="category/java/errorprone.xml/EmptyFinallyBlock" /> --> @@ -641,4 +644,4 @@ </property> </properties> </rule> -</ruleset> \ No newline at end of file +</ruleset> diff --git a/docs/core/logging.md b/docs/core/logging.md index 2d9e57dda..be3bd7e5c 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -12,6 +12,7 @@ Logging provides an opinionated logger with output structured as JSON. * Optionally logs Lambda request * Optionally logs Lambda response * Optionally supports log sampling by including a configurable percentage of DEBUG logs in logging output +* Optionally supports buffering lower level logs and flushing them on error or manually * Allows additional keys to be appended to the structured log at any point in time * GraalVM support @@ -311,9 +312,8 @@ We prioritise log level settings in this order: If you set `POWERTOOLS_LOG_LEVEL` lower than ALC, we will emit a warning informing you that your messages will be discarded by Lambda. -> **NOTE** -> -> With ALC enabled, we are unable to increase the minimum log level below the `AWS_LAMBDA_LOG_LEVEL` environment variable value, see [AWS Lambda service documentation](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-log-level){target="_blank"} for more details. +!!! note + With ALC enabled, we are unable to increase the minimum log level below the `AWS_LAMBDA_LOG_LEVEL` environment variable value, see [AWS Lambda service documentation](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-log-level){target="_blank"} for more details. ## Basic Usage @@ -787,7 +787,377 @@ with `logError` param or via `POWERTOOLS_LOGGER_LOG_ERROR` env var. } ``` -# Advanced +## Advanced + +### Buffering logs + +Log buffering enables you to buffer logs for a specific request or invocation. Enable log buffering by configuring the `BufferingAppender` in your logging configuration. You can buffer logs at the `WARNING`, `INFO` or `DEBUG` level, and flush them automatically on error or manually as needed. + +!!! tip "This is useful when you want to reduce the number of log messages emitted while still having detailed logs when needed, such as when troubleshooting issues." + +=== "log4j2.xml" + + ```xml hl_lines="7-12 16 19" + <?xml version="1.0" encoding="UTF-8"?> + <Configuration> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + <BufferingAppender name="BufferedJsonAppender" + maxBytes="20480" + bufferAtVerbosity="DEBUG" + flushOnErrorLog="true"> + <AppenderRef ref="JsonAppender"/> + </BufferingAppender> + </Appenders> + <Loggers> + <Logger name="com.example" level="debug" additivity="false"> + <AppenderRef ref="BufferedJsonAppender"/> + </Logger> + <Root level="debug"> + <AppenderRef ref="BufferedJsonAppender"/> + </Root> + </Loggers> + </Configuration> + ``` + +=== "logback.xml" + + ```xml hl_lines="6-11 13 16" + <?xml version="1.0" encoding="UTF-8"?> + <configuration> + <appender name="JsonAppender" class="ch.qos.logback.core.ConsoleAppender"> + <encoder class="software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder" /> + </appender> + <appender name="BufferedJsonAppender" class="software.amazon.lambda.powertools.logging.logback.BufferingAppender"> + <maxBytes>20480</maxBytes> + <bufferAtVerbosity>DEBUG</bufferAtVerbosity> + <flushOnErrorLog>true</flushOnErrorLog> + <appender-ref ref="JsonAppender" /> + </appender> + <logger name="com.example" level="DEBUG" additivity="false"> + <appender-ref ref="BufferedJsonAppender" /> + </logger> + <root level="DEBUG"> + <appender-ref ref="BufferedJsonAppender" /> + </root> + </configuration> + ``` + +=== "PaymentFunction.java" + + ```java hl_lines="8 12" + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.logging.Logging; + // ... other imports + + public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); + + @Logging + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + LOGGER.debug("a debug log"); // this is buffered + LOGGER.info("an info log"); // this is not buffered + + // do stuff + + // Buffer is automatically cleared at the end of the method by @Logging annotation + return new APIGatewayProxyResponseEvent().withStatusCode(200); + } + } + ``` + +#### Configuring the buffer + +When configuring log buffering, you have options to fine-tune how logs are captured, stored, and emitted. You can configure the following parameters in the `BufferingAppender` configuration: + +| Parameter | Description | Configuration | +| --------------------- | ----------------------------------------------- | ---------------------------- | +| `maxBytes` | Maximum size of the log buffer in bytes | `int` (default: 20480 bytes) | +| `bufferAtVerbosity` | Minimum log level to buffer | `DEBUG` (default), `INFO`, `WARNING` | +| `flushOnErrorLog` | Automatically flush buffer when `ERROR` or `FATAL` level logs are emitted | `true` (default), `false` | + +!!! warning "Logger Level Configuration" + To use log buffering effectively, you must set your logger levels to the same level as `bufferAtVerbosity` or more verbose for the logging framework to capture and forward logs to the `BufferingAppender`. For example, if you want to buffer `DEBUG` level logs and emit `INFO`+ level logs directly, you must: + + - Set your logger levels to `DEBUG` in your log4j2.xml or logback.xml configuration + - Set `POWERTOOLS_LOG_LEVEL=DEBUG` if using the environment variable (see [Log level](#log-level) section for more details) + + If you want to sample `INFO` and `WARNING` logs but not `DEBUG` logs, set your log level to `INFO` and `bufferAtVerbosity` to `WARNING`. This allows you to define the lower and upper bounds for buffering. All logs with a more severe level than `bufferAtVerbosity` will be emitted directly. + +=== "log4j2.xml - Buffer at WARNING level" + + ```xml hl_lines="9 14-15 18" + <?xml version="1.0" encoding="UTF-8"?> + <Configuration> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + <BufferingAppender name="BufferedJsonAppender" + maxBytes="20480" + bufferAtVerbosity="WARNING"> + <AppenderRef ref="JsonAppender"/> + </BufferingAppender> + </Appenders> + <Loggers> + <!-- Intentionally set to DEBUG to forward all logs to BufferingAppender --> + <Logger name="com.example" level="debug" additivity="false"> + <AppenderRef ref="BufferedJsonAppender"/> + </Logger> + <Root level="debug"> + <AppenderRef ref="BufferedJsonAppender"/> + </Root> + </Loggers> + </Configuration> + ``` + +=== "PaymentFunction.java - Buffer at WARNING level" + + ```java hl_lines="7-9 13" + public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); + + @Logging + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + LOGGER.warn("a warning log"); // this is buffered + LOGGER.info("an info log"); // this is buffered + LOGGER.debug("a debug log"); // this is buffered + + // do stuff + + // Buffer is automatically cleared at the end of the method by @Logging annotation + return new APIGatewayProxyResponseEvent().withStatusCode(200); + } + } + ``` + +=== "log4j2.xml - Disable flush on error" + + ```xml hl_lines="9" + <?xml version="1.0" encoding="UTF-8"?> + <Configuration> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + <BufferingAppender name="BufferedJsonAppender" + maxBytes="20480" + flushOnErrorLog="false"> + <AppenderRef ref="JsonAppender"/> + </BufferingAppender> + </Appenders> + <Loggers> + <Logger name="com.example" level="debug" additivity="false"> + <AppenderRef ref="BufferedJsonAppender"/> + </Logger> + <Root level="debug"> + <AppenderRef ref="BufferedJsonAppender"/> + </Root> + </Loggers> + </Configuration> + ``` + +=== "PaymentFunction.java - Manual flush required" + + ```java hl_lines="1 16 19-20" + import software.amazon.lambda.powertools.logging.PowertoolsLogging; + + public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); + + @Logging + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + LOGGER.debug("a debug log"); // this is buffered + + // do stuff + + try { + throw new RuntimeException("Something went wrong"); + } catch (RuntimeException error) { + LOGGER.error("An error occurred", error); // Logs won't be flushed here + } + + // Manually flush buffered logs + PowertoolsLogging.flushBuffer(); + + return new APIGatewayProxyResponseEvent().withStatusCode(200); + } + } + ``` + +!!! note "Disabling `flushOnErrorLog` will not flush the buffer when logging an error. This is useful when you want to control when the buffer is flushed by calling the flush method manually." + +#### Manual buffer control + +You can manually control the log buffer using the `PowertoolsLogging` utility class, which provides a backend-independent API that works with both Log4j2 and Logback: + +=== "Manual flush" + + ```java hl_lines="1 12-13" + import software.amazon.lambda.powertools.logging.PowertoolsLogging; + + public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); + + @Logging + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + LOGGER.debug("Processing payment"); // this is buffered + LOGGER.info("Payment validation complete"); // this is buffered + + // Manually flush all buffered logs + PowertoolsLogging.flushBuffer(); + + return new APIGatewayProxyResponseEvent().withStatusCode(200); + } + } + ``` + +=== "Manual clear" + + ```java hl_lines="1 12-13" + import software.amazon.lambda.powertools.logging.PowertoolsLogging; + + public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); + + @Logging + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + LOGGER.debug("Processing payment"); // this is buffered + LOGGER.info("Payment validation complete"); // this is buffered + + // Manually clear buffered logs without outputting them + PowertoolsLogging.clearBuffer(); + + return new APIGatewayProxyResponseEvent().withStatusCode(200); + } + } + ``` + +**Available methods:** + +- `#!java PowertoolsLogging.flushBuffer()` - Outputs all buffered logs and clears the buffer +- `#!java PowertoolsLogging.clearBuffer()` - Discards all buffered logs without outputting them + +#### Flushing on exceptions + +Use the `@Logging` annotation to automatically flush buffered logs when an uncaught exception is raised in your Lambda function. This is enabled by default (`flushBufferOnUncaughtError = true`), but you can explicitly configure it if needed. + +=== "PaymentFunction.java" + + ```java hl_lines="5 11" + public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); + + @Logging(flushBufferOnUncaughtError = true) + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + LOGGER.debug("a debug log"); // this is buffered + + // do stuff + + throw new RuntimeException("Something went wrong"); // Logs will be flushed here + } + } + ``` + +#### Buffering workflows + +##### Manual flush + +<center> +```mermaid +sequenceDiagram + participant Client + participant Lambda + participant Logger + participant CloudWatch + Client->>Lambda: Invoke Lambda + Lambda->>Logger: Initialize with DEBUG level buffering + Logger-->>Lambda: Logger buffer ready + Lambda->>Logger: logger.debug("First debug log") + Logger-->>Logger: Buffer first debug log + Lambda->>Logger: logger.info("Info log") + Logger->>CloudWatch: Directly log info message + Lambda->>Logger: logger.debug("Second debug log") + Logger-->>Logger: Buffer second debug log + Lambda->>Logger: Manual flush call + Logger->>CloudWatch: Emit buffered logs to stdout + Lambda->>Client: Return execution result +``` +<i>Flushing buffer manually</i> +</center> + +##### Flushing when logging an error + +<center> +```mermaid +sequenceDiagram + participant Client + participant Lambda + participant Logger + participant CloudWatch + Client->>Lambda: Invoke Lambda + Lambda->>Logger: Initialize with DEBUG level buffering + Logger-->>Lambda: Logger buffer ready + Lambda->>Logger: logger.debug("First log") + Logger-->>Logger: Buffer first debug log + Lambda->>Logger: logger.debug("Second log") + Logger-->>Logger: Buffer second debug log + Lambda->>Logger: logger.debug("Third log") + Logger-->>Logger: Buffer third debug log + Lambda->>Lambda: Exception occurs + Lambda->>Logger: logger.error("Error details") + Logger->>CloudWatch: Emit error log + Logger->>CloudWatch: Emit buffered debug logs + Lambda->>Client: Raise exception +``` +<i>Flushing buffer when an error happens</i> +</center> + +##### Flushing on exception + +This works when using the `@Logging` annotation which automatically clears the buffer at the end of method execution. + +<center> +```mermaid +sequenceDiagram + participant Client + participant Lambda + participant Logger + participant CloudWatch + Client->>Lambda: Invoke Lambda + Lambda->>Logger: Using @Logging annotation + Logger-->>Lambda: Logger context injected + Lambda->>Logger: logger.debug("First log") + Logger-->>Logger: Buffer first debug log + Lambda->>Logger: logger.debug("Second log") + Logger-->>Logger: Buffer second debug log + Lambda->>Lambda: Uncaught Exception + Lambda->>CloudWatch: Automatically emit buffered debug logs + Lambda->>Client: Raise uncaught exception +``` +<i>Flushing buffer when an uncaught exception happens</i> +</center> + +#### Buffering FAQs + +1. **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. +2. **Are my logs buffered during cold starts (INIT phase)?** 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. +3. **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 `BufferingAppender` configuration. This will ensure that the buffer does not grow indefinitely. +4. **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. +5. **How is the log size of a log line calculated?** The log size is calculated based on the size of the log line in bytes. This includes the size of the log message, any exception (if present), the log line location, additional keys, and the timestamp. +6. **What timestamp is used when I flush the logs?** The timestamp is 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. +7. **What happens if I try to add a log line that is bigger than max buffer size?** The log will be emitted directly to standard output and not buffered. When this happens, we emit a warning to indicate that the log line was too big to be buffered. +8. **What happens if Lambda times out without flushing the buffer?** Logs that are still in the buffer will be lost. +9. **How does the `BufferingAppender` work with different appenders?** The `BufferingAppender` is designed to wrap arbitrary appenders, providing maximum flexibility. You can wrap console appenders, file appenders, or any custom appenders with buffering functionality. ## Sampling debug logs diff --git a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java index 2675c96eb..2844e50fe 100644 --- a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java +++ b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/App.java @@ -97,11 +97,6 @@ public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEv } } - @Tracing - private void log() { - log.info("inside threaded logging for function"); - } - @Tracing(namespace = "getPageContents", captureMode = CaptureMode.DISABLED) private String getPageContents(String address) throws IOException { URL url = new URL(address); diff --git a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/AppStream.java b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/AppStream.java index 8bc57b201..d3ebbef5d 100644 --- a/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/AppStream.java +++ b/examples/powertools-examples-core-utilities/sam/src/main/java/helloworld/AppStream.java @@ -14,41 +14,45 @@ package helloworld; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; -import com.fasterxml.jackson.databind.ObjectMapper; - +import java.io.BufferedReader; +import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; import java.nio.charset.StandardCharsets; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import com.fasterxml.jackson.databind.ObjectMapper; + import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.metrics.FlushMetrics; -import java.io.InputStreamReader; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; - public class AppStream implements RequestStreamHandler { private static final ObjectMapper mapper = new ObjectMapper(); - private final static Logger log = LogManager.getLogger(AppStream.class); + private static final Logger log = LoggerFactory.getLogger(AppStream.class); @Override @Logging(logEvent = true) @FlushMetrics(namespace = "ServerlessAirline", service = "payment", captureColdStart = true) - // RequestStreamHandler can be used instead of RequestHandler for cases when you'd like to deserialize request body or serialize response body yourself, instead of allowing that to happen automatically - // Note that you still need to return a proper JSON for API Gateway to handle - // See Lambda Response format for examples: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html + // RequestStreamHandler can be used instead of RequestHandler for cases when you'd like to deserialize request body + // or serialize response body yourself, instead of allowing that to happen automatically + // Note that you still need to return a proper JSON for API Gateway to handle + // See Lambda Response format for examples: + // https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html public void handleRequest(InputStream input, OutputStream output, Context context) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)); - PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8)))) { + PrintWriter writer = new PrintWriter( + new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8)))) { - log.info("Received: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(reader))); + log.info( + "Received: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readTree(reader))); writer.write("{\"body\": \"" + System.currentTimeMillis() + "\"} "); } catch (IOException e) { @@ -56,4 +60,3 @@ public void handleRequest(InputStream input, OutputStream output, Context contex } } } - diff --git a/examples/powertools-examples-core-utilities/sam/src/main/resources/log4j2.xml b/examples/powertools-examples-core-utilities/sam/src/main/resources/log4j2.xml index e1fd14cea..e140022e4 100644 --- a/examples/powertools-examples-core-utilities/sam/src/main/resources/log4j2.xml +++ b/examples/powertools-examples-core-utilities/sam/src/main/resources/log4j2.xml @@ -4,13 +4,13 @@ <Console name="JsonAppender" target="SYSTEM_OUT"> <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> </Console> + <BufferingAppender name="BufferedAppender" bufferAtVerbosity="DEBUG"> + <AppenderRef ref="JsonAppender" /> + </BufferingAppender> </Appenders> <Loggers> - <Logger name="JsonLogger" level="INFO" additivity="false"> - <AppenderRef ref="JsonAppender"/> - </Logger> - <Root level="info"> - <AppenderRef ref="JsonAppender"/> + <Root level="debug"> + <AppenderRef ref="BufferedAppender" /> </Root> </Loggers> -</Configuration> \ No newline at end of file +</Configuration> diff --git a/examples/powertools-examples-core-utilities/sam/template.yaml b/examples/powertools-examples-core-utilities/sam/template.yaml index 9a51a1ba9..6b1814dce 100644 --- a/examples/powertools-examples-core-utilities/sam/template.yaml +++ b/examples/powertools-examples-core-utilities/sam/template.yaml @@ -1,4 +1,4 @@ -AWSTemplateFormatVersion: '2010-09-09' +AWSTemplateFormatVersion: "2010-09-09" Transform: AWS::Serverless-2016-10-31 Description: > CoreUtilities @@ -13,7 +13,7 @@ Globals: Environment: Variables: # Powertools for AWS Lambda (Java) env vars: https://docs.powertools.aws.dev/lambda/java/#environment-variables - POWERTOOLS_LOG_LEVEL: INFO + POWERTOOLS_LOG_LEVEL: DEBUG # We use log buffering to buffer DEBUG logs (see log4j2.xml) POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1 POWERTOOLS_LOGGER_LOG_EVENT: true POWERTOOLS_METRICS_NAMESPACE: Coreutilities diff --git a/powertools-e2e-tests/handlers/logging/pom.xml b/powertools-e2e-tests/handlers/logging-log4j/pom.xml similarity index 90% rename from powertools-e2e-tests/handlers/logging/pom.xml rename to powertools-e2e-tests/handlers/logging-log4j/pom.xml index f8b5689c8..d415ae4b3 100644 --- a/powertools-e2e-tests/handlers/logging/pom.xml +++ b/powertools-e2e-tests/handlers/logging-log4j/pom.xml @@ -8,20 +8,15 @@ <version>2.3.0</version> </parent> - <artifactId>e2e-test-handler-logging</artifactId> + <artifactId>e2e-test-handler-logging-log4j</artifactId> <packaging>jar</packaging> - <name>E2E test handler – Logging</name> + <name>E2E test handler – Logging Log4j</name> <dependencies> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging-log4j</artifactId> </dependency> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-layout-template-json</artifactId> - <version>2.25.1</version> - </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> diff --git a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/logging-log4j/src/main/java/software/amazon/lambda/powertools/e2e/Function.java similarity index 86% rename from powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java rename to powertools-e2e-tests/handlers/logging-log4j/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index 58492653a..94520c447 100644 --- a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/logging-log4j/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -14,12 +14,15 @@ package software.amazon.lambda.powertools.e2e; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.PowertoolsLogging; public class Function implements RequestHandler<Input, String> { private static final Logger LOG = LoggerFactory.getLogger(Function.class); @@ -29,6 +32,9 @@ public String handleRequest(Input input, Context context) { input.getKeys().forEach(MDC::put); LOG.info(input.getMessage()); + // Flush buffer manually since we buffer at INFO level to test log buffering + PowertoolsLogging.flushBuffer(); + return "OK"; } -} \ No newline at end of file +} diff --git a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/logging-log4j/src/main/java/software/amazon/lambda/powertools/e2e/Input.java similarity index 97% rename from powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Input.java rename to powertools-e2e-tests/handlers/logging-log4j/src/main/java/software/amazon/lambda/powertools/e2e/Input.java index cc449922e..66fd49ddc 100644 --- a/powertools-e2e-tests/handlers/logging/src/main/java/software/amazon/lambda/powertools/e2e/Input.java +++ b/powertools-e2e-tests/handlers/logging-log4j/src/main/java/software/amazon/lambda/powertools/e2e/Input.java @@ -20,9 +20,6 @@ public class Input { private String message; private Map<String, String> keys; - public Input() { - } - public String getMessage() { return message; } diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json similarity index 100% rename from powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json rename to powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json similarity index 100% rename from powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json rename to powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json similarity index 100% rename from powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json rename to powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties similarity index 100% rename from powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties rename to powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json similarity index 100% rename from powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json rename to powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json similarity index 100% rename from powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json rename to powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json similarity index 100% rename from powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json rename to powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json similarity index 100% rename from powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json rename to powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json similarity index 100% rename from powertools-e2e-tests/handlers/logging/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json rename to powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json diff --git a/powertools-e2e-tests/handlers/logging/src/main/resources/log4j2.xml b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/log4j2.xml similarity index 52% rename from powertools-e2e-tests/handlers/logging/src/main/resources/log4j2.xml rename to powertools-e2e-tests/handlers/logging-log4j/src/main/resources/log4j2.xml index 8925f70b9..28e03a9e0 100644 --- a/powertools-e2e-tests/handlers/logging/src/main/resources/log4j2.xml +++ b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/log4j2.xml @@ -4,13 +4,14 @@ <Console name="JsonAppender" target="SYSTEM_OUT"> <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> </Console> + <!-- We buffer everything to implicitly test buffer flushing --> + <BufferingAppender name="BufferedAppender" bufferAtVerbosity="INFO"> + <AppenderRef ref="JsonAppender" /> + </BufferingAppender> </Appenders> <Loggers> <Root level="INFO"> - <AppenderRef ref="JsonAppender"/> + <AppenderRef ref="BufferedAppender" /> </Root> - <Logger name="JsonLogger" level="INFO" additivity="false"> - <AppenderRef ref="JsonAppender"/> - </Logger> </Loggers> -</Configuration> \ No newline at end of file +</Configuration> diff --git a/powertools-e2e-tests/handlers/logging-logback/pom.xml b/powertools-e2e-tests/handlers/logging-logback/pom.xml new file mode 100644 index 000000000..932eb0612 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/pom.xml @@ -0,0 +1,82 @@ +<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 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>software.amazon.lambda</groupId> + <artifactId>e2e-test-handlers-parent</artifactId> + <version>2.3.0</version> + </parent> + + <artifactId>e2e-test-handler-logging-logback</artifactId> + <packaging>jar</packaging> + <name>E2E test handler – Logging Logback</name> + + <dependencies> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging-logback</artifactId> + </dependency> + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjrt</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-events</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>dev.aspectj</groupId> + <artifactId>aspectj-maven-plugin</artifactId> + <configuration> + <source>${maven.compiler.source}</source> + <target>${maven.compiler.target}</target> + <complianceLevel>${maven.compiler.target}</complianceLevel> + <aspectLibraries> + <aspectLibrary> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging</artifactId> + </aspectLibrary> + </aspectLibraries> + </configuration> + <executions> + <execution> + <goals> + <goal>compile</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/logging-logback/src/main/java/software/amazon/lambda/powertools/e2e/Function.java new file mode 100644 index 000000000..94520c447 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -0,0 +1,40 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.PowertoolsLogging; + +public class Function implements RequestHandler<Input, String> { + private static final Logger LOG = LoggerFactory.getLogger(Function.class); + + @Logging + public String handleRequest(Input input, Context context) { + input.getKeys().forEach(MDC::put); + LOG.info(input.getMessage()); + + // Flush buffer manually since we buffer at INFO level to test log buffering + PowertoolsLogging.flushBuffer(); + + return "OK"; + } +} diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/logging-logback/src/main/java/software/amazon/lambda/powertools/e2e/Input.java new file mode 100644 index 000000000..66fd49ddc --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/java/software/amazon/lambda/powertools/e2e/Input.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +import java.util.Map; + +public class Input { + private String message; + private Map<String, String> keys; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Map<String, String> getKeys() { + return keys; + } + + public void setKeys(Map<String, String> keys) { + this.keys = keys; + } +} diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json new file mode 100644 index 000000000..a603a9398 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlogback.xml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/logback.xml b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/logback.xml new file mode 100644 index 000000000..0a5e4d146 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/logback.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + <appender name="JsonAppender" class="ch.qos.logback.core.ConsoleAppender"> + <encoder class="software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder"/> + </appender> + + <!-- We buffer everything to implicitly test buffer flushing --> + <appender name="BufferedAppender" class="software.amazon.lambda.powertools.logging.logback.BufferingAppender"> + <bufferAtVerbosity>INFO</bufferAtVerbosity> + <appender-ref ref="JsonAppender"/> + </appender> + + <root level="INFO"> + <appender-ref ref="BufferedAppender"/> + </root> +</configuration> \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java index 1328ded77..054c2867a 100644 --- a/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java +++ b/powertools-e2e-tests/handlers/metrics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java @@ -23,9 +23,6 @@ public class Input { private String highResolution; - public Input() { - } - public Map<String, Double> getMetrics() { return metrics; } diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 7b8718671..53f9ed3ad 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -28,7 +28,8 @@ <module>batch</module> <module>largemessage</module> <module>largemessage_idempotent</module> - <module>logging</module> + <module>logging-log4j</module> + <module>logging-logback</module> <module>tracing</module> <module>metrics</module> <module>idempotency</module> @@ -56,6 +57,11 @@ <artifactId>powertools-logging-log4j</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging-logback</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> diff --git a/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Input.java index 92078d0b3..ed89f4498 100644 --- a/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Input.java +++ b/powertools-e2e-tests/handlers/tracing/src/main/java/software/amazon/lambda/powertools/e2e/Input.java @@ -17,9 +17,6 @@ public class Input { private String message; - public Input() { - } - public String getMessage() { return message; } diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index babfaf7a2..5f3e2506a 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -102,6 +102,11 @@ <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-params</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java index ad2c2564f..f5d2cea84 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java @@ -25,10 +25,11 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; @@ -37,20 +38,19 @@ import software.amazon.lambda.powertools.testutils.Infrastructure; import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class LoggingE2ET { private static final ObjectMapper objectMapper = new ObjectMapper(); - private static Infrastructure infrastructure; - private static String functionName; + private Infrastructure infrastructure; + private String functionName; - @BeforeAll - @Timeout(value = 10, unit = TimeUnit.MINUTES) - static void setup() { + private void setupInfrastructure(String pathToFunction) { infrastructure = Infrastructure.builder() - .testName(LoggingE2ET.class.getSimpleName()) + .testName(LoggingE2ET.class.getSimpleName() + "-" + pathToFunction) .tracing(true) - .pathToFunction("logging") + .pathToFunction(pathToFunction) .environmentVariables( Stream.of(new String[][] { { "POWERTOOLS_LOG_LEVEL", "INFO" }, @@ -62,15 +62,19 @@ static void setup() { functionName = outputs.get(FUNCTION_NAME_OUTPUT); } - @AfterAll - static void tearDown() { + @AfterEach + void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } - @Test - void test_logInfoWithAdditionalKeys() throws JsonProcessingException { + @ParameterizedTest + @ValueSource(strings = { "logging-log4j", "logging-logback" }) + @Timeout(value = 15, unit = TimeUnit.MINUTES) + void test_logInfoWithAdditionalKeys(String pathToFunction) throws JsonProcessingException { + setupInfrastructure(pathToFunction); + // GIVEN String orderId = UUID.randomUUID().toString(); String event = "{\"message\":\"New Order\", \"keys\":{\"orderId\":\"" + orderId + "\"}}"; diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppender.java b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppender.java new file mode 100644 index 000000000..fcf4a2040 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppender.java @@ -0,0 +1,201 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.log4j; + +import java.io.Serializable; +import java.util.Deque; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Appender; +import org.apache.logging.log4j.core.Core; +import org.apache.logging.log4j.core.Filter; +import org.apache.logging.log4j.core.Layout; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.appender.AbstractAppender; +import org.apache.logging.log4j.core.config.AppenderRef; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.config.plugins.PluginAttribute; +import org.apache.logging.log4j.core.config.plugins.PluginConfiguration; +import org.apache.logging.log4j.core.config.plugins.PluginElement; +import org.apache.logging.log4j.core.config.plugins.PluginFactory; +import org.apache.logging.log4j.core.impl.Log4jLogEvent; +import org.apache.logging.log4j.message.SimpleMessage; + +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.logging.internal.BufferManager; +import software.amazon.lambda.powertools.logging.internal.KeyBuffer; + +/** + * A Log4j2 appender that buffers log events by AWS X-Ray trace ID for optimized Lambda logging. + * + * <p>This appender is designed specifically for AWS Lambda functions to reduce log ingestion + * by buffering lower-level logs and only outputting them when errors occur, preserving + * full context for troubleshooting while minimizing routine log volume. + * + * <h3>Key Features:</h3> + * <ul> + * <li><strong>Trace-based buffering:</strong> Groups logs by AWS X-Ray trace ID</li> + * <li><strong>Selective output:</strong> Only buffers logs at or below configured verbosity level</li> + * <li><strong>Auto-flush on errors:</strong> Automatically outputs buffered logs when ERROR/FATAL events occur</li> + * <li><strong>Memory management:</strong> Prevents memory leaks with configurable buffer size limits</li> + * <li><strong>Overflow protection:</strong> Warns when logs are discarded due to buffer limits</li> + * </ul> + * + * <h3>Configuration Example:</h3> + * <pre>{@code + * <BufferingAppender name="BufferedAppender" + * bufferAtVerbosity="DEBUG" + * maxBytes="20480" + * flushOnErrorLog="true"> + * <AppenderRef ref="ConsoleAppender"/> + * </BufferingAppender> + * }</pre> + * + * <h3>Configuration Parameters:</h3> + * <ul> + * <li><strong>bufferAtVerbosity:</strong> Log level to buffer (default: DEBUG). Logs at this level and below are buffered</li> + * <li><strong>maxBytes:</strong> Maximum buffer size in bytes per trace ID (default: 20480)</li> + * <li><strong>flushOnErrorLog:</strong> Whether to flush buffer on ERROR/FATAL logs (default: true)</li> + * </ul> + * + * <h3>Behavior:</h3> + * <ul> + * <li>During Lambda INIT phase (no trace ID): logs are output directly</li> + * <li>During Lambda execution (with trace ID): logs are buffered or output based on level</li> + * <li>When buffer overflows: oldest logs are discarded and a warning is logged</li> + * <li>On Lambda completion: buffer is auto-cleared when used with {@code @Logging} annotation</li> + * </ul> + * + * @see software.amazon.lambda.powertools.logging.PowertoolsLogging#flushBuffer() + */ +@Plugin(name = "BufferingAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE) +public class BufferingAppender extends AbstractAppender implements BufferManager { + + private final AppenderRef[] appenderRefs; + private final Configuration configuration; + private final Level bufferAtVerbosity; + private final boolean flushOnErrorLog; + private final KeyBuffer<String, LogEvent> buffer; + + @SuppressWarnings("java:S107") // Constructor has too many parameters, which is OK for a Log4j2 plugin + protected BufferingAppender(String name, Filter filter, Layout<? extends Serializable> layout, + AppenderRef[] appenderRefs, Configuration configuration, Level bufferAtVerbosity, int maxBytes, + boolean flushOnErrorLog) { + super(name, filter, layout, false, null); + this.appenderRefs = appenderRefs; + this.configuration = configuration; + this.bufferAtVerbosity = bufferAtVerbosity; + this.flushOnErrorLog = flushOnErrorLog; + this.buffer = new KeyBuffer<>(maxBytes, event -> event.getMessage().getFormattedMessage().length(), + this::logOverflowWarning); + } + + @Override + public void append(LogEvent event) { + if (appenderRefs == null || appenderRefs.length == 0) { + return; + } + + LambdaHandlerProcessor.getXrayTraceId().ifPresentOrElse( + traceId -> { + if (shouldBuffer(event.getLevel())) { + bufferEvent(traceId, event); + } else { + callAppenders(event); + } + + // Flush buffer on error logs if configured + if (flushOnErrorLog && event.getLevel().isMoreSpecificThan(Level.WARN)) { + flushBuffer(traceId); + } + }, + () -> callAppenders(event) // No trace ID (INIT phase), log directly + ); + } + + private void callAppenders(LogEvent event) { + for (AppenderRef ref : appenderRefs) { + Appender appender = configuration.getAppender(ref.getRef()); + if (appender != null) { + appender.append(event); + } + } + } + + private boolean shouldBuffer(Level level) { + return level.isLessSpecificThan(bufferAtVerbosity) || level.equals(bufferAtVerbosity); + } + + private void bufferEvent(String traceId, LogEvent event) { + LogEvent immutableEvent = Log4jLogEvent.createMemento(event); + buffer.add(traceId, immutableEvent); + } + + public void clearBuffer() { + LambdaHandlerProcessor.getXrayTraceId().ifPresent(buffer::clear); + } + + public void flushBuffer() { + LambdaHandlerProcessor.getXrayTraceId().ifPresent(this::flushBuffer); + } + + private void flushBuffer(String traceId) { + Deque<LogEvent> events = buffer.removeAll(traceId); + if (events != null) { + events.forEach(this::callAppenders); + } + } + + @PluginFactory + @SuppressWarnings("java:S107") // Method has too many parameters, which is OK for a Log4j2 plugin factory + public static BufferingAppender createAppender( + @PluginAttribute("name") String name, + @PluginElement("Filter") Filter filter, + @PluginElement("Layout") Layout<? extends Serializable> layout, + @PluginElement("AppenderRef") AppenderRef[] appenderRefs, + @PluginConfiguration Configuration configuration, + @PluginAttribute(value = "bufferAtVerbosity", defaultString = "DEBUG") String bufferAtVerbosity, + @PluginAttribute(value = "maxBytes", defaultInt = 20480) int maxBytes, + @PluginAttribute(value = "flushOnErrorLog", defaultBoolean = true) boolean flushOnErrorLog) { + + if (name == null) { + LOGGER.error("No name provided for BufferingAppender"); + return null; + } + + Level level = Level.getLevel(bufferAtVerbosity); + if (level == null) { + level = Level.DEBUG; + } + + return new BufferingAppender(name, filter, layout, appenderRefs, configuration, level, maxBytes, + flushOnErrorLog); + } + + private void logOverflowWarning() { + // Create a properly formatted warning event and send directly to child appenders. Used to avoid circular + // dependency between KeyBuffer and BufferingAppender. + SimpleMessage message = new SimpleMessage( + "Some logs are not displayed because they were evicted from the buffer. Increase buffer size to store more logs in the buffer."); + LogEvent warningEvent = Log4jLogEvent.newBuilder() + .setLoggerName(BufferingAppender.class.getName()) + .setLevel(Level.WARN) + .setMessage(message) + .setTimeMillis(System.currentTimeMillis()) + .build(); + callAppenders(warningEvent); + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/Log4jLoggingManager.java b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jLoggingManager.java similarity index 54% rename from powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/Log4jLoggingManager.java rename to powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jLoggingManager.java index 4e57a8e45..90bbe1d32 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4/internal/Log4jLoggingManager.java +++ b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jLoggingManager.java @@ -12,19 +12,26 @@ * */ -package software.amazon.lambda.powertools.logging.log4.internal; +package software.amazon.lambda.powertools.logging.log4j.internal; + +import java.util.Collection; +import java.util.stream.Collectors; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.Configurator; import org.slf4j.Logger; + +import software.amazon.lambda.powertools.logging.internal.BufferManager; import software.amazon.lambda.powertools.logging.internal.LoggingManager; +import software.amazon.lambda.powertools.logging.log4j.BufferingAppender; /** - * LoggingManager for Log4j2 (see {@link LoggingManager}). + * LoggingManager for Log4j2 that provides log level management and buffer operations. + * Implements both {@link LoggingManager} and {@link BufferManager} interfaces. */ -public class Log4jLoggingManager implements LoggingManager { +public class Log4jLoggingManager implements LoggingManager, BufferManager { /** * @inheritDoc @@ -45,4 +52,29 @@ public org.slf4j.event.Level getLogLevel(Logger logger) { LoggerContext ctx = (LoggerContext) LogManager.getContext(false); return org.slf4j.event.Level.valueOf(ctx.getLogger(logger.getName()).getLevel().toString()); } + + /** + * @inheritDoc + */ + @Override + public void flushBuffer() { + getBufferingAppenders().forEach(BufferingAppender::flushBuffer); + } + + /** + * @inheritDoc + */ + @Override + public void clearBuffer() { + getBufferingAppenders().forEach(BufferingAppender::clearBuffer); + } + + private Collection<BufferingAppender> getBufferingAppenders() { + // Search all buffering appenders to avoid relying on the appender name given by the user + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + return ctx.getConfiguration().getAppenders().values().stream() + .filter(BufferingAppender.class::isInstance) + .map(BufferingAppender.class::cast) + .collect(Collectors.toList()); + } } diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/jni-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/jni-config.json index 2c4de0562..c8b081385 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/jni-config.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/jni-config.json @@ -3,22 +3,6 @@ "name":"java.lang.Boolean", "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] }, -{ - "name":"java.lang.String", - "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] -}, -{ - "name":"java.lang.System", - "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] -}, -{ - "name":"org.apache.maven.surefire.booter.ForkedBooter", - "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] -}, -{ - "name":"sun.instrument.InstrumentationImpl", - "methods":[{"name":"<init>","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] -}, { "name":"sun.management.VMManagementImpl", "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json index 9b2afe183..adbd9e0c1 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json @@ -1,4 +1,10 @@ [ +{ + "name":"[Ljava.lang.Object;" +}, +{ + "name":"[Ljava.lang.String;" +}, { "name":"[Lorg.apache.logging.log4j.core.Appender;" }, @@ -15,16 +21,7 @@ "name":"[Lorg.apache.logging.log4j.layout.template.json.JsonTemplateLayout$EventTemplateAdditionalField;" }, { - "name":"com.amazonaws.services.lambda.runtime.Context", - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] -}, -{ - "name":"com.amazonaws.services.lambda.runtime.RequestHandler", - "allDeclaredClasses":true, - "queryAllPublicMethods":true + "name":"com.amazonaws.services.lambda.runtime.Context" }, { "name":"com.amazonaws.services.lambda.runtime.events.SQSEvent$MessageAttribute", @@ -60,155 +57,88 @@ "name":"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl", "methods":[{"name":"<init>","parameterTypes":[] }] }, -{ - "name":"com.sun.tools.attach.VirtualMachine" -}, { "name":"jakarta.servlet.Servlet" }, { "name":"java.io.Serializable", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true -}, -{ - "name":"java.lang.Class", - "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] -}, -{ - "name":"java.lang.ClassLoader", - "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] + "queryAllDeclaredMethods":true }, { "name":"java.lang.Cloneable", "queryAllDeclaredMethods":true }, { - "name":"java.lang.Comparable", - "allDeclaredClasses":true, - "queryAllPublicMethods":true -}, -{ - "name":"java.lang.Enum", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"java.lang.Module", - "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] + "name":"java.lang.Iterable", + "queryAllDeclaredMethods":true }, { "name":"java.lang.Object", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] + "allDeclaredFields":true }, { "name":"java.lang.ProcessEnvironment", "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] }, -{ - "name":"java.lang.ProcessHandle", - "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] -}, -{ - "name":"java.lang.Runtime", - "methods":[{"name":"version","parameterTypes":[] }] -}, -{ - "name":"java.lang.Runtime$Version", - "methods":[{"name":"feature","parameterTypes":[] }] -}, -{ - "name":"java.lang.StackWalker" -}, { "name":"java.lang.String" }, -{ - "name":"java.lang.System", - "methods":[{"name":"getSecurityManager","parameterTypes":[] }] -}, { "name":"java.lang.Thread", "fields":[{"name":"threadLocalRandomProbe"}] }, { - "name":"java.lang.annotation.Retention", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true -}, -{ - "name":"java.lang.annotation.Target", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true -}, -{ - "name":"java.lang.constant.Constable", - "allDeclaredClasses":true, - "queryAllPublicMethods":true -}, -{ - "name":"java.lang.invoke.MethodHandle", - "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] -}, -{ - "name":"java.lang.invoke.MethodHandles", - "methods":[{"name":"lookup","parameterTypes":[] }] -}, -{ - "name":"java.lang.invoke.MethodHandles$Lookup", - "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] -}, -{ - "name":"java.lang.invoke.MethodType", - "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] + "name":"java.sql.Date" }, { - "name":"java.lang.reflect.AccessibleObject", - "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] + "name":"java.sql.Time" }, { - "name":"java.lang.reflect.AnnotatedArrayType", - "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] + "name":"java.util.AbstractCollection", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true }, { - "name":"java.lang.reflect.AnnotatedType", - "methods":[{"name":"getType","parameterTypes":[] }] + "name":"java.util.AbstractList", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true }, { - "name":"java.lang.reflect.Executable", - "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] + "name":"java.util.AbstractMap", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true }, { - "name":"java.lang.reflect.Method", - "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] + "name":"java.util.Arrays$ArrayList", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true }, { - "name":"java.lang.reflect.Parameter", - "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] + "name":"java.util.Collection", + "queryAllDeclaredMethods":true }, { - "name":"java.security.AccessController", - "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] + "name":"java.util.Collections$SingletonMap", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true }, { - "name":"java.sql.Date" + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] }, { - "name":"java.sql.Time" + "name":"java.util.List", + "queryAllDeclaredMethods":true }, { - "name":"java.util.Collections$UnmodifiableMap", - "fields":[{"name":"m"}] + "name":"java.util.Map", + "queryAllDeclaredMethods":true }, { - "name":"java.util.concurrent.ForkJoinTask", - "fields":[{"name":"aux"}, {"name":"status"}] + "name":"java.util.RandomAccess", + "queryAllDeclaredMethods":true }, { "name":"java.util.concurrent.atomic.AtomicBoolean", @@ -230,10 +160,7 @@ "name":"javax.servlet.Servlet" }, { - "name":"jdk.internal.misc.Unsafe" -}, -{ - "name":"kotlin.jvm.JvmInline" + "name":"kotlin.Metadata" }, { "name":"org.apache.logging.log4j.core.appender.AbstractAppender$Builder", @@ -493,6 +420,12 @@ "queryAllDeclaredMethods":true, "methods":[{"name":"createLoggers","parameterTypes":["org.apache.logging.log4j.core.config.LoggerConfig[]"] }] }, +{ + "name":"org.apache.logging.log4j.core.config.MonitorResource" +}, +{ + "name":"org.apache.logging.log4j.core.config.MonitorResources" +}, { "name":"org.apache.logging.log4j.core.config.PropertiesPlugin" }, @@ -743,7 +676,13 @@ "name":"org.apache.logging.log4j.core.layout.MessageLayout" }, { - "name":"org.apache.logging.log4j.core.layout.PatternLayout" + "name":"org.apache.logging.log4j.core.layout.PatternLayout", + "queryAllDeclaredMethods":true, + "methods":[{"name":"newBuilder","parameterTypes":[] }] +}, +{ + "name":"org.apache.logging.log4j.core.layout.PatternLayout$Builder", + "allDeclaredFields":true }, { "name":"org.apache.logging.log4j.core.layout.PatternMatch" @@ -878,9 +817,7 @@ "name":"org.apache.logging.log4j.core.pattern.ClassNamePatternConverter" }, { - "name":"org.apache.logging.log4j.core.pattern.DatePatternConverter", - "queryAllDeclaredMethods":true, - "methods":[{"name":"newInstance","parameterTypes":["java.lang.String[]"] }] + "name":"org.apache.logging.log4j.core.pattern.DatePatternConverter" }, { "name":"org.apache.logging.log4j.core.pattern.EncodingPatternConverter" @@ -913,9 +850,7 @@ "name":"org.apache.logging.log4j.core.pattern.IntegerPatternConverter" }, { - "name":"org.apache.logging.log4j.core.pattern.LevelPatternConverter", - "queryAllDeclaredMethods":true, - "methods":[{"name":"newInstance","parameterTypes":["java.lang.String[]"] }] + "name":"org.apache.logging.log4j.core.pattern.LevelPatternConverter" }, { "name":"org.apache.logging.log4j.core.pattern.LineLocationPatternConverter" @@ -929,9 +864,7 @@ "name":"org.apache.logging.log4j.core.pattern.LoggerFqcnPatternConverter" }, { - "name":"org.apache.logging.log4j.core.pattern.LoggerPatternConverter", - "queryAllDeclaredMethods":true, - "methods":[{"name":"newInstance","parameterTypes":["java.lang.String[]"] }] + "name":"org.apache.logging.log4j.core.pattern.LoggerPatternConverter" }, { "name":"org.apache.logging.log4j.core.pattern.MapPatternConverter" @@ -990,9 +923,7 @@ "name":"org.apache.logging.log4j.core.pattern.ThreadIdPatternConverter" }, { - "name":"org.apache.logging.log4j.core.pattern.ThreadNamePatternConverter", - "queryAllDeclaredMethods":true, - "methods":[{"name":"newInstance","parameterTypes":["java.lang.String[]"] }] + "name":"org.apache.logging.log4j.core.pattern.ThreadNamePatternConverter" }, { "name":"org.apache.logging.log4j.core.pattern.ThreadPriorityPatternConverter" @@ -1105,29 +1036,6 @@ "queryAllDeclaredMethods":true, "methods":[{"name":"getInstance","parameterTypes":[] }] }, -{ - "name":"org.apache.logging.log4j.layout.template.json.resolver.PowerToolsResolverFactoryTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"cleanUp","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"shouldLogInEcsFormat","parameterTypes":[] }, {"name":"shouldLogInJsonFormat","parameterTypes":[] }] -}, -{ - "name":"org.apache.logging.log4j.layout.template.json.resolver.PowertoolsResolverArgumentsTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"cleanUp","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"shouldLogArgumentsAsJsonWhenUsingKeyValue","parameterTypes":[] }, {"name":"shouldLogArgumentsAsJsonWhenUsingRawJson","parameterTypes":[] }] -}, -{ - "name":"org.apache.logging.log4j.layout.template.json.resolver.PowertoolsResolverFactory", - "queryAllDeclaredMethods":true, - "methods":[{"name":"getInstance","parameterTypes":[] }] -}, { "name":"org.apache.logging.log4j.layout.template.json.resolver.SourceResolverFactory", "queryAllDeclaredMethods":true, @@ -1161,12 +1069,6 @@ "name":"org.apiguardian.api.API", "queryAllPublicMethods":true }, -{ - "name":"org.aspectj.runtime.internal.AroundClosure", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, { "name":"org.jctools.queues.MpmcArrayQueue" }, @@ -1178,48 +1080,8 @@ "fields":[{"name":"IS_COLD_START"}] }, { - "name":"software.amazon.lambda.powertools.logging.internal.Log4jLoggingManagerTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getLogLevel_shouldReturnConfiguredLogLevel","parameterTypes":[] }, {"name":"resetLogLevel","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments", - "allDeclaredClasses":true, + "name":"software.amazon.lambda.powertools.logging.log4j.BufferingAppender", "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent$SQSMessage","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments$ArgumentFormat", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"sun.reflect.ReflectionFactory", - "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] + "methods":[{"name":"createAppender","parameterTypes":["java.lang.String","org.apache.logging.log4j.core.Filter","org.apache.logging.log4j.core.Layout","org.apache.logging.log4j.core.config.AppenderRef[]","org.apache.logging.log4j.core.config.Configuration","java.lang.String","int","boolean"] }] } ] diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json index aca0e0356..cf017fdeb 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json @@ -12,8 +12,6 @@ "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" }, { "pattern":"\\QMETA-INF/services/java.net.spi.InetAddressResolverProvider\\E" - }, { - "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" }, { "pattern":"\\QMETA-INF/services/javax.xml.parsers.DocumentBuilderFactory\\E" }, { @@ -36,60 +34,6 @@ "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" }, { "pattern":"\\QStackTraceElementLayout.json\\E" - }, { - "pattern":"\\Qlog4j2-test.jsn\\E" - }, { - "pattern":"\\Qlog4j2-test.json\\E" - }, { - "pattern":"\\Qlog4j2-test.properties\\E" - }, { - "pattern":"\\Qlog4j2-test.xml\\E" - }, { - "pattern":"\\Qlog4j2-test.yaml\\E" - }, { - "pattern":"\\Qlog4j2-test.yml\\E" - }, { - "pattern":"\\Qlog4j2-test18b4aac2.jsn\\E" - }, { - "pattern":"\\Qlog4j2-test18b4aac2.json\\E" - }, { - "pattern":"\\Qlog4j2-test18b4aac2.properties\\E" - }, { - "pattern":"\\Qlog4j2-test18b4aac2.xml\\E" - }, { - "pattern":"\\Qlog4j2-test18b4aac2.yaml\\E" - }, { - "pattern":"\\Qlog4j2-test18b4aac2.yml\\E" - }, { - "pattern":"\\Qlog4j2.StatusLogger.properties\\E" - }, { - "pattern":"\\Qlog4j2.component.properties\\E" - }, { - "pattern":"\\Qlog4j2.jsn\\E" - }, { - "pattern":"\\Qlog4j2.json\\E" - }, { - "pattern":"\\Qlog4j2.properties\\E" - }, { - "pattern":"\\Qlog4j2.system.properties\\E" - }, { - "pattern":"\\Qlog4j2.xml\\E" - }, { - "pattern":"\\Qlog4j2.yaml\\E" - }, { - "pattern":"\\Qlog4j2.yml\\E" - }, { - "pattern":"\\Qlog4j218b4aac2.jsn\\E" - }, { - "pattern":"\\Qlog4j218b4aac2.json\\E" - }, { - "pattern":"\\Qlog4j218b4aac2.properties\\E" - }, { - "pattern":"\\Qlog4j218b4aac2.xml\\E" - }, { - "pattern":"\\Qlog4j218b4aac2.yaml\\E" - }, { - "pattern":"\\Qlog4j218b4aac2.yml\\E" }]}, "bundles":[] } diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager index d444c5525..d4b2a72a0 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager @@ -1 +1 @@ -software.amazon.lambda.powertools.logging.log4.internal.Log4jLoggingManager \ No newline at end of file +software.amazon.lambda.powertools.logging.log4j.internal.Log4jLoggingManager diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/Log4jLoggingManagerTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/Log4jLoggingManagerTest.java deleted file mode 100644 index 69e1ee710..000000000 --- a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/Log4jLoggingManagerTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package software.amazon.lambda.powertools.logging.internal; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.slf4j.event.Level.DEBUG; -import static org.slf4j.event.Level.ERROR; -import static org.slf4j.event.Level.WARN; - -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.slf4j.event.Level; -import software.amazon.lambda.powertools.logging.log4.internal.Log4jLoggingManager; - -class Log4jLoggingManagerTest { - - private final static Logger LOG = LoggerFactory.getLogger(Log4jLoggingManagerTest.class); - private final static Logger ROOT = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); - - @Test - @Order(1) - void getLogLevel_shouldReturnConfiguredLogLevel() { - // Given log4j2.xml in resources - - // When - Log4jLoggingManager manager = new Log4jLoggingManager(); - Level logLevel = manager.getLogLevel(LOG); - Level rootLevel = manager.getLogLevel(ROOT); - - // Then - assertThat(logLevel).isEqualTo(DEBUG); - assertThat(rootLevel).isEqualTo(WARN); - } - - @Test - @Order(2) - void resetLogLevel() { - // Given log4j2.xml in resources - - // When - Log4jLoggingManager manager = new Log4jLoggingManager(); - manager.setLogLevel(ERROR); - - Level rootLevel = manager.getLogLevel(ROOT); - Level logLevel = manager.getLogLevel(LOG); - - // Then - assertThat(rootLevel).isEqualTo(ERROR); - assertThat(logLevel).isEqualTo(ERROR); - } -} diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java index 1fc235ff7..0d95f29fa 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsArguments.java @@ -34,7 +34,7 @@ import software.amazon.lambda.powertools.utilities.JsonConfig; public class PowertoolsArguments implements RequestHandler<SQSEvent.SQSMessage, String> { - private final Logger LOG = LoggerFactory.getLogger(PowertoolsArguments.class); + private static final Logger LOG = LoggerFactory.getLogger(PowertoolsArguments.class); private final ArgumentFormat argumentFormat; public PowertoolsArguments(ArgumentFormat argumentFormat) { diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java index e8c0c5851..0ee7f14fa 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/internal/handler/PowertoolsLogEnabled.java @@ -14,15 +14,17 @@ package software.amazon.lambda.powertools.logging.internal.handler; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + import software.amazon.lambda.powertools.logging.Logging; public class PowertoolsLogEnabled implements RequestHandler<Object, Object> { - private final Logger LOG = LoggerFactory.getLogger(PowertoolsLogEnabled.class); + private static final Logger LOG = LoggerFactory.getLogger(PowertoolsLogEnabled.class); @Override @Logging(clearState = true) diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppenderTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppenderTest.java new file mode 100644 index 000000000..434d3983b --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppenderTest.java @@ -0,0 +1,141 @@ +package software.amazon.lambda.powertools.logging.log4j; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; + +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.Appender; +import org.apache.logging.log4j.core.LoggerContext; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.ClearEnvironmentVariable; + +class BufferingAppenderTest { + + private Logger logger; + + @BeforeEach + void setUp() throws IOException { + logger = LogManager.getLogger(BufferingAppenderTest.class); + + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } + } + + @AfterEach + void cleanUp() throws IOException { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } + + @Test + void shouldBufferDebugLogsAndFlushOnError() { + // When - log debug messages (should be buffered) + logger.debug("Debug message 1"); + logger.debug("Debug message 2"); + + // Then - no logs written yet + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).isEmpty(); + + // When - log error (should flush buffer) + logger.error("Error message"); + + // Then - all logs written + assertThat(contentOf(logFile)) + .contains("Debug message 1") + .contains("Debug message 2") + .contains("Error message"); + } + + @Test + @ClearEnvironmentVariable(key = "_X_AMZN_TRACE_ID") + void shouldLogDirectlyWhenNoTraceId() { + // When + logger.debug("Debug without trace"); + + // Then - log written directly + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("Debug without trace"); + } + + @Test + void shouldNotBufferInfoLogs() { + // When - log info message (above buffer level) + logger.info("Info message"); + + // Then - log written directly + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("Info message"); + } + + @Test + void shouldFlushBufferManually() { + // When - buffer debug logs + logger.debug("Buffered message"); + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).isEmpty(); + + // When - manual flush + BufferingAppender appender = getBufferingAppender(); + appender.flushBuffer(); + + // Then - logs written + assertThat(contentOf(logFile)).contains("Buffered message"); + } + + @Test + void shouldClearBufferManually() { + // When - buffer debug logs then clear + logger.debug("Buffered message"); + BufferingAppender appender = getBufferingAppender(); + appender.clearBuffer(); + + // When - log error (should not flush cleared buffer) + logger.error("Error after clear"); + + // Then - only error logged + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("Error after clear") + .doesNotContain("Buffered message"); + } + + @Test + void shouldLogOverflowWarningWhenBufferOverflows() { + // When - fill buffer beyond capacity to trigger overflow + for (int i = 0; i < 100; i++) { + logger.debug("Debug message {}", i); + } + + // When - flush buffer to trigger overflow warning + BufferingAppender appender = getBufferingAppender(); + appender.flushBuffer(); + + // Then - overflow warning should be logged + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("Some logs are not displayed because they were evicted from the buffer"); + } + + private BufferingAppender getBufferingAppender() { + LoggerContext context = (LoggerContext) LogManager.getContext(false); + Appender appender = context.getConfiguration().getAppender("BufferingAppender"); + if (appender == null) { + throw new IllegalStateException("BufferingAppender not found in configuration. Available appenders: " + + context.getConfiguration().getAppenders().keySet()); + } + return (BufferingAppender) appender; + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jLoggingManagerTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jLoggingManagerTest.java new file mode 100644 index 000000000..16036fe3e --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jLoggingManagerTest.java @@ -0,0 +1,118 @@ +package software.amazon.lambda.powertools.logging.log4j.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; +import static org.slf4j.event.Level.DEBUG; +import static org.slf4j.event.Level.ERROR; +import static org.slf4j.event.Level.WARN; + +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.ConfigurationFactory; +import org.apache.logging.log4j.core.config.ConfigurationSource; +import org.apache.logging.log4j.core.config.Configurator; +import org.apache.logging.log4j.core.config.xml.XmlConfigurationFactory; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.event.Level; + +class Log4jLoggingManagerTest { + + private static final Logger LOG = LoggerFactory.getLogger(Log4jLoggingManagerTest.class); + private static final Logger ROOT = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); + + @BeforeEach + void setUp() { + // Force reconfiguration from XML to ensure clean state + Configurator.reconfigure(); + } + + @Test + void getLogLevel_shouldReturnConfiguredLogLevel() { + // Given log4j2.xml in resources + + // When + Log4jLoggingManager manager = new Log4jLoggingManager(); + Level logLevel = manager.getLogLevel(LOG); + Level rootLevel = manager.getLogLevel(ROOT); + + // Then + assertThat(logLevel).isEqualTo(DEBUG); + assertThat(rootLevel).isEqualTo(WARN); + } + + @Test + void resetLogLevel() { + // Given log4j2.xml in resources + + // When + Log4jLoggingManager manager = new Log4jLoggingManager(); + manager.setLogLevel(ERROR); + + Level rootLevel = manager.getLogLevel(ROOT); + Level logLevel = manager.getLogLevel(LOG); + + // Then + assertThat(rootLevel).isEqualTo(ERROR); + assertThat(logLevel).isEqualTo(ERROR); + } + + @Test + void shouldDetectMultipleBufferingAppendersRegardlessOfName() throws IOException { + // Given - configuration with multiple BufferingAppenders with different names + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } + + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + ConfigurationFactory factory = new XmlConfigurationFactory(); + ConfigurationSource source = new ConfigurationSource( + getClass().getResourceAsStream("/log4j2-multiple-buffering.xml")); + Configuration config = factory.getConfiguration(null, source); + + ctx.setConfiguration(config); + ctx.updateLoggers(); + + org.apache.logging.log4j.Logger logger = LogManager.getLogger("test.multiple.appenders"); + + // When - log messages and flush buffers + logger.debug("Test message 1"); + logger.debug("Test message 2"); + + Log4jLoggingManager manager = new Log4jLoggingManager(); + manager.flushBuffer(); + + // Then - both appenders should have flushed their buffers + File logFile = new File("target/logfile.json"); + assertThat(logFile).exists(); + String content = contentOf(logFile); + // Each message should appear twice (once from each BufferingAppender) + assertThat(content.split("Test message 1", -1)).hasSize(3); // 2 occurrences = 3 parts + assertThat(content.split("Test message 2", -1)).hasSize(3); // 2 occurrences = 3 parts + } + + @AfterEach + void cleanUp() throws IOException { + // Reset to original configuration from XML + Configurator.reconfigure(); + + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there + } + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/test/resources/log4j2-multiple-buffering.xml b/powertools-logging/powertools-logging-log4j/src/test/resources/log4j2-multiple-buffering.xml new file mode 100644 index 000000000..53995e4f5 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/resources/log4j2-multiple-buffering.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <File name="testFile" fileName="target/logfile.json"> + <PatternLayout pattern="%msg%n" /> + </File> + <BufferingAppender name="FirstBufferingAppender" + bufferAtVerbosity="DEBUG" + maxBytes="1024" + flushOnErrorLog="true"> + <AppenderRef ref="testFile" /> + </BufferingAppender> + <BufferingAppender name="SecondBufferingAppender" + bufferAtVerbosity="DEBUG" + maxBytes="1024" + flushOnErrorLog="true"> + <AppenderRef ref="testFile" /> + </BufferingAppender> + </Appenders> + <Loggers> + <Logger name="test.multiple.appenders" level="DEBUG" additivity="false"> + <AppenderRef ref="FirstBufferingAppender" /> + <AppenderRef ref="SecondBufferingAppender" /> + </Logger> + </Loggers> +</Configuration> diff --git a/powertools-logging/powertools-logging-log4j/src/test/resources/log4j2.xml b/powertools-logging/powertools-logging-log4j/src/test/resources/log4j2.xml index 778077bc5..870e3a803 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/resources/log4j2.xml +++ b/powertools-logging/powertools-logging-log4j/src/test/resources/log4j2.xml @@ -10,8 +10,17 @@ <File name="logFileWithEcs" fileName="target/ecslogfile.json"> <JsonTemplateLayout eventTemplateUri="classpath:LambdaEcsLayout.json" /> </File> + <BufferingAppender name="BufferingAppender" + bufferAtVerbosity="DEBUG" + maxBytes="1024" + flushOnErrorLog="true"> + <AppenderRef ref="logFile"/> + </BufferingAppender> </Appenders> - <Loggers>q + <Loggers> + <Logger name="software.amazon.lambda.powertools.logging.log4j.BufferingAppenderTest" level="DEBUG" additivity="false"> + <AppenderRef ref="BufferingAppender"/> + </Logger> <Logger name="software.amazon.lambda.powertools" level="DEBUG" additivity="false"> <AppenderRef ref="logFileWithEcs"/> <AppenderRef ref="logFile"/> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 433a3774a..e2c16019f 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -85,6 +85,11 @@ <artifactId>jsonassert</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.junit-pioneer</groupId> + <artifactId>junit-pioneer</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/BufferingAppender.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/BufferingAppender.java new file mode 100644 index 000000000..8f323ff46 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/BufferingAppender.java @@ -0,0 +1,196 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.logback; + +import java.util.Deque; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.AppenderBase; +import ch.qos.logback.core.spi.AppenderAttachable; +import ch.qos.logback.core.spi.AppenderAttachableImpl; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.logging.internal.BufferManager; +import software.amazon.lambda.powertools.logging.internal.KeyBuffer; + +/** + * A Logback appender that buffers log events by AWS X-Ray trace ID for optimized Lambda logging. + * + * <p>This appender is designed specifically for AWS Lambda functions to reduce log ingestion + * by buffering lower-level logs and only outputting them when errors occur, preserving + * full context for troubleshooting while minimizing routine log volume. + * + * <h3>Key Features:</h3> + * <ul> + * <li><strong>Trace-based buffering:</strong> Groups logs by AWS X-Ray trace ID</li> + * <li><strong>Selective output:</strong> Only buffers logs at or below configured verbosity level</li> + * <li><strong>Auto-flush on errors:</strong> Automatically outputs buffered logs when ERROR/FATAL events occur</li> + * <li><strong>Memory management:</strong> Prevents memory leaks with configurable buffer size limits</li> + * <li><strong>Overflow protection:</strong> Warns when logs are discarded due to buffer limits</li> + * </ul> + * + * <h3>Configuration Example:</h3> + * <pre>{@code + * <appender name="BufferedAppender" class="software.amazon.lambda.powertools.logging.logback.BufferingAppender"> + * <bufferAtVerbosity>DEBUG</bufferAtVerbosity> + * <maxBytes>20480</maxBytes> + * <flushOnErrorLog>true</flushOnErrorLog> + * <appender-ref ref="ConsoleAppender"/> + * </appender> + * }</pre> + * + * <h3>Configuration Parameters:</h3> + * <ul> + * <li><strong>bufferAtVerbosity:</strong> Log level to buffer (default: DEBUG). Logs at this level and below are buffered</li> + * <li><strong>maxBytes:</strong> Maximum buffer size in bytes per trace ID (default: 20480)</li> + * <li><strong>flushOnErrorLog:</strong> Whether to flush buffer on ERROR/FATAL logs (default: true)</li> + * </ul> + * + * <h3>Behavior:</h3> + * <ul> + * <li>During Lambda INIT phase (no trace ID): logs are output directly</li> + * <li>During Lambda execution (with trace ID): logs are buffered or output based on level</li> + * <li>When buffer overflows: oldest logs are discarded and a warning is logged</li> + * <li>On Lambda completion: buffer is auto-cleared when used with {@code @Logging} annotation</li> + * </ul> + * + * @see software.amazon.lambda.powertools.logging.PowertoolsLogging#flushBuffer() + */ +public class BufferingAppender extends AppenderBase<ILoggingEvent> + implements AppenderAttachable<ILoggingEvent>, BufferManager { + + private static final int DEFAULT_BUFFER_SIZE = 20480; + + private final AppenderAttachableImpl<ILoggingEvent> aai = new AppenderAttachableImpl<>(); + private Level bufferAtVerbosity = Level.DEBUG; + private boolean flushOnErrorLog = true; + private int maxBytes = DEFAULT_BUFFER_SIZE; + private KeyBuffer<String, ILoggingEvent> buffer; + + @Override + public void start() { + // Initialize lazily to ensure configuration properties are set first. + if (buffer == null) { + buffer = new KeyBuffer<>(maxBytes, event -> event.getFormattedMessage().length(), this::logOverflowWarning); + } + super.start(); + } + + @Override + protected void append(ILoggingEvent event) { + LambdaHandlerProcessor.getXrayTraceId().ifPresentOrElse( + traceId -> { + if (shouldBuffer(event.getLevel())) { + buffer.add(traceId, event); + } else { + aai.appendLoopOnAppenders(event); + } + + // Flush buffer on error logs if configured + if (flushOnErrorLog && event.getLevel().isGreaterOrEqual(Level.ERROR)) { + flushBuffer(traceId); + } + }, + () -> aai.appendLoopOnAppenders(event) // No trace ID (INIT phase), log directly + ); + } + + private boolean shouldBuffer(Level level) { + return level.levelInt <= bufferAtVerbosity.levelInt; + } + + public void clearBuffer() { + LambdaHandlerProcessor.getXrayTraceId().ifPresent(buffer::clear); + } + + public void flushBuffer() { + LambdaHandlerProcessor.getXrayTraceId().ifPresent(this::flushBuffer); + } + + private void flushBuffer(String traceId) { + Deque<ILoggingEvent> events = buffer.removeAll(traceId); + if (events != null) { + events.forEach(aai::appendLoopOnAppenders); + } + } + + // Configuration setters. These will be inspected as JavaBean properties by Logback + // when configuring the appender via XML or programmatically. They run before start(). + public void setBufferAtVerbosity(String level) { + this.bufferAtVerbosity = Level.toLevel(level, Level.DEBUG); + } + + public void setMaxBytes(int maxBytes) { + this.maxBytes = maxBytes; + } + + public void setFlushOnErrorLog(boolean flushOnErrorLog) { + this.flushOnErrorLog = flushOnErrorLog; + } + + // AppenderAttachable implementation. We simply delegate to the internal logback AppenderAttachableImpl. This is + // needed to be able to attach other appenders to this appender so that customers can wrap existing appenders with + // this buffering appender. + @Override + public void addAppender(Appender<ILoggingEvent> newAppender) { + aai.addAppender(newAppender); + } + + @Override + public java.util.Iterator<Appender<ILoggingEvent>> iteratorForAppenders() { + return aai.iteratorForAppenders(); + } + + @Override + public Appender<ILoggingEvent> getAppender(String name) { + return aai.getAppender(name); + } + + @Override + public boolean isAttached(Appender<ILoggingEvent> appender) { + return aai.isAttached(appender); + } + + @Override + public void detachAndStopAllAppenders() { + aai.detachAndStopAllAppenders(); + } + + @Override + public boolean detachAppender(Appender<ILoggingEvent> appender) { + return aai.detachAppender(appender); + } + + @Override + public boolean detachAppender(String name) { + return aai.detachAppender(name); + } + + private void logOverflowWarning() { + // Create a properly formatted warning event and send directly to child appenders. Used to avoid circular + // dependency between KeyBuffer and BufferingAppender. + Logger logbackLogger = (Logger) org.slf4j.LoggerFactory + .getLogger(BufferingAppender.class); + LoggingEvent warningEvent = new LoggingEvent( + BufferingAppender.class.getName(), logbackLogger, Level.WARN, + "Some logs are not displayed because they were evicted from the buffer. Increase buffer size to store more logs in the buffer.", + null, null); + warningEvent.setTimeStamp(System.currentTimeMillis()); + aai.appendLoopOnAppenders(warningEvent); + } +} diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackLoggingManager.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackLoggingManager.java index 86982b444..906ebdad5 100644 --- a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackLoggingManager.java +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackLoggingManager.java @@ -14,18 +14,29 @@ package software.amazon.lambda.powertools.logging.logback.internal; -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import java.util.List; +import java.util.stream.Collectors; + import org.slf4j.ILoggerFactory; import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Appender; +import software.amazon.lambda.powertools.logging.internal.BufferManager; import software.amazon.lambda.powertools.logging.internal.LoggingManager; +import software.amazon.lambda.powertools.logging.logback.BufferingAppender; /** - * LoggingManager for Logback (see {@link LoggingManager}). + * LoggingManager for Logback that provides log level management and buffer operations. + * Implements both {@link LoggingManager} and {@link BufferManager} interfaces. */ -public class LogbackLoggingManager implements LoggingManager { +public class LogbackLoggingManager implements LoggingManager, BufferManager { private final LoggerContext loggerContext; @@ -56,4 +67,34 @@ public void setLogLevel(org.slf4j.event.Level logLevel) { public org.slf4j.event.Level getLogLevel(org.slf4j.Logger logger) { return org.slf4j.event.Level.valueOf(loggerContext.getLogger(logger.getName()).getEffectiveLevel().toString()); } + + /** + * @inheritDoc + */ + @Override + public void flushBuffer() { + getBufferingAppenders().forEach(BufferingAppender::flushBuffer); + } + + /** + * @inheritDoc + */ + @Override + public void clearBuffer() { + getBufferingAppenders().forEach(BufferingAppender::clearBuffer); + } + + private Collection<BufferingAppender> getBufferingAppenders() { + // Search all buffering appenders to avoid relying on the appender name given by the user + return loggerContext.getLoggerList().stream() + .flatMap(logger -> { + Iterator<Appender<ILoggingEvent>> iterator = logger.iteratorForAppenders(); + List<Appender<ILoggingEvent>> appenders = new ArrayList<>(); + iterator.forEachRemaining(appenders::add); + return appenders.stream(); + }) + .filter(BufferingAppender.class::isInstance) + .map(BufferingAppender.class::cast) + .collect(Collectors.toList()); + } } diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json index 753dafdea..c8b081385 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/jni-config.json @@ -3,18 +3,6 @@ "name":"java.lang.Boolean", "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] }, -{ - "name":"java.lang.String", - "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] -}, -{ - "name":"java.lang.System", - "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] -}, -{ - "name":"org.apache.maven.surefire.booter.ForkedBooter", - "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] -}, { "name":"sun.management.VMManagementImpl", "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json index 683933a77..dfc50427f 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json @@ -1,4 +1,15 @@ [ +{ + "name":"[Ljava.lang.Object;" +}, +{ + "name":"[Ljava.lang.String;" +}, +{ + "name":"ch.qos.logback.classic.encoder.PatternLayoutEncoder", + "queryAllPublicMethods":true, + "methods":[{"name":"<init>","parameterTypes":[] }] +}, { "name":"ch.qos.logback.classic.joran.SerializedModelConfigurator", "methods":[{"name":"<init>","parameterTypes":[] }] @@ -20,6 +31,18 @@ "name":"ch.qos.logback.core.encoder.Encoder", "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] }, +{ + "name":"ch.qos.logback.core.encoder.LayoutWrappingEncoder", + "methods":[{"name":"setParent","parameterTypes":["ch.qos.logback.core.spi.ContextAware"] }] +}, +{ + "name":"ch.qos.logback.core.pattern.PatternLayoutEncoderBase", + "methods":[{"name":"setPattern","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"ch.qos.logback.core.spi.ContextAware", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, { "name":"com.amazonaws.services.lambda.runtime.Context" }, @@ -69,6 +92,10 @@ { "name":"java.lang.Object" }, +{ + "name":"java.lang.ProcessEnvironment", + "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] +}, { "name":"java.lang.String" }, @@ -103,6 +130,10 @@ "queryAllDeclaredMethods":true, "queryAllDeclaredConstructors":true }, +{ + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] +}, { "name":"java.util.List", "queryAllDeclaredMethods":true @@ -135,59 +166,9 @@ "fields":[{"name":"IS_COLD_START"}] }, { - "name":"software.amazon.lambda.powertools.logging.LogbackLoggingManagerTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"getLogLevel_shouldReturnConfiguredLogLevel","parameterTypes":[] }, {"name":"resetLogLevel","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.LambdaEcsEncoderTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"cleanUp","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"shouldLogException","parameterTypes":[] }, {"name":"shouldLogInEcsFormat","parameterTypes":[] }, {"name":"shouldNotLogCloudInfo","parameterTypes":[] }, {"name":"shouldNotLogFunctionInfo","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.LambdaJsonEncoderTest", - "allDeclaredFields":true, - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, + "name":"software.amazon.lambda.powertools.logging.logback.BufferingAppender", "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"cleanUp","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }, {"name":"shouldLogArgumentsAsJsonWhenUsingKeyValue","parameterTypes":[] }, {"name":"shouldLogArgumentsAsJsonWhenUsingRawJson","parameterTypes":[] }, {"name":"shouldLogEventAsStringForStreamHandler","parameterTypes":[] }, {"name":"shouldLogEventForHandlerWhenEnvVariableSetToTrue","parameterTypes":[] }, {"name":"shouldLogEventForHandlerWithLogEventAnnotation","parameterTypes":[] }, {"name":"shouldLogException","parameterTypes":[] }, {"name":"shouldLogInJsonFormat","parameterTypes":[] }, {"name":"shouldLogResponseForHandlerWhenEnvVariableSetToTrue","parameterTypes":[] }, {"name":"shouldLogResponseForHandlerWithLogResponseAnnotation","parameterTypes":[] }, {"name":"shouldLogResponseForStreamHandler","parameterTypes":[] }, {"name":"shouldLogStructuredArgumentsAsNewEntries","parameterTypes":[] }, {"name":"shouldLogThreadInfo","parameterTypes":[] }, {"name":"shouldLogTimestampDifferently","parameterTypes":[] }, {"name":"shouldNotLogEventForHandlerWhenEnvVariableSetToFalse","parameterTypes":[] }, {"name":"shouldNotLogPowertoolsInfo","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments", - "methods":[{"name":"handleRequest","parameterTypes":["com.amazonaws.services.lambda.runtime.events.SQSEvent$SQSMessage","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEvent", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEventDisabled", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEventForStream", - "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogResponse", - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogResponseForStream", - "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"setBufferAtVerbosity","parameterTypes":["java.lang.String"] }, {"name":"setFlushOnErrorLog","parameterTypes":["boolean"] }, {"name":"setMaxBytes","parameterTypes":["int"] }] }, { "name":"software.amazon.lambda.powertools.logging.logback.LambdaEcsEncoder", diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json index 2fc3c56bd..33d1d61c4 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json @@ -4,16 +4,12 @@ "pattern":"\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\E" }, { "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" - }, { - "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" }, { "pattern":"\\QMETA-INF/services/javax.xml.parsers.SAXParserFactory\\E" }, { "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" }, { "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" - }, { - "pattern":"\\Qlogback.scmo\\E" }]}, "bundles":[] } diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/LogbackLoggingManagerTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/LogbackLoggingManagerTest.java index 214057917..60f158739 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/LogbackLoggingManagerTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/LogbackLoggingManagerTest.java @@ -15,15 +15,27 @@ package software.amazon.lambda.powertools.logging; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; import static org.slf4j.event.Level.DEBUG; import static org.slf4j.event.Level.ERROR; import static org.slf4j.event.Level.WARN; -import org.junit.jupiter.api.Order; +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; + +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.event.Level; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; import software.amazon.lambda.powertools.logging.logback.internal.LogbackLoggingManager; class LogbackLoggingManagerTest { @@ -31,8 +43,18 @@ class LogbackLoggingManagerTest { private static final Logger LOG = LoggerFactory.getLogger(LogbackLoggingManagerTest.class); private static final Logger ROOT = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); + @BeforeEach + void setUp() throws JoranException, IOException { + resetLogbackConfig("/logback-test.xml"); + + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } + } + @Test - @Order(1) void getLogLevel_shouldReturnConfiguredLogLevel() { LogbackLoggingManager manager = new LogbackLoggingManager(); Level logLevel = manager.getLogLevel(LOG); @@ -43,7 +65,6 @@ void getLogLevel_shouldReturnConfiguredLogLevel() { } @Test - @Order(2) void resetLogLevel() { LogbackLoggingManager manager = new LogbackLoggingManager(); manager.setLogLevel(ERROR); @@ -51,4 +72,35 @@ void resetLogLevel() { Level logLevel = manager.getLogLevel(LOG); assertThat(logLevel).isEqualTo(ERROR); } + + @Test + void shouldDetectMultipleBufferingAppendersRegardlessOfName() throws JoranException { + // Given - configuration with multiple BufferingAppenders with different names + resetLogbackConfig("/logback-multiple-buffering.xml"); + + Logger logger = LoggerFactory.getLogger("test.multiple.appenders"); + + // When - log messages and flush buffers + logger.debug("Test message 1"); + logger.debug("Test message 2"); + + LogbackLoggingManager manager = new LogbackLoggingManager(); + manager.flushBuffer(); + + // Then - both appenders should have flushed their buffers + File logFile = new File("target/logfile.json"); + assertThat(logFile).exists(); + String content = contentOf(logFile); + // Each message should appear twice (once from each BufferingAppender) + assertThat(content.split("Test message 1", -1)).hasSize(3); // 2 occurrences = 3 parts + assertThat(content.split("Test message 2", -1)).hasSize(3); // 2 occurrences = 3 parts + } + + private void resetLogbackConfig(String configFileName) throws JoranException { + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + context.reset(); + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(context); + configurator.doConfigure(getClass().getResourceAsStream(configFileName)); + } } diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/BufferingAppenderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/BufferingAppenderTest.java new file mode 100644 index 000000000..62d2e3056 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/BufferingAppenderTest.java @@ -0,0 +1,150 @@ +package software.amazon.lambda.powertools.logging.logback; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.contentOf; + +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.ClearEnvironmentVariable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.core.joran.spi.JoranException; + +class BufferingAppenderTest { + + private Logger logger; + + @BeforeEach + void setUp() throws IOException, JoranException { + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } + + // Configure Logback with BufferingAppender + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + context.reset(); + + JoranConfigurator configurator = new JoranConfigurator(); + configurator.setContext(context); + configurator.doConfigure(getClass().getResourceAsStream("/logback-buffering-test.xml")); + + logger = LoggerFactory.getLogger(BufferingAppenderTest.class); + } + + @AfterEach + void cleanUp() throws IOException { + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there + } + } + + @Test + void shouldBufferDebugLogsAndFlushOnError() { + // When - log debug messages (should be buffered) + logger.debug("Debug message 1"); + logger.debug("Debug message 2"); + + // Then - no logs written yet + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).isEmpty(); + + // When - log error (should flush buffer) + logger.error("Error message"); + + // Then - all logs written + assertThat(contentOf(logFile)) + .contains("Debug message 1") + .contains("Debug message 2") + .contains("Error message"); + } + + @Test + @ClearEnvironmentVariable(key = "_X_AMZN_TRACE_ID") + void shouldLogDirectlyWhenNoTraceId() { + // When + logger.debug("Debug without trace"); + + // Then - log written directly + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("Debug without trace"); + } + + @Test + void shouldNotBufferInfoLogs() { + // When - log info message (above buffer level) + logger.info("Info message"); + + // Then - log written directly + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).contains("Info message"); + } + + @Test + void shouldFlushBufferManually() { + // When - buffer debug logs + logger.debug("Buffered message"); + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)).isEmpty(); + + // When - manual flush + BufferingAppender appender = getBufferingAppender(); + appender.flushBuffer(); + + // Then - logs written + assertThat(contentOf(logFile)).contains("Buffered message"); + } + + @Test + void shouldClearBufferManually() { + // When - buffer debug logs then clear + logger.debug("Buffered message"); + BufferingAppender appender = getBufferingAppender(); + appender.clearBuffer(); + + // When - log error (should not flush cleared buffer) + logger.error("Error after clear"); + + // Then - only error logged + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("Error after clear") + .doesNotContain("Buffered message"); + } + + @Test + void shouldLogOverflowWarningWhenBufferOverflows() { + // When - fill buffer beyond capacity to trigger overflow + for (int i = 0; i < 100; i++) { + logger.debug("Debug message {}", i); + } + + // When - flush buffer to trigger overflow warning + BufferingAppender appender = getBufferingAppender(); + appender.flushBuffer(); + + // Then - overflow warning should be logged + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .contains("Some logs are not displayed because they were evicted from the buffer"); + } + + private BufferingAppender getBufferingAppender() { + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + return (BufferingAppender) context.getLogger(BufferingAppenderTest.class).getAppender("TestBufferingAppender"); + } +} diff --git a/powertools-logging/powertools-logging-logback/src/test/resources/logback-buffering-test.xml b/powertools-logging/powertools-logging-logback/src/test/resources/logback-buffering-test.xml new file mode 100644 index 000000000..b9ec3917f --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/resources/logback-buffering-test.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + <appender name="testFile" class="ch.qos.logback.core.FileAppender"> + <file>target/logfile.json</file> + <encoder> + <pattern>%msg%n</pattern> + </encoder> + </appender> + + <appender name="TestBufferingAppender" class="software.amazon.lambda.powertools.logging.logback.BufferingAppender"> + <bufferAtVerbosity>DEBUG</bufferAtVerbosity> + <maxBytes>1024</maxBytes> + <flushOnErrorLog>true</flushOnErrorLog> + <appender-ref ref="testFile" /> + </appender> + + <logger name="software.amazon.lambda.powertools.logging.logback.BufferingAppenderTest" level="DEBUG" + additivity="false"> + <appender-ref ref="TestBufferingAppender" /> + </logger> +</configuration> diff --git a/powertools-logging/powertools-logging-logback/src/test/resources/logback-multiple-buffering.xml b/powertools-logging/powertools-logging-logback/src/test/resources/logback-multiple-buffering.xml new file mode 100644 index 000000000..84c348d61 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/resources/logback-multiple-buffering.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + <appender name="testFile" class="ch.qos.logback.core.FileAppender"> + <file>target/logfile.json</file> + <encoder> + <pattern>%msg%n</pattern> + </encoder> + </appender> + + <appender name="FirstBufferingAppender" class="software.amazon.lambda.powertools.logging.logback.BufferingAppender"> + <bufferAtVerbosity>DEBUG</bufferAtVerbosity> + <maxBytes>1024</maxBytes> + <flushOnErrorLog>true</flushOnErrorLog> + <appender-ref ref="testFile" /> + </appender> + + <appender name="SecondBufferingAppender" class="software.amazon.lambda.powertools.logging.logback.BufferingAppender"> + <bufferAtVerbosity>DEBUG</bufferAtVerbosity> + <maxBytes>1024</maxBytes> + <flushOnErrorLog>true</flushOnErrorLog> + <appender-ref ref="testFile" /> + </appender> + + <logger name="test.multiple.appenders" level="DEBUG" additivity="false"> + <appender-ref ref="FirstBufferingAppender" /> + <appender-ref ref="SecondBufferingAppender" /> + </logger> +</configuration> diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java index 9e5e735d1..79d1a95fd 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/Logging.java @@ -72,7 +72,7 @@ /** * Set to true if you want to log the response sent by the Lambda function handler.<br/> - * Can also be configured with the 'POWERTOOLS_LOGGER_LOG_RESPONE' environment variable + * Can also be configured with the 'POWERTOOLS_LOGGER_LOG_RESPONSE' environment variable */ boolean logResponse() default false; @@ -102,4 +102,10 @@ * Set this attribute to true if you want all custom keys to be deleted on each request. */ boolean clearState() default false; + + /** + * Set to true if you want to flush the log buffer when an uncaught exception occurs. + * This ensures that buffered logs are output when errors happen. + */ + boolean flushBufferOnUncaughtError() default true; } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/PowertoolsLogging.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/PowertoolsLogging.java new file mode 100644 index 000000000..1276c2a87 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/PowertoolsLogging.java @@ -0,0 +1,55 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging; + +import software.amazon.lambda.powertools.logging.internal.BufferManager; +import software.amazon.lambda.powertools.logging.internal.LoggingManager; +import software.amazon.lambda.powertools.logging.internal.LoggingManagerRegistry; + +/** + * PowertoolsLogging provides a backend-independent API for log buffering operations. + * This class abstracts away the underlying logging framework (Log4j2, Logback) and + * provides a unified interface for buffer management. + */ +public final class PowertoolsLogging { + + private PowertoolsLogging() { + // Utility class + } + + /** + * Flushes the log buffer for the current Lambda execution. + * This method will flush any buffered logs to the output stream. + * The operation is backend-independent and works with both Log4j2 and Logback. + */ + public static void flushBuffer() { + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + if (loggingManager instanceof BufferManager) { + ((BufferManager) loggingManager).flushBuffer(); + } + } + + /** + * Clears the log buffer for the current Lambda execution. + * This method will discard any buffered logs without outputting them. + * The operation is backend-independent and works with both Log4j2 and Logback. + */ + public static void clearBuffer() { + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + if (loggingManager instanceof BufferManager) { + ((BufferManager) loggingManager).clearBuffer(); + } + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/BufferManager.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/BufferManager.java new file mode 100644 index 000000000..d81d1fd31 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/BufferManager.java @@ -0,0 +1,33 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +/** + * Interface for logging managers that support buffer operations. + * This extends the logging framework capabilities with buffer-specific functionality. + */ +public interface BufferManager { + /** + * Flushes the log buffer for the current Lambda execution. + * This method will flush any buffered logs to the target appender. + */ + void flushBuffer(); + + /** + * Clears the log buffer for the current Lambda execution. + * This method will discard any buffered logs without outputting them. + */ + void clearBuffer(); +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefautlLoggingManager.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefaultLoggingManager.java similarity index 94% rename from powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefautlLoggingManager.java rename to powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefaultLoggingManager.java index 5326f53e6..ed2c14c38 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefautlLoggingManager.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/DefaultLoggingManager.java @@ -21,7 +21,7 @@ * When no LoggingManager is found, setting a default one with no action on logging implementation * Powertools cannot change the log level based on the environment variable, will use the logger configuration */ -public class DefautlLoggingManager implements LoggingManager { +public class DefaultLoggingManager implements LoggingManager { @Override public void setLogLevel(Level logLevel) { diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/KeyBuffer.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/KeyBuffer.java new file mode 100644 index 000000000..3510a544d --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/KeyBuffer.java @@ -0,0 +1,95 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; + +/** + * Thread-safe buffer that stores events by key with size-based eviction. + * + * <p>Maintains separate queues per key. When buffer size exceeds maxBytes, + * oldest events are evicted FIFO. Events larger than maxBytes are rejected. + * + * @param <K> key type for buffering + * @param <T> event type to buffer + */ +public class KeyBuffer<K, T> { + + private final Map<K, Deque<T>> keyBufferCache = new ConcurrentHashMap<>(); + private final Map<K, Boolean> overflowTriggered = new ConcurrentHashMap<>(); + private final int maxBytes; + private final Function<T, Integer> sizeCalculator; + private final Runnable overflowWarningLogger; + + @SuppressWarnings("java:S106") // Using System.err to avoid circular dependency with logging implementation + public KeyBuffer(int maxBytes, Function<T, Integer> sizeCalculator) { + this(maxBytes, sizeCalculator, () -> System.err.println("WARN [" + KeyBuffer.class.getSimpleName() + + "] - Some logs are not displayed because they were evicted from the buffer. Increase buffer size to store more logs in the buffer.")); + } + + public KeyBuffer(int maxBytes, Function<T, Integer> sizeCalculator, Runnable overflowWarningLogger) { + this.maxBytes = maxBytes; + this.sizeCalculator = sizeCalculator; + this.overflowWarningLogger = overflowWarningLogger; + } + + public void add(K key, T event) { + int eventSize = sizeCalculator.apply(event); + // Immediately reject events larger than the whole buffer-size to avoid evicting all elements. + if (eventSize > maxBytes) { + overflowTriggered.put(key, true); + return; + } + + Deque<T> buffer = keyBufferCache.computeIfAbsent(key, k -> new ArrayDeque<>()); + synchronized (buffer) { + buffer.add(event); + while (getBufferSize(buffer) > maxBytes && !buffer.isEmpty()) { + overflowTriggered.put(key, true); + buffer.removeFirst(); + } + } + } + + public Deque<T> removeAll(K key) { + logOverflowWarningIfNeeded(key); + Deque<T> buffer = keyBufferCache.remove(key); + if (buffer != null) { + synchronized (buffer) { + return new ArrayDeque<>(buffer); + } + } + return buffer; + } + + public void clear(K key) { + keyBufferCache.remove(key); + overflowTriggered.remove(key); + } + + private void logOverflowWarningIfNeeded(K key) { + if (Boolean.TRUE.equals(overflowTriggered.remove(key))) { + overflowWarningLogger.run(); + } + } + + private int getBufferSize(Deque<T> buffer) { + return buffer.stream().mapToInt(sizeCalculator::apply).sum(); + } +} diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java index eccfdae4f..591283996 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java @@ -35,9 +35,6 @@ import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SERVICE; -import com.amazonaws.services.lambda.runtime.Context; -import com.fasterxml.jackson.databind.JsonNode; -import io.burt.jmespath.Expression; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -45,14 +42,10 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.io.PrintStream; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; +import java.util.Locale; import java.util.Random; -import java.util.ServiceLoader; + import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @@ -63,10 +56,14 @@ import org.slf4j.MDC; import org.slf4j.MarkerFactory; import org.slf4j.event.Level; + +import com.amazonaws.services.lambda.runtime.Context; +import com.fasterxml.jackson.databind.JsonNode; + +import io.burt.jmespath.Expression; import software.amazon.lambda.powertools.logging.Logging; import software.amazon.lambda.powertools.utilities.JsonConfig; - @Aspect @DeclarePrecedence("*, software.amazon.lambda.powertools.logging.internal.LambdaLoggingAspect") public final class LambdaLoggingAspect { @@ -77,7 +74,7 @@ public final class LambdaLoggingAspect { private static final LoggingManager LOGGING_MANAGER; static { - LOGGING_MANAGER = getLoggingManagerFromServiceLoader(); + LOGGING_MANAGER = LoggingManagerRegistry.getLoggingManager(); setLogLevel(); @@ -90,7 +87,8 @@ static void setLogLevel() { if (LAMBDA_LOG_LEVEL != null) { Level lambdaLevel = getLevelFromString(LAMBDA_LOG_LEVEL); if (powertoolsLevel.toInt() < lambdaLevel.toInt()) { - LOG.warn("Current log level ({}) does not match AWS Lambda Advanced Logging Controls minimum log level ({}). This can lead to data loss, consider adjusting them.", + LOG.warn( + "Current log level ({}) does not match AWS Lambda Advanced Logging Controls minimum log level ({}). This can lead to data loss, consider adjusting them.", POWERTOOLS_LOG_LEVEL, LAMBDA_LOG_LEVEL); } } @@ -102,7 +100,7 @@ static void setLogLevel() { private static Level getLevelFromString(String level) { if (Arrays.stream(Level.values()).anyMatch(slf4jLevel -> slf4jLevel.name().equalsIgnoreCase(level))) { - return Level.valueOf(level.toUpperCase()); + return Level.valueOf(level.toUpperCase(Locale.ROOT)); } else { // FATAL does not exist in slf4j if ("FATAL".equalsIgnoreCase(level)) { @@ -113,60 +111,14 @@ private static Level getLevelFromString(String level) { return Level.INFO; } - /** - * Use {@link ServiceLoader} to lookup for a {@link LoggingManager}. - * A file <i>software.amazon.lambda.powertools.logging.internal.LoggingManager</i> must be created in - * <i>META-INF/services/</i> folder with the appropriate implementation of the {@link LoggingManager} - * - * @return an instance of {@link LoggingManager} - * @throws IllegalStateException if no {@link LoggingManager} could be found - */ - @SuppressWarnings("java:S106") // S106: System.err is used rather than logger to make sure message is printed - private static LoggingManager getLoggingManagerFromServiceLoader() { - ServiceLoader<LoggingManager> loggingManagers; - SecurityManager securityManager = System.getSecurityManager(); - if (securityManager == null) { - loggingManagers = ServiceLoader.load(LoggingManager.class); - } else { - final PrivilegedAction<ServiceLoader<LoggingManager>> action = () -> ServiceLoader.load(LoggingManager.class); - loggingManagers = AccessController.doPrivileged(action); - } - - List<LoggingManager> loggingManagerList = new ArrayList<>(); - for (LoggingManager lm : loggingManagers) { - loggingManagerList.add(lm); - } - return getLoggingManager(loggingManagerList, System.err); - } - - static LoggingManager getLoggingManager(List<LoggingManager> loggingManagerList, PrintStream printStream) { - LoggingManager loggingManager; - if (loggingManagerList.isEmpty()) { - printStream.println("ERROR. No LoggingManager was found on the classpath"); - printStream.println("ERROR. Applying default LoggingManager: POWERTOOLS_LOG_LEVEL variable is ignored"); - printStream.println("ERROR. Make sure to add either powertools-logging-log4j or powertools-logging-logback to your dependencies"); - loggingManager = new DefautlLoggingManager(); - } else { - if (loggingManagerList.size() > 1) { - printStream.println("WARN. Multiple LoggingManagers were found on the classpath"); - for (LoggingManager manager : loggingManagerList) { - printStream.println("WARN. Found LoggingManager: [" + manager + "]"); - } - printStream.println("WARN. Make sure to have only one of powertools-logging-log4j OR powertools-logging-logback to your dependencies"); - printStream.println("WARN. Using the first LoggingManager found on the classpath: [" + loggingManagerList.get(0) + "]"); - } - loggingManager = loggingManagerList.get(0); - } - return loggingManager; - } - private static void setLogLevels(Level logLevel) { LOGGING_MANAGER.setLogLevel(logLevel); } - @SuppressWarnings({"EmptyMethod"}) + @SuppressWarnings({ "EmptyMethod" }) @Pointcut("@annotation(logging)") public void callAt(Logging logging) { + // Pointcut method - body intentionally empty } /** @@ -174,69 +126,51 @@ public void callAt(Logging logging) { */ @Around(value = "callAt(logging) && execution(@Logging * *.*(..))", argNames = "pjp,logging") public Object around(ProceedingJoinPoint pjp, - Logging logging) throws Throwable { + Logging logging) throws Throwable { boolean isOnRequestHandler = placedOnRequestHandler(pjp); boolean isOnRequestStreamHandler = placedOnStreamHandler(pjp); setLogLevelBasedOnSamplingRate(pjp, logging); - addLambdaContextToLoggingContext(pjp); - getXrayTraceId().ifPresent(xRayTraceId -> MDC.put(FUNCTION_TRACE_ID.getName(), xRayTraceId)); - // Log Event Object[] proceedArgs = logEvent(pjp, logging, isOnRequestHandler, isOnRequestStreamHandler); if (!logging.correlationIdPath().isEmpty()) { - captureCorrelationId(logging.correlationIdPath(), proceedArgs, isOnRequestHandler, isOnRequestStreamHandler); + captureCorrelationId(logging.correlationIdPath(), proceedArgs, isOnRequestHandler, + isOnRequestStreamHandler); } - // To log the result of a RequestStreamHandler (OutputStream), we need to do the following: - // 1. backup a reference to the OutputStream provided by Lambda - // 2. create a temporary OutputStream and pass it to the handler method - // 3. retrieve this temporary stream to log it (if enabled) - // 4. write it back to the OutputStream provided by Lambda + @SuppressWarnings("PMD.CloseResource") // Lambda-owned stream, not ours to close OutputStream backupOutputStream = null; - if ((logging.logResponse() || POWERTOOLS_LOG_RESPONSE) && isOnRequestStreamHandler) { - backupOutputStream = (OutputStream) proceedArgs[1]; - proceedArgs[1] = new ByteArrayOutputStream(); + if (isOnRequestStreamHandler) { + // To log the result of a RequestStreamHandler (OutputStream), we need to do the following: + // 1. backup a reference to the OutputStream provided by Lambda + // 2. create a temporary OutputStream and pass it to the handler method + // 3. retrieve this temporary stream to log it (if enabled) + // 4. write it back to the OutputStream provided by Lambda + backupOutputStream = prepareOutputStreamForLogging(logging, proceedArgs); } Object lambdaFunctionResponse; - try { - // Call Function Handler lambdaFunctionResponse = pjp.proceed(proceedArgs); - } catch (Throwable t) { - if (logging.logError() || POWERTOOLS_LOG_ERROR) { - // logging the exception with additional context - logger(pjp).error(MarkerFactory.getMarker("FATAL"), "Exception in Lambda Handler", t); - } + } catch (Throwable t) { // NOPMD - AspectJ proceed() throws Throwable + handleException(pjp, logging, t); throw t; } finally { - if (logging.clearState()) { - MDC.clear(); - } - coldStartDone(); + performCleanup(logging); } - // Log Response - if ((logging.logResponse() || POWERTOOLS_LOG_RESPONSE)) { - if (isOnRequestHandler) { - logRequestHandlerResponse(pjp, lambdaFunctionResponse); - } else if (isOnRequestStreamHandler && backupOutputStream != null) { - byte[] bytes = ((ByteArrayOutputStream)proceedArgs[1]).toByteArray(); - logRequestStreamHandlerResponse(pjp, bytes); - backupOutputStream.write(bytes); - } - } + logResponse(pjp, logging, lambdaFunctionResponse, isOnRequestHandler, isOnRequestStreamHandler, + backupOutputStream, proceedArgs); return lambdaFunctionResponse; } private Object[] logEvent(ProceedingJoinPoint pjp, Logging logging, - boolean isOnRequestHandler, boolean isOnRequestStreamHandler) { + boolean isOnRequestHandler, boolean isOnRequestStreamHandler) { Object[] proceedArgs = pjp.getArgs(); if (logging.logEvent() || POWERTOOLS_LOG_EVENT) { @@ -260,7 +194,7 @@ private void addLambdaContextToLoggingContext(ProceedingJoinPoint pjp) { } private void setLogLevelBasedOnSamplingRate(final ProceedingJoinPoint pjp, - final Logging logging) { + final Logging logging) { double samplingRate = samplingRate(logging); if (isHandlerMethod(pjp)) { @@ -346,9 +280,9 @@ private void logRequestStreamHandlerResponse(final ProceedingJoinPoint pjp, fina } private void captureCorrelationId(final String correlationIdPath, - Object[] proceedArgs, - final boolean isOnRequestHandler, - final boolean isOnRequestStreamHandler) { + Object[] proceedArgs, + final boolean isOnRequestHandler, + final boolean isOnRequestStreamHandler) { if (isOnRequestHandler) { JsonNode jsonNode = JsonConfig.get().getObjectMapper().valueToTree(proceedArgs[0]); setCorrelationIdFromNode(correlationIdPath, jsonNode); @@ -377,11 +311,10 @@ private void setCorrelationIdFromNode(String correlationIdPath, JsonNode jsonNod } } - private byte[] bytesFromInputStreamSafely(final InputStream inputStream) throws IOException { try (ByteArrayOutputStream out = new ByteArrayOutputStream(); - InputStreamReader reader = new InputStreamReader(inputStream, UTF_8)) { - OutputStreamWriter writer = new OutputStreamWriter(out, UTF_8); + InputStreamReader reader = new InputStreamReader(inputStream, UTF_8); + OutputStreamWriter writer = new OutputStreamWriter(out, UTF_8)) { int n; char[] buffer = new char[4096]; while (-1 != (n = reader.read(buffer))) { @@ -392,6 +325,53 @@ private byte[] bytesFromInputStreamSafely(final InputStream inputStream) throws } } + private OutputStream prepareOutputStreamForLogging(Logging logging, + Object[] proceedArgs) { + if (logging.logResponse() || POWERTOOLS_LOG_RESPONSE) { + OutputStream backupOutputStream = (OutputStream) proceedArgs[1]; + proceedArgs[1] = new ByteArrayOutputStream(); + return backupOutputStream; + } + return null; + } + + private void handleException(ProceedingJoinPoint pjp, Logging logging, Throwable t) { + if (LOGGING_MANAGER instanceof BufferManager) { + if (logging.flushBufferOnUncaughtError()) { + ((BufferManager) LOGGING_MANAGER).flushBuffer(); + } else { + ((BufferManager) LOGGING_MANAGER).clearBuffer(); + } + } + if (logging.logError() || POWERTOOLS_LOG_ERROR) { + logger(pjp).error(MarkerFactory.getMarker("FATAL"), "Exception in Lambda Handler", t); + } + } + + private void performCleanup(Logging logging) { + if (logging.clearState()) { + MDC.clear(); + } + if (LOGGING_MANAGER instanceof BufferManager) { + ((BufferManager) LOGGING_MANAGER).clearBuffer(); + } + coldStartDone(); + } + + private void logResponse(ProceedingJoinPoint pjp, Logging logging, Object lambdaFunctionResponse, + boolean isOnRequestHandler, boolean isOnRequestStreamHandler, + OutputStream backupOutputStream, Object[] proceedArgs) throws IOException { + if (logging.logResponse() || POWERTOOLS_LOG_RESPONSE) { + if (isOnRequestHandler) { + logRequestHandlerResponse(pjp, lambdaFunctionResponse); + } else if (isOnRequestStreamHandler && backupOutputStream != null) { + byte[] bytes = ((ByteArrayOutputStream) proceedArgs[1]).toByteArray(); + logRequestStreamHandlerResponse(pjp, bytes); + backupOutputStream.write(bytes); + } + } + } + private Logger logger(final ProceedingJoinPoint pjp) { return LoggerFactory.getLogger(pjp.getSignature().getDeclaringType()); } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingManagerRegistry.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingManagerRegistry.java new file mode 100644 index 000000000..463981903 --- /dev/null +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingManagerRegistry.java @@ -0,0 +1,99 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import java.io.PrintStream; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; +import java.util.ServiceLoader; + +/** + * Thread-safe singleton registry for LoggingManager instances. + * Handles lazy loading and caching of the LoggingManager implementation. + */ +public final class LoggingManagerRegistry { + + // Used with double-checked locking within getLoggingManger() + @SuppressWarnings({ "java:S3077", "PMD.AvoidUsingVolatile" }) + private static volatile LoggingManager instance; + + private LoggingManagerRegistry() { + // Utility class + } + + /** + * Gets the LoggingManager instance, loading it lazily on first access. + * + * @return the LoggingManager instance + */ + public static LoggingManager getLoggingManager() { + LoggingManager manager = instance; + if (manager == null) { + synchronized (LoggingManagerRegistry.class) { + manager = instance; + if (manager == null) { + manager = loadLoggingManager(); + instance = manager; + } + } + } + return manager; + } + + @SuppressWarnings("java:S106") // S106: System.err is used rather than logger to make sure message is printed + private static LoggingManager loadLoggingManager() { + ServiceLoader<LoggingManager> loggingManagers; + SecurityManager securityManager = System.getSecurityManager(); + if (securityManager == null) { + loggingManagers = ServiceLoader.load(LoggingManager.class); + } else { + final PrivilegedAction<ServiceLoader<LoggingManager>> action = () -> ServiceLoader + .load(LoggingManager.class); + loggingManagers = AccessController.doPrivileged(action); + } + + List<LoggingManager> loggingManagerList = new ArrayList<>(); + for (LoggingManager lm : loggingManagers) { + loggingManagerList.add(lm); + } + return selectLoggingManager(loggingManagerList, System.err); + } + + static LoggingManager selectLoggingManager(List<LoggingManager> loggingManagerList, PrintStream printStream) { + LoggingManager loggingManager; + if (loggingManagerList.isEmpty()) { + printStream.println("ERROR. No LoggingManager was found on the classpath"); + printStream.println("ERROR. Applying default LoggingManager: POWERTOOLS_LOG_LEVEL variable is ignored"); + printStream.println( + "ERROR. Make sure to add either powertools-logging-log4j or powertools-logging-logback to your dependencies"); + loggingManager = new DefaultLoggingManager(); + } else { + if (loggingManagerList.size() > 1) { + printStream.println("WARN. Multiple LoggingManagers were found on the classpath"); + for (LoggingManager manager : loggingManagerList) { + printStream.println("WARN. Found LoggingManager: [" + manager + "]"); + } + printStream.println( + "WARN. Make sure to have only one of powertools-logging-log4j OR powertools-logging-logback in your dependencies"); + printStream.println("WARN. Using the first LoggingManager found on the classpath: [" + + loggingManagerList.get(0) + "]"); + } + loggingManager = loggingManagerList.get(0); + } + return loggingManager; + } +} diff --git a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/jni-config.json b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/jni-config.json index 2c4de0562..c8b081385 100644 --- a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/jni-config.json +++ b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/jni-config.json @@ -3,22 +3,6 @@ "name":"java.lang.Boolean", "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] }, -{ - "name":"java.lang.String", - "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] -}, -{ - "name":"java.lang.System", - "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] -}, -{ - "name":"org.apache.maven.surefire.booter.ForkedBooter", - "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] -}, -{ - "name":"sun.instrument.InstrumentationImpl", - "methods":[{"name":"<init>","parameterTypes":["long","boolean","boolean","boolean"] }, {"name":"loadClassAndCallAgentmain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"loadClassAndCallPremain","parameterTypes":["java.lang.String","java.lang.String"] }, {"name":"transform","parameterTypes":["java.lang.Module","java.lang.ClassLoader","java.lang.String","java.lang.Class","java.security.ProtectionDomain","byte[]","boolean"] }] -}, { "name":"sun.management.VMManagementImpl", "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] diff --git a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json index 7347b8400..4c66ebd97 100644 --- a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json +++ b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json @@ -23,21 +23,7 @@ "methods":[{"name":"<init>","parameterTypes":[] }] }, { - "name":"com.amazonaws.services.lambda.runtime.Context", - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"getAwsRequestId","parameterTypes":[] }, {"name":"getClientContext","parameterTypes":[] }, {"name":"getFunctionName","parameterTypes":[] }, {"name":"getFunctionVersion","parameterTypes":[] }, {"name":"getIdentity","parameterTypes":[] }, {"name":"getInvokedFunctionArn","parameterTypes":[] }, {"name":"getLogGroupName","parameterTypes":[] }, {"name":"getLogStreamName","parameterTypes":[] }, {"name":"getLogger","parameterTypes":[] }, {"name":"getMemoryLimitInMB","parameterTypes":[] }, {"name":"getRemainingTimeInMillis","parameterTypes":[] }] -}, -{ - "name":"com.amazonaws.services.lambda.runtime.RequestHandler", - "allDeclaredClasses":true, - "queryAllPublicMethods":true -}, -{ - "name":"com.amazonaws.services.lambda.runtime.RequestStreamHandler", - "allDeclaredClasses":true, - "queryAllPublicMethods":true + "name":"com.amazonaws.services.lambda.runtime.Context" }, { "name":"com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", @@ -129,6 +115,7 @@ "name":"com.amazonaws.services.lambda.runtime.tests.EventArgumentsProvider", "queryAllDeclaredMethods":true, "queryAllPublicMethods":true, + "queryAllDeclaredConstructors":true, "methods":[{"name":"<init>","parameterTypes":[] }] }, { @@ -139,9 +126,6 @@ "name":"com.fasterxml.jackson.databind.ext.Java7SupportImpl", "methods":[{"name":"<init>","parameterTypes":[] }] }, -{ - "name":"com.sun.tools.attach.VirtualMachine" -}, { "name":"double", "queryAllDeclaredMethods":true @@ -159,137 +143,43 @@ "name":"java.io.Serializable", "allDeclaredClasses":true, "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "queryAllDeclaredConstructors":true + "queryAllPublicMethods":true }, { "name":"java.lang.Boolean" }, -{ - "name":"java.lang.Class", - "methods":[{"name":"forName","parameterTypes":["java.lang.String"] }, {"name":"getAnnotatedInterfaces","parameterTypes":[] }, {"name":"getAnnotatedSuperclass","parameterTypes":[] }, {"name":"getDeclaredMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getMethod","parameterTypes":["java.lang.String","java.lang.Class[]"] }, {"name":"getModule","parameterTypes":[] }, {"name":"getNestHost","parameterTypes":[] }, {"name":"getNestMembers","parameterTypes":[] }, {"name":"getPermittedSubclasses","parameterTypes":[] }, {"name":"getRecordComponents","parameterTypes":[] }, {"name":"isNestmateOf","parameterTypes":["java.lang.Class"] }, {"name":"isRecord","parameterTypes":[] }, {"name":"isSealed","parameterTypes":[] }] -}, -{ - "name":"java.lang.ClassLoader", - "methods":[{"name":"getDefinedPackage","parameterTypes":["java.lang.String"] }, {"name":"getUnnamedModule","parameterTypes":[] }, {"name":"registerAsParallelCapable","parameterTypes":[] }] -}, { "name":"java.lang.Cloneable", "queryAllDeclaredMethods":true }, { - "name":"java.lang.Comparable", - "allDeclaredClasses":true, - "queryAllPublicMethods":true -}, -{ - "name":"java.lang.Enum", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"java.lang.Module", - "methods":[{"name":"addExports","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"addReads","parameterTypes":["java.lang.Module"] }, {"name":"canRead","parameterTypes":["java.lang.Module"] }, {"name":"getClassLoader","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPackages","parameterTypes":[] }, {"name":"getResourceAsStream","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String"] }, {"name":"isExported","parameterTypes":["java.lang.String","java.lang.Module"] }, {"name":"isNamed","parameterTypes":[] }, {"name":"isOpen","parameterTypes":["java.lang.String","java.lang.Module"] }] -}, -{ - "name":"java.lang.Object", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"clone","parameterTypes":[] }, {"name":"getClass","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] + "name":"java.lang.Object" }, { "name":"java.lang.ProcessEnvironment", "fields":[{"name":"theCaseInsensitiveEnvironment"}, {"name":"theEnvironment"}] }, { - "name":"java.lang.ProcessHandle", - "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] -}, -{ - "name":"java.lang.Runtime", - "methods":[{"name":"version","parameterTypes":[] }] + "name":"java.lang.String" }, { - "name":"java.lang.Runtime$Version", - "methods":[{"name":"feature","parameterTypes":[] }] -}, -{ - "name":"java.lang.StackWalker" -}, -{ - "name":"java.lang.System", - "methods":[{"name":"getSecurityManager","parameterTypes":[] }] -}, -{ - "name":"java.lang.annotation.Retention", - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true + "name":"java.util.AbstractMap", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true }, { - "name":"java.lang.annotation.Target", + "name":"java.util.Collections$SingletonMap", + "allDeclaredFields":true, "queryAllDeclaredMethods":true, "queryAllDeclaredConstructors":true }, -{ - "name":"java.lang.constant.Constable", - "allDeclaredClasses":true, - "queryAllPublicMethods":true -}, -{ - "name":"java.lang.invoke.MethodHandle", - "methods":[{"name":"bindTo","parameterTypes":["java.lang.Object"] }, {"name":"invokeWithArguments","parameterTypes":["java.lang.Object[]"] }] -}, -{ - "name":"java.lang.invoke.MethodHandles", - "methods":[{"name":"lookup","parameterTypes":[] }] -}, -{ - "name":"java.lang.invoke.MethodHandles$Lookup", - "methods":[{"name":"findVirtual","parameterTypes":["java.lang.Class","java.lang.String","java.lang.invoke.MethodType"] }] -}, -{ - "name":"java.lang.invoke.MethodType", - "methods":[{"name":"methodType","parameterTypes":["java.lang.Class","java.lang.Class[]"] }] -}, -{ - "name":"java.lang.reflect.AccessibleObject", - "methods":[{"name":"setAccessible","parameterTypes":["boolean"] }] -}, -{ - "name":"java.lang.reflect.AnnotatedArrayType", - "methods":[{"name":"getAnnotatedGenericComponentType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.AnnotatedType", - "methods":[{"name":"getType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.Executable", - "methods":[{"name":"getAnnotatedExceptionTypes","parameterTypes":[] }, {"name":"getAnnotatedParameterTypes","parameterTypes":[] }, {"name":"getAnnotatedReceiverType","parameterTypes":[] }, {"name":"getParameterCount","parameterTypes":[] }, {"name":"getParameters","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.Method", - "methods":[{"name":"getAnnotatedReturnType","parameterTypes":[] }] -}, -{ - "name":"java.lang.reflect.Parameter", - "methods":[{"name":"getModifiers","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"isNamePresent","parameterTypes":[] }] -}, -{ - "name":"java.security.AccessController", - "methods":[{"name":"doPrivileged","parameterTypes":["java.security.PrivilegedAction"] }, {"name":"doPrivileged","parameterTypes":["java.security.PrivilegedExceptionAction"] }] -}, { "name":"java.util.Collections$UnmodifiableMap", "fields":[{"name":"m"}] }, { - "name":"java.util.Map" -}, -{ - "name":"java.util.concurrent.ForkJoinTask", - "fields":[{"name":"aux"}, {"name":"status"}] + "name":"java.util.Map", + "queryAllDeclaredMethods":true }, { "name":"java.util.concurrent.atomic.AtomicBoolean", @@ -303,22 +193,10 @@ "name":"java.util.function.Consumer", "queryAllPublicMethods":true }, -{ - "name":"jdk.internal.misc.Unsafe" -}, -{ - "name":"kotlin.jvm.JvmInline" -}, { "name":"org.apiguardian.api.API", "queryAllPublicMethods":true }, -{ - "name":"org.aspectj.runtime.internal.AroundClosure", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, { "name":"org.joda.time.DateTime" }, @@ -349,42 +227,6 @@ "allDeclaredClasses":true, "queryAllPublicMethods":true }, -{ - "name":"org.slf4j.test.OutputChoice", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"org.slf4j.test.OutputChoice$OutputChoiceType", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"org.slf4j.test.TestLogger", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"org.slf4j.test.TestLoggerConfiguration", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"org.slf4j.test.TestLoggerFactory", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"org.slf4j.test.TestServiceProvider", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, { "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", "fields":[{"name":"IS_COLD_START"}, {"name":"SERVICE_NAME"}] @@ -396,232 +238,11 @@ "queryAllDeclaredMethods":true, "queryAllPublicMethods":true, "queryAllDeclaredConstructors":true, - "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"arrayArgument","parameterTypes":[] }, {"name":"jsonArgument","parameterTypes":[] }, {"name":"keyValueArgument","parameterTypes":[] }, {"name":"mapArgument","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["com.amazonaws.services.lambda.runtime.events.ApplicationLoadBalancerRequestEvent","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayRestApiCorrelationId", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayRestApiCorrelationId$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAppSyncCorrelationId", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAppSyncCorrelationId$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogClearState", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.util.Map","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogClearState$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogDisabled", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogDisabledForStream", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabled", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"anotherMethod","parameterTypes":[] }, {"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabled$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabled$AjcClosure3", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabledForStream", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabledForStream$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogError", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogError$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEvent", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEvent$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventBridgeCorrelationId", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] + "methods":[{"name":"<init>","parameterTypes":[] }, {"name":"arrayArgument","parameterTypes":[] }, {"name":"emptyMapArgument","parameterTypes":[] }, {"name":"jsonArgument","parameterTypes":[] }, {"name":"keyValueArgument","parameterTypes":[] }, {"name":"mapArgument","parameterTypes":[] }, {"name":"reservedKeywordArgumentIgnored","parameterTypes":[] }, {"name":"setUp","parameterTypes":[] }] }, { - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventBridgeCorrelationId$AjcClosure1", + "name":"software.amazon.lambda.powertools.logging.internal.BufferManager", "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventEnvVar", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventEnvVar$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventForStream", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventForStream$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponse", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponse$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponseForStream", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.io.InputStream","java.io.OutputStream","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogResponseForStream$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogSamplingDisabled", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogSamplingDisabled$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogSamplingEnabled", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, - "methods":[{"name":"handleRequest","parameterTypes":["java.lang.Object","com.amazonaws.services.lambda.runtime.Context"] }] -}, -{ - "name":"software.amazon.lambda.powertools.logging.handlers.PowertoolsLogSamplingEnabled$AjcClosure1", - "allDeclaredClasses":true, - "queryAllDeclaredMethods":true, "queryAllPublicMethods":true }, { @@ -647,23 +268,15 @@ { "name":"software.amazon.lambda.powertools.logging.model.Basket", "allDeclaredFields":true, - "allDeclaredClasses":true, "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, "queryAllDeclaredConstructors":true, "methods":[{"name":"getProducts","parameterTypes":[] }] }, { "name":"software.amazon.lambda.powertools.logging.model.Product", "allDeclaredFields":true, - "allDeclaredClasses":true, "queryAllDeclaredMethods":true, - "queryAllPublicMethods":true, "queryAllDeclaredConstructors":true, "methods":[{"name":"getId","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPrice","parameterTypes":[] }] -}, -{ - "name":"sun.reflect.ReflectionFactory", - "methods":[{"name":"getReflectionFactory","parameterTypes":[] }, {"name":"newConstructorForSerialization","parameterTypes":["java.lang.Class","java.lang.reflect.Constructor"] }] } ] diff --git a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/resource-config.json b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/resource-config.json index ca77675e0..832be3d72 100644 --- a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/resource-config.json +++ b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/resource-config.json @@ -2,8 +2,6 @@ "resources":{ "includes":[{ "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" - }, { - "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" }, { "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" }, { @@ -14,10 +12,6 @@ "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" }, { "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" - }, { - "pattern":"\\Qcom/amazonaws/lambda/thirdparty/org/joda/time/tz/data/Europe/Berlin\\E" - }, { - "pattern":"\\Qcom/amazonaws/lambda/thirdparty/org/joda/time/tz/data/ZoneInfoMap\\E" }]}, "bundles":[] } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/PowertoolsLoggingTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/PowertoolsLoggingTest.java new file mode 100644 index 000000000..ea3a2f3f6 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/PowertoolsLoggingTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import software.amazon.lambda.powertools.logging.internal.LoggingManagerRegistry; +import software.amazon.lambda.powertools.logging.internal.TestLoggingManager; + +class PowertoolsLoggingTest { + + private TestLoggingManager testManager; + + @BeforeEach + void setUp() { + // Get the TestLoggingManager instance from registry + testManager = (TestLoggingManager) LoggingManagerRegistry.getLoggingManager(); + testManager.resetBufferState(); + } + + @Test + void testFlushBuffer_shouldCallBufferManager() { + // WHEN + PowertoolsLogging.flushBuffer(); + + // THEN + assertThat(testManager.isBufferFlushed()).isTrue(); + } + + @Test + void testClearBuffer_shouldCallBufferManager() { + // WHEN + PowertoolsLogging.clearBuffer(); + + // THEN + assertThat(testManager.isBufferCleared()).isTrue(); + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogErrorNoFlush.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogErrorNoFlush.java new file mode 100644 index 000000000..87515654c --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/handlers/PowertoolsLogErrorNoFlush.java @@ -0,0 +1,15 @@ +package software.amazon.lambda.powertools.logging.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.logging.Logging; + +public class PowertoolsLogErrorNoFlush implements RequestHandler<String, String> { + + @Override + @Logging(logError = true, flushBufferOnUncaughtError = false) + public String handleRequest(String input, Context context) { + throw new RuntimeException("This is an error without buffer flush"); + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/KeyBufferTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/KeyBufferTest.java new file mode 100644 index 000000000..15a54fa5c --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/KeyBufferTest.java @@ -0,0 +1,356 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.PrintStream; +import java.nio.channels.FileChannel; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Deque; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class KeyBufferTest { + + private KeyBuffer<String, String> buffer; + private static final int MAX_BYTES = 20; + + @BeforeEach + void setUp() throws IOException { + buffer = new KeyBuffer<>(MAX_BYTES, String::length); + // Clean up log file before each test + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (IOException e) { + // may not be there in the first run + } + } + + @AfterEach + void cleanUp() throws IOException { + // Make sure file is cleaned up after each test + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } + + @Test + void shouldAddEventToBuffer() { + buffer.add("key1", "test"); + + Deque<String> events = buffer.removeAll("key1"); + assertThat(events).containsExactly("test"); + } + + @Test + void shouldMaintainSeparateBuffersPerKey() { + buffer.add("key1", "event1"); + buffer.add("key2", "event2"); + + Deque<String> events1 = buffer.removeAll("key1"); + Deque<String> events2 = buffer.removeAll("key2"); + + assertThat(events1).containsExactly("event1"); + assertThat(events2).containsExactly("event2"); + } + + @Test + void shouldMaintainFIFOOrder() { + buffer.add("key1", "first"); + buffer.add("key1", "second"); + buffer.add("key1", "third"); + + Deque<String> events = buffer.removeAll("key1"); + assertThat(events).containsExactly("first", "second", "third"); + } + + @Test + void shouldEvictOldestEventsWhenBufferOverflows() { + // Add events that total exactly maxBytes + buffer.add("key1", "12345678901234567890"); // 20 bytes + + // Add another event that causes overflow + buffer.add("key1", "extra"); + + Deque<String> events = buffer.removeAll("key1"); + assertThat(events).containsExactly("extra"); + } + + @Test + void shouldEvictMultipleEventsIfNeeded() { + buffer.add("key1", "1234567890"); // 10 bytes + buffer.add("key1", "1234567890"); // 10 bytes, total 20 + buffer.add("key1", "12345678901234567890"); // 20 bytes, should evict both previous + + Deque<String> events = buffer.removeAll("key1"); + assertThat(events).containsExactly("12345678901234567890"); + } + + @Test + void shouldEvictMultipleSmallEventsForLargeValidEvent() { + // Add many small events that fill the buffer + buffer.add("key1", "12"); // 2 bytes + buffer.add("key1", "34"); // 2 bytes, total 4 + buffer.add("key1", "56"); // 2 bytes, total 6 + buffer.add("key1", "78"); // 2 bytes, total 8 + buffer.add("key1", "90"); // 2 bytes, total 10 + buffer.add("key1", "ab"); // 2 bytes, total 12 + buffer.add("key1", "cd"); // 2 bytes, total 14 + buffer.add("key1", "ef"); // 2 bytes, total 16 + buffer.add("key1", "gh"); // 2 bytes, total 18 + buffer.add("key1", "ij"); // 2 bytes, total 20 (exactly at limit) + + // Add a large event that requires multiple evictions + buffer.add("key1", "123456789012345678"); // 18 bytes, should evict multiple small events + + Deque<String> events = buffer.removeAll("key1"); + // Should only contain the last few small events plus the large event + // 18 bytes for large event leaves 2 bytes, so only "ij" should remain with the large event + assertThat(events).containsExactly("ij", "123456789012345678"); + } + + @Test + void shouldRejectEventLargerThanMaxBytes() { + String largeEvent = "123456789012345678901"; // 21 bytes > 20 max + + buffer.add("key1", largeEvent); + + Deque<String> events = buffer.removeAll("key1"); + assertThat(events).isNull(); + } + + @Test + void shouldNotEvictExistingEventsWhenRejectingLargeEvent() { + buffer.add("key1", "small"); + + String largeEvent = "123456789012345678901"; // 21 bytes > 20 max + buffer.add("key1", largeEvent); + + Deque<String> events = buffer.removeAll("key1"); + assertThat(events).containsExactly("small"); + } + + @Test + void shouldClearSpecificKeyBuffer() { + buffer.add("key1", "event1"); + buffer.add("key2", "event2"); + + buffer.clear("key1"); + + assertThat(buffer.removeAll("key1")).isNull(); + assertThat(buffer.removeAll("key2")).containsExactly("event2"); + } + + @Test + void shouldReturnNullForNonExistentKey() { + Deque<String> events = buffer.removeAll("nonexistent"); + assertThat(events).isNull(); + } + + @Test + void shouldReturnDefensiveCopyOnRemoveAll() { + buffer.add("key1", "event"); + + Deque<String> events1 = buffer.removeAll("key1"); + buffer.add("key1", "event"); + Deque<String> events2 = buffer.removeAll("key1"); + + // Modifying first copy shouldn't affect second + events1.add("modified"); + assertThat(events2).containsExactly("event"); + assertThat(events1).containsExactly("event", "modified"); + } + + @Test + void shouldLogWarningOnOverflow() { + StringBuilder warningCapture = new StringBuilder(); + KeyBuffer<String, String> testBuffer = new KeyBuffer<>(10, String::length, + () -> warningCapture.append("Some logs are not displayed because they were evicted from the buffer")); + + // Cause overflow + testBuffer.add("key1", "1234567890"); // 10 bytes + testBuffer.add("key1", "extra"); // causes overflow + + // Trigger warning by removing + testBuffer.removeAll("key1"); + + assertThat(warningCapture.toString()) + .contains("Some logs are not displayed because they were evicted from the buffer"); + } + + @Test + void shouldLogWarningOnLargeEventRejection() { + StringBuilder warningCapture = new StringBuilder(); + KeyBuffer<String, String> testBuffer = new KeyBuffer<>(10, String::length, + () -> warningCapture.append("Some logs are not displayed because they were evicted from the buffer")); + + // Add large event that gets rejected + testBuffer.add("key1", "12345678901"); // 11 bytes > 10 max + + // Trigger warning by removing + testBuffer.removeAll("key1"); + + assertThat(warningCapture.toString()) + .contains("Some logs are not displayed because they were evicted from the buffer"); + } + + @Test + void shouldNotLogWarningWhenNoOverflow() { + StringBuilder warningCapture = new StringBuilder(); + KeyBuffer<String, String> testBuffer = new KeyBuffer<>(20, String::length, + () -> warningCapture.append("Some logs are not displayed because they were evicted from the buffer")); + + testBuffer.add("key1", "small"); + testBuffer.removeAll("key1"); + + assertThat(warningCapture.toString()) + .doesNotContain("Some logs are not displayed because they were evicted from the buffer"); + } + + @Test + void shouldBeThreadSafeForDifferentKeys() throws InterruptedException, IOException { + int threadCount = 10; + int eventsPerThread = 100; + KeyBuffer<String, String> largeBuffer = new KeyBuffer<>(10000, String::length); + ExecutorService executor = Executors.newFixedThreadPool(threadCount); + try (Closeable ignored = executor::shutdown) { + CountDownLatch latch = new CountDownLatch(threadCount); + + // Each thread works with different key + for (int i = 0; i < threadCount; i++) { + final String key = "key" + i; + executor.submit(() -> { + try { + for (int j = 0; j < eventsPerThread; j++) { + largeBuffer.add(key, "event" + j); + } + } finally { + latch.countDown(); + } + }); + } + + assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue(); + + // Verify each key has its events + for (int i = 0; i < threadCount; i++) { + String key = "key" + i; + Deque<String> events = largeBuffer.removeAll(key); + assertThat(events) + .isNotNull() + .hasSize(eventsPerThread); + } + } + } + + @Test + void shouldBeThreadSafeForSameKey() throws InterruptedException, IOException { + int threadCount = 5; + int eventsPerThread = 20; + KeyBuffer<String, String> largeBuffer = new KeyBuffer<>(10000, String::length); + ExecutorService executor = Executors.newFixedThreadPool(threadCount); + try (Closeable ignored = executor::shutdown) { + CountDownLatch latch = new CountDownLatch(threadCount); + + // All threads work with same key + for (int i = 0; i < threadCount; i++) { + final int threadId = i; + executor.submit(() -> { + try { + for (int j = 0; j < eventsPerThread; j++) { + largeBuffer.add("sharedKey", "t" + threadId + "e" + j); + } + } finally { + latch.countDown(); + } + }); + } + + assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue(); + + Deque<String> events = largeBuffer.removeAll("sharedKey"); + assertThat(events) + .isNotNull() + .hasSize(threadCount * eventsPerThread); + } + } + + @Test + void shouldHandleEmptyBuffer() { + buffer.clear("nonexistent"); + assertThat(buffer.removeAll("nonexistent")).isNull(); + } + + @Test + void shouldHandleZeroSizeEvents() { + KeyBuffer<String, String> zeroBuffer = new KeyBuffer<>(10, s -> 0); + + zeroBuffer.add("key1", "event1"); + zeroBuffer.add("key1", "event2"); + + Deque<String> events = zeroBuffer.removeAll("key1"); + assertThat(events).containsExactly("event1", "event2"); + } + + @Test + void shouldUseCustomWarningLogger() { + StringBuilder customWarning = new StringBuilder(); + KeyBuffer<String, String> testBuffer = new KeyBuffer<>(5, String::length, + () -> customWarning.append("CUSTOM WARNING LOGGED")); + + // Cause overflow + testBuffer.add("key1", "12345"); // 5 bytes + testBuffer.add("key1", "extra"); // causes overflow + + // Trigger warning + testBuffer.removeAll("key1"); + + assertThat(customWarning).hasToString("CUSTOM WARNING LOGGED"); + } + + @Test + void shouldUseDefaultWarningLoggerWhenNotProvided() { + // Capture System.err output + ByteArrayOutputStream errCapture = new ByteArrayOutputStream(); + @SuppressWarnings("PMD.CloseResource") // System.err is not ours to close + PrintStream originalErr = System.err; + try (PrintStream newErr = new PrintStream(errCapture)) { + System.setErr(newErr); + + KeyBuffer<String, String> defaultBuffer = new KeyBuffer<>(5, String::length); + + // Cause overflow + defaultBuffer.add("key1", "12345"); + defaultBuffer.add("key1", "extra"); + defaultBuffer.removeAll("key1"); + + // Assert System.err received the warning + assertThat(errCapture) + .hasToString( + "WARN [KeyBuffer] - Some logs are not displayed because they were evicted from the buffer. Increase buffer size to store more logs in the buffer.\n"); + } finally { + System.setErr(originalErr); + } + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index 751d195b5..3ff531321 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -31,8 +31,6 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.io.PrintStream; -import java.io.UnsupportedEncodingException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.channels.FileChannel; @@ -40,7 +38,6 @@ import java.nio.file.NoSuchFileException; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -81,6 +78,7 @@ import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabled; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEnabledForStream; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogError; +import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogErrorNoFlush; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEvent; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventBridgeCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogEventEnvVar; @@ -111,6 +109,13 @@ void setUp() throws IllegalAccessException, NoSuchMethodException, InvocationTar writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", null, true); writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_EVENT", false, true); writeStaticField(LoggingConstants.class, "POWERTOOLS_SAMPLING_RATE", null, true); + + // Reset buffer state for clean test isolation + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + if (loggingManager instanceof TestLoggingManager) { + ((TestLoggingManager) loggingManager).resetBufferState(); + } + try { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); } catch (NoSuchFileException e) { @@ -721,47 +726,129 @@ void shouldLogCorrelationIdOnAppSyncEvent() throws IOException { } @Test - void testMultipleLoggingManagers_shouldWarnAndSelectFirstOne() throws UnsupportedEncodingException { - // GIVEN - List<LoggingManager> list = new ArrayList<>(); - list.add(new TestLoggingManager()); - list.add(new DefautlLoggingManager()); + void shouldClearBufferAfterSuccessfulHandlerExecution() { + // WHEN + requestHandler.handleRequest(new Object(), context); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - PrintStream stream = new PrintStream(outputStream); + // THEN + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + if (loggingManager instanceof TestLoggingManager) { + assertThat(((TestLoggingManager) loggingManager).isBufferCleared()).isTrue(); + } + } + @Test + void shouldClearBufferAfterSuccessfulStreamHandlerExecution() throws IOException { // WHEN - LambdaLoggingAspect.getLoggingManager(list, stream); + requestStreamHandler.handleRequest(new ByteArrayInputStream(new byte[] {}), new ByteArrayOutputStream(), + context); // THEN - String output = outputStream.toString("UTF-8"); - assertThat(output) - .contains("WARN. Multiple LoggingManagers were found on the classpath") - .contains( - "WARN. Make sure to have only one of powertools-logging-log4j OR powertools-logging-logback to your dependencies") - .contains("WARN. Using the first LoggingManager found on the classpath: [" + list.get(0) + "]"); + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + if (loggingManager instanceof TestLoggingManager) { + assertThat(((TestLoggingManager) loggingManager).isBufferCleared()).isTrue(); + } + } + + @Test + void shouldClearBufferAfterHandlerExceptionWithLogError() { + // GIVEN + requestHandler = new PowertoolsLogError(); + + // WHEN + try { + requestHandler.handleRequest("input", context); + } catch (Exception e) { + // ignore + } + + // THEN + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + if (loggingManager instanceof TestLoggingManager) { + assertThat(((TestLoggingManager) loggingManager).isBufferCleared()).isTrue(); + } + } + + @Test + void shouldClearBufferAfterHandlerExceptionWithEnvVarLogError() { + try { + // GIVEN + LoggingConstants.POWERTOOLS_LOG_ERROR = true; + requestHandler = new PowertoolsLogEnabled(true); + + // WHEN + try { + requestHandler.handleRequest("input", context); + } catch (Exception e) { + // ignore + } + + // THEN + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + if (loggingManager instanceof TestLoggingManager) { + assertThat(((TestLoggingManager) loggingManager).isBufferCleared()).isTrue(); + } + } finally { + LoggingConstants.POWERTOOLS_LOG_ERROR = false; + } } @Test - void testNoLoggingManagers_shouldWarnAndCreateDefault() throws UnsupportedEncodingException { + void shouldFlushBufferOnUncaughtErrorWhenEnabled() { // GIVEN - List<LoggingManager> list = new ArrayList<>(); + requestHandler = new PowertoolsLogError(); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - PrintStream stream = new PrintStream(outputStream); + // WHEN + try { + requestHandler.handleRequest("input", context); + } catch (Exception e) { + // ignore + } + + // THEN + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + if (loggingManager instanceof TestLoggingManager) { + assertThat(((TestLoggingManager) loggingManager).isBufferFlushed()).isTrue(); + } + } + + @Test + void shouldNotFlushBufferOnUncaughtErrorWhenDisabled() { + // GIVEN + PowertoolsLogErrorNoFlush handler = new PowertoolsLogErrorNoFlush(); // WHEN - LoggingManager loggingManager = LambdaLoggingAspect.getLoggingManager(list, stream); + try { + handler.handleRequest("input", context); + } catch (Exception e) { + // ignore + } // THEN - String output = outputStream.toString("UTF-8"); - assertThat(output) - .contains("ERROR. No LoggingManager was found on the classpath") - .contains("ERROR. Applying default LoggingManager: POWERTOOLS_LOG_LEVEL variable is ignored") - .contains( - "ERROR. Make sure to add either powertools-logging-log4j or powertools-logging-logback to your dependencies"); + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + if (loggingManager instanceof TestLoggingManager) { + assertThat(((TestLoggingManager) loggingManager).isBufferFlushed()).isFalse(); + } + } - assertThat(loggingManager).isExactlyInstanceOf(DefautlLoggingManager.class); + @Test + void shouldClearBufferBeforeErrorLoggingWhenFlushBufferOnUncaughtErrorDisabled() { + // GIVEN + PowertoolsLogErrorNoFlush handler = new PowertoolsLogErrorNoFlush(); + + // WHEN + try { + handler.handleRequest("input", context); + } catch (Exception e) { + // ignore + } + + // THEN - Buffer should be cleared and not flushed + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + if (loggingManager instanceof TestLoggingManager) { + assertThat(((TestLoggingManager) loggingManager).isBufferCleared()).isTrue(); + assertThat(((TestLoggingManager) loggingManager).isBufferFlushed()).isFalse(); + } } private void resetLogLevel(Level level) diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LoggingManagerRegistryTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LoggingManagerRegistryTest.java new file mode 100644 index 000000000..6bed0d9c1 --- /dev/null +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LoggingManagerRegistryTest.java @@ -0,0 +1,141 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.logging.internal; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import org.junit.jupiter.api.Test; + +class LoggingManagerRegistryTest { + + @Test + void testMultipleLoggingManagers_shouldWarnAndSelectFirstOne() throws UnsupportedEncodingException { + // GIVEN + List<LoggingManager> list = new ArrayList<>(); + list.add(new TestLoggingManager()); + list.add(new DefaultLoggingManager()); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream stream = new PrintStream(outputStream); + + // WHEN + LoggingManagerRegistry.selectLoggingManager(list, stream); + + // THEN + String output = outputStream.toString("UTF-8"); + assertThat(output) + .contains("WARN. Multiple LoggingManagers were found on the classpath") + .contains( + "WARN. Make sure to have only one of powertools-logging-log4j OR powertools-logging-logback in your dependencies") + .contains("WARN. Using the first LoggingManager found on the classpath: [" + list.get(0) + "]"); + } + + @Test + void testNoLoggingManagers_shouldWarnAndCreateDefault() throws UnsupportedEncodingException { + // GIVEN + List<LoggingManager> list = new ArrayList<>(); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream stream = new PrintStream(outputStream); + + // WHEN + LoggingManager loggingManager = LoggingManagerRegistry.selectLoggingManager(list, stream); + + // THEN + String output = outputStream.toString("UTF-8"); + assertThat(output) + .contains("ERROR. No LoggingManager was found on the classpath") + .contains("ERROR. Applying default LoggingManager: POWERTOOLS_LOG_LEVEL variable is ignored") + .contains( + "ERROR. Make sure to add either powertools-logging-log4j or powertools-logging-logback to your dependencies"); + + assertThat(loggingManager).isExactlyInstanceOf(DefaultLoggingManager.class); + } + + @Test + void testSingleLoggingManager_shouldReturnWithoutWarning() throws UnsupportedEncodingException { + // GIVEN + List<LoggingManager> list = new ArrayList<>(); + TestLoggingManager testManager = new TestLoggingManager(); + list.add(testManager); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream stream = new PrintStream(outputStream); + + // WHEN + LoggingManager loggingManager = LoggingManagerRegistry.selectLoggingManager(list, stream); + + // THEN + String output = outputStream.toString("UTF-8"); + assertThat(output).isEmpty(); + assertThat(loggingManager) + .isSameAs(testManager) + .isInstanceOf(BufferManager.class); + } + + @Test + void testGetLoggingManager_shouldReturnSameInstance() { + // WHEN + LoggingManager first = LoggingManagerRegistry.getLoggingManager(); + LoggingManager second = LoggingManagerRegistry.getLoggingManager(); + + // THEN + assertThat(first) + .isSameAs(second) + .isNotNull() + .isInstanceOf(BufferManager.class); + } + + @Test + void testGetLoggingManager_shouldBeThreadSafe() throws InterruptedException, IOException { + // GIVEN + int threadCount = 10; + ExecutorService executor = Executors.newFixedThreadPool(threadCount); + try (Closeable ignored = executor::shutdown) { + CountDownLatch latch = new CountDownLatch(threadCount); + AtomicReference<LoggingManager> sharedInstance = new AtomicReference<>(); + + // WHEN + for (int i = 0; i < threadCount; i++) { + executor.submit(() -> { + try { + LoggingManager instance = LoggingManagerRegistry.getLoggingManager(); + sharedInstance.compareAndSet(null, instance); + assertThat(instance).isSameAs(sharedInstance.get()); + } finally { + latch.countDown(); + } + }); + } + + // THEN + latch.await(5, TimeUnit.SECONDS); + assertThat(sharedInstance.get()).isNotNull(); + } + } +} diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/TestLoggingManager.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/TestLoggingManager.java index 0958e0d3b..f2aa2417e 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/TestLoggingManager.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/TestLoggingManager.java @@ -7,17 +7,19 @@ import org.slf4j.test.TestLogger; import org.slf4j.test.TestLoggerFactory; -public class TestLoggingManager implements LoggingManager { +public class TestLoggingManager implements LoggingManager, BufferManager { private final TestLoggerFactory loggerFactory; + private boolean bufferFlushed = false; + private boolean bufferCleared = false; public TestLoggingManager() { - ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory(); - if (!(loggerFactory instanceof TestLoggerFactory)) { + ILoggerFactory loggerFactoryInstance = LoggerFactory.getILoggerFactory(); + if (!(loggerFactoryInstance instanceof TestLoggerFactory)) { throw new RuntimeException( "LoggerFactory does not match required type: " + TestLoggerFactory.class.getName()); } - this.loggerFactory = (TestLoggerFactory) loggerFactory; + this.loggerFactory = (TestLoggerFactory) loggerFactoryInstance; } @Override @@ -29,4 +31,27 @@ public void setLogLevel(Level logLevel) { public Level getLogLevel(Logger logger) { return org.slf4j.event.Level.intToLevel(((TestLogger) logger).getLogLevel()); } + + @Override + public void flushBuffer() { + bufferFlushed = true; + } + + @Override + public void clearBuffer() { + bufferCleared = true; + } + + public boolean isBufferFlushed() { + return bufferFlushed; + } + + public boolean isBufferCleared() { + return bufferCleared; + } + + public void resetBufferState() { + bufferFlushed = false; + bufferCleared = false; + } } From ea0aed1827f6df3caa39181a9346a6c9d850892b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:08:11 +0200 Subject: [PATCH 409/577] chore: bump squidfunk/mkdocs-material in /docs (#2127) Bumps squidfunk/mkdocs-material from `1a4e939` to `209b62d`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: 209b62dd9530163cc5cf9a49853b5bb8570ffb3f3b5fe4eadc1d319bbda5ce2f dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 4d3135506..6fef5966e 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -FROM squidfunk/mkdocs-material@sha256:1a4e939cfd62b90943b6a829eb8544933e4e94eab18b8ca1d0f912fa9a532c37 +FROM squidfunk/mkdocs-material@sha256:209b62dd9530163cc5cf9a49853b5bb8570ffb3f3b5fe4eadc1d319bbda5ce2f COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From 5c2f0311228aed84f81342231972d9c2e21ac7a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:08:40 +0200 Subject: [PATCH 410/577] chore: bump github/codeql-action from 3.30.0 to 3.30.1 (#2126) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.0 to 3.30.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d...f1f6e5f6af878fb37288ce1c627459e94dbf7d01) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index dfa0b2121..8ff72b365 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@2d92b76c45b91eb80fc44c74ce3fce0ee94e8f9d # v3.29.5 + uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # v3.29.5 with: sarif_file: results.sarif From fdbe3a25434b161e2620d9ab670cd2f7fcddf6bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:08:51 +0200 Subject: [PATCH 411/577] chore: bump com.github.spotbugs:spotbugs-maven-plugin (#2125) Bumps [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) from 4.9.4.0 to 4.9.4.2. - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.9.4.0...spotbugs-maven-plugin-4.9.4.2) --- updated-dependencies: - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-version: 4.9.4.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c1fd3b9c4..f96c434a8 100644 --- a/pom.xml +++ b/pom.xml @@ -598,7 +598,7 @@ <plugin> <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> - <version>4.9.4.0</version> + <version>4.9.4.2</version> <executions> <execution> <id>test</id> From cb9e4d4aaddf25720cdad586b97ac456ed136c25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:09:08 +0200 Subject: [PATCH 412/577] chore: bump aws-actions/configure-aws-credentials from 4.3.1 to 5.0.0 (#2120) Bumps [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) from 4.3.1 to 5.0.0. - [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases) - [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/7474bc4690e29a8392af63c5b98e7449536d5c3a...a03048d87541d1d9fcf2ecf528a4a65ba9bd7838) --- updated-dependencies: - dependency-name: aws-actions/configure-aws-credentials dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 2 +- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/release.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index bf241cc1b..a9d3fbf7b 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -41,7 +41,7 @@ jobs: docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a + uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 462bfbc34..f18964852 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -64,7 +64,7 @@ jobs: java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 + uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v5.0.0 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -97,7 +97,7 @@ jobs: java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a # v4.3.1 + uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v5.0.0 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 08dfa90dc..61dd6234d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -281,7 +281,7 @@ jobs: docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@7474bc4690e29a8392af63c5b98e7449536d5c3a + uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} From eb8bc4e8edaf7941ea470201ace8e0aedb711f58 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:09:24 +0200 Subject: [PATCH 413/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.213.0 to 2.214.0 (#2117) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.213.0 to 2.214.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.213.0...v2.214.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.214.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index db4857448..daf50203c 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.3.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.213.0</cdk.version> + <cdk.version>2.214.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.13.4</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 5f3e2506a..1bf9d0e75 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.2</constructs.version> - <cdk.version>2.213.0</cdk.version> + <cdk.version>2.214.0</cdk.version> </properties> <dependencies> From 7d7906615d28a0b36a01d8f95c03d518b1712e79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:09:43 +0200 Subject: [PATCH 414/577] chore: bump graalvm/setup-graalvm from 1.3.5 to 1.3.6 (#2116) Bumps [graalvm/setup-graalvm](https://github.com/graalvm/setup-graalvm) from 1.3.5 to 1.3.6. - [Release notes](https://github.com/graalvm/setup-graalvm/releases) - [Commits](https://github.com/graalvm/setup-graalvm/compare/7f488cf82a3629ee755e4e97342c01d6bed318fa...7a1da54cb7fdef4ea19f6ecdfa9ecf59dc5a48fe) --- updated-dependencies: - dependency-name: graalvm/setup-graalvm dependency-version: 1.3.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index b84db997b..482ba4186 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -102,7 +102,7 @@ jobs: powertools-*/** pom.xml - name: Setup GraalVM - uses: graalvm/setup-graalvm@7f488cf82a3629ee755e4e97342c01d6bed318fa # v1.3.5 + uses: graalvm/setup-graalvm@7a1da54cb7fdef4ea19f6ecdfa9ecf59dc5a48fe # v1.3.6 with: java-version: "21" distribution: "graalvm" From 1ffc374d2dd62360d1fdb3a4f141621893cd73d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:09:55 +0200 Subject: [PATCH 415/577] chore: bump aws.sdk.version from 2.32.31 to 2.33.1 (#2115) Bumps `aws.sdk.version` from 2.32.31 to 2.33.1. Updates `software.amazon.awssdk:bom` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:http-client-spi` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:dynamodb` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:lambda` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:cloudwatch` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:xray` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:cloudformation` from 2.32.31 to 2.33.1 Updates `software.amazon.awssdk:sts` from 2.32.31 to 2.33.1 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.33.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.33.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.33.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.33.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.33.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.33.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.33.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.33.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-version: 2.33.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.33.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.33.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-version: 2.33.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 5dbb73489..f27a16181 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.32.31</aws.sdk.version> + <aws.sdk.version>2.33.2</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index f96c434a8..6a6b97844 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.32.31</aws.sdk.version> + <aws.sdk.version>2.33.2</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 53f9ed3ad..ca5aaa8af 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -20,7 +20,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.0</maven.compiler.version> - <aws.sdk.version>2.32.31</aws.sdk.version> + <aws.sdk.version>2.33.2</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> From 7c5acf508ad8e3e1fabafbc3c74706b61f22f159 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:10:13 +0200 Subject: [PATCH 416/577] chore: bump io.github.ascopes:protobuf-maven-plugin from 3.8.1 to 3.9.0 (#2114) Bumps [io.github.ascopes:protobuf-maven-plugin](https://github.com/ascopes/protobuf-maven-plugin) from 3.8.1 to 3.9.0. - [Release notes](https://github.com/ascopes/protobuf-maven-plugin/releases) - [Commits](https://github.com/ascopes/protobuf-maven-plugin/compare/v3.8.1...v3.9.0) --- updated-dependencies: - dependency-name: io.github.ascopes:protobuf-maven-plugin dependency-version: 3.9.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 85798000f..e3f1dd153 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -141,7 +141,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.8.1</version> + <version>3.9.0</version> <executions> <execution> <goals> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 5faa929b7..6f24c1aac 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -181,7 +181,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.8.1</version> + <version>3.9.0</version> <executions> <execution> <id>generate-test-sources</id> From b36d8bac90087d5ccda1c87eac338ef50edd4ff2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:10:27 +0200 Subject: [PATCH 417/577] chore: bump org.yaml:snakeyaml from 2.4 to 2.5 (#2111) Bumps [org.yaml:snakeyaml](https://bitbucket.org/snakeyaml/snakeyaml) from 2.4 to 2.5. - [Commits](https://bitbucket.org/snakeyaml/snakeyaml/branches/compare/snakeyaml-2.5..snakeyaml-2.4) --- updated-dependencies: - dependency-name: org.yaml:snakeyaml dependency-version: '2.5' dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 1bf9d0e75..ef9836226 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -152,7 +152,7 @@ <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> - <version>2.4</version> + <version>2.5</version> <scope>test</scope> </dependency> <dependency> From a2eecae9a9f69047efa43500031f19bcb96c5b14 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 9 Sep 2025 12:18:49 +0200 Subject: [PATCH 418/577] chore(ci): Fix circular dependency in dynamodb-local and maven packaging phases. (#2129) --- powertools-idempotency/powertools-idempotency-dynamodb/pom.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index b7c4f317c..64b7b49b3 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -186,6 +186,9 @@ <configuration> <includeScope>test</includeScope> <excludeTransitive>false</excludeTransitive> + <!-- MDEP-187: Avoids Maven phase circular dependency by not trying to copy unpacked reactor + artifacts (powertools-idempotency-core) --> + <excludeGroupIds>software.amazon.lambda</excludeGroupIds> <outputDirectory>${project.build.directory}/dynamodb-local</outputDirectory> </configuration> </execution> From 4c1520eee38d59628b38433afeada0a74230731b Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 9 Sep 2025 13:07:18 +0200 Subject: [PATCH 419/577] Skip maven deployment for e2e test handlers. (#2131) --- powertools-e2e-tests/handlers/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index ca5aaa8af..aa172d704 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -13,7 +13,6 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> - <lambda.java.core>1.3.0</lambda.java.core> <lambda.java.serialization>1.1.6</lambda.java.serialization> <lambda.java.events>3.16.1</lambda.java.events> @@ -22,6 +21,7 @@ <maven.compiler.version>3.14.0</maven.compiler.version> <aws.sdk.version>2.33.2</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> + <maven.deploy.skip>true</maven.deploy.skip> </properties> <modules> From 29e52c2fded7042560d4eaa0f87ad4048b203701 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 9 Sep 2025 13:36:03 +0200 Subject: [PATCH 420/577] chore(ci): Do not use Mockito SNAPSHOT version for release. (#2137) --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index 6a6b97844..9b91ab2c9 100644 --- a/pom.xml +++ b/pom.xml @@ -536,6 +536,12 @@ <profiles> <profile> <id>release</id> + <!-- TODO: Revert once 5.19.1 is stable released. --> + <!-- https://github.com/aws-powertools/powertools-lambda-java/issues/2079 --> + <properties> + <mockito.version>5.19.0</mockito.version> + <mockito-junit-jupiter.version>5.19.0</mockito-junit-jupiter.version> + </properties> <build> <plugins> <plugin> @@ -637,6 +643,7 @@ </plugins> </build> </profile> + </profiles> </project> From 3de08f958b22e14ec6e5469b31d6e213de0b13b9 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 9 Sep 2025 14:30:38 +0200 Subject: [PATCH 421/577] chore(ci): Set mockito SNAPSHOT version only for Graal profiles. (#2138) --- pom.xml | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 9b91ab2c9..86f7858cb 100644 --- a/pom.xml +++ b/pom.xml @@ -114,8 +114,8 @@ <aws.sdk.v1.version>1.12.781</aws.sdk.v1.version> <versions-maven-plugin.version>2.18.0</versions-maven-plugin.version> <elastic.version>1.7.0</elastic.version> - <mockito.version>5.19.1-SNAPSHOT</mockito.version> - <mockito-junit-jupiter.version>5.19.1-SNAPSHOT</mockito-junit-jupiter.version> + <mockito.version>5.19.0</mockito.version> + <mockito-junit-jupiter.version>5.19.0</mockito-junit-jupiter.version> <junit-pioneer.version>2.3.0</junit-pioneer.version> <crac.version>1.5.0</crac.version> @@ -643,7 +643,21 @@ </plugins> </build> </profile> - + <profile> + <id>generate-graalvm-files</id> + <properties> + <mockito.version>5.19.1-SNAPSHOT</mockito.version> + <mockito-junit-jupiter.version>5.19.1-SNAPSHOT</mockito-junit-jupiter.version> + </properties> + </profile> + <profile> + <id>graalvm-native</id> + <properties> + <mockito.version>5.19.1-SNAPSHOT</mockito.version> + <mockito-junit-jupiter.version>5.19.1-SNAPSHOT</mockito-junit-jupiter.version> + </properties> + </profile> + </profiles> </project> From 9200c9caf69cc099a7054a9d586bfc5f6fc92957 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 15:17:02 +0200 Subject: [PATCH 422/577] chore(ci): bump version to 2.4.0 (#2139) Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/README.md | 4 ++-- .../infra/sam-graalvm/README.md | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- .../powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- .../powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/handlers/batch/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency/pom.xml | 2 +- powertools-e2e-tests/handlers/largemessage/pom.xml | 2 +- .../handlers/largemessage_idempotent/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-log4j/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-logback/pom.xml | 2 +- powertools-e2e-tests/handlers/metrics/pom.xml | 2 +- powertools-e2e-tests/handlers/parameters/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/handlers/tracing/pom.xml | 2 +- powertools-e2e-tests/handlers/validation-alb-event/pom.xml | 2 +- .../handlers/validation-apigw-event/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 58 files changed, 65 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 62d34e9c5..5e0266744 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-metrics</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </dependency> ... </dependencies> diff --git a/examples/pom.xml b/examples/pom.xml index 554e97168..b892f43ce 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-examples</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Examples</name> diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 9857aa717..aa42acaf6 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-batch</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Batch</name> diff --git a/examples/powertools-examples-cloudformation/README.md b/examples/powertools-examples-cloudformation/README.md index b2951b28b..262a6b14f 100644 --- a/examples/powertools-examples-cloudformation/README.md +++ b/examples/powertools-examples-cloudformation/README.md @@ -15,7 +15,7 @@ Run the following in your shell: ```bash cd infra/sam sam build -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.3.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.4.0718 ``` ### Deploy with CDK @@ -32,5 +32,5 @@ To build and deploy this application for the first time, run the following in yo cd infra/cdk mvn package cdk synth -cdk deploy -c BucketNameParam=my-unique-bucket-2.3.0718 +cdk deploy -c BucketNameParam=my-unique-bucket-2.4.0718 ``` \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md index e8deeb8fd..0f06fe084 100644 --- a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md +++ b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md @@ -40,7 +40,7 @@ sam build ## Deploy the sample application ```shell -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.3.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.4.0718 ``` This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting started with SAM in [the examples directory](../../../README.md) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index f27a16181..1de9921a3 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-cloudformation</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index e02a636bf..e1d0e7c1d 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ <groupId>software.amazon.lambda.examples</groupId> <!-- TODO TODO TODO this should build from SNAPSHOT, but it doesn't, because the snapshots don't appear in the docker environment CDK builds it in in our CDK tests. How to procede? V2 blocker --> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-core-utilities-cdk</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index daf50203c..491c9ec68 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <artifactId>cdk</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.214.0</cdk.version> diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 8770d5b31..1325eadaf 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.3.0' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.3.0' - aspect 'software.amazon.lambda:powertools-metrics:2.3.0' + aspect 'software.amazon.lambda:powertools-tracing:2.4.0' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.4.0' + aspect 'software.amazon.lambda:powertools-metrics:2.4.0' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index ca0604517..98c41093f 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.3.0") - aspect("software.amazon.lambda:powertools-logging-log4j:2.3.0") - aspect("software.amazon.lambda:powertools-metrics:2.3.0") + aspect("software.amazon.lambda:powertools-tracing:2.4.0") + aspect("software.amazon.lambda:powertools-logging-log4j:2.4.0") + aspect("software.amazon.lambda:powertools-metrics:2.4.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 302fa8074..668e24cf8 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-core-utilities-sam-graalvm</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 3df44f441..ae85d9efd 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-core-utilities-sam</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index c4dc9c099..3f1559b12 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-core-utilities-serverless</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index f02189948..cc83aa5f6 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-core-utilities-terraform</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index 6abb743f9..47ca3e50c 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-idempotency-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency GraalVM</name> diff --git a/examples/powertools-examples-idempotency/sam/pom.xml b/examples/powertools-examples-idempotency/sam/pom.xml index a5f49d9c6..32b595e48 100644 --- a/examples/powertools-examples-idempotency/sam/pom.xml +++ b/examples/powertools-examples-idempotency/sam/pom.xml @@ -17,7 +17,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-idempotency</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency</name> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index e3f1dd153..149310c60 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-kafka</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Kafka</name> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 815506325..a03b5d819 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-parameters-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index f10a20aab..9d83adb0b 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-parameters-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters</name> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index e660aeba2..e99400d0f 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-serialization-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 64ee8c465..0c8e7c89b 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-serialization-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization</name> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index bdd14e5fb..7e6f48445 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <artifactId>powertools-examples-validation</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Validation</name> diff --git a/mkdocs.yml b/mkdocs.yml index ea7617353..372dfedd7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -128,7 +128,7 @@ extra_javascript: extra: powertools: - version: 2.3.0 + version: 2.4.0 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index 86f7858cb..8e79eea34 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Parent</name> diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index bbdc5b0c2..b389df6fe 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <description>A suite of utilities that makes batch message processing using AWS Lambda easier.</description> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 862f5832e..ca4e7536f 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Cloudformation</name> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index ea9baa98c..7620d84ee 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Common Internal Utilities</name> diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index 630ff7cfa..99ce7d3c4 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-batch</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index b9555ee47..79fd5b8e0 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-idempotency</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index 3aa876bfc..3aa6c5bee 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-largemessage</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index dea0f7263..4261ff459 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-large-msg-idempotent</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-log4j/pom.xml b/powertools-e2e-tests/handlers/logging-log4j/pom.xml index d415ae4b3..792e19fba 100644 --- a/powertools-e2e-tests/handlers/logging-log4j/pom.xml +++ b/powertools-e2e-tests/handlers/logging-log4j/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-logging-log4j</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-logback/pom.xml b/powertools-e2e-tests/handlers/logging-logback/pom.xml index 932eb0612..ac643b969 100644 --- a/powertools-e2e-tests/handlers/logging-logback/pom.xml +++ b/powertools-e2e-tests/handlers/logging-logback/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-logging-logback</artifactId> diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 809f7faa2..54f9015c5 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-metrics</artifactId> diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index d1cd4bf74..957242f0f 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-parameters</artifactId> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index aa172d704..d26cbf740 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -4,7 +4,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> <packaging>pom</packaging> <name>Handlers for End-to-End tests</name> <description>Fake handlers that use Powertools for AWS Lambda (Java).</description> diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index 304941b0c..0a88cc92c 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-tracing</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml index c595b7201..dcecfc0a8 100644 --- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-validation-alb-event</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml index bdcc6813b..f4e9ff341 100644 --- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>e2e-test-handler-validation-apigw-event</artifactId> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index ef9836226..a0d500686 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>powertools-e2e-tests</artifactId> diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index e20d90565..096c6ea07 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>powertools-idempotency</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 2f575d3de..b2a6459a5 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>powertools-idempotency-core</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index 64b7b49b3..191d75eeb 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>powertools-idempotency-dynamodb</artifactId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 6f24c1aac..1ffa533fc 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>powertools-kafka</artifactId> diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index d61dacf48..b78fa225b 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>powertools-large-messages</artifactId> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 7a288870a..14cc8898d 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Logging</name> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 836f8c53f..92283b0cf 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index e2c16019f..ff0312001 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index b90506c25..c1ac723f1 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Metrics</name> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 617e0cc00..f7347c03a 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>powertools-parameters</artifactId> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index ed92930fc..bbb6a1111 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index b8857b0c9..fa969e585 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index b486a1bb3..55c254f88 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 709ea6634..d1dc88d84 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 6dcf2c4ae..136b2ef43 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 7e4e2af15..2cc8fa5d4 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <artifactId>powertools-serialization</artifactId> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 67de0be7d..6081abd66 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Tracing</name> diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 118edc66f..1c048e66a 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.3.0</version> + <version>2.4.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Validation</name> From f8a02854b64656cfb81ce27554494aba7ca32727 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 14:55:52 +0200 Subject: [PATCH 423/577] chore: bump aws.sdk.version from 2.33.2 to 2.33.5 (#2132) Bumps `aws.sdk.version` from 2.33.2 to 2.33.5. Updates `software.amazon.awssdk:bom` from 2.33.2 to 2.33.5 Updates `software.amazon.awssdk:http-client-spi` from 2.33.2 to 2.33.5 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.33.5 Updates `software.amazon.awssdk:dynamodb` from 2.33.2 to 2.33.5 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.33.5 Updates `software.amazon.awssdk:lambda` from 2.33.2 to 2.33.5 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.33.5 Updates `software.amazon.awssdk:cloudwatch` from 2.33.2 to 2.33.5 Updates `software.amazon.awssdk:xray` from 2.33.2 to 2.33.5 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.33.5 Updates `software.amazon.awssdk:cloudformation` from 2.33.2 to 2.33.5 Updates `software.amazon.awssdk:sts` from 2.33.2 to 2.33.5 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.33.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.33.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.33.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.33.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.33.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.33.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.33.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.33.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.33.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.33.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.33.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.33.5 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 1de9921a3..0abe6e5d6 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.3.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.33.2</aws.sdk.version> + <aws.sdk.version>2.33.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 8e79eea34..ddf703375 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.33.2</aws.sdk.version> + <aws.sdk.version>2.33.5</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index d26cbf740..fca2fec7b 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.0</maven.compiler.version> - <aws.sdk.version>2.33.2</aws.sdk.version> + <aws.sdk.version>2.33.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From a34689d0bef26285b4d3bdfaabe57523800f2c1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 14:56:19 +0200 Subject: [PATCH 424/577] chore: bump org.apache.kafka:kafka-clients from 4.0.0 to 4.1.0 (#2134) Bumps org.apache.kafka:kafka-clients from 4.0.0 to 4.1.0. --- updated-dependencies: - dependency-name: org.apache.kafka:kafka-clients dependency-version: 4.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 149310c60..7f9449361 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -24,7 +24,7 @@ <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> - <version>4.0.0</version> <!-- Supports >= 3.0.0 --> + <version>4.1.0</version> <!-- Supports >= 3.0.0 --> </dependency> <dependency> <groupId>org.apache.avro</groupId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 1ffa533fc..b0705a204 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -34,7 +34,7 @@ </description> <properties> - <kafka-clients.version>4.0.0</kafka-clients.version> + <kafka-clients.version>4.1.0</kafka-clients.version> <avro.version>1.12.0</avro.version> <protobuf.version>4.32.0</protobuf.version> <lambda-serialization.version>1.1.6</lambda-serialization.version> From d14e73e4c43ac0b89f983f38c1f18877045ddc01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 14:57:07 +0200 Subject: [PATCH 425/577] chore: bump com.amazonaws:aws-lambda-java-core from 1.3.0 to 1.4.0 (#2135) Bumps [com.amazonaws:aws-lambda-java-core](https://github.com/aws/aws-lambda-java-libs) from 1.3.0 to 1.4.0. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-core dependency-version: 1.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- examples/powertools-examples-core-utilities/serverless/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- examples/powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index aa42acaf6..c31277d6a 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -36,7 +36,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 0abe6e5d6..eb762665b 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -12,7 +12,7 @@ <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> - <lambda.core.version>1.3.0</lambda.core.version> + <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> <aws.sdk.version>2.33.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index e1d0e7c1d..db3750e53 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -36,7 +36,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 668e24cf8..a47be2458 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -34,7 +34,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index ae85d9efd..3647509c6 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -33,7 +33,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 3f1559b12..b5236b11e 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -33,7 +33,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index cc83aa5f6..95fcc07c1 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -33,7 +33,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index 47ca3e50c..7b34c94c2 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -33,7 +33,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-idempotency/sam/pom.xml b/examples/powertools-examples-idempotency/sam/pom.xml index 32b595e48..8bc2a6311 100644 --- a/examples/powertools-examples-idempotency/sam/pom.xml +++ b/examples/powertools-examples-idempotency/sam/pom.xml @@ -48,7 +48,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index a03b5d819..3bd5a5de7 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -34,7 +34,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 9d83adb0b..09a67104f 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -33,7 +33,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index e99400d0f..a85e466fe 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -26,7 +26,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 0c8e7c89b..2bdaafbd1 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -26,7 +26,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 7e6f48445..303ce73cb 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -41,7 +41,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> </dependency> <dependency> <groupId>org.aspectj</groupId> diff --git a/pom.xml b/pom.xml index ddf703375..b2e225659 100644 --- a/pom.xml +++ b/pom.xml @@ -89,7 +89,7 @@ <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <lambda.core.version>1.3.0</lambda.core.version> + <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> <lambda.serial.version>1.1.6</lambda.serial.version> <maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index fca2fec7b..9bc7c5e37 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -13,7 +13,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> - <lambda.java.core>1.3.0</lambda.java.core> + <lambda.java.core>1.4.0</lambda.java.core> <lambda.java.serialization>1.1.6</lambda.java.serialization> <lambda.java.events>3.16.1</lambda.java.events> <maven.shade.version>3.6.0</maven.shade.version> From a2fdf23a2183276b6fe300320178afd883322bac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 14:57:21 +0200 Subject: [PATCH 426/577] chore: bump sam/build-java21 (#2141) Bumps sam/build-java21 from `853ac90` to `fd3b445`. --- updated-dependencies: - dependency-name: sam/build-java21 dependency-version: fd3b44561b51626c15ae4437630afcfdc84ad883edca64d2cdb87aad755eb7ac dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index 4ce9ad1ed..5086f4532 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:853ac90b359be42f95fe913fde43517ed5f3ed086aa93a6c0bd4b2d8fe07df9d +FROM public.ecr.aws/sam/build-java21@sha256:fd3b44561b51626c15ae4437630afcfdc84ad883edca64d2cdb87aad755eb7ac # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From 87d691b5122fa314a4211041480517da5cf85e11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 14:57:40 +0200 Subject: [PATCH 427/577] chore: bump tj-actions/changed-files from 46.0.5 to 47.0.0 (#2143) Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 46.0.5 to 47.0.0. - [Release notes](https://github.com/tj-actions/changed-files/releases) - [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/changed-files/compare/ed68ef82c095e0d48ec87eccea555d944a631a4c...24d32ffd492484c1d75e0c0b894501ddb9d30d62) --- updated-dependencies: - dependency-name: tj-actions/changed-files dependency-version: 47.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 482ba4186..09a232188 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -96,7 +96,7 @@ jobs: fetch-depth: 0 - name: Get changed files id: changed-files - uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5 + uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: files: | powertools-*/** From 08e7c948f6a633e9f27d9f8df1d0944c6ecb9b02 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 14:57:51 +0200 Subject: [PATCH 428/577] chore: bump squidfunk/mkdocs-material in /docs (#2144) Bumps squidfunk/mkdocs-material from `209b62d` to `86d21da`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: 86d21da4f45f16e30774bf911e5b4795da13ce0cd197dbf8d3d059f256b2cc37 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 6fef5966e..696d43a12 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -FROM squidfunk/mkdocs-material@sha256:209b62dd9530163cc5cf9a49853b5bb8570ffb3f3b5fe4eadc1d319bbda5ce2f +FROM squidfunk/mkdocs-material@sha256:86d21da4f45f16e30774bf911e5b4795da13ce0cd197dbf8d3d059f256b2cc37 COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From 4d9fc6023836a93bb621b45821759bf654462215 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 14:58:52 +0200 Subject: [PATCH 429/577] chore: bump org.codehaus.mojo:versions-maven-plugin (#2148) Bumps [org.codehaus.mojo:versions-maven-plugin](https://github.com/mojohaus/versions) from 2.18.0 to 2.19.1. - [Release notes](https://github.com/mojohaus/versions/releases) - [Changelog](https://github.com/mojohaus/versions/blob/master/ReleaseNotes.md) - [Commits](https://github.com/mojohaus/versions/compare/2.18.0...2.19.1) --- updated-dependencies: - dependency-name: org.codehaus.mojo:versions-maven-plugin dependency-version: 2.19.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b2e225659..cb14997c4 100644 --- a/pom.xml +++ b/pom.xml @@ -112,7 +112,7 @@ <aws-embedded-metrics.version>4.1.2</aws-embedded-metrics.version> <jmespath.version>0.6.0</jmespath.version> <aws.sdk.v1.version>1.12.781</aws.sdk.v1.version> - <versions-maven-plugin.version>2.18.0</versions-maven-plugin.version> + <versions-maven-plugin.version>2.19.1</versions-maven-plugin.version> <elastic.version>1.7.0</elastic.version> <mockito.version>5.19.0</mockito.version> <mockito-junit-jupiter.version>5.19.0</mockito-junit-jupiter.version> From e2707c5b628f34d1c039a9008e9eecad449dd99d Mon Sep 17 00:00:00 2001 From: Kyle Zurawski <39493372+kylez-ithaka@users.noreply.github.com> Date: Tue, 30 Sep 2025 10:41:56 -0400 Subject: [PATCH 430/577] docs(logger): Fix logging environment variables names in documentation (#2161) The table of environment variables had the wrong variable names, even though other references in the same file had the correct values --- docs/core/logging.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/core/logging.md b/docs/core/logging.md index be3bd7e5c..db01a3ec0 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -209,9 +209,9 @@ There are some other environment variables which can be set to modify Logging's | Environment variable | Type | Description | |---------------------------------|----------|-------------------------------------------------------------------------------------------------------------------------| | `POWERTOOLS_LOGGER_SAMPLE_RATE` | float | Configure the sampling rate at which `DEBUG` logs should be included. See [sampling rate](#sampling-debug-logs) | -| `POWERTOOLS_LOG_EVENT` | boolean | Specify if the incoming Lambda event should be logged. See [Logging event](#logging-incoming-event) | -| `POWERTOOLS_LOG_RESPONSE` | boolean | Specify if the Lambda response should be logged. See [logging response](#logging-handler-response) | -| `POWERTOOLS_LOG_ERROR` | boolean | Specify if a Lambda uncaught exception should be logged. See [logging exception](#logging-handler-uncaught-exception ) | +| `POWERTOOLS_LOGGER_LOG_EVENT` | boolean | Specify if the incoming Lambda event should be logged. See [Logging event](#logging-incoming-event) | +| `POWERTOOLS_LOGGER_LOG_RESPONSE` | boolean | Specify if the Lambda response should be logged. See [logging response](#logging-handler-response) | +| `POWERTOOLS_LOGGER_LOG_ERROR` | boolean | Specify if a Lambda uncaught exception should be logged. See [logging exception](#logging-handler-uncaught-exception ) | #### Logging configuration From fe5aef6360a5551bc7aa9d19501c8cf24976b157 Mon Sep 17 00:00:00 2001 From: Ahmed Kamel <humanzz@hotmail.com> Date: Thu, 2 Oct 2025 11:46:20 +0100 Subject: [PATCH 431/577] feat(metrics): introduce Metrics.flushMetrics (#2154) * feat(metrics): introduce Metrics.flushMetrics - introduce `Metrics.flushMetrics` as a more powerful version of `flushSingleMetrics` to allow - using defaults by inheriting state e.g. namespace, dimensions and metadata - emitting multiple metrics in one metrics context - refactor `flushSingleMetrics` to use `flushMetrics` - move namespace/service setting from `MetricsFactory` to `EmfMetricsLogger` * feat(metrics): introduce Metrics.flushMetrics - introduce `Metrics.flushMetrics` as a more powerful version of `flushSingleMetrics` to allow - using defaults by inheriting state e.g. namespace, dimensions and metadata - emitting multiple metrics in one metrics context - refactor `flushSingleMetrics` to use `flushMetrics` - move namespace/service setting from `MetricsFactory` to `EmfMetricsLogger` * address metrics context issue * fix addDimension wrongly adding to defaultDimensions * introduce Metrics.addProperty and use it instead of addMetadata * use flushMetrics in captureColdStartMetric * use putProperty for addMetadata and consolidate duplicate logic * update docs and javadoc * Update docs/core/metrics.md Co-authored-by: Philipp Page <philipp.page@yahoo.de> --------- Co-authored-by: Philipp Page <philipp.page@yahoo.de> --- docs/core/metrics.md | 30 +++--- .../lambda/powertools/metrics/Metrics.java | 27 ++++- .../metrics/internal/EmfMetricsLogger.java | 99 +++++-------------- .../metrics/internal/LambdaMetricsAspect.java | 33 +++---- .../metrics/internal/MetricsUtils.java | 22 +++++ .../internal/EmfMetricsLoggerTest.java | 41 +++++++- .../metrics/testutils/TestMetrics.java | 6 ++ 7 files changed, 140 insertions(+), 118 deletions(-) create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUtils.java diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 61d4c38f0..71c56bb8b 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -462,9 +462,9 @@ If you wish to set custom default dimensions, it can be done via `#!java metrics Overwriting the default dimensions will also overwrite the default `Service` dimension. If you wish to keep `Service` in your default dimensions, you need to add it manually. <!-- prettier-ignore-end --> -### Creating a single metric with different configuration +### Creating metrics with different configuration -You can create a single metric with its own namespace and dimensions using `flushSingleMetric`: +You can create metrics with different configurations e.g. different namespace and/or dimensions using `flushMetrics()`: === "App.java" @@ -480,13 +480,17 @@ You can create a single metric with its own namespace and dimensions using `flus @Override @FlushMetrics(namespace = "ServerlessAirline", service = "payment") public Object handleRequest(Object input, Context context) { - metrics.flushSingleMetric( - "CustomMetric", - 1, - MetricUnit.COUNT, - "CustomNamespace", - DimensionSet.of("CustomDimension", "value") // Dimensions are optional - ); + metrics.flushMetrics((customMetrics) -> { + customMetrics.addMetric("CustomMetric", 1, MetricUnit.COUNT); + // To optionally set a different namespace + customMetrics.setNamespace("CustomNamespace"); + // To optionally set different default dimensions + customMetrics.setDefaultDimensions(DimensionSet.of("CustomDefaultDimension", "value")); + // To optionally append additional dimensions to default dimensions + customMetrics.addDimension(DimensionSet.of("CustomDimension", "value")); + // To optionally add metadata + customMetrics.addMetadata("CustomMetadata", "value")); + }); } } ``` @@ -516,7 +520,7 @@ The following example shows how to configure a custom `Metrics` Singleton using public class App implements RequestHandler<Object, Object> { // Create and configure a Metrics singleton without annotation - private static final Metrics customMetrics = MetricsBuilder.builder() + private static final Metrics metrics = MetricsBuilder.builder() .withNamespace("ServerlessAirline") .withRaiseOnEmptyMetrics(true) .withService("payment") @@ -527,11 +531,11 @@ The following example shows how to configure a custom `Metrics` Singleton using // You can manually capture the cold start metric // Lambda context is an optional argument if not available in your environment // Dimensions are also optional. - customMetrics.captureColdStartMetric(context, DimensionSet.of("FunctionName", "MyFunction", "Service", "payment")); + metrics.captureColdStartMetric(context, DimensionSet.of("FunctionName", "MyFunction", "Service", "payment")); // Add metrics to the custom metrics singleton - customMetrics.addMetric("CustomMetric", 1, MetricUnit.COUNT); - customMetrics.flush(); + metrics.addMetric("CustomMetric", 1, MetricUnit.COUNT); + metrics.flush(); } } ``` diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java index d21fe163e..77db2aba0 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/Metrics.java @@ -16,6 +16,7 @@ import com.amazonaws.services.lambda.runtime.Context; import java.time.Instant; +import java.util.function.Consumer; import software.amazon.lambda.powertools.metrics.model.DimensionSet; import software.amazon.lambda.powertools.metrics.model.MetricResolution; @@ -162,7 +163,15 @@ default void captureColdStartMetric() { } /** - * Flush a single metric with custom dimensions. This creates a separate metrics context + * Flush a separate metrics context that inherits the namespace, default dimensions, and metadata. This creates a separate metrics context + * that doesn't affect the default metrics context. + * + * @param metricsConsumer the consumer to use to edit the metrics instance (e.g. add metrics, override namespace, set or add custom dimensions) before flushing + */ + void flushMetrics(Consumer<Metrics> metricsConsumer); + + /** + * Flush a single metric with custom namespace and dimensions. This creates a separate metrics context * that doesn't affect the default metrics context. * * @param name the name of the metric @@ -171,10 +180,17 @@ default void captureColdStartMetric() { * @param namespace the namespace for the metric * @param dimensions custom dimensions for this metric (optional) */ - void flushSingleMetric(String name, double value, MetricUnit unit, String namespace, DimensionSet dimensions); + default void flushSingleMetric(String name, double value, MetricUnit unit, String namespace, DimensionSet dimensions) { + flushMetrics(metrics -> { + metrics.setNamespace(namespace); + metrics.setDefaultDimensions(dimensions); + metrics.addMetric(name, value, unit); + }); + + } /** - * Flush a single metric with custom dimensions. This creates a separate metrics context + * Flush a single metric with custom namespace. This creates a separate metrics context * that doesn't affect the default metrics context. * * @param name the name of the metric @@ -183,6 +199,9 @@ default void captureColdStartMetric() { * @param namespace the namespace for the metric */ default void flushSingleMetric(String name, double value, MetricUnit unit, String namespace) { - flushSingleMetric(name, value, unit, namespace, null); + flushMetrics(metrics -> { + metrics.setNamespace(namespace); + metrics.addMetric(name, value, unit); + }); } } diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java index c9651585f..37f2d193a 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java @@ -14,7 +14,6 @@ package software.amazon.lambda.powertools.metrics.internal; -import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isColdStart; import java.time.Instant; @@ -22,6 +21,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,16 +43,15 @@ */ public class EmfMetricsLogger implements Metrics { private static final Logger LOGGER = LoggerFactory.getLogger(EmfMetricsLogger.class); - private static final String TRACE_ID_PROPERTY = "xray_trace_id"; - private static final String REQUEST_ID_PROPERTY = "function_request_id"; private static final String COLD_START_METRIC = "ColdStart"; private static final String METRICS_DISABLED_ENV_VAR = "POWERTOOLS_METRICS_DISABLED"; private final software.amazon.cloudwatchlogs.emf.logger.MetricsLogger emfLogger; private final EnvironmentProvider environmentProvider; - private AtomicBoolean raiseOnEmptyMetrics = new AtomicBoolean(false); + private final AtomicBoolean raiseOnEmptyMetrics = new AtomicBoolean(false); private String namespace; private Map<String, String> defaultDimensions = new HashMap<>(); + private final Map<String, Object> properties = new HashMap<>(); private final AtomicBoolean hasMetrics = new AtomicBoolean(false); public EmfMetricsLogger(EnvironmentProvider environmentProvider, MetricsContext metricsContext) { @@ -79,8 +78,6 @@ public void addDimension(software.amazon.lambda.powertools.metrics.model.Dimensi dimensionSet.getDimensions().forEach((key, val) -> { try { emfDimensionSet.addDimension(key, val); - // Update our local copy of default dimensions - defaultDimensions.put(key, val); } catch (Exception e) { // Ignore dimension errors } @@ -91,7 +88,8 @@ public void addDimension(software.amazon.lambda.powertools.metrics.model.Dimensi @Override public void addMetadata(String key, Object value) { - emfLogger.putMetadata(key, value); + emfLogger.putProperty(key, value); + properties.put(key, value); } @Override @@ -173,45 +171,13 @@ public void flush() { public void captureColdStartMetric(Context context, software.amazon.lambda.powertools.metrics.model.DimensionSet dimensions) { if (isColdStart()) { - if (isMetricsDisabled()) { - LOGGER.debug("Metrics are disabled, skipping cold start metric capture"); - return; - } - - Validator.validateNamespace(namespace); - - software.amazon.cloudwatchlogs.emf.logger.MetricsLogger coldStartLogger = new software.amazon.cloudwatchlogs.emf.logger.MetricsLogger(); - - try { - coldStartLogger.setNamespace(namespace); - } catch (Exception e) { - LOGGER.error("Namespace cannot be set for cold start metrics due to an error in EMF", e); - } - - coldStartLogger.putMetric(COLD_START_METRIC, 1, Unit.COUNT); - - // Set dimensions if provided - if (dimensions != null) { - DimensionSet emfDimensionSet = new DimensionSet(); - dimensions.getDimensions().forEach((key, val) -> { - try { - emfDimensionSet.addDimension(key, val); - } catch (Exception e) { - // Ignore dimension errors - } - }); - coldStartLogger.setDimensions(emfDimensionSet); - } - - // Add request ID from context if available - if (context != null && context.getAwsRequestId() != null) { - coldStartLogger.putProperty(REQUEST_ID_PROPERTY, context.getAwsRequestId()); - } - - // Add trace ID using the standard logic - getXrayTraceId().ifPresent(traceId -> coldStartLogger.putProperty(TRACE_ID_PROPERTY, traceId)); - - coldStartLogger.flush(); + flushMetrics(metrics -> { + MetricsUtils.addRequestIdAndXrayTraceIdIfAvailable(context, metrics); + if (dimensions != null) { + metrics.setDefaultDimensions(dimensions); + } + metrics.addMetric(COLD_START_METRIC, 1, MetricUnit.COUNT); + }); } } @@ -221,43 +187,24 @@ public void captureColdStartMetric(software.amazon.lambda.powertools.metrics.mod } @Override - public void flushSingleMetric(String name, double value, MetricUnit unit, String namespace, - software.amazon.lambda.powertools.metrics.model.DimensionSet dimensions) { + public void flushMetrics(Consumer<Metrics> metricsConsumer) { if (isMetricsDisabled()) { LOGGER.debug("Metrics are disabled, skipping single metric flush"); return; } - - Validator.validateNamespace(namespace); - - // Create a new logger for this single metric - software.amazon.cloudwatchlogs.emf.logger.MetricsLogger singleMetricLogger = new software.amazon.cloudwatchlogs.emf.logger.MetricsLogger( - environmentProvider); - - try { - singleMetricLogger.setNamespace(namespace); - } catch (Exception e) { - LOGGER.error("Namespace cannot be set for single metric due to an error in EMF", e); + // Create a new instance, inheriting namespace, default dimensions, and metadata + EmfMetricsLogger metrics = new EmfMetricsLogger(environmentProvider, new MetricsContext()); + if (namespace != null) { + metrics.setNamespace(this.namespace); } - - // Add the metric - singleMetricLogger.putMetric(name, value, convertUnit(unit)); - - // Set dimensions if provided - if (dimensions != null) { - DimensionSet emfDimensionSet = new DimensionSet(); - dimensions.getDimensions().forEach((key, val) -> { - try { - emfDimensionSet.addDimension(key, val); - } catch (Exception e) { - // Ignore dimension errors - } - }); - singleMetricLogger.setDimensions(emfDimensionSet); + if (!defaultDimensions.isEmpty()) { + metrics.setDefaultDimensions(software.amazon.lambda.powertools.metrics.model.DimensionSet.of(defaultDimensions)); } + properties.forEach(metrics::addMetadata); + + metricsConsumer.accept(metrics); - // Flush the metric - singleMetricLogger.flush(); + metrics.flush(); } private boolean isMetricsDisabled() { diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java index 32824e24f..1f0e3ec8c 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspect.java @@ -34,8 +34,6 @@ @Aspect public class LambdaMetricsAspect { - public static final String TRACE_ID_PROPERTY = "xray_trace_id"; - public static final String REQUEST_ID_PROPERTY = "function_request_id"; private static final String SERVICE_DIMENSION = "Service"; private static final String FUNCTION_NAME_ENV_VAR = "POWERTOOLS_METRICS_FUNCTION_NAME"; @@ -90,11 +88,10 @@ public Object around(ProceedingJoinPoint pjp, metricsInstance.setRaiseOnEmptyMetrics(metrics.raiseOnEmptyMetrics()); - // Add trace ID metadata if available - LambdaHandlerProcessor.getXrayTraceId() - .ifPresent(traceId -> metricsInstance.addMetadata(TRACE_ID_PROPERTY, traceId)); + Context extractedContext = extractContext(pjp); + MetricsUtils.addRequestIdAndXrayTraceIdIfAvailable(extractedContext, metricsInstance); - captureColdStartMetricIfEnabled(extractContext(pjp), metrics); + captureColdStartMetricIfEnabled(extractedContext, metrics); try { return pjp.proceed(proceedArgs); @@ -107,40 +104,36 @@ public Object around(ProceedingJoinPoint pjp, return pjp.proceed(proceedArgs); } - private void captureColdStartMetricIfEnabled(Context extractedContext, FlushMetrics metrics) { + private void captureColdStartMetricIfEnabled(Context extractedContext, FlushMetrics flushMetrics) { if (extractedContext == null) { return; } - Metrics metricsInstance = MetricsFactory.getMetricsInstance(); - // This can be null e.g. during unit tests when mocking the Lambda context - if (extractedContext.getAwsRequestId() != null) { - metricsInstance.addMetadata(REQUEST_ID_PROPERTY, extractedContext.getAwsRequestId()); - } + Metrics metrics = MetricsFactory.getMetricsInstance(); // Only capture cold start metrics if enabled on annotation - if (metrics.captureColdStart()) { + if (flushMetrics.captureColdStart()) { // Get function name from annotation or context - String funcName = functionName(metrics, extractedContext); + String funcName = functionName(flushMetrics, extractedContext); - DimensionSet coldStartDimensions = new DimensionSet(); + DimensionSet dimensionSet = new DimensionSet(); // Get service name from metrics instance default dimensions or fallback - String serviceName = metricsInstance.getDefaultDimensions().getDimensions().getOrDefault( + String serviceName = metrics.getDefaultDimensions().getDimensions().getOrDefault( SERVICE_DIMENSION, - serviceNameWithFallback(metrics)); + serviceNameWithFallback(flushMetrics)); // Only add service if it is not undefined if (!LambdaConstants.SERVICE_UNDEFINED.equals(serviceName)) { - coldStartDimensions.addDimension(SERVICE_DIMENSION, serviceName); + dimensionSet.addDimension(SERVICE_DIMENSION, serviceName); } // Add function name if (funcName != null) { - coldStartDimensions.addDimension("FunctionName", funcName); + dimensionSet.addDimension("FunctionName", funcName); } - metricsInstance.captureColdStartMetric(extractedContext, coldStartDimensions); + metrics.captureColdStartMetric(extractedContext, dimensionSet); } } } diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUtils.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUtils.java new file mode 100644 index 000000000..246f6effc --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUtils.java @@ -0,0 +1,22 @@ +package software.amazon.lambda.powertools.metrics.internal; + +import com.amazonaws.services.lambda.runtime.Context; +import software.amazon.lambda.powertools.metrics.Metrics; + +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; + +final class MetricsUtils { + private static final String TRACE_ID_PROPERTY = "xray_trace_id"; + private static final String REQUEST_ID_PROPERTY = "function_request_id"; + + private MetricsUtils() { + // Utility class + } + + static void addRequestIdAndXrayTraceIdIfAvailable(Context context, Metrics metrics) { + if (context != null && context.getAwsRequestId() != null) { + metrics.addMetadata(REQUEST_ID_PROPERTY, context.getAwsRequestId()); + } + getXrayTraceId().ifPresent(traceId -> metrics.addMetadata(TRACE_ID_PROPERTY, traceId)); + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java index 6c324221c..9f793f977 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java @@ -246,7 +246,7 @@ void shouldAddDimensionSet() throws Exception { @Test void shouldThrowExceptionWhenDimensionSetIsNull() { // When/Then - assertThatThrownBy(() -> metrics.addDimension((DimensionSet) null)) + assertThatThrownBy(() -> metrics.addDimension(null)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("DimensionSet cannot be null"); } @@ -263,8 +263,8 @@ void shouldAddMetadata() throws Exception { JsonNode rootNode = objectMapper.readTree(emfOutput); // The metadata is added to the _aws section in the EMF output - assertThat(rootNode.get("_aws").has("CustomMetadata")).isTrue(); - assertThat(rootNode.get("_aws").get("CustomMetadata").asText()).isEqualTo("MetadataValue"); + assertThat(rootNode.has("CustomMetadata")).isTrue(); + assertThat(rootNode.get("CustomMetadata").asText()).isEqualTo("MetadataValue"); } @Test @@ -304,7 +304,7 @@ void shouldGetDefaultDimensions() { @Test void shouldThrowExceptionWhenDefaultDimensionSetIsNull() { // When/Then - assertThatThrownBy(() -> metrics.setDefaultDimensions((DimensionSet) null)) + assertThatThrownBy(() -> metrics.setDefaultDimensions(null)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("DimensionSet cannot be null"); } @@ -346,7 +346,7 @@ void shouldLogWarningOnEmptyMetrics() throws Exception { // Then // Read the log file and check for the warning - String logContent = new String(Files.readAllBytes(logFile.toPath()), StandardCharsets.UTF_8); + String logContent = Files.readString(logFile.toPath(), StandardCharsets.UTF_8); assertThat(logContent).contains("No metrics were emitted"); // No EMF output should be generated assertThat(outputStreamCaptor.toString().trim()).isEmpty(); @@ -446,6 +446,37 @@ void shouldReuseNamespaceForColdStartMetric() throws Exception { .isEqualTo(customNamespace); } + @Test + void shouldFlushMetrics() throws Exception { + // Given + metrics.setNamespace("MainNamespace"); + metrics.setDefaultDimensions(DimensionSet.of("CustomDim", "CustomValue")); + metrics.addDimension(DimensionSet.of("CustomDim2", "CustomValue2")); + metrics.addMetadata("CustomMetadata", "MetadataValue"); + + // When + metrics.flushMetrics(m -> { + m.addMetric("metric-one", 200, MetricUnit.COUNT); + m.addMetric("metric-two", 100, MetricUnit.COUNT); + }); + + // Then + String emfOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(emfOutput); + + assertThat(rootNode.has("metric-one")).isTrue(); + assertThat(rootNode.get("metric-one").asDouble()).isEqualTo(200.0); + assertThat(rootNode.has("metric-two")).isTrue(); + assertThat(rootNode.get("metric-two").asDouble()).isEqualTo(100); + assertThat(rootNode.has("CustomDim")).isTrue(); + assertThat(rootNode.get("CustomDim").asText()).isEqualTo("CustomValue"); + assertThat(rootNode.get("CustomDim2")).isNull(); + assertThat(rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Namespace").asText()) + .isEqualTo("MainNamespace"); + assertThat(rootNode.has("CustomMetadata")).isTrue(); + assertThat(rootNode.get("CustomMetadata").asText()).isEqualTo("MetadataValue"); + } + @Test void shouldFlushSingleMetric() throws Exception { // Given diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetrics.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetrics.java index 949828a13..4a2e33a78 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetrics.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/testutils/TestMetrics.java @@ -2,6 +2,7 @@ import java.time.Instant; import java.util.Collections; +import java.util.function.Consumer; import com.amazonaws.services.lambda.runtime.Context; @@ -77,6 +78,11 @@ public void captureColdStartMetric(DimensionSet dimensions) { // Test placeholder } + @Override + public void flushMetrics(Consumer<Metrics> metricsConsumer) { + // Test placeholder + } + @Override public void flushSingleMetric(String name, double value, MetricUnit unit, String namespace, DimensionSet dimensions) { From 89f7b97c845ceff2b209c0d9994deda7672fc34d Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 2 Oct 2025 13:42:35 +0200 Subject: [PATCH 432/577] Update docs javascript. (#2169) --- docs/javascript/aws-amplify.min.js | 108 ----------------------------- docs/javascript/extra.js | 76 -------------------- mkdocs.yml | 5 +- 3 files changed, 2 insertions(+), 187 deletions(-) delete mode 100644 docs/javascript/aws-amplify.min.js delete mode 100644 docs/javascript/extra.js diff --git a/docs/javascript/aws-amplify.min.js b/docs/javascript/aws-amplify.min.js deleted file mode 100644 index f19b36a50..000000000 --- a/docs/javascript/aws-amplify.min.js +++ /dev/null @@ -1,108 +0,0 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("aws_amplify",[],t):"object"==typeof exports?exports.aws_amplify=t():e.aws_amplify=t()}(this,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=157)}([function(e,t,n){"use strict";n.d(t,"a",(function(){return a})),n.d(t,"b",(function(){return u})),n.d(t,"f",(function(){return c})),n.d(t,"g",(function(){return f})),n.d(t,"h",(function(){return l})),n.d(t,"c",(function(){return h})),n.d(t,"e",(function(){return g})),n.d(t,"d",(function(){return m}));var r=n(1),i=function(){var e=[],t=[],n=new Set,a=function(n){return e.forEach((function(e){n.add(e.middleware,Object(r.__assign)({},e))})),t.forEach((function(e){n.addRelativeTo(e.middleware,Object(r.__assign)({},e))})),n},u=function(e){var t=[];return e.before.forEach((function(e){0===e.before.length&&0===e.after.length?t.push(e):t.push.apply(t,Object(r.__spread)(u(e)))})),t.push(e),e.after.reverse().forEach((function(e){0===e.before.length&&0===e.after.length?t.push(e):t.push.apply(t,Object(r.__spread)(u(e)))})),t},c=function(){var n,i=[],a=[],c={};return e.forEach((function(e){var t=Object(r.__assign)(Object(r.__assign)({},e),{before:[],after:[]});t.name&&(c[t.name]=t),i.push(t)})),t.forEach((function(e){var t=Object(r.__assign)(Object(r.__assign)({},e),{before:[],after:[]});t.name&&(c[t.name]=t),a.push(t)})),a.forEach((function(e){if(e.toMiddleware){var t=c[e.toMiddleware];if(void 0===t)throw new Error(e.toMiddleware+" is not found when adding "+(e.name||"anonymous")+" middleware "+e.relation+" "+e.toMiddleware);"after"===e.relation&&t.after.push(e),"before"===e.relation&&t.before.push(e)}})),(n=i,n.sort((function(e,t){return o[t.step]-o[e.step]||s[t.priority||"normal"]-s[e.priority||"normal"]}))).map(u).reduce((function(e,t){return e.push.apply(e,Object(r.__spread)(t)),e}),[]).map((function(e){return e.middleware}))},f={add:function(t,i){void 0===i&&(i={});var o=i.name,s=Object(r.__assign)({step:"initialize",priority:"normal",middleware:t},i);if(o){if(n.has(o))throw new Error("Duplicate middleware name '"+o+"'");n.add(o)}e.push(s)},addRelativeTo:function(e,i){var o=i.name,s=Object(r.__assign)({middleware:e},i);if(o){if(n.has(o))throw new Error("Duplicated middleware name '"+o+"'");n.add(o)}t.push(s)},clone:function(){return a(i())},use:function(e){e.applyToStack(f)},remove:function(r){return"string"==typeof r?function(r){var i=!1,o=function(e){return!e.name||e.name!==r||(i=!0,n.delete(r),!1)};return e=e.filter(o),t=t.filter(o),i}(r):function(r){var i=!1,o=function(e){return e.middleware!==r||(i=!0,e.name&&n.delete(e.name),!1)};return e=e.filter(o),t=t.filter(o),i}(r)},removeByTag:function(r){var i=!1,o=function(e){var t=e.tags,o=e.name;return!t||!t.includes(r)||(o&&n.delete(o),i=!0,!1)};return e=e.filter(o),t=t.filter(o),i},concat:function(e){var t=a(i());return t.use(e),t},applyToStack:a,resolve:function(e,t){var n,i;try{for(var o=Object(r.__values)(c().reverse()),s=o.next();!s.done;s=o.next()){e=(0,s.value)(e,t)}}catch(e){n={error:e}}finally{try{s&&!s.done&&(i=o.return)&&i.call(o)}finally{if(n)throw n.error}}return e}};return f},o={initialize:5,serialize:4,build:3,finalizeRequest:2,deserialize:1},s={high:3,normal:2,low:1},a=function(){function e(e){this.middlewareStack=i(),this.config=e}return e.prototype.send=function(e,t,n){var r="function"!=typeof t?t:void 0,i="function"==typeof t?t:n,o=e.resolveMiddleware(this.middlewareStack,this.config,r);if(!i)return o(e).then((function(e){return e.output}));o(e).then((function(e){return i(null,e.output)}),(function(e){return i(e)})).catch((function(){}))},e.prototype.destroy=function(){this.config.requestHandler.destroy&&this.config.requestHandler.destroy()},e}(),u=function(){this.middlewareStack=i()};function c(e){return encodeURIComponent(e).replace(/[!'()*]/g,(function(e){return"%"+e.charCodeAt(0).toString(16)}))}var f=function(e){return Array.isArray(e)?e:[e]},l=function(e){for(var t in e)e.hasOwnProperty(t)&&void 0!==e[t]["#text"]?e[t]=e[t]["#text"]:"object"==typeof e[t]&&null!==e[t]&&(e[t]=l(e[t]));return e},d=function(){var e=Object.getPrototypeOf(this).constructor,t=Function.bind.apply(String,Object(r.__spread)([null],arguments)),n=new t;return Object.setPrototypeOf(n,e.prototype),n};d.prototype=Object.create(String.prototype,{constructor:{value:d,enumerable:!1,writable:!0,configurable:!0}}),Object.setPrototypeOf(d,String);var h=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return Object(r.__extends)(t,e),t.prototype.deserializeJSON=function(){return JSON.parse(e.prototype.toString.call(this))},t.prototype.toJSON=function(){return e.prototype.toString.call(this)},t.fromObject=function(e){return e instanceof t?e:new t(e instanceof String||"string"==typeof e?e:JSON.stringify(e))},t}(d),p=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],v=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function g(e){var t=e.getUTCFullYear(),n=e.getUTCMonth(),r=e.getUTCDay(),i=e.getUTCDate(),o=e.getUTCHours(),s=e.getUTCMinutes(),a=e.getUTCSeconds();return p[r]+", "+(i<10?"0"+i:""+i)+" "+v[n]+" "+t+" "+(o<10?"0"+o:""+o)+":"+(s<10?"0"+s:""+s)+":"+(a<10?"0"+a:""+a)+" GMT"}var m="***SensitiveInformation***"},function(e,t,n){"use strict";n.r(t),n.d(t,"__extends",(function(){return i})),n.d(t,"__assign",(function(){return o})),n.d(t,"__rest",(function(){return s})),n.d(t,"__decorate",(function(){return a})),n.d(t,"__param",(function(){return u})),n.d(t,"__metadata",(function(){return c})),n.d(t,"__awaiter",(function(){return f})),n.d(t,"__generator",(function(){return l})),n.d(t,"__createBinding",(function(){return d})),n.d(t,"__exportStar",(function(){return h})),n.d(t,"__values",(function(){return p})),n.d(t,"__read",(function(){return v})),n.d(t,"__spread",(function(){return g})),n.d(t,"__spreadArrays",(function(){return m})),n.d(t,"__await",(function(){return b})),n.d(t,"__asyncGenerator",(function(){return y})),n.d(t,"__asyncDelegator",(function(){return w})),n.d(t,"__asyncValues",(function(){return _})),n.d(t,"__makeTemplateObject",(function(){return S})),n.d(t,"__importStar",(function(){return E})),n.d(t,"__importDefault",(function(){return M})),n.d(t,"__classPrivateFieldGet",(function(){return A})),n.d(t,"__classPrivateFieldSet",(function(){return I})); -/*! ***************************************************************************** -Copyright (c) Microsoft Corporation. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. -***************************************************************************** */ -var r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function i(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var o=function(){return(o=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function s(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n}function a(e,t,n,r){var i,o=arguments.length,s=o<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(o<3?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s}function u(e,t){return function(n,r){t(n,r,e)}}function c(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}function f(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))}function l(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}}function d(e,t,n,r){void 0===r&&(r=n),e[r]=t[n]}function h(e,t){for(var n in e)"default"===n||t.hasOwnProperty(n)||(t[n]=e[n])}function p(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function v(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s}function g(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(v(arguments[t]));return e}function m(){for(var e=0,t=0,n=arguments.length;t<n;t++)e+=arguments[t].length;var r=Array(e),i=0;for(t=0;t<n;t++)for(var o=arguments[t],s=0,a=o.length;s<a;s++,i++)r[i]=o[s];return r}function b(e){return this instanceof b?(this.v=e,this):new b(e)}function y(e,t,n){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var r,i=n.apply(e,t||[]),o=[];return r={},s("next"),s("throw"),s("return"),r[Symbol.asyncIterator]=function(){return this},r;function s(e){i[e]&&(r[e]=function(t){return new Promise((function(n,r){o.push([e,t,n,r])>1||a(e,t)}))})}function a(e,t){try{(n=i[e](t)).value instanceof b?Promise.resolve(n.value.v).then(u,c):f(o[0][2],n)}catch(e){f(o[0][3],e)}var n}function u(e){a("next",e)}function c(e){a("throw",e)}function f(e,t){e(t),o.shift(),o.length&&a(o[0][0],o[0][1])}}function w(e){var t,n;return t={},r("next"),r("throw",(function(e){throw e})),r("return"),t[Symbol.iterator]=function(){return this},t;function r(r,i){t[r]=e[r]?function(t){return(n=!n)?{value:b(e[r](t)),done:"return"===r}:i?i(t):t}:i}}function _(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e=p(e),t={},r("next"),r("throw"),r("return"),t[Symbol.asyncIterator]=function(){return this},t);function r(n){t[n]=e[n]&&function(t){return new Promise((function(r,i){(function(e,t,n,r){Promise.resolve(r).then((function(t){e({value:t,done:n})}),t)})(r,i,(t=e[n](t)).done,t.value)}))}}}function S(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e}function E(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var n in e)Object.hasOwnProperty.call(e,n)&&(t[n]=e[n]);return t.default=e,t}function M(e){return e&&e.__esModule?e:{default:e}}function A(e,t){if(!t.has(e))throw new TypeError("attempted to get private field on non-instance");return t.get(e)}function I(e,t,n){if(!t.has(e))throw new TypeError("attempted to set private field on non-instance");return t.set(e,n),n}},function(e,t,n){"use strict";n.d(t,"b",(function(){return r})),n.d(t,"a",(function(){return o}));var r=function(){function e(e){this.statusCode=e.statusCode,this.headers=e.headers||{},this.body=e.body}return e.isInstance=function(e){if(!e)return!1;var t=e;return"number"==typeof t.statusCode&&"object"==typeof t.headers},e}(),i=n(1),o=function(){function e(e){this.method=e.method||"GET",this.hostname=e.hostname||"localhost",this.port=e.port,this.query=e.query||{},this.headers=e.headers||{},this.body=e.body,this.protocol=e.protocol?":"!==e.protocol.substr(-1)?e.protocol+":":e.protocol:"https:",this.path=e.path?"/"!==e.path.charAt(0)?"/"+e.path:e.path:"/"}return e.isInstance=function(e){if(!e)return!1;var t=e;return"method"in t&&"protocol"in t&&"hostname"in t&&"path"in t&&"object"==typeof t.query&&"object"==typeof t.headers},e.prototype.clone=function(){var t,n=new e(Object(i.__assign)(Object(i.__assign)({},this),{headers:Object(i.__assign)({},this.headers)}));return n.query&&(n.query=(t=n.query,Object.keys(t).reduce((function(e,n){var r,o=t[n];return Object(i.__assign)(Object(i.__assign)({},e),((r={})[n]=Array.isArray(o)?Object(i.__spread)(o):o,r))}),{}))),n},e}()},function(e,t,n){"use strict";n.d(t,"f",(function(){return A})),n.d(t,"t",(function(){return I})),n.d(t,"y",(function(){return k})),n.d(t,"s",(function(){return x})),n.d(t,"e",(function(){return C})),n.d(t,"x",(function(){return P})),n.d(t,"g",(function(){return N})),n.d(t,"h",(function(){return R})),n.d(t,"d",(function(){return D})),n.d(t,"c",(function(){return U})),n.d(t,"b",(function(){return B})),n.d(t,"a",(function(){return j})),n.d(t,"u",(function(){return F})),n.d(t,"v",(function(){return q})),n.d(t,"i",(function(){return K})),n.d(t,"w",(function(){return H})),n.d(t,"j",(function(){return V})),n.d(t,"p",(function(){return G})),n.d(t,"k",(function(){return W})),n.d(t,"q",(function(){return $})),n.d(t,"l",(function(){return Y})),n.d(t,"n",(function(){return J})),n.d(t,"r",(function(){return Z})),n.d(t,"o",(function(){return X})),n.d(t,"m",(function(){return Q}));var r=n(6),i=n(32),o=n.n(i);function s(e){var t=new Error(e);return t.source="ulid",t}var a="0123456789ABCDEFGHJKMNPQRSTVWXYZ",u=a.length,c=Math.pow(2,48)-1;function f(e,t,n){return t>e.length-1?e:e.substr(0,t)+n+e.substr(t+1)}function l(e){var t=Math.floor(e()*u);return t===u&&(t=u-1),a.charAt(t)}function d(e,t){if(isNaN(e))throw new Error(e+" must be a number");if(e>c)throw s("cannot encode time greater than "+c);if(e<0)throw s("time must be positive");if(!1===Number.isInteger(e))throw s("time must be an integer");for(var n=void 0,r="";t>0;t--)r=a.charAt(n=e%u)+r,e=(e-n)/u;return r}function h(e,t){for(var n="";e>0;e--)n=l(t)+n;return n}function p(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=arguments[1];t||(t="undefined"!=typeof window?window:null);var r=t&&(t.crypto||t.msCrypto);if(r)return function(){var e=new Uint8Array(1);return r.getRandomValues(e),e[0]/255};try{var i=n(485);return function(){return i.randomBytes(1).readUInt8()/255}}catch(e){}if(e){try{console.error("secure crypto unusable, falling back to insecure Math.random()!")}catch(e){}return function(){return Math.random()}}throw s("secure crypto unusable, insecure Math.random not allowed")}function v(e){e||(e=p());var t=0,n=void 0;return function(r){if(isNaN(r)&&(r=Date.now()),r<=t){var i=n=function(e){for(var t=void 0,n=e.length,r=void 0,i=void 0,o=u-1;!t&&n-- >=0;){if(r=e[n],-1===(i=a.indexOf(r)))throw s("incorrectly encoded string");i!==o?t=f(e,n,a[i+1]):e=f(e,n,a[0])}if("string"==typeof t)return t;throw s("cannot increment this string")}(n);return d(t,10)+i}t=r;var o=n=h(16,e);return d(r,10)+o}}g||(g=p());var g,m=n(109),b=n(4);function y(e){return(y="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var w,_=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},S=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},E=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},M=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},A=function(e,t){if(void 0===t&&(t=!0),t)throw new Error("Invalid "+e)},I=function(e){return void 0===e||null==e},k=function e(t,n,r){var i,o=!1;if(0===r.length)return!0;switch(n){case"not":i="every",o=!0;break;case"and":i="every";break;case"or":i="some";break;default:A(n)}var s=r[i]((function(n){if(Object(b.k)(n)){var r=n.field,i=n.operator,o=n.operand,s=t[r];return O(s,i,o)}if(Object(b.j)(n)){var a=n.type,u=n.predicates;return e(t,a,u)}throw new Error("Not a predicate or group")}));return o?!s:s},O=function(e,t,n){switch(t){case"ne":return e!==n;case"eq":return e===n;case"le":return e<=n;case"lt":return e<n;case"ge":return e>=n;case"gt":return e>n;case"between":var r=E(n,2),i=r[0],o=r[1];return e>=i&&e<=o;case"beginsWith":return e.startsWith(n);case"contains":return e.indexOf(n)>-1;case"notContains":return-1===e.indexOf(n);default:return A(t,!1),!1}},x=function(e){return e&&"function"==typeof e.copyOf},C=function(e){var t={};return Object.keys(e.models).forEach((function(n){t[n]={indexes:[],relationTypes:[]};var r=e.models[n];Object.keys(r.fields).forEach((function(e){var i=r.fields[e];if("object"===y(i.type)&&"model"in i.type){var o=i.association.connectionType;t[n].relationTypes.push({fieldName:i.name,modelName:i.type.model,relationType:o,targetName:i.association.targetName,associatedWith:i.association.associatedWith}),"BELONGS_TO"===o&&t[n].indexes.push(i.association.targetName)}})),r.attributes&&r.attributes.forEach((function(e){if("key"===e.type){var r=e.properties.fields;r&&r.forEach((function(e){t[n].indexes.includes(e)||t[n].indexes.push(e)}))}}))})),t},T=new WeakMap,P=function(e,t,n,r,i){var o=n.relationships,s=i(n.name,e),a=o[e],u=[],c=s.copyOf(t,(function(e){a.relationTypes.forEach((function(o){var s=i(n.name,o.modelName);switch(o.relationType){case"HAS_ONE":if(t[o.fieldName]){var a=void 0;try{a=r(s,t[o.fieldName])}catch(e){}u.push({modelName:o.modelName,item:t[o.fieldName],instance:a}),e[o.fieldName]=e[o.fieldName].id}break;case"BELONGS_TO":if(t[o.fieldName]){a=void 0;try{a=r(s,t[o.fieldName])}catch(e){}e[o.fieldName]._deleted||u.push({modelName:o.modelName,item:t[o.fieldName],instance:a})}e[o.targetName]=e[o.fieldName]?e[o.fieldName].id:null,delete e[o.fieldName];break;case"HAS_MANY":break;default:A(o.relationType)}}))}));u.unshift({modelName:e,item:c,instance:c}),T.has(n)||T.set(n,Array.from(n.modelTopologicalOrdering.keys()));var f=T.get(n);return u.sort((function(e,t){return f.indexOf(e.modelName)-f.indexOf(t.modelName)})),u},N=function(e,t){var n="";return e.some((function(e){e.modelName===t&&(n=e.targetName)})),n},R=function(e,t){return e.find((function(e){return e===t}))};!function(e){e.DATASTORE="datastore",e.USER="user",e.SYNC="sync",e.STORAGE="storage"}(w||(w={}));var L,j=w.DATASTORE,D=w.USER,U=w.SYNC,B=w.STORAGE,F=function(){return new Promise((function(e){var t,n=Object(m.v4)(),r=function(){L=!1,e(!0)},i=function(){return _(void 0,void 0,void 0,(function(){return S(this,(function(r){switch(r.label){case 0:return t&&t.result&&"function"==typeof t.result.close?[4,t.result.close()]:[3,2];case 1:r.sent(),r.label=2;case 2:return[4,indexedDB.deleteDatabase(n)];case 3:return r.sent(),L=!0,[2,e(!1)]}}))}))};return!0===L?i():!1===L||null===indexedDB?r():((t=indexedDB.open(n)).onerror=r,void(t.onsuccess=i))}))},z=function(){return(e=1,r.Buffer.from(o.a.lib.WordArray.random(e).toString(),"hex")).readUInt8(0)/255;var e};function q(e){var t=v(z);return function(){return t(e)}}function K(){return"undefined"!=typeof performance&&performance&&"function"==typeof performance.now?0|performance.now():Date.now()}function H(e){return function(t,n){var r,i;try{for(var o=M(e),s=o.next();!s.done;s=o.next()){var a=s.value,u=a.field,c=a.sortDirection===b.e.ASCENDING?1:-1;if(t[u]<n[u])return-1*c;if(t[u]>n[u])return 1*c}}catch(e){r={error:e}}finally{try{s&&!s.done&&(i=o.return)&&i.call(o)}finally{if(r)throw r.error}}return 0}}var V=function(e){return!!/^\d{4}-\d{2}-\d{2}(Z|[+-]\d{2}:\d{2}($|:\d{2}))?$/.exec(e)},G=function(e){return!!/^\d{2}:\d{2}(:\d{2}(.\d+)?)?(Z|[+-]\d{2}:\d{2}($|:\d{2}))?$/.exec(e)},W=function(e){return!!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(.\d+)?)?(Z|[+-]\d{2}:\d{2}($|:\d{2}))?$/.exec(e)},$=function(e){return!!/^\d+$/.exec(String(e))},Y=function(e){return!!/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.exec(e)},J=function(e){try{return JSON.parse(e),!0}catch(e){return!1}},Z=function(e){try{return!!new URL(e)}catch(e){return!1}},X=function(e){return!!/^\+?\d[\d\s-]+$/.exec(e)},Q=function(e){return!!/((^((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))$)|(^((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?$))$/.exec(e)}},function(e,t,n){"use strict";n.d(t,"l",(function(){return f})),n.d(t,"m",(function(){return l})),n.d(t,"b",(function(){return r})),n.d(t,"g",(function(){return d})),n.d(t,"h",(function(){return h})),n.d(t,"i",(function(){return p})),n.d(t,"f",(function(){return v})),n.d(t,"c",(function(){return i})),n.d(t,"k",(function(){return g})),n.d(t,"j",(function(){return m})),n.d(t,"d",(function(){return o})),n.d(t,"e",(function(){return s})),n.d(t,"n",(function(){return b})),n.d(t,"a",(function(){return y}));var r,i,o,s,a=n(3),u=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},c=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}};function f(e){return e&&void 0!==e.pluralName}function l(e){return e&&e.targetName}function d(e){return e&&void 0!==r[e]}function h(e){return!(!e||!e.model)}function p(e){return!(!e||!e.nonModel)}function v(e){return!(!e||!e.enum)}function g(e){return e&&void 0!==e.field}function m(e){return e&&void 0!==e.type}function b(e,t){return u(this,void 0,void 0,(function(){return c(this,(function(n){return[2,{modelConstructor:e,conditionProducer:t}]}))}))}!function(e){e[e.ID=0]="ID",e[e.String=1]="String",e[e.Int=2]="Int",e[e.Float=3]="Float",e[e.Boolean=4]="Boolean",e[e.AWSDate=5]="AWSDate",e[e.AWSTime=6]="AWSTime",e[e.AWSDateTime=7]="AWSDateTime",e[e.AWSTimestamp=8]="AWSTimestamp",e[e.AWSEmail=9]="AWSEmail",e[e.AWSJSON=10]="AWSJSON",e[e.AWSURL=11]="AWSURL",e[e.AWSPhone=12]="AWSPhone",e[e.AWSIPAddress=13]="AWSIPAddress"}(r||(r={})),function(e){e.getJSType=function(e){switch(e){case"Boolean":return"boolean";case"ID":case"String":case"AWSDate":case"AWSTime":case"AWSDateTime":case"AWSEmail":case"AWSJSON":case"AWSURL":case"AWSPhone":case"AWSIPAddress":return"string";case"Int":case"Float":case"AWSTimestamp":return"number";default:Object(a.f)(e)}},e.getValidationFunction=function(e){switch(e){case"AWSDate":return a.j;case"AWSTime":return a.p;case"AWSDateTime":return a.k;case"AWSTimestamp":return a.q;case"AWSEmail":return a.l;case"AWSJSON":return a.n;case"AWSURL":return a.r;case"AWSPhone":return a.o;case"AWSIPAddress":return a.m;default:return}}}(r||(r={})),function(e){e.INSERT="INSERT",e.UPDATE="UPDATE",e.DELETE="DELETE"}(i||(i={})),function(e){e[e.FIRST=0]="FIRST",e[e.LAST=1]="LAST"}(o||(o={})),function(e){e.ASCENDING="ASCENDING",e.DESCENDING="DESCENDING"}(s||(s={}));var y=Symbol("DISCARD")},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=n(19),i=n(50),o=(n(142),n(89),{userAgent:i.a.userAgent});r.a},function(e,t,n){"use strict";(function(e){ -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh <http://feross.org> - * @license MIT - */ -var r=n(269),i=n(270),o=n(160);function s(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(e,t){if(s()<t)throw new RangeError("Invalid typed array length");return u.TYPED_ARRAY_SUPPORT?(e=new Uint8Array(t)).__proto__=u.prototype:(null===e&&(e=new u(t)),e.length=t),e}function u(e,t,n){if(!(u.TYPED_ARRAY_SUPPORT||this instanceof u))return new u(e,t,n);if("number"==typeof e){if("string"==typeof t)throw new Error("If encoding is specified then the first argument must be a string");return l(this,e)}return c(this,e,t,n)}function c(e,t,n,r){if("number"==typeof t)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&t instanceof ArrayBuffer?function(e,t,n,r){if(t.byteLength,n<0||t.byteLength<n)throw new RangeError("'offset' is out of bounds");if(t.byteLength<n+(r||0))throw new RangeError("'length' is out of bounds");t=void 0===n&&void 0===r?new Uint8Array(t):void 0===r?new Uint8Array(t,n):new Uint8Array(t,n,r);u.TYPED_ARRAY_SUPPORT?(e=t).__proto__=u.prototype:e=d(e,t);return e}(e,t,n,r):"string"==typeof t?function(e,t,n){"string"==typeof n&&""!==n||(n="utf8");if(!u.isEncoding(n))throw new TypeError('"encoding" must be a valid string encoding');var r=0|p(t,n),i=(e=a(e,r)).write(t,n);i!==r&&(e=e.slice(0,i));return e}(e,t,n):function(e,t){if(u.isBuffer(t)){var n=0|h(t.length);return 0===(e=a(e,n)).length||t.copy(e,0,0,n),e}if(t){if("undefined"!=typeof ArrayBuffer&&t.buffer instanceof ArrayBuffer||"length"in t)return"number"!=typeof t.length||(r=t.length)!=r?a(e,0):d(e,t);if("Buffer"===t.type&&o(t.data))return d(e,t.data)}var r;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(e,t)}function f(e){if("number"!=typeof e)throw new TypeError('"size" argument must be a number');if(e<0)throw new RangeError('"size" argument must not be negative')}function l(e,t){if(f(t),e=a(e,t<0?0:0|h(t)),!u.TYPED_ARRAY_SUPPORT)for(var n=0;n<t;++n)e[n]=0;return e}function d(e,t){var n=t.length<0?0:0|h(t.length);e=a(e,n);for(var r=0;r<n;r+=1)e[r]=255&t[r];return e}function h(e){if(e>=s())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s().toString(16)+" bytes");return 0|e}function p(e,t){if(u.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var n=e.length;if(0===n)return 0;for(var r=!1;;)switch(t){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return F(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return z(e).length;default:if(r)return F(e).length;t=(""+t).toLowerCase(),r=!0}}function v(e,t,n){var r=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if((n>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return x(this,t,n);case"utf8":case"utf-8":return I(this,t,n);case"ascii":return k(this,t,n);case"latin1":case"binary":return O(this,t,n);case"base64":return A(this,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return C(this,t,n);default:if(r)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),r=!0}}function g(e,t,n){var r=e[t];e[t]=e[n],e[n]=r}function m(e,t,n,r,i){if(0===e.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=i?0:e.length-1),n<0&&(n=e.length+n),n>=e.length){if(i)return-1;n=e.length-1}else if(n<0){if(!i)return-1;n=0}if("string"==typeof t&&(t=u.from(t,r)),u.isBuffer(t))return 0===t.length?-1:b(e,t,n,r,i);if("number"==typeof t)return t&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(e,t,n):Uint8Array.prototype.lastIndexOf.call(e,t,n):b(e,[t],n,r,i);throw new TypeError("val must be string, number or Buffer")}function b(e,t,n,r,i){var o,s=1,a=e.length,u=t.length;if(void 0!==r&&("ucs2"===(r=String(r).toLowerCase())||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(e.length<2||t.length<2)return-1;s=2,a/=2,u/=2,n/=2}function c(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(i){var f=-1;for(o=n;o<a;o++)if(c(e,o)===c(t,-1===f?0:o-f)){if(-1===f&&(f=o),o-f+1===u)return f*s}else-1!==f&&(o-=o-f),f=-1}else for(n+u>a&&(n=a-u),o=n;o>=0;o--){for(var l=!0,d=0;d<u;d++)if(c(e,o+d)!==c(t,d)){l=!1;break}if(l)return o}return-1}function y(e,t,n,r){n=Number(n)||0;var i=e.length-n;r?(r=Number(r))>i&&(r=i):r=i;var o=t.length;if(o%2!=0)throw new TypeError("Invalid hex string");r>o/2&&(r=o/2);for(var s=0;s<r;++s){var a=parseInt(t.substr(2*s,2),16);if(isNaN(a))return s;e[n+s]=a}return s}function w(e,t,n,r){return q(F(t,e.length-n),e,n,r)}function _(e,t,n,r){return q(function(e){for(var t=[],n=0;n<e.length;++n)t.push(255&e.charCodeAt(n));return t}(t),e,n,r)}function S(e,t,n,r){return _(e,t,n,r)}function E(e,t,n,r){return q(z(t),e,n,r)}function M(e,t,n,r){return q(function(e,t){for(var n,r,i,o=[],s=0;s<e.length&&!((t-=2)<0);++s)n=e.charCodeAt(s),r=n>>8,i=n%256,o.push(i),o.push(r);return o}(t,e.length-n),e,n,r)}function A(e,t,n){return 0===t&&n===e.length?r.fromByteArray(e):r.fromByteArray(e.slice(t,n))}function I(e,t,n){n=Math.min(e.length,n);for(var r=[],i=t;i<n;){var o,s,a,u,c=e[i],f=null,l=c>239?4:c>223?3:c>191?2:1;if(i+l<=n)switch(l){case 1:c<128&&(f=c);break;case 2:128==(192&(o=e[i+1]))&&(u=(31&c)<<6|63&o)>127&&(f=u);break;case 3:o=e[i+1],s=e[i+2],128==(192&o)&&128==(192&s)&&(u=(15&c)<<12|(63&o)<<6|63&s)>2047&&(u<55296||u>57343)&&(f=u);break;case 4:o=e[i+1],s=e[i+2],a=e[i+3],128==(192&o)&&128==(192&s)&&128==(192&a)&&(u=(15&c)<<18|(63&o)<<12|(63&s)<<6|63&a)>65535&&u<1114112&&(f=u)}null===f?(f=65533,l=1):f>65535&&(f-=65536,r.push(f>>>10&1023|55296),f=56320|1023&f),r.push(f),i+=l}return function(e){var t=e.length;if(t<=4096)return String.fromCharCode.apply(String,e);var n="",r=0;for(;r<t;)n+=String.fromCharCode.apply(String,e.slice(r,r+=4096));return n}(r)}t.Buffer=u,t.SlowBuffer=function(e){+e!=e&&(e=0);return u.alloc(+e)},t.INSPECT_MAX_BYTES=50,u.TYPED_ARRAY_SUPPORT=void 0!==e.TYPED_ARRAY_SUPPORT?e.TYPED_ARRAY_SUPPORT:function(){try{var e=new Uint8Array(1);return e.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===e.foo()&&"function"==typeof e.subarray&&0===e.subarray(1,1).byteLength}catch(e){return!1}}(),t.kMaxLength=s(),u.poolSize=8192,u._augment=function(e){return e.__proto__=u.prototype,e},u.from=function(e,t,n){return c(null,e,t,n)},u.TYPED_ARRAY_SUPPORT&&(u.prototype.__proto__=Uint8Array.prototype,u.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&u[Symbol.species]===u&&Object.defineProperty(u,Symbol.species,{value:null,configurable:!0})),u.alloc=function(e,t,n){return function(e,t,n,r){return f(t),t<=0?a(e,t):void 0!==n?"string"==typeof r?a(e,t).fill(n,r):a(e,t).fill(n):a(e,t)}(null,e,t,n)},u.allocUnsafe=function(e){return l(null,e)},u.allocUnsafeSlow=function(e){return l(null,e)},u.isBuffer=function(e){return!(null==e||!e._isBuffer)},u.compare=function(e,t){if(!u.isBuffer(e)||!u.isBuffer(t))throw new TypeError("Arguments must be Buffers");if(e===t)return 0;for(var n=e.length,r=t.length,i=0,o=Math.min(n,r);i<o;++i)if(e[i]!==t[i]){n=e[i],r=t[i];break}return n<r?-1:r<n?1:0},u.isEncoding=function(e){switch(String(e).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},u.concat=function(e,t){if(!o(e))throw new TypeError('"list" argument must be an Array of Buffers');if(0===e.length)return u.alloc(0);var n;if(void 0===t)for(t=0,n=0;n<e.length;++n)t+=e[n].length;var r=u.allocUnsafe(t),i=0;for(n=0;n<e.length;++n){var s=e[n];if(!u.isBuffer(s))throw new TypeError('"list" argument must be an Array of Buffers');s.copy(r,i),i+=s.length}return r},u.byteLength=p,u.prototype._isBuffer=!0,u.prototype.swap16=function(){var e=this.length;if(e%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var t=0;t<e;t+=2)g(this,t,t+1);return this},u.prototype.swap32=function(){var e=this.length;if(e%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var t=0;t<e;t+=4)g(this,t,t+3),g(this,t+1,t+2);return this},u.prototype.swap64=function(){var e=this.length;if(e%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var t=0;t<e;t+=8)g(this,t,t+7),g(this,t+1,t+6),g(this,t+2,t+5),g(this,t+3,t+4);return this},u.prototype.toString=function(){var e=0|this.length;return 0===e?"":0===arguments.length?I(this,0,e):v.apply(this,arguments)},u.prototype.equals=function(e){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===u.compare(this,e)},u.prototype.inspect=function(){var e="",n=t.INSPECT_MAX_BYTES;return this.length>0&&(e=this.toString("hex",0,n).match(/.{2}/g).join(" "),this.length>n&&(e+=" ... ")),"<Buffer "+e+">"},u.prototype.compare=function(e,t,n,r,i){if(!u.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===n&&(n=e?e.length:0),void 0===r&&(r=0),void 0===i&&(i=this.length),t<0||n>e.length||r<0||i>this.length)throw new RangeError("out of range index");if(r>=i&&t>=n)return 0;if(r>=i)return-1;if(t>=n)return 1;if(this===e)return 0;for(var o=(i>>>=0)-(r>>>=0),s=(n>>>=0)-(t>>>=0),a=Math.min(o,s),c=this.slice(r,i),f=e.slice(t,n),l=0;l<a;++l)if(c[l]!==f[l]){o=c[l],s=f[l];break}return o<s?-1:s<o?1:0},u.prototype.includes=function(e,t,n){return-1!==this.indexOf(e,t,n)},u.prototype.indexOf=function(e,t,n){return m(this,e,t,n,!0)},u.prototype.lastIndexOf=function(e,t,n){return m(this,e,t,n,!1)},u.prototype.write=function(e,t,n,r){if(void 0===t)r="utf8",n=this.length,t=0;else if(void 0===n&&"string"==typeof t)r=t,n=this.length,t=0;else{if(!isFinite(t))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");t|=0,isFinite(n)?(n|=0,void 0===r&&(r="utf8")):(r=n,n=void 0)}var i=this.length-t;if((void 0===n||n>i)&&(n=i),e.length>0&&(n<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var o=!1;;)switch(r){case"hex":return y(this,e,t,n);case"utf8":case"utf-8":return w(this,e,t,n);case"ascii":return _(this,e,t,n);case"latin1":case"binary":return S(this,e,t,n);case"base64":return E(this,e,t,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return M(this,e,t,n);default:if(o)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),o=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function k(e,t,n){var r="";n=Math.min(e.length,n);for(var i=t;i<n;++i)r+=String.fromCharCode(127&e[i]);return r}function O(e,t,n){var r="";n=Math.min(e.length,n);for(var i=t;i<n;++i)r+=String.fromCharCode(e[i]);return r}function x(e,t,n){var r=e.length;(!t||t<0)&&(t=0),(!n||n<0||n>r)&&(n=r);for(var i="",o=t;o<n;++o)i+=B(e[o]);return i}function C(e,t,n){for(var r=e.slice(t,n),i="",o=0;o<r.length;o+=2)i+=String.fromCharCode(r[o]+256*r[o+1]);return i}function T(e,t,n){if(e%1!=0||e<0)throw new RangeError("offset is not uint");if(e+t>n)throw new RangeError("Trying to access beyond buffer length")}function P(e,t,n,r,i,o){if(!u.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>i||t<o)throw new RangeError('"value" argument is out of bounds');if(n+r>e.length)throw new RangeError("Index out of range")}function N(e,t,n,r){t<0&&(t=65535+t+1);for(var i=0,o=Math.min(e.length-n,2);i<o;++i)e[n+i]=(t&255<<8*(r?i:1-i))>>>8*(r?i:1-i)}function R(e,t,n,r){t<0&&(t=4294967295+t+1);for(var i=0,o=Math.min(e.length-n,4);i<o;++i)e[n+i]=t>>>8*(r?i:3-i)&255}function L(e,t,n,r,i,o){if(n+r>e.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function j(e,t,n,r,o){return o||L(e,0,n,4),i.write(e,t,n,r,23,4),n+4}function D(e,t,n,r,o){return o||L(e,0,n,8),i.write(e,t,n,r,52,8),n+8}u.prototype.slice=function(e,t){var n,r=this.length;if((e=~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),(t=void 0===t?r:~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),t<e&&(t=e),u.TYPED_ARRAY_SUPPORT)(n=this.subarray(e,t)).__proto__=u.prototype;else{var i=t-e;n=new u(i,void 0);for(var o=0;o<i;++o)n[o]=this[o+e]}return n},u.prototype.readUIntLE=function(e,t,n){e|=0,t|=0,n||T(e,t,this.length);for(var r=this[e],i=1,o=0;++o<t&&(i*=256);)r+=this[e+o]*i;return r},u.prototype.readUIntBE=function(e,t,n){e|=0,t|=0,n||T(e,t,this.length);for(var r=this[e+--t],i=1;t>0&&(i*=256);)r+=this[e+--t]*i;return r},u.prototype.readUInt8=function(e,t){return t||T(e,1,this.length),this[e]},u.prototype.readUInt16LE=function(e,t){return t||T(e,2,this.length),this[e]|this[e+1]<<8},u.prototype.readUInt16BE=function(e,t){return t||T(e,2,this.length),this[e]<<8|this[e+1]},u.prototype.readUInt32LE=function(e,t){return t||T(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},u.prototype.readUInt32BE=function(e,t){return t||T(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},u.prototype.readIntLE=function(e,t,n){e|=0,t|=0,n||T(e,t,this.length);for(var r=this[e],i=1,o=0;++o<t&&(i*=256);)r+=this[e+o]*i;return r>=(i*=128)&&(r-=Math.pow(2,8*t)),r},u.prototype.readIntBE=function(e,t,n){e|=0,t|=0,n||T(e,t,this.length);for(var r=t,i=1,o=this[e+--r];r>0&&(i*=256);)o+=this[e+--r]*i;return o>=(i*=128)&&(o-=Math.pow(2,8*t)),o},u.prototype.readInt8=function(e,t){return t||T(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},u.prototype.readInt16LE=function(e,t){t||T(e,2,this.length);var n=this[e]|this[e+1]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt16BE=function(e,t){t||T(e,2,this.length);var n=this[e+1]|this[e]<<8;return 32768&n?4294901760|n:n},u.prototype.readInt32LE=function(e,t){return t||T(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},u.prototype.readInt32BE=function(e,t){return t||T(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},u.prototype.readFloatLE=function(e,t){return t||T(e,4,this.length),i.read(this,e,!0,23,4)},u.prototype.readFloatBE=function(e,t){return t||T(e,4,this.length),i.read(this,e,!1,23,4)},u.prototype.readDoubleLE=function(e,t){return t||T(e,8,this.length),i.read(this,e,!0,52,8)},u.prototype.readDoubleBE=function(e,t){return t||T(e,8,this.length),i.read(this,e,!1,52,8)},u.prototype.writeUIntLE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||P(this,e,t,n,Math.pow(2,8*n)-1,0);var i=1,o=0;for(this[t]=255&e;++o<n&&(i*=256);)this[t+o]=e/i&255;return t+n},u.prototype.writeUIntBE=function(e,t,n,r){(e=+e,t|=0,n|=0,r)||P(this,e,t,n,Math.pow(2,8*n)-1,0);var i=n-1,o=1;for(this[t+i]=255&e;--i>=0&&(o*=256);)this[t+i]=e/o&255;return t+n},u.prototype.writeUInt8=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,1,255,0),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},u.prototype.writeUInt16LE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},u.prototype.writeUInt16BE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},u.prototype.writeUInt32LE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):R(this,e,t,!0),t+4},u.prototype.writeUInt32BE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):R(this,e,t,!1),t+4},u.prototype.writeIntLE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);P(this,e,t,n,i-1,-i)}var o=0,s=1,a=0;for(this[t]=255&e;++o<n&&(s*=256);)e<0&&0===a&&0!==this[t+o-1]&&(a=1),this[t+o]=(e/s>>0)-a&255;return t+n},u.prototype.writeIntBE=function(e,t,n,r){if(e=+e,t|=0,!r){var i=Math.pow(2,8*n-1);P(this,e,t,n,i-1,-i)}var o=n-1,s=1,a=0;for(this[t+o]=255&e;--o>=0&&(s*=256);)e<0&&0===a&&0!==this[t+o+1]&&(a=1),this[t+o]=(e/s>>0)-a&255;return t+n},u.prototype.writeInt8=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,1,127,-128),u.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},u.prototype.writeInt16LE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):N(this,e,t,!0),t+2},u.prototype.writeInt16BE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):N(this,e,t,!1),t+2},u.prototype.writeInt32LE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):R(this,e,t,!0),t+4},u.prototype.writeInt32BE=function(e,t,n){return e=+e,t|=0,n||P(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),u.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):R(this,e,t,!1),t+4},u.prototype.writeFloatLE=function(e,t,n){return j(this,e,t,!0,n)},u.prototype.writeFloatBE=function(e,t,n){return j(this,e,t,!1,n)},u.prototype.writeDoubleLE=function(e,t,n){return D(this,e,t,!0,n)},u.prototype.writeDoubleBE=function(e,t,n){return D(this,e,t,!1,n)},u.prototype.copy=function(e,t,n,r){if(n||(n=0),r||0===r||(r=this.length),t>=e.length&&(t=e.length),t||(t=0),r>0&&r<n&&(r=n),r===n)return 0;if(0===e.length||0===this.length)return 0;if(t<0)throw new RangeError("targetStart out of bounds");if(n<0||n>=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),e.length-t<r-n&&(r=e.length-t+n);var i,o=r-n;if(this===e&&n<t&&t<r)for(i=o-1;i>=0;--i)e[i+t]=this[i+n];else if(o<1e3||!u.TYPED_ARRAY_SUPPORT)for(i=0;i<o;++i)e[i+t]=this[i+n];else Uint8Array.prototype.set.call(e,this.subarray(n,n+o),t);return o},u.prototype.fill=function(e,t,n,r){if("string"==typeof e){if("string"==typeof t?(r=t,t=0,n=this.length):"string"==typeof n&&(r=n,n=this.length),1===e.length){var i=e.charCodeAt(0);i<256&&(e=i)}if(void 0!==r&&"string"!=typeof r)throw new TypeError("encoding must be a string");if("string"==typeof r&&!u.isEncoding(r))throw new TypeError("Unknown encoding: "+r)}else"number"==typeof e&&(e&=255);if(t<0||this.length<t||this.length<n)throw new RangeError("Out of range index");if(n<=t)return this;var o;if(t>>>=0,n=void 0===n?this.length:n>>>0,e||(e=0),"number"==typeof e)for(o=t;o<n;++o)this[o]=e;else{var s=u.isBuffer(e)?e:F(new u(e,r).toString()),a=s.length;for(o=0;o<n-t;++o)this[o+t]=s[o%a]}return this};var U=/[^+\/0-9A-Za-z-_]/g;function B(e){return e<16?"0"+e.toString(16):e.toString(16)}function F(e,t){var n;t=t||1/0;for(var r=e.length,i=null,o=[],s=0;s<r;++s){if((n=e.charCodeAt(s))>55295&&n<57344){if(!i){if(n>56319){(t-=3)>-1&&o.push(239,191,189);continue}if(s+1===r){(t-=3)>-1&&o.push(239,191,189);continue}i=n;continue}if(n<56320){(t-=3)>-1&&o.push(239,191,189),i=n;continue}n=65536+(i-55296<<10|n-56320)}else i&&(t-=3)>-1&&o.push(239,191,189);if(i=null,n<128){if((t-=1)<0)break;o.push(n)}else if(n<2048){if((t-=2)<0)break;o.push(n>>6|192,63&n|128)}else if(n<65536){if((t-=3)<0)break;o.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;o.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return o}function z(e){return r.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(U,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function q(e,t,n,r){for(var i=0;i<r&&!(i+n>=t.length||i>=e.length);++i)t[i+n]=e[i];return i}}).call(this,n(31))},function(e,t){"function"==typeof Object.create?e.exports=function(e,t){t&&(e.super_=t,e.prototype=Object.create(t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}))}:e.exports=function(e,t){if(t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}}},function(e,t,n){ -/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */ -var r=n(6),i=r.Buffer;function o(e,t){for(var n in e)t[n]=e[n]}function s(e,t,n){return i(e,t,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=r:(o(r,t),t.Buffer=s),s.prototype=Object.create(i.prototype),o(i,s),s.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return i(e,t,n)},s.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=i(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},s.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return i(e)},s.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){"use strict";n.d(t,"c",(function(){return o})),n.d(t,"b",(function(){return s})),n.d(t,"a",(function(){return a}));var r=n(3),i=new WeakSet;function o(e){return i.has(e)}Symbol("A predicate that matches all records");var s=function(){function e(){}return Object.defineProperty(e,"ALL",{get:function(){var e=function(e){return e};return i.add(e),e},enumerable:!0,configurable:!0}),e}(),a=function(){function e(){}return e.createPredicateBuilder=function(t){var n,i=t.name,o=new Set(Object.keys(t.fields)),s=new Proxy({},n={get:function(t,s,a){var u=s;switch(u){case"and":case"or":case"not":return function(t){var r={type:u,predicates:[]},i=new Proxy({},n);return e.predicateGroupsMap.set(i,r),t(i),e.predicateGroupsMap.get(a).predicates.push(r),a};default:Object(r.f)(u,!1)}var c=s;if(!o.has(c))throw new Error("Invalid field for model. field: "+c+", model: "+i);return function(t,n){return e.predicateGroupsMap.get(a).predicates.push({field:c,operator:t,operand:n}),a}}});return e.predicateGroupsMap.set(s,{type:"and",predicates:[]}),s},e.isValidPredicate=function(t){return e.predicateGroupsMap.has(t)},e.getPredicates=function(t,n){if(void 0===n&&(n=!0),n&&!e.isValidPredicate(t))throw new Error("The predicate is not valid");return e.predicateGroupsMap.get(t)},e.createFromExisting=function(t,n){if(n&&t)return n(e.createPredicateBuilder(t))},e.createForId=function(t,n){return e.createPredicateBuilder(t).id("eq",n)},e.predicateGroupsMap=new WeakMap,e}()},function(e,t,n){"use strict";n.d(t,"a",(function(){return s}));var r=n(1),i={name:"deserializerMiddleware",step:"deserialize",tags:["DESERIALIZER"]},o={name:"serializerMiddleware",step:"serialize",tags:["SERIALIZER"]};function s(e,t,n){return{applyToStack:function(s){s.add(function(e,t){return function(n,i){return function(o){return Object(r.__awaiter)(void 0,void 0,void 0,(function(){var s,a,u,c,f;return Object(r.__generator)(this,(function(l){switch(l.label){case 0:return s=i.logger,a=i.outputFilterSensitiveLog,[4,n(o)];case 1:return u=l.sent().response,"function"==typeof(null==s?void 0:s.debug)&&s.debug({httpResponse:u}),[4,t(u,e)];case 2:return c=l.sent(),c.$metadata,f=Object(r.__rest)(c,["$metadata"]),"function"==typeof(null==s?void 0:s.info)&&s.info({output:a(f)}),[2,{response:u,output:c}]}}))}))}}}(e,n),i),s.add(function(e,t){return function(n,i){return function(o){return Object(r.__awaiter)(void 0,void 0,void 0,(function(){var s,a,u;return Object(r.__generator)(this,(function(c){switch(c.label){case 0:return s=i.logger,a=i.inputFilterSensitiveLog,"function"==typeof(null==s?void 0:s.info)&&s.info({input:a(o.input)}),[4,t(o.input,e)];case 1:return u=c.sent(),"function"==typeof(null==s?void 0:s.debug)&&s.debug({httpRequest:u}),[2,n(Object(r.__assign)(Object(r.__assign)({},o),{request:u}))]}}))}))}}}(e,t),o)}}}},function(e,t,n){"use strict";n.d(t,"b",(function(){return o})),n.d(t,"a",(function(){return v})),n.d(t,"c",(function(){return m}));var r=n(1),i={name:"retryMiddleware",tags:["RETRY"],step:"finalizeRequest",priority:"high"},o=function(e){return{applyToStack:function(t){t.add(function(e){return function(t){return function(n){return Object(r.__awaiter)(void 0,void 0,void 0,(function(){return Object(r.__generator)(this,(function(r){return[2,e.retryStrategy.retry(t,n)]}))}))}}}(e),i)}}},s=n(2),a=["AuthFailure","InvalidSignatureException","RequestExpired","RequestInTheFuture","RequestTimeTooSkewed","SignatureDoesNotMatch"],u=["Throttling","ThrottlingException","ThrottledException","RequestThrottledException","TooManyRequestsException","ProvisionedThroughputExceededException","TransactionInProgressException","RequestLimitExceeded","BandwidthLimitExceeded","LimitExceededException","RequestThrottled","SlowDown","PriorRequestNotComplete","EC2ThrottledException"],c=["AbortError","TimeoutError","RequestTimeout","RequestTimeoutException"],f=[500,502,503,504],l=function(e){var t;return u.includes(e.name)||1==(null===(t=e.$retryable)||void 0===t?void 0:t.throttling)},d=n(27),h=function(e,t){return Math.floor(Math.min(2e4,Math.random()*Math.pow(2,t)*e))},p=function(e){return!!e&&(function(e){return void 0!==e.$retryable}(e)||function(e){return a.includes(e.name)}(e)||l(e)||function(e){var t;return c.includes(e.name)||f.includes((null===(t=e.$metadata)||void 0===t?void 0:t.httpStatusCode)||0)}(e))},v=3,g=function(){function e(e,t){var n,r,i,o,s,a,u,c;this.maxAttemptsProvider=e,this.retryDecider=null!==(n=null==t?void 0:t.retryDecider)&&void 0!==n?n:p,this.delayDecider=null!==(r=null==t?void 0:t.delayDecider)&&void 0!==r?r:h,this.retryQuota=null!==(i=null==t?void 0:t.retryQuota)&&void 0!==i?i:(s=o=500,a=o,u=function(e){return"TimeoutError"===e.name?10:5},c=function(e){return u(e)<=a},Object.freeze({hasRetryTokens:c,retrieveRetryTokens:function(e){if(!c(e))throw new Error("No retry token available");var t=u(e);return a-=t,t},releaseRetryTokens:function(e){a+=null!=e?e:1,a=Math.min(a,s)}}))}return e.prototype.shouldRetry=function(e,t,n){return t<n&&this.retryDecider(e)&&this.retryQuota.hasRetryTokens(e)},e.prototype.getMaxAttempts=function(){return Object(r.__awaiter)(this,void 0,void 0,(function(){var e;return Object(r.__generator)(this,(function(t){switch(t.label){case 0:return t.trys.push([0,2,,3]),[4,this.maxAttemptsProvider()];case 1:return e=t.sent(),[3,3];case 2:return t.sent(),e=v,[3,3];case 3:return[2,e]}}))}))},e.prototype.retry=function(e,t){return Object(r.__awaiter)(this,void 0,void 0,(function(){var n,i,o,a,u,c,f,h;return Object(r.__generator)(this,(function(p){switch(p.label){case 0:return i=0,o=0,[4,this.getMaxAttempts()];case 1:a=p.sent(),u=t.request,s.a.isInstance(u)&&(u.headers["amz-sdk-invocation-id"]=Object(d.v4)()),c=function(){var c,d,h,p,v;return Object(r.__generator)(this,(function(r){switch(r.label){case 0:return r.trys.push([0,2,,5]),s.a.isInstance(u)&&(u.headers["amz-sdk-request"]="attempt="+(i+1)+"; max="+a),[4,e(t)];case 1:return c=r.sent(),d=c.response,h=c.output,f.retryQuota.releaseRetryTokens(n),h.$metadata.attempts=i+1,h.$metadata.totalRetryDelay=o,[2,{value:{response:d,output:h}}];case 2:return p=r.sent(),i++,f.shouldRetry(p,i,a)?(n=f.retryQuota.retrieveRetryTokens(p),v=f.delayDecider(l(p)?500:100,i),o+=v,[4,new Promise((function(e){return setTimeout(e,v)}))]):[3,4];case 3:return r.sent(),[2,"continue"];case 4:throw p.$metadata||(p.$metadata={}),p.$metadata.attempts=i,p.$metadata.totalRetryDelay=o,p;case 5:return[2]}}))},f=this,p.label=2;case 2:return[5,c()];case 3:return"object"==typeof(h=p.sent())?[2,h.value]:[3,2];case 4:return[2]}}))}))},e}(),m=function(e){var t=b(e.maxAttempts);return Object(r.__assign)(Object(r.__assign)({},e),{maxAttempts:t,retryStrategy:e.retryStrategy||new g(t)})},b=function(e){if(void 0===e&&(e=v),"number"==typeof e){var t=Promise.resolve(e);return function(){return t}}return e}},function(e,t,n){"use strict";var r,i;function o(e){return e&&!!["provider"].find((function(t){return e.hasOwnProperty(t)}))}function s(e){return e&&!!["customProvider"].find((function(t){return e.hasOwnProperty(t)}))}function a(e){return e&&!!["customState"].find((function(t){return e.hasOwnProperty(t)}))}function u(e){return void 0!==e.redirectSignIn}function c(e){return!!e.username}n.d(t,"b",(function(){return r})),n.d(t,"e",(function(){return o})),n.d(t,"f",(function(){return s})),n.d(t,"c",(function(){return a})),n.d(t,"d",(function(){return u})),n.d(t,"a",(function(){return i})),n.d(t,"g",(function(){return c})),function(e){e.Cognito="COGNITO",e.Google="Google",e.Facebook="Facebook",e.Amazon="LoginWithAmazon",e.Apple="SignInWithApple"}(r||(r={})),function(e){e.NoConfig="noConfig",e.MissingAuthConfig="missingAuthConfig",e.EmptyUsername="emptyUsername",e.InvalidUsername="invalidUsername",e.EmptyPassword="emptyPassword",e.EmptyCode="emptyCode",e.SignUpError="signUpError",e.NoMFA="noMFA",e.InvalidMFA="invalidMFA",e.EmptyChallengeResponse="emptyChallengeResponse",e.NoUserSession="noUserSession",e.Default="default"}(i||(i={}))},function(e,t,n){"use strict";n.d(t,"a",(function(){return i})),n.d(t,"e",(function(){return d})),n.d(t,"c",(function(){return h})),n.d(t,"b",(function(){return p})),n.d(t,"d",(function(){return v})),n.d(t,"g",(function(){return g})),n.d(t,"h",(function(){return m})),n.d(t,"f",(function(){return b}));var r,i,o=n(4),s=n(3),a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};!function(e){e.LIST="query",e.CREATE="mutation",e.UPDATE="mutation",e.DELETE="mutation",e.GET="query"}(r||(r={})),function(e){e.CREATE="Create",e.UPDATE="Update",e.DELETE="Delete",e.GET="Get"}(i||(i={}));var u={_version:void 0,_lastChangedAt:void 0,_deleted:void 0},c=Object.keys(u);function f(e,t){var n=l(t),r=function(e,t){var n=[];return Object.values(t.fields).forEach((function(t){var r=t.name,i=t.type;if(Object(o.i)(i)){var s=e.nonModels[i.nonModel],a=Object.values(l(s)).map((function(e){return e.name})),u=[];Object.values(s.fields).forEach((function(t){var n=t.type,r=t.name;if(Object(o.i)(n)){var i=e.nonModels[n.nonModel];u.push(r+" { "+f(e,i)+" }")}})),n.push(r+" { "+a.join(" ")+" "+u.join(" ")+" }")}})),n}(e,t),i=function(e,t){var n=function(e){var t=[];Object(o.l)(e)&&e.attributes&&e.attributes.forEach((function(e){if(e.properties&&e.properties.rules){var n=e.properties.rules.find((function(e){return"owner"===e.allow}));n&&n.ownerField&&t.push(n.ownerField)}}));return t}(e);if(!t.owner&&n.includes("owner"))return["owner"];return[]}(t,n),a=Object.values(n).map((function(e){return e.name})).concat(i).concat(r);return Object(o.l)(t)&&(a=a.concat(c).concat(function(e){var t=[];return Object.values(e.fields).filter((function(e){var t=e.association;return t&&Object.keys(t).length})).forEach((function(e){var n=e.name,r=e.association,i=r.connectionType;switch(i){case"HAS_ONE":case"HAS_MANY":break;case"BELONGS_TO":Object(o.m)(r)&&t.push(n+" { id _deleted }");break;default:Object(s.f)(i)}})),t}(t))),a.join("\n")}function l(e){var t=e.fields;return Object.values(t).filter((function(e){return!(!Object(o.g)(e.type)&&!Object(o.f)(e.type))})).reduce((function(e,t){return e[t.name]=t,e}),{})}function d(e){var t=([].concat(e.attributes).find((function(e){return e&&"auth"===e.type}))||{}).properties,n=(void 0===t?{}:t).rules,r=[];return(void 0===n?[]:n).forEach((function(t){var n=t.identityClaim,i=void 0===n?"cognito:username":n,o=t.ownerField,s=void 0===o?"owner":o,a=t.operations,u=void 0===a?["create","update","delete","read"]:a,c=t.provider,f=void 0===c?"userPools":c,l=t.groupClaim,d=void 0===l?"cognito:groups":l,h=t.allow,p=void 0===h?"iam":h,v=t.groups,g=void 0===v?[]:v,m="owner"===p;if(u.includes("read")||m){var b={identityClaim:i,ownerField:s,provider:f,groupClaim:d,authStrategy:p,groups:g,areSubscriptionsPublic:!1};if(m){var y=([].concat(e.attributes).find((function(e){return e&&"model"===e.type}))||{}).properties,w=(void 0===y?{}:y).subscriptions,_=(void 0===w?{}:w).level,S=void 0===_?"on":_;b.areSubscriptionsPublic=!u.includes("read")||"public"===S}m?r.push(b):r.unshift(b)}})),r}function h(e,t,n,r,i){var o=f(e,t),s=t.name,a=(t.pluralName,"on"+n+s),u="",c="";return r&&(u="($"+i+": String!)",c="("+i+": $"+i+")"),[n,a,"subscription operation"+u+"{\n\t\t\t"+a+c+"{\n\t\t\t\t"+o+"\n\t\t\t}\n\t\t}"]}function p(e,t,n){var o,a,u=f(e,t),c=t.name,l=t.pluralName,d=" ",h=" ";switch(n){case"LIST":o="sync"+l,d="($limit: Int, $nextToken: String, $lastSync: AWSTimestamp, $filter: Model"+c+"FilterInput)",h="(limit: $limit, nextToken: $nextToken, lastSync: $lastSync, filter: $filter)",u="items {\n\t\t\t\t\t\t\t"+u+"\n\t\t\t\t\t\t}\n\t\t\t\t\t\tnextToken\n\t\t\t\t\t\tstartedAt";break;case"CREATE":o="create"+c,d="($input: Create"+c+"Input!)",h="(input: $input)",a=i.CREATE;break;case"UPDATE":o="update"+c,d="($input: Update"+c+"Input!, $condition: Model"+c+"ConditionInput)",h="(input: $input, condition: $condition)",a=i.UPDATE;break;case"DELETE":o="delete"+c,d="($input: Delete"+c+"Input!, $condition: Model"+c+"ConditionInput)",h="(input: $input, condition: $condition)",a=i.DELETE;break;case"GET":o="get"+c,d="($id: ID!)",h="(id: $id)",a=i.GET;break;default:Object(s.f)(n)}return[[a,o,r[n]+" operation"+d+"{\n\t\t"+o+h+"{\n\t\t\t"+u+"\n\t\t}\n\t}"]]}function v(e,t,n,r,u,c,f,l,d){var h;switch(n){case o.c.INSERT:h=i.CREATE;break;case o.c.UPDATE:h=i.UPDATE;break;case o.c.DELETE:h=i.DELETE;break;default:Object(s.f)(n)}return l(f,a(a({},d?{id:d}:{}),{data:JSON.stringify(u),modelId:u.id,model:r.name,operation:h,condition:JSON.stringify(c)}))}function g(e){var t={};return e&&Array.isArray(e.predicates)?(e.predicates.forEach((function(e){var n;if(Object(o.k)(e)){var r=e.field,i=e.operator,s=e.operand;if("id"===r)return;t[r]=((n={})[i]=s,n)}else t[e.type]=g(e)})),t):t}function m(e){var t={};if(!e||!Array.isArray(e.predicates))return t;var n=e.type,r=e.predicates,i="and"===n||"or"===n;t[n]=i?[]:{};var s=function(e){return i?t[n].push(e):t[n]=e};return r.forEach((function(e){var t,n;if(Object(o.k)(e)){var r=e.field,i=e.operator,a=e.operand,u=((t={})[r]=((n={})[i]=a,n),t);s(u)}else s(m(e))})),t}function b(e,t){var n=e[t.groupClaim]||[];if("string"==typeof n){var r=void 0;try{r=JSON.parse(n)}catch(e){r=n}n=[].concat(r)}return n}},function(e,t,n){"use strict";var r=n(255),i=n.n(r).a;t.a=i},function(e,t,n){"use strict";n.d(t,"a",(function(){return r})),n.d(t,"b",(function(){return i}));var r=function(e){return"function"==typeof TextEncoder?function(e){return(new TextEncoder).encode(e)}(e):function(e){for(var t=[],n=0,r=e.length;n<r;n++){var i=e.charCodeAt(n);if(i<128)t.push(i);else if(i<2048)t.push(i>>6|192,63&i|128);else if(n+1<e.length&&55296==(64512&i)&&56320==(64512&e.charCodeAt(n+1))){var o=65536+((1023&i)<<10)+(1023&e.charCodeAt(++n));t.push(o>>18|240,o>>12&63|128,o>>6&63|128,63&o|128)}else t.push(i>>12|224,i>>6&63|128,63&i|128)}return Uint8Array.from(t)}(e)},i=function(e){return"function"==typeof TextDecoder?function(e){return new TextDecoder("utf-8").decode(e)}(e):function(e){for(var t="",n=0,r=e.length;n<r;n++){var i=e[n];if(i<128)t+=String.fromCharCode(i);else if(192<=i&&i<224){var o=e[++n];t+=String.fromCharCode((31&i)<<6|63&o)}else if(240<=i&&i<365){var s="%"+[i,e[++n],e[++n],e[++n]].map((function(e){return e.toString(16)})).join("%");t+=decodeURIComponent(s)}else t+=String.fromCharCode((15&i)<<12|(63&e[++n])<<6|63&e[++n])}return t}(e)}},function(e,t,n){"use strict";var r=n(366),i=n(367);function o(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}t.parse=y,t.resolve=function(e,t){return y(e,!1,!0).resolve(t)},t.resolveObject=function(e,t){return e?y(e,!1,!0).resolveObject(t):t},t.format=function(e){i.isString(e)&&(e=y(e));return e instanceof o?e.format():o.prototype.format.call(e)},t.Url=o;var s=/^([a-z0-9.+-]+:)/i,a=/:[0-9]*$/,u=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,c=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r","\n","\t"]),f=["'"].concat(c),l=["%","/","?",";","#"].concat(f),d=["/","?","#"],h=/^[+a-z0-9A-Z_-]{0,63}$/,p=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,v={javascript:!0,"javascript:":!0},g={javascript:!0,"javascript:":!0},m={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},b=n(368);function y(e,t,n){if(e&&i.isObject(e)&&e instanceof o)return e;var r=new o;return r.parse(e,t,n),r}o.prototype.parse=function(e,t,n){if(!i.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var o=e.indexOf("?"),a=-1!==o&&o<e.indexOf("#")?"?":"#",c=e.split(a);c[0]=c[0].replace(/\\/g,"/");var y=e=c.join(a);if(y=y.trim(),!n&&1===e.split("#").length){var w=u.exec(y);if(w)return this.path=y,this.href=y,this.pathname=w[1],w[2]?(this.search=w[2],this.query=t?b.parse(this.search.substr(1)):this.search.substr(1)):t&&(this.search="",this.query={}),this}var _=s.exec(y);if(_){var S=(_=_[0]).toLowerCase();this.protocol=S,y=y.substr(_.length)}if(n||_||y.match(/^\/\/[^@\/]+@[^@\/]+/)){var E="//"===y.substr(0,2);!E||_&&g[_]||(y=y.substr(2),this.slashes=!0)}if(!g[_]&&(E||_&&!m[_])){for(var M,A,I=-1,k=0;k<d.length;k++){-1!==(O=y.indexOf(d[k]))&&(-1===I||O<I)&&(I=O)}-1!==(A=-1===I?y.lastIndexOf("@"):y.lastIndexOf("@",I))&&(M=y.slice(0,A),y=y.slice(A+1),this.auth=decodeURIComponent(M)),I=-1;for(k=0;k<l.length;k++){var O;-1!==(O=y.indexOf(l[k]))&&(-1===I||O<I)&&(I=O)}-1===I&&(I=y.length),this.host=y.slice(0,I),y=y.slice(I),this.parseHost(),this.hostname=this.hostname||"";var x="["===this.hostname[0]&&"]"===this.hostname[this.hostname.length-1];if(!x)for(var C=this.hostname.split(/\./),T=(k=0,C.length);k<T;k++){var P=C[k];if(P&&!P.match(h)){for(var N="",R=0,L=P.length;R<L;R++)P.charCodeAt(R)>127?N+="x":N+=P[R];if(!N.match(h)){var j=C.slice(0,k),D=C.slice(k+1),U=P.match(p);U&&(j.push(U[1]),D.unshift(U[2])),D.length&&(y="/"+D.join(".")+y),this.hostname=j.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),x||(this.hostname=r.toASCII(this.hostname));var B=this.port?":"+this.port:"",F=this.hostname||"";this.host=F+B,this.href+=this.host,x&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==y[0]&&(y="/"+y))}if(!v[S])for(k=0,T=f.length;k<T;k++){var z=f[k];if(-1!==y.indexOf(z)){var q=encodeURIComponent(z);q===z&&(q=escape(z)),y=y.split(z).join(q)}}var K=y.indexOf("#");-1!==K&&(this.hash=y.substr(K),y=y.slice(0,K));var H=y.indexOf("?");if(-1!==H?(this.search=y.substr(H),this.query=y.substr(H+1),t&&(this.query=b.parse(this.query)),y=y.slice(0,H)):t&&(this.search="",this.query={}),y&&(this.pathname=y),m[S]&&this.hostname&&!this.pathname&&(this.pathname="/"),this.pathname||this.search){B=this.pathname||"";var V=this.search||"";this.path=B+V}return this.href=this.format(),this},o.prototype.format=function(){var e=this.auth||"";e&&(e=(e=encodeURIComponent(e)).replace(/%3A/i,":"),e+="@");var t=this.protocol||"",n=this.pathname||"",r=this.hash||"",o=!1,s="";this.host?o=e+this.host:this.hostname&&(o=e+(-1===this.hostname.indexOf(":")?this.hostname:"["+this.hostname+"]"),this.port&&(o+=":"+this.port)),this.query&&i.isObject(this.query)&&Object.keys(this.query).length&&(s=b.stringify(this.query));var a=this.search||s&&"?"+s||"";return t&&":"!==t.substr(-1)&&(t+=":"),this.slashes||(!t||m[t])&&!1!==o?(o="//"+(o||""),n&&"/"!==n.charAt(0)&&(n="/"+n)):o||(o=""),r&&"#"!==r.charAt(0)&&(r="#"+r),a&&"?"!==a.charAt(0)&&(a="?"+a),t+o+(n=n.replace(/[?#]/g,(function(e){return encodeURIComponent(e)})))+(a=a.replace("#","%23"))+r},o.prototype.resolve=function(e){return this.resolveObject(y(e,!1,!0)).format()},o.prototype.resolveObject=function(e){if(i.isString(e)){var t=new o;t.parse(e,!1,!0),e=t}for(var n=new o,r=Object.keys(this),s=0;s<r.length;s++){var a=r[s];n[a]=this[a]}if(n.hash=e.hash,""===e.href)return n.href=n.format(),n;if(e.slashes&&!e.protocol){for(var u=Object.keys(e),c=0;c<u.length;c++){var f=u[c];"protocol"!==f&&(n[f]=e[f])}return m[n.protocol]&&n.hostname&&!n.pathname&&(n.path=n.pathname="/"),n.href=n.format(),n}if(e.protocol&&e.protocol!==n.protocol){if(!m[e.protocol]){for(var l=Object.keys(e),d=0;d<l.length;d++){var h=l[d];n[h]=e[h]}return n.href=n.format(),n}if(n.protocol=e.protocol,e.host||g[e.protocol])n.pathname=e.pathname;else{for(var p=(e.pathname||"").split("/");p.length&&!(e.host=p.shift()););e.host||(e.host=""),e.hostname||(e.hostname=""),""!==p[0]&&p.unshift(""),p.length<2&&p.unshift(""),n.pathname=p.join("/")}if(n.search=e.search,n.query=e.query,n.host=e.host||"",n.auth=e.auth,n.hostname=e.hostname||e.host,n.port=e.port,n.pathname||n.search){var v=n.pathname||"",b=n.search||"";n.path=v+b}return n.slashes=n.slashes||e.slashes,n.href=n.format(),n}var y=n.pathname&&"/"===n.pathname.charAt(0),w=e.host||e.pathname&&"/"===e.pathname.charAt(0),_=w||y||n.host&&e.pathname,S=_,E=n.pathname&&n.pathname.split("/")||[],M=(p=e.pathname&&e.pathname.split("/")||[],n.protocol&&!m[n.protocol]);if(M&&(n.hostname="",n.port=null,n.host&&(""===E[0]?E[0]=n.host:E.unshift(n.host)),n.host="",e.protocol&&(e.hostname=null,e.port=null,e.host&&(""===p[0]?p[0]=e.host:p.unshift(e.host)),e.host=null),_=_&&(""===p[0]||""===E[0])),w)n.host=e.host||""===e.host?e.host:n.host,n.hostname=e.hostname||""===e.hostname?e.hostname:n.hostname,n.search=e.search,n.query=e.query,E=p;else if(p.length)E||(E=[]),E.pop(),E=E.concat(p),n.search=e.search,n.query=e.query;else if(!i.isNullOrUndefined(e.search)){if(M)n.hostname=n.host=E.shift(),(x=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@"))&&(n.auth=x.shift(),n.host=n.hostname=x.shift());return n.search=e.search,n.query=e.query,i.isNull(n.pathname)&&i.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.href=n.format(),n}if(!E.length)return n.pathname=null,n.search?n.path="/"+n.search:n.path=null,n.href=n.format(),n;for(var A=E.slice(-1)[0],I=(n.host||e.host||E.length>1)&&("."===A||".."===A)||""===A,k=0,O=E.length;O>=0;O--)"."===(A=E[O])?E.splice(O,1):".."===A?(E.splice(O,1),k++):k&&(E.splice(O,1),k--);if(!_&&!S)for(;k--;k)E.unshift("..");!_||""===E[0]||E[0]&&"/"===E[0].charAt(0)||E.unshift(""),I&&"/"!==E.join("/").substr(-1)&&E.push("");var x,C=""===E[0]||E[0]&&"/"===E[0].charAt(0);M&&(n.hostname=n.host=C?"":E.length?E.shift():"",(x=!!(n.host&&n.host.indexOf("@")>0)&&n.host.split("@"))&&(n.auth=x.shift(),n.host=n.hostname=x.shift()));return(_=_||n.host&&E.length)&&!C&&E.unshift(""),E.length?n.pathname=E.join("/"):(n.pathname=null,n.path=null),i.isNull(n.pathname)&&i.isNull(n.search)||(n.path=(n.pathname?n.pathname:"")+(n.search?n.search:"")),n.auth=e.auth||n.auth,n.slashes=n.slashes||e.slashes,n.href=n.format(),n},o.prototype.parseHost=function(){var e=this.host,t=a.exec(e);t&&(":"!==(t=t[0])&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},function(e,t,n){"use strict";n.d(t,"a",(function(){return f})),n.d(t,"b",(function(){return l}));for(var r={},i=new Array(64),o=0,s="A".charCodeAt(0),a="Z".charCodeAt(0);o+s<=a;o++){var u=String.fromCharCode(o+s);r[u]=o,i[o]=u}for(o=0,s="a".charCodeAt(0),a="z".charCodeAt(0);o+s<=a;o++){u=String.fromCharCode(o+s);var c=o+26;r[u]=c,i[c]=u}for(o=0;o<10;o++){r[o.toString(10)]=o+52;u=o.toString(10),c=o+52;r[u]=c,i[c]=u}r["+"]=62,i[62]="+",r["/"]=63,i[63]="/";function f(e){var t=e.length/4*3;"=="===e.substr(-2)?t-=2:"="===e.substr(-1)&&t--;for(var n=new ArrayBuffer(t),i=new DataView(n),o=0;o<e.length;o+=4){for(var s=0,a=0,u=o,c=o+3;u<=c;u++)"="!==e[u]?(s|=r[e[u]]<<6*(c-u),a+=6):s>>=6;var f=o/4*3;s>>=a%8;for(var l=Math.floor(a/8),d=0;d<l;d++){var h=8*(l-d-1);i.setUint8(f+d,(s&255<<h)>>h)}}return new Uint8Array(n)}function l(e){for(var t="",n=0;n<e.length;n+=3){for(var r=0,o=0,s=n,a=Math.min(n+3,e.length);s<a;s++)r|=e[s]<<8*(a-s-1),o+=8;var u=Math.ceil(o/6);r<<=6*u-o;for(var c=1;c<=u;c++){var f=6*(u-c);t+=i[(r&63<<f)>>f]}t+="==".slice(0,4-u)}return t}},function(e,t,n){"use strict";n.d(t,"a",(function(){return s})),n.d(t,"b",(function(){return u}));var r=n(1),i=n(2),o=n(74);var s=function(){function e(e){void 0===e&&(e={}),this.httpOptions=e}return e.prototype.destroy=function(){},e.prototype.handle=function(e,t){var n=null==t?void 0:t.abortSignal,s=this.httpOptions.requestTimeout;if(null==n?void 0:n.aborted){var a=new Error("Request aborted");return a.name="AbortError",Promise.reject(a)}var u=e.path;if(e.query){var c=Object(o.a)(e.query);c&&(u+="?"+c)}var f=e.port,l=e.protocol+"//"+e.hostname+(f?":"+f:"")+u,d={body:e.body,headers:new Headers(e.headers),method:e.method};"undefined"!=typeof AbortController&&(d.signal=n);var h,p=new Request(l,d),v=[fetch(p).then((function(e){var t,n,o=e.headers,s={};try{for(var a=Object(r.__values)(o.entries()),u=a.next();!u.done;u=a.next()){var c=u.value;s[c[0]]=c[1]}}catch(e){t={error:e}}finally{try{u&&!u.done&&(n=a.return)&&n.call(a)}finally{if(t)throw t.error}}return void 0!==e.body?{response:new i.b({headers:s,statusCode:e.status,body:e.body})}:e.blob().then((function(t){return{response:new i.b({headers:s,statusCode:e.status,body:t})}}))})),(h=s,void 0===h&&(h=0),new Promise((function(e,t){h&&setTimeout((function(){var e=new Error("Request did not complete within "+h+" ms");e.name="TimeoutError",t(e)}),h)})))];return n&&v.push(new Promise((function(e,t){n.onabort=function(){var e=new Error("Request aborted");e.name="AbortError",t(e)}}))),Promise.race(v)},e}(),a=n(17),u=function(e){return"function"==typeof Blob&&e instanceof Blob?function(e){return Object(r.__awaiter)(this,void 0,void 0,(function(){var t,n;return Object(r.__generator)(this,(function(r){switch(r.label){case 0:return[4,c(e)];case 1:return t=r.sent(),n=Object(a.a)(t),[2,new Uint8Array(n)]}}))}))}(e):function(e){return Object(r.__awaiter)(this,void 0,void 0,(function(){var t,n,i,o,s,a,u;return Object(r.__generator)(this,(function(r){switch(r.label){case 0:t=new Uint8Array(0),n=e.getReader(),i=!1,r.label=1;case 1:return i?[3,3]:[4,n.read()];case 2:return o=r.sent(),s=o.done,(a=o.value)&&(u=t,(t=new Uint8Array(u.length+a.length)).set(u),t.set(a,u.length)),i=s,[3,1];case 3:return[2,t]}}))}))}(e)};function c(e){return new Promise((function(t,n){var r=new FileReader;r.onloadend=function(){var e;if(2!==r.readyState)return n(new Error("Reader aborted too early"));var i=null!==(e=r.result)&&void 0!==e?e:"",o=i.indexOf(","),s=o>-1?o+1:i.length;t(i.substring(s))},r.onabort=function(){return n(new Error("Read aborted"))},r.onerror=function(){return n(r.error)},r.readAsDataURL(e)}))}},function(e,t,n){"use strict";n.d(t,"b",(function(){return s})),n.d(t,"a",(function(){return a}));var r=n(44),i=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},o=new r.a("Amplify"),s=function(){function e(){this._components=[],this._config={},this._modules={},this.Auth=null,this.Analytics=null,this.API=null,this.Credentials=null,this.Storage=null,this.I18n=null,this.Cache=null,this.PubSub=null,this.Interactions=null,this.Pushnotification=null,this.UI=null,this.XR=null,this.Predictions=null,this.DataStore=null,this.Logger=r.a,this.ServiceWorker=null}return e.prototype.register=function(e){o.debug("component registered in amplify",e),this._components.push(e),"function"==typeof e.getModuleName?(this._modules[e.getModuleName()]=e,this[e.getModuleName()]=e):o.debug("no getModuleName method for component",e),e.configure(this._config)},e.prototype.configure=function(e){var t=this;return e?(this._config=Object.assign(this._config,e),o.debug("amplify config",this._config),Object.entries(this._modules).forEach((function(e){var n=i(e,2),r=(n[0],n[1]);Object.keys(r).forEach((function(e){t._modules[e]&&(r[e]=t._modules[e])}))})),this._components.map((function(e){e.configure(t._config)})),this._config):this._config},e.prototype.addPluggable=function(e){e&&e.getCategory&&"function"==typeof e.getCategory&&this._components.map((function(t){t.addPluggable&&"function"==typeof t.addPluggable&&t.addPluggable(e)}))},e}(),a=new s},function(e,t){var n,r,i=e.exports={};function o(){throw new Error("setTimeout has not been defined")}function s(){throw new Error("clearTimeout has not been defined")}function a(e){if(n===setTimeout)return setTimeout(e,0);if((n===o||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:o}catch(e){n=o}try{r="function"==typeof clearTimeout?clearTimeout:s}catch(e){r=s}}();var u,c=[],f=!1,l=-1;function d(){f&&u&&(f=!1,u.length?c=u.concat(c):l=-1,c.length&&h())}function h(){if(!f){var e=a(d);f=!0;for(var t=c.length;t;){for(u=c,c=[];++l<t;)u&&u[l].run();l=-1,t=c.length}u=null,f=!1,function(e){if(r===clearTimeout)return clearTimeout(e);if((r===s||!r)&&clearTimeout)return r=clearTimeout,clearTimeout(e);try{r(e)}catch(t){try{return r.call(null,e)}catch(t){return r.call(this,e)}}}(e)}}function p(e,t){this.fun=e,this.array=t}function v(){}i.nextTick=function(e){var t=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)t[n-1]=arguments[n];c.push(new p(e,t)),1!==c.length||f||a(h)},p.prototype.run=function(){this.fun.apply(null,this.array)},i.title="browser",i.browser=!0,i.env={},i.argv=[],i.version="",i.versions={},i.on=v,i.addListener=v,i.once=v,i.off=v,i.removeListener=v,i.removeAllListeners=v,i.emit=v,i.prependListener=v,i.prependOnceListener=v,i.listeners=function(e){return[]},i.binding=function(e){throw new Error("process.binding is not supported")},i.cwd=function(){return"/"},i.chdir=function(e){throw new Error("process.chdir is not supported")},i.umask=function(){return 0}},function(e,t,n){"use strict";n.d(t,"b",(function(){return o})),n.d(t,"a",(function(){return a}));var r=n(1),i=n(2);function o(e){return e}var s={name:"hostHeaderMiddleware",step:"build",priority:"low",tags:["HOST"]},a=function(e){return{applyToStack:function(t){t.add(function(e){return function(t){return function(n){return Object(r.__awaiter)(void 0,void 0,void 0,(function(){var o,s;return Object(r.__generator)(this,(function(r){return i.a.isInstance(n.request)?(o=n.request,s=(e.requestHandler.metadata||{}).handlerProtocol,(void 0===s?"":s).indexOf("h2")>=0&&!o.headers[":authority"]?(delete o.headers.host,o.headers[":authority"]=""):o.headers.host||(o.headers.host=o.hostname),[2,t(n)]):[2,t(n)]}))}))}}}(e),s)}}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return i})),n.d(t,"b",(function(){return a}));var r=n(1),i=function(e){var t;return Object(r.__assign)(Object(r.__assign)({},e),{tls:null===(t=e.tls)||void 0===t||t,endpoint:e.endpoint?o(e):function(){return s(e)},isCustomEndpoint:!!e.endpoint})},o=function(e){var t=e.endpoint,n=e.urlParser;if("string"==typeof t){var r=Promise.resolve(n(t));return function(){return r}}if("object"==typeof t){var i=Promise.resolve(t);return function(){return i}}return t},s=function(e){return Object(r.__awaiter)(void 0,void 0,void 0,(function(){var t,n,i,o,s;return Object(r.__generator)(this,(function(r){switch(r.label){case 0:return t=e.tls,n=void 0===t||t,[4,e.region()];case 1:if(i=r.sent(),!new RegExp(/^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9])$/).test(i))throw new Error("Invalid region in client config");return[4,e.regionInfoProvider(i)];case 2:if(!(o=(null!==(s=r.sent())&&void 0!==s?s:{}).hostname))throw new Error("Cannot resolve hostname from client config");return[2,e.urlParser((n?"https:":"http:")+"//"+o)]}}))}))},a=function(e){if(!e.region)throw new Error("Region is missing");return Object(r.__assign)(Object(r.__assign)({},e),{region:u(e.region)})},u=function(e){if("string"==typeof e){var t=Promise.resolve(e);return function(){return t}}return e}},function(e,t,n){"use strict";function r(e){return e}n.d(t,"b",(function(){return r})),n.d(t,"a",(function(){return a}));var i=n(1),o=n(2);var s={name:"getUserAgentMiddleware",step:"build",tags:["SET_USER_AGENT","USER_AGENT"]},a=function(e){return{applyToStack:function(t){var n;t.add((n=e,function(e){return function(t){var r=t.request;if(!o.a.isInstance(r))return e(t);var s=r.headers,a="node"===n.runtime?"user-agent":"x-amz-user-agent";return s[a]?s[a]+=" "+n.defaultUserAgent:s[a]=""+n.defaultUserAgent,n.customUserAgent&&(s[a]+=" "+n.customUserAgent),e(Object(i.__assign)(Object(i.__assign)({},t),{request:r}))}}),s)}}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return r}));var r=function(e){return function(){throw new Error(e)}}},function(e,t,n){"use strict";n.d(t,"b",(function(){return o})),n.d(t,"a",(function(){return l}));var r=n(1),i=n(111);function o(e){var t,n=this,o=s(e.credentials||e.credentialDefaultProvider(e)),a=e.signingEscapePath,u=void 0===a||a,c=e.systemClockOffset,f=void 0===c?e.systemClockOffset||0:c,l=e.sha256;return t=e.signer?s(e.signer):function(){return s(e.region)().then((function(t){return Object(r.__awaiter)(n,void 0,void 0,(function(){return Object(r.__generator)(this,(function(n){switch(n.label){case 0:return[4,e.regionInfoProvider(t)];case 1:return[2,[n.sent()||{},t]]}}))}))})).then((function(t){var n=Object(r.__read)(t,2),s=n[0],a=n[1],c=s.signingRegion,f=void 0===c?e.signingRegion:c,d=s.signingService,h=void 0===d?e.signingName:d;return e.signingRegion=e.signingRegion||f||a,e.signingName=e.signingName||h,new i.a({credentials:o,region:e.signingRegion,service:e.signingName,sha256:l,uriEscapePath:u})}))},Object(r.__assign)(Object(r.__assign)({},e),{systemClockOffset:f,signingEscapePath:u,credentials:o,signer:t})}function s(e){if("object"==typeof e){var t=Promise.resolve(e);return function(){return t}}return e}var a=n(2),u=function(e){return new Date(Date.now()+e)};function c(e){return function(t,n){return function(i){return Object(r.__awaiter)(this,void 0,void 0,(function(){var o,s,c,f,l,d,h,p,v;return Object(r.__generator)(this,(function(g){switch(g.label){case 0:return a.a.isInstance(i.request)?"function"!=typeof e.signer?[3,2]:[4,e.signer()]:[2,t(i)];case 1:return s=g.sent(),[3,3];case 2:s=e.signer,g.label=3;case 3:return o=s,f=t,l=[Object(r.__assign)({},i)],v={},[4,o.sign(i.request,{signingDate:new Date(Date.now()+e.systemClockOffset),signingRegion:n.signing_region,signingService:n.signing_service})];case 4:return[4,f.apply(void 0,[r.__assign.apply(void 0,l.concat([(v.request=g.sent(),v)]))])];case 5:return c=g.sent(),d=c.response.headers,(h=d&&(d.date||d.Date))&&(p=Date.parse(h),m=p,b=e.systemClockOffset,Math.abs(u(b).getTime()-m)>=3e5&&(e.systemClockOffset=p-Date.now())),[2,c]}var m,b}))}))}}}var f={name:"awsAuthMiddleware",tags:["SIGNATURE","AWSAUTH"],relation:"after",toMiddleware:"retryMiddleware"},l=function(e){return{applyToStack:function(t){t.addRelativeTo(c(e),f)}}}},function(e,t,n){"use strict";var r=n(19),i={keyPrefix:"aws-amplify-cache",capacityInBytes:1048576,itemMaxSize:21e4,defaultTTL:2592e5,defaultPriority:5,warningThreshold:.8,storage:(new(n(86).a)).getStorage()};function o(e){var t=0;t=e.length;for(var n=e.length;n>=0;n-=1){var r=e.charCodeAt(n);r>127&&r<=2047?t+=1:r>2047&&r<=65535&&(t+=2),r>=56320&&r<=57343&&(n-=1)}return t}function s(){return(new Date).getTime()}function a(e){return Number.isInteger?Number.isInteger(e):function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e}(e)}var u={},c=(function(){function e(){}e.clear=function(){u={}},e.getItem=function(e){return u[e]||null},e.setItem=function(e,t){u[e]=t},e.removeItem=function(e){delete u[e]}}(),n(44));function f(e){return(f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var l,d=new c.a("StorageCache"),h=function(){function e(e){this.config=Object.assign({},e),this.cacheCurSizeKey=this.config.keyPrefix+"CurSize",this.checkConfig()}return e.prototype.getModuleName=function(){return"Cache"},e.prototype.checkConfig=function(){a(this.config.capacityInBytes)||(d.error("Invalid parameter: capacityInBytes. It should be an Integer. Setting back to default."),this.config.capacityInBytes=i.capacityInBytes),a(this.config.itemMaxSize)||(d.error("Invalid parameter: itemMaxSize. It should be an Integer. Setting back to default."),this.config.itemMaxSize=i.itemMaxSize),a(this.config.defaultTTL)||(d.error("Invalid parameter: defaultTTL. It should be an Integer. Setting back to default."),this.config.defaultTTL=i.defaultTTL),a(this.config.defaultPriority)||(d.error("Invalid parameter: defaultPriority. It should be an Integer. Setting back to default."),this.config.defaultPriority=i.defaultPriority),this.config.itemMaxSize>this.config.capacityInBytes&&(d.error("Invalid parameter: itemMaxSize. It should be smaller than capacityInBytes. Setting back to default."),this.config.itemMaxSize=i.itemMaxSize),(this.config.defaultPriority>5||this.config.defaultPriority<1)&&(d.error("Invalid parameter: defaultPriority. It should be between 1 and 5. Setting back to default."),this.config.defaultPriority=i.defaultPriority),(Number(this.config.warningThreshold)>1||Number(this.config.warningThreshold)<0)&&(d.error("Invalid parameter: warningThreshold. It should be between 0 and 1. Setting back to default."),this.config.warningThreshold=i.warningThreshold);this.config.capacityInBytes>5242880&&(d.error("Cache Capacity should be less than 5MB. Setting back to default. Setting back to default."),this.config.capacityInBytes=i.capacityInBytes)},e.prototype.fillCacheItem=function(e,t,n){var r={key:e,data:t,timestamp:s(),visitedTime:s(),priority:n.priority,expires:n.expires,type:f(t),byteSize:0};return r.byteSize=o(JSON.stringify(r)),r.byteSize=o(JSON.stringify(r)),r},e.prototype.configure=function(e){return e?(e.keyPrefix&&d.warn("Don't try to configure keyPrefix!"),this.config=Object.assign({},this.config,e,e.Cache),this.checkConfig(),this.config):this.config},e}(),p=(l=function(e,t){return(l=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}l(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),v=new c.a("Cache"),g=new(function(e){function t(t){var n=this,r=t?Object.assign({},i,t):i;return(n=e.call(this,r)||this).config.storage=r.storage,n.getItem=n.getItem.bind(n),n.setItem=n.setItem.bind(n),n.removeItem=n.removeItem.bind(n),n}return p(t,e),t.prototype._decreaseCurSizeInBytes=function(e){var t=this.getCacheCurSize();this.config.storage.setItem(this.cacheCurSizeKey,(t-e).toString())},t.prototype._increaseCurSizeInBytes=function(e){var t=this.getCacheCurSize();this.config.storage.setItem(this.cacheCurSizeKey,(t+e).toString())},t.prototype._refreshItem=function(e,t){return e.visitedTime=s(),this.config.storage.setItem(t,JSON.stringify(e)),e},t.prototype._isExpired=function(e){var t=this.config.storage.getItem(e),n=JSON.parse(t);return s()>=n.expires},t.prototype._removeItem=function(e,t){var n=t||JSON.parse(this.config.storage.getItem(e)).byteSize;this._decreaseCurSizeInBytes(n),this.config.storage.removeItem(e)},t.prototype._setItem=function(e,t){this._increaseCurSizeInBytes(t.byteSize);try{this.config.storage.setItem(e,JSON.stringify(t))}catch(e){this._decreaseCurSizeInBytes(t.byteSize),v.error("Failed to set item "+e)}},t.prototype._sizeToPop=function(e){var t=this.getCacheCurSize()+e-this.config.capacityInBytes,n=(1-this.config.warningThreshold)*this.config.capacityInBytes;return t>n?t:n},t.prototype._isCacheFull=function(e){return e+this.getCacheCurSize()>this.config.capacityInBytes},t.prototype._findValidKeys=function(){for(var e=[],t=[],n=0;n<this.config.storage.length;n+=1)t.push(this.config.storage.key(n));for(n=0;n<t.length;n+=1){var r=t[n];0===r.indexOf(this.config.keyPrefix)&&r!==this.cacheCurSizeKey&&(this._isExpired(r)?this._removeItem(r):e.push(r))}return e},t.prototype._popOutItems=function(e,t){for(var n=[],r=t,i=0;i<e.length;i+=1){var o=this.config.storage.getItem(e[i]);if(null!=o){var s=JSON.parse(o);n.push(s)}}n.sort((function(e,t){return e.priority>t.priority?-1:e.priority<t.priority?1:e.visitedTime<t.visitedTime?-1:1}));for(i=0;i<n.length;i+=1)if(this._removeItem(n[i].key,n[i].byteSize),(r-=n[i].byteSize)<=0)return},t.prototype.setItem=function(e,t,n){v.log("Set item: key is "+e+", value is "+t+" with options: "+n);var r=this.config.keyPrefix+e;if(r!==this.config.keyPrefix&&r!==this.cacheCurSizeKey)if(void 0!==t){var i={priority:n&&void 0!==n.priority?n.priority:this.config.defaultPriority,expires:n&&void 0!==n.expires?n.expires:this.config.defaultTTL+s()};if(i.priority<1||i.priority>5)v.warn("Invalid parameter: priority due to out or range. It should be within 1 and 5.");else{var o=this.fillCacheItem(r,t,i);if(o.byteSize>this.config.itemMaxSize)v.warn("Item with key: "+e+" you are trying to put into is too big!");else try{var a=this.config.storage.getItem(r);if(a&&this._removeItem(r,JSON.parse(a).byteSize),this._isCacheFull(o.byteSize)){var u=this._findValidKeys();if(this._isCacheFull(o.byteSize)){var c=this._sizeToPop(o.byteSize);this._popOutItems(u,c)}}this._setItem(r,o)}catch(e){v.warn("setItem failed! "+e)}}}else v.warn("The value of item should not be undefined!");else v.warn("Invalid key: should not be empty or 'CurSize'")},t.prototype.getItem=function(e,t){v.log("Get item: key is "+e+" with options "+t);var n=null,r=this.config.keyPrefix+e;if(r===this.config.keyPrefix||r===this.cacheCurSizeKey)return v.warn("Invalid key: should not be empty or 'CurSize'"),null;try{if(null!=(n=this.config.storage.getItem(r))){if(!this._isExpired(r)){var i=JSON.parse(n);return(i=this._refreshItem(i,r)).data}this._removeItem(r,JSON.parse(n).byteSize),n=null}if(t&&void 0!==t.callback){var o=t.callback();return null!==o&&this.setItem(e,o,t),o}return null}catch(e){return v.warn("getItem failed! "+e),null}},t.prototype.removeItem=function(e){v.log("Remove item: key is "+e);var t=this.config.keyPrefix+e;if(t!==this.config.keyPrefix&&t!==this.cacheCurSizeKey)try{var n=this.config.storage.getItem(t);n&&this._removeItem(t,JSON.parse(n).byteSize)}catch(e){v.warn("removeItem failed! "+e)}},t.prototype.clear=function(){v.log("Clear Cache");for(var e=[],t=0;t<this.config.storage.length;t+=1){var n=this.config.storage.key(t);0===n.indexOf(this.config.keyPrefix)&&e.push(n)}try{for(t=0;t<e.length;t+=1)this.config.storage.removeItem(e[t])}catch(e){v.warn("clear failed! "+e)}},t.prototype.getAllKeys=function(){for(var e=[],t=0;t<this.config.storage.length;t+=1){var n=this.config.storage.key(t);0===n.indexOf(this.config.keyPrefix)&&n!==this.cacheCurSizeKey&&e.push(n.substring(this.config.keyPrefix.length))}return e},t.prototype.getCacheCurSize=function(){var e=this.config.storage.getItem(this.cacheCurSizeKey);return e||(this.config.storage.setItem(this.cacheCurSizeKey,"0"),e="0"),Number(e)},t.prototype.createInstance=function(e){return e.keyPrefix&&e.keyPrefix!==i.keyPrefix||(v.error("invalid keyPrefix, setting keyPrefix with timeStamp"),e.keyPrefix=s.toString()),new t(e)},t}(h));t.a=g;r.a.register(g)},function(e,t,n){var r=n(371),i=n(372),o=i;o.v1=r,o.v4=i,e.exports=o},function(e,t,n){"use strict";n.d(t,"a",(function(){return a})),n.d(t,"b",(function(){return u}));for(var r={},i={},o=0;o<256;o++){var s=o.toString(16).toLowerCase();1===s.length&&(s="0"+s),r[o]=s,i[s]=o}function a(e){if(e.length%2!=0)throw new Error("Hex encoded strings must have an even number length");for(var t=new Uint8Array(e.length/2),n=0;n<e.length;n+=2){var r=e.substr(n,2).toLowerCase();if(!(r in i))throw new Error("Cannot decode unrecognized sequence "+r+" as hexadecimal");t[n/2]=i[r]}return t}function u(e){for(var t="",n=0;n<e.byteLength;n++)t+=r[e[n]];return t}},function(e,t,n){(function(e){!function(e,t){"use strict";function r(e,t){if(!e)throw new Error(t||"Assertion failed")}function i(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}function o(e,t,n){if(o.isBN(e))return e;this.negative=0,this.words=null,this.length=0,this.red=null,null!==e&&("le"!==t&&"be"!==t||(n=t,t=10),this._init(e||0,t||10,n||"be"))}var s;"object"==typeof e?e.exports=o:t.BN=o,o.BN=o,o.wordSize=26;try{s=n(315).Buffer}catch(e){}function a(e,t,n){for(var r=0,i=Math.min(e.length,n),o=t;o<i;o++){var s=e.charCodeAt(o)-48;r<<=4,r|=s>=49&&s<=54?s-49+10:s>=17&&s<=22?s-17+10:15&s}return r}function u(e,t,n,r){for(var i=0,o=Math.min(e.length,n),s=t;s<o;s++){var a=e.charCodeAt(s)-48;i*=r,i+=a>=49?a-49+10:a>=17?a-17+10:a}return i}o.isBN=function(e){return e instanceof o||null!==e&&"object"==typeof e&&e.constructor.wordSize===o.wordSize&&Array.isArray(e.words)},o.max=function(e,t){return e.cmp(t)>0?e:t},o.min=function(e,t){return e.cmp(t)<0?e:t},o.prototype._init=function(e,t,n){if("number"==typeof e)return this._initNumber(e,t,n);if("object"==typeof e)return this._initArray(e,t,n);"hex"===t&&(t=16),r(t===(0|t)&&t>=2&&t<=36);var i=0;"-"===(e=e.toString().replace(/\s+/g,""))[0]&&i++,16===t?this._parseHex(e,i):this._parseBase(e,t,i),"-"===e[0]&&(this.negative=1),this.strip(),"le"===n&&this._initArray(this.toArray(),t,n)},o.prototype._initNumber=function(e,t,n){e<0&&(this.negative=1,e=-e),e<67108864?(this.words=[67108863&e],this.length=1):e<4503599627370496?(this.words=[67108863&e,e/67108864&67108863],this.length=2):(r(e<9007199254740992),this.words=[67108863&e,e/67108864&67108863,1],this.length=3),"le"===n&&this._initArray(this.toArray(),t,n)},o.prototype._initArray=function(e,t,n){if(r("number"==typeof e.length),e.length<=0)return this.words=[0],this.length=1,this;this.length=Math.ceil(e.length/3),this.words=new Array(this.length);for(var i=0;i<this.length;i++)this.words[i]=0;var o,s,a=0;if("be"===n)for(i=e.length-1,o=0;i>=0;i-=3)s=e[i]|e[i-1]<<8|e[i-2]<<16,this.words[o]|=s<<a&67108863,this.words[o+1]=s>>>26-a&67108863,(a+=24)>=26&&(a-=26,o++);else if("le"===n)for(i=0,o=0;i<e.length;i+=3)s=e[i]|e[i+1]<<8|e[i+2]<<16,this.words[o]|=s<<a&67108863,this.words[o+1]=s>>>26-a&67108863,(a+=24)>=26&&(a-=26,o++);return this.strip()},o.prototype._parseHex=function(e,t){this.length=Math.ceil((e.length-t)/6),this.words=new Array(this.length);for(var n=0;n<this.length;n++)this.words[n]=0;var r,i,o=0;for(n=e.length-6,r=0;n>=t;n-=6)i=a(e,n,n+6),this.words[r]|=i<<o&67108863,this.words[r+1]|=i>>>26-o&4194303,(o+=24)>=26&&(o-=26,r++);n+6!==t&&(i=a(e,t,n+6),this.words[r]|=i<<o&67108863,this.words[r+1]|=i>>>26-o&4194303),this.strip()},o.prototype._parseBase=function(e,t,n){this.words=[0],this.length=1;for(var r=0,i=1;i<=67108863;i*=t)r++;r--,i=i/t|0;for(var o=e.length-n,s=o%r,a=Math.min(o,o-s)+n,c=0,f=n;f<a;f+=r)c=u(e,f,f+r,t),this.imuln(i),this.words[0]+c<67108864?this.words[0]+=c:this._iaddn(c);if(0!==s){var l=1;for(c=u(e,f,e.length,t),f=0;f<s;f++)l*=t;this.imuln(l),this.words[0]+c<67108864?this.words[0]+=c:this._iaddn(c)}},o.prototype.copy=function(e){e.words=new Array(this.length);for(var t=0;t<this.length;t++)e.words[t]=this.words[t];e.length=this.length,e.negative=this.negative,e.red=this.red},o.prototype.clone=function(){var e=new o(null);return this.copy(e),e},o.prototype._expand=function(e){for(;this.length<e;)this.words[this.length++]=0;return this},o.prototype.strip=function(){for(;this.length>1&&0===this.words[this.length-1];)this.length--;return this._normSign()},o.prototype._normSign=function(){return 1===this.length&&0===this.words[0]&&(this.negative=0),this},o.prototype.inspect=function(){return(this.red?"<BN-R: ":"<BN: ")+this.toString(16)+">"};var c=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],f=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],l=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];function d(e,t,n){n.negative=t.negative^e.negative;var r=e.length+t.length|0;n.length=r,r=r-1|0;var i=0|e.words[0],o=0|t.words[0],s=i*o,a=67108863&s,u=s/67108864|0;n.words[0]=a;for(var c=1;c<r;c++){for(var f=u>>>26,l=67108863&u,d=Math.min(c,t.length-1),h=Math.max(0,c-e.length+1);h<=d;h++){var p=c-h|0;f+=(s=(i=0|e.words[p])*(o=0|t.words[h])+l)/67108864|0,l=67108863&s}n.words[c]=0|l,u=0|f}return 0!==u?n.words[c]=0|u:n.length--,n.strip()}o.prototype.toString=function(e,t){var n;if(t=0|t||1,16===(e=e||10)||"hex"===e){n="";for(var i=0,o=0,s=0;s<this.length;s++){var a=this.words[s],u=(16777215&(a<<i|o)).toString(16);n=0!==(o=a>>>24-i&16777215)||s!==this.length-1?c[6-u.length]+u+n:u+n,(i+=2)>=26&&(i-=26,s--)}for(0!==o&&(n=o.toString(16)+n);n.length%t!=0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}if(e===(0|e)&&e>=2&&e<=36){var d=f[e],h=l[e];n="";var p=this.clone();for(p.negative=0;!p.isZero();){var v=p.modn(h).toString(e);n=(p=p.idivn(h)).isZero()?v+n:c[d-v.length]+v+n}for(this.isZero()&&(n="0"+n);n.length%t!=0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}r(!1,"Base should be between 2 and 36")},o.prototype.toNumber=function(){var e=this.words[0];return 2===this.length?e+=67108864*this.words[1]:3===this.length&&1===this.words[2]?e+=4503599627370496+67108864*this.words[1]:this.length>2&&r(!1,"Number can only safely store up to 53 bits"),0!==this.negative?-e:e},o.prototype.toJSON=function(){return this.toString(16)},o.prototype.toBuffer=function(e,t){return r(void 0!==s),this.toArrayLike(s,e,t)},o.prototype.toArray=function(e,t){return this.toArrayLike(Array,e,t)},o.prototype.toArrayLike=function(e,t,n){var i=this.byteLength(),o=n||Math.max(1,i);r(i<=o,"byte array longer than desired length"),r(o>0,"Requested array length <= 0"),this.strip();var s,a,u="le"===t,c=new e(o),f=this.clone();if(u){for(a=0;!f.isZero();a++)s=f.andln(255),f.iushrn(8),c[a]=s;for(;a<o;a++)c[a]=0}else{for(a=0;a<o-i;a++)c[a]=0;for(a=0;!f.isZero();a++)s=f.andln(255),f.iushrn(8),c[o-a-1]=s}return c},Math.clz32?o.prototype._countBits=function(e){return 32-Math.clz32(e)}:o.prototype._countBits=function(e){var t=e,n=0;return t>=4096&&(n+=13,t>>>=13),t>=64&&(n+=7,t>>>=7),t>=8&&(n+=4,t>>>=4),t>=2&&(n+=2,t>>>=2),n+t},o.prototype._zeroBits=function(e){if(0===e)return 26;var t=e,n=0;return 0==(8191&t)&&(n+=13,t>>>=13),0==(127&t)&&(n+=7,t>>>=7),0==(15&t)&&(n+=4,t>>>=4),0==(3&t)&&(n+=2,t>>>=2),0==(1&t)&&n++,n},o.prototype.bitLength=function(){var e=this.words[this.length-1],t=this._countBits(e);return 26*(this.length-1)+t},o.prototype.zeroBits=function(){if(this.isZero())return 0;for(var e=0,t=0;t<this.length;t++){var n=this._zeroBits(this.words[t]);if(e+=n,26!==n)break}return e},o.prototype.byteLength=function(){return Math.ceil(this.bitLength()/8)},o.prototype.toTwos=function(e){return 0!==this.negative?this.abs().inotn(e).iaddn(1):this.clone()},o.prototype.fromTwos=function(e){return this.testn(e-1)?this.notn(e).iaddn(1).ineg():this.clone()},o.prototype.isNeg=function(){return 0!==this.negative},o.prototype.neg=function(){return this.clone().ineg()},o.prototype.ineg=function(){return this.isZero()||(this.negative^=1),this},o.prototype.iuor=function(e){for(;this.length<e.length;)this.words[this.length++]=0;for(var t=0;t<e.length;t++)this.words[t]=this.words[t]|e.words[t];return this.strip()},o.prototype.ior=function(e){return r(0==(this.negative|e.negative)),this.iuor(e)},o.prototype.or=function(e){return this.length>e.length?this.clone().ior(e):e.clone().ior(this)},o.prototype.uor=function(e){return this.length>e.length?this.clone().iuor(e):e.clone().iuor(this)},o.prototype.iuand=function(e){var t;t=this.length>e.length?e:this;for(var n=0;n<t.length;n++)this.words[n]=this.words[n]&e.words[n];return this.length=t.length,this.strip()},o.prototype.iand=function(e){return r(0==(this.negative|e.negative)),this.iuand(e)},o.prototype.and=function(e){return this.length>e.length?this.clone().iand(e):e.clone().iand(this)},o.prototype.uand=function(e){return this.length>e.length?this.clone().iuand(e):e.clone().iuand(this)},o.prototype.iuxor=function(e){var t,n;this.length>e.length?(t=this,n=e):(t=e,n=this);for(var r=0;r<n.length;r++)this.words[r]=t.words[r]^n.words[r];if(this!==t)for(;r<t.length;r++)this.words[r]=t.words[r];return this.length=t.length,this.strip()},o.prototype.ixor=function(e){return r(0==(this.negative|e.negative)),this.iuxor(e)},o.prototype.xor=function(e){return this.length>e.length?this.clone().ixor(e):e.clone().ixor(this)},o.prototype.uxor=function(e){return this.length>e.length?this.clone().iuxor(e):e.clone().iuxor(this)},o.prototype.inotn=function(e){r("number"==typeof e&&e>=0);var t=0|Math.ceil(e/26),n=e%26;this._expand(t),n>0&&t--;for(var i=0;i<t;i++)this.words[i]=67108863&~this.words[i];return n>0&&(this.words[i]=~this.words[i]&67108863>>26-n),this.strip()},o.prototype.notn=function(e){return this.clone().inotn(e)},o.prototype.setn=function(e,t){r("number"==typeof e&&e>=0);var n=e/26|0,i=e%26;return this._expand(n+1),this.words[n]=t?this.words[n]|1<<i:this.words[n]&~(1<<i),this.strip()},o.prototype.iadd=function(e){var t,n,r;if(0!==this.negative&&0===e.negative)return this.negative=0,t=this.isub(e),this.negative^=1,this._normSign();if(0===this.negative&&0!==e.negative)return e.negative=0,t=this.isub(e),e.negative=1,t._normSign();this.length>e.length?(n=this,r=e):(n=e,r=this);for(var i=0,o=0;o<r.length;o++)t=(0|n.words[o])+(0|r.words[o])+i,this.words[o]=67108863&t,i=t>>>26;for(;0!==i&&o<n.length;o++)t=(0|n.words[o])+i,this.words[o]=67108863&t,i=t>>>26;if(this.length=n.length,0!==i)this.words[this.length]=i,this.length++;else if(n!==this)for(;o<n.length;o++)this.words[o]=n.words[o];return this},o.prototype.add=function(e){var t;return 0!==e.negative&&0===this.negative?(e.negative=0,t=this.sub(e),e.negative^=1,t):0===e.negative&&0!==this.negative?(this.negative=0,t=e.sub(this),this.negative=1,t):this.length>e.length?this.clone().iadd(e):e.clone().iadd(this)},o.prototype.isub=function(e){if(0!==e.negative){e.negative=0;var t=this.iadd(e);return e.negative=1,t._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(e),this.negative=1,this._normSign();var n,r,i=this.cmp(e);if(0===i)return this.negative=0,this.length=1,this.words[0]=0,this;i>0?(n=this,r=e):(n=e,r=this);for(var o=0,s=0;s<r.length;s++)o=(t=(0|n.words[s])-(0|r.words[s])+o)>>26,this.words[s]=67108863&t;for(;0!==o&&s<n.length;s++)o=(t=(0|n.words[s])+o)>>26,this.words[s]=67108863&t;if(0===o&&s<n.length&&n!==this)for(;s<n.length;s++)this.words[s]=n.words[s];return this.length=Math.max(this.length,s),n!==this&&(this.negative=1),this.strip()},o.prototype.sub=function(e){return this.clone().isub(e)};var h=function(e,t,n){var r,i,o,s=e.words,a=t.words,u=n.words,c=0,f=0|s[0],l=8191&f,d=f>>>13,h=0|s[1],p=8191&h,v=h>>>13,g=0|s[2],m=8191&g,b=g>>>13,y=0|s[3],w=8191&y,_=y>>>13,S=0|s[4],E=8191&S,M=S>>>13,A=0|s[5],I=8191&A,k=A>>>13,O=0|s[6],x=8191&O,C=O>>>13,T=0|s[7],P=8191&T,N=T>>>13,R=0|s[8],L=8191&R,j=R>>>13,D=0|s[9],U=8191&D,B=D>>>13,F=0|a[0],z=8191&F,q=F>>>13,K=0|a[1],H=8191&K,V=K>>>13,G=0|a[2],W=8191&G,$=G>>>13,Y=0|a[3],J=8191&Y,Z=Y>>>13,X=0|a[4],Q=8191&X,ee=X>>>13,te=0|a[5],ne=8191&te,re=te>>>13,ie=0|a[6],oe=8191&ie,se=ie>>>13,ae=0|a[7],ue=8191&ae,ce=ae>>>13,fe=0|a[8],le=8191&fe,de=fe>>>13,he=0|a[9],pe=8191&he,ve=he>>>13;n.negative=e.negative^t.negative,n.length=19;var ge=(c+(r=Math.imul(l,z))|0)+((8191&(i=(i=Math.imul(l,q))+Math.imul(d,z)|0))<<13)|0;c=((o=Math.imul(d,q))+(i>>>13)|0)+(ge>>>26)|0,ge&=67108863,r=Math.imul(p,z),i=(i=Math.imul(p,q))+Math.imul(v,z)|0,o=Math.imul(v,q);var me=(c+(r=r+Math.imul(l,H)|0)|0)+((8191&(i=(i=i+Math.imul(l,V)|0)+Math.imul(d,H)|0))<<13)|0;c=((o=o+Math.imul(d,V)|0)+(i>>>13)|0)+(me>>>26)|0,me&=67108863,r=Math.imul(m,z),i=(i=Math.imul(m,q))+Math.imul(b,z)|0,o=Math.imul(b,q),r=r+Math.imul(p,H)|0,i=(i=i+Math.imul(p,V)|0)+Math.imul(v,H)|0,o=o+Math.imul(v,V)|0;var be=(c+(r=r+Math.imul(l,W)|0)|0)+((8191&(i=(i=i+Math.imul(l,$)|0)+Math.imul(d,W)|0))<<13)|0;c=((o=o+Math.imul(d,$)|0)+(i>>>13)|0)+(be>>>26)|0,be&=67108863,r=Math.imul(w,z),i=(i=Math.imul(w,q))+Math.imul(_,z)|0,o=Math.imul(_,q),r=r+Math.imul(m,H)|0,i=(i=i+Math.imul(m,V)|0)+Math.imul(b,H)|0,o=o+Math.imul(b,V)|0,r=r+Math.imul(p,W)|0,i=(i=i+Math.imul(p,$)|0)+Math.imul(v,W)|0,o=o+Math.imul(v,$)|0;var ye=(c+(r=r+Math.imul(l,J)|0)|0)+((8191&(i=(i=i+Math.imul(l,Z)|0)+Math.imul(d,J)|0))<<13)|0;c=((o=o+Math.imul(d,Z)|0)+(i>>>13)|0)+(ye>>>26)|0,ye&=67108863,r=Math.imul(E,z),i=(i=Math.imul(E,q))+Math.imul(M,z)|0,o=Math.imul(M,q),r=r+Math.imul(w,H)|0,i=(i=i+Math.imul(w,V)|0)+Math.imul(_,H)|0,o=o+Math.imul(_,V)|0,r=r+Math.imul(m,W)|0,i=(i=i+Math.imul(m,$)|0)+Math.imul(b,W)|0,o=o+Math.imul(b,$)|0,r=r+Math.imul(p,J)|0,i=(i=i+Math.imul(p,Z)|0)+Math.imul(v,J)|0,o=o+Math.imul(v,Z)|0;var we=(c+(r=r+Math.imul(l,Q)|0)|0)+((8191&(i=(i=i+Math.imul(l,ee)|0)+Math.imul(d,Q)|0))<<13)|0;c=((o=o+Math.imul(d,ee)|0)+(i>>>13)|0)+(we>>>26)|0,we&=67108863,r=Math.imul(I,z),i=(i=Math.imul(I,q))+Math.imul(k,z)|0,o=Math.imul(k,q),r=r+Math.imul(E,H)|0,i=(i=i+Math.imul(E,V)|0)+Math.imul(M,H)|0,o=o+Math.imul(M,V)|0,r=r+Math.imul(w,W)|0,i=(i=i+Math.imul(w,$)|0)+Math.imul(_,W)|0,o=o+Math.imul(_,$)|0,r=r+Math.imul(m,J)|0,i=(i=i+Math.imul(m,Z)|0)+Math.imul(b,J)|0,o=o+Math.imul(b,Z)|0,r=r+Math.imul(p,Q)|0,i=(i=i+Math.imul(p,ee)|0)+Math.imul(v,Q)|0,o=o+Math.imul(v,ee)|0;var _e=(c+(r=r+Math.imul(l,ne)|0)|0)+((8191&(i=(i=i+Math.imul(l,re)|0)+Math.imul(d,ne)|0))<<13)|0;c=((o=o+Math.imul(d,re)|0)+(i>>>13)|0)+(_e>>>26)|0,_e&=67108863,r=Math.imul(x,z),i=(i=Math.imul(x,q))+Math.imul(C,z)|0,o=Math.imul(C,q),r=r+Math.imul(I,H)|0,i=(i=i+Math.imul(I,V)|0)+Math.imul(k,H)|0,o=o+Math.imul(k,V)|0,r=r+Math.imul(E,W)|0,i=(i=i+Math.imul(E,$)|0)+Math.imul(M,W)|0,o=o+Math.imul(M,$)|0,r=r+Math.imul(w,J)|0,i=(i=i+Math.imul(w,Z)|0)+Math.imul(_,J)|0,o=o+Math.imul(_,Z)|0,r=r+Math.imul(m,Q)|0,i=(i=i+Math.imul(m,ee)|0)+Math.imul(b,Q)|0,o=o+Math.imul(b,ee)|0,r=r+Math.imul(p,ne)|0,i=(i=i+Math.imul(p,re)|0)+Math.imul(v,ne)|0,o=o+Math.imul(v,re)|0;var Se=(c+(r=r+Math.imul(l,oe)|0)|0)+((8191&(i=(i=i+Math.imul(l,se)|0)+Math.imul(d,oe)|0))<<13)|0;c=((o=o+Math.imul(d,se)|0)+(i>>>13)|0)+(Se>>>26)|0,Se&=67108863,r=Math.imul(P,z),i=(i=Math.imul(P,q))+Math.imul(N,z)|0,o=Math.imul(N,q),r=r+Math.imul(x,H)|0,i=(i=i+Math.imul(x,V)|0)+Math.imul(C,H)|0,o=o+Math.imul(C,V)|0,r=r+Math.imul(I,W)|0,i=(i=i+Math.imul(I,$)|0)+Math.imul(k,W)|0,o=o+Math.imul(k,$)|0,r=r+Math.imul(E,J)|0,i=(i=i+Math.imul(E,Z)|0)+Math.imul(M,J)|0,o=o+Math.imul(M,Z)|0,r=r+Math.imul(w,Q)|0,i=(i=i+Math.imul(w,ee)|0)+Math.imul(_,Q)|0,o=o+Math.imul(_,ee)|0,r=r+Math.imul(m,ne)|0,i=(i=i+Math.imul(m,re)|0)+Math.imul(b,ne)|0,o=o+Math.imul(b,re)|0,r=r+Math.imul(p,oe)|0,i=(i=i+Math.imul(p,se)|0)+Math.imul(v,oe)|0,o=o+Math.imul(v,se)|0;var Ee=(c+(r=r+Math.imul(l,ue)|0)|0)+((8191&(i=(i=i+Math.imul(l,ce)|0)+Math.imul(d,ue)|0))<<13)|0;c=((o=o+Math.imul(d,ce)|0)+(i>>>13)|0)+(Ee>>>26)|0,Ee&=67108863,r=Math.imul(L,z),i=(i=Math.imul(L,q))+Math.imul(j,z)|0,o=Math.imul(j,q),r=r+Math.imul(P,H)|0,i=(i=i+Math.imul(P,V)|0)+Math.imul(N,H)|0,o=o+Math.imul(N,V)|0,r=r+Math.imul(x,W)|0,i=(i=i+Math.imul(x,$)|0)+Math.imul(C,W)|0,o=o+Math.imul(C,$)|0,r=r+Math.imul(I,J)|0,i=(i=i+Math.imul(I,Z)|0)+Math.imul(k,J)|0,o=o+Math.imul(k,Z)|0,r=r+Math.imul(E,Q)|0,i=(i=i+Math.imul(E,ee)|0)+Math.imul(M,Q)|0,o=o+Math.imul(M,ee)|0,r=r+Math.imul(w,ne)|0,i=(i=i+Math.imul(w,re)|0)+Math.imul(_,ne)|0,o=o+Math.imul(_,re)|0,r=r+Math.imul(m,oe)|0,i=(i=i+Math.imul(m,se)|0)+Math.imul(b,oe)|0,o=o+Math.imul(b,se)|0,r=r+Math.imul(p,ue)|0,i=(i=i+Math.imul(p,ce)|0)+Math.imul(v,ue)|0,o=o+Math.imul(v,ce)|0;var Me=(c+(r=r+Math.imul(l,le)|0)|0)+((8191&(i=(i=i+Math.imul(l,de)|0)+Math.imul(d,le)|0))<<13)|0;c=((o=o+Math.imul(d,de)|0)+(i>>>13)|0)+(Me>>>26)|0,Me&=67108863,r=Math.imul(U,z),i=(i=Math.imul(U,q))+Math.imul(B,z)|0,o=Math.imul(B,q),r=r+Math.imul(L,H)|0,i=(i=i+Math.imul(L,V)|0)+Math.imul(j,H)|0,o=o+Math.imul(j,V)|0,r=r+Math.imul(P,W)|0,i=(i=i+Math.imul(P,$)|0)+Math.imul(N,W)|0,o=o+Math.imul(N,$)|0,r=r+Math.imul(x,J)|0,i=(i=i+Math.imul(x,Z)|0)+Math.imul(C,J)|0,o=o+Math.imul(C,Z)|0,r=r+Math.imul(I,Q)|0,i=(i=i+Math.imul(I,ee)|0)+Math.imul(k,Q)|0,o=o+Math.imul(k,ee)|0,r=r+Math.imul(E,ne)|0,i=(i=i+Math.imul(E,re)|0)+Math.imul(M,ne)|0,o=o+Math.imul(M,re)|0,r=r+Math.imul(w,oe)|0,i=(i=i+Math.imul(w,se)|0)+Math.imul(_,oe)|0,o=o+Math.imul(_,se)|0,r=r+Math.imul(m,ue)|0,i=(i=i+Math.imul(m,ce)|0)+Math.imul(b,ue)|0,o=o+Math.imul(b,ce)|0,r=r+Math.imul(p,le)|0,i=(i=i+Math.imul(p,de)|0)+Math.imul(v,le)|0,o=o+Math.imul(v,de)|0;var Ae=(c+(r=r+Math.imul(l,pe)|0)|0)+((8191&(i=(i=i+Math.imul(l,ve)|0)+Math.imul(d,pe)|0))<<13)|0;c=((o=o+Math.imul(d,ve)|0)+(i>>>13)|0)+(Ae>>>26)|0,Ae&=67108863,r=Math.imul(U,H),i=(i=Math.imul(U,V))+Math.imul(B,H)|0,o=Math.imul(B,V),r=r+Math.imul(L,W)|0,i=(i=i+Math.imul(L,$)|0)+Math.imul(j,W)|0,o=o+Math.imul(j,$)|0,r=r+Math.imul(P,J)|0,i=(i=i+Math.imul(P,Z)|0)+Math.imul(N,J)|0,o=o+Math.imul(N,Z)|0,r=r+Math.imul(x,Q)|0,i=(i=i+Math.imul(x,ee)|0)+Math.imul(C,Q)|0,o=o+Math.imul(C,ee)|0,r=r+Math.imul(I,ne)|0,i=(i=i+Math.imul(I,re)|0)+Math.imul(k,ne)|0,o=o+Math.imul(k,re)|0,r=r+Math.imul(E,oe)|0,i=(i=i+Math.imul(E,se)|0)+Math.imul(M,oe)|0,o=o+Math.imul(M,se)|0,r=r+Math.imul(w,ue)|0,i=(i=i+Math.imul(w,ce)|0)+Math.imul(_,ue)|0,o=o+Math.imul(_,ce)|0,r=r+Math.imul(m,le)|0,i=(i=i+Math.imul(m,de)|0)+Math.imul(b,le)|0,o=o+Math.imul(b,de)|0;var Ie=(c+(r=r+Math.imul(p,pe)|0)|0)+((8191&(i=(i=i+Math.imul(p,ve)|0)+Math.imul(v,pe)|0))<<13)|0;c=((o=o+Math.imul(v,ve)|0)+(i>>>13)|0)+(Ie>>>26)|0,Ie&=67108863,r=Math.imul(U,W),i=(i=Math.imul(U,$))+Math.imul(B,W)|0,o=Math.imul(B,$),r=r+Math.imul(L,J)|0,i=(i=i+Math.imul(L,Z)|0)+Math.imul(j,J)|0,o=o+Math.imul(j,Z)|0,r=r+Math.imul(P,Q)|0,i=(i=i+Math.imul(P,ee)|0)+Math.imul(N,Q)|0,o=o+Math.imul(N,ee)|0,r=r+Math.imul(x,ne)|0,i=(i=i+Math.imul(x,re)|0)+Math.imul(C,ne)|0,o=o+Math.imul(C,re)|0,r=r+Math.imul(I,oe)|0,i=(i=i+Math.imul(I,se)|0)+Math.imul(k,oe)|0,o=o+Math.imul(k,se)|0,r=r+Math.imul(E,ue)|0,i=(i=i+Math.imul(E,ce)|0)+Math.imul(M,ue)|0,o=o+Math.imul(M,ce)|0,r=r+Math.imul(w,le)|0,i=(i=i+Math.imul(w,de)|0)+Math.imul(_,le)|0,o=o+Math.imul(_,de)|0;var ke=(c+(r=r+Math.imul(m,pe)|0)|0)+((8191&(i=(i=i+Math.imul(m,ve)|0)+Math.imul(b,pe)|0))<<13)|0;c=((o=o+Math.imul(b,ve)|0)+(i>>>13)|0)+(ke>>>26)|0,ke&=67108863,r=Math.imul(U,J),i=(i=Math.imul(U,Z))+Math.imul(B,J)|0,o=Math.imul(B,Z),r=r+Math.imul(L,Q)|0,i=(i=i+Math.imul(L,ee)|0)+Math.imul(j,Q)|0,o=o+Math.imul(j,ee)|0,r=r+Math.imul(P,ne)|0,i=(i=i+Math.imul(P,re)|0)+Math.imul(N,ne)|0,o=o+Math.imul(N,re)|0,r=r+Math.imul(x,oe)|0,i=(i=i+Math.imul(x,se)|0)+Math.imul(C,oe)|0,o=o+Math.imul(C,se)|0,r=r+Math.imul(I,ue)|0,i=(i=i+Math.imul(I,ce)|0)+Math.imul(k,ue)|0,o=o+Math.imul(k,ce)|0,r=r+Math.imul(E,le)|0,i=(i=i+Math.imul(E,de)|0)+Math.imul(M,le)|0,o=o+Math.imul(M,de)|0;var Oe=(c+(r=r+Math.imul(w,pe)|0)|0)+((8191&(i=(i=i+Math.imul(w,ve)|0)+Math.imul(_,pe)|0))<<13)|0;c=((o=o+Math.imul(_,ve)|0)+(i>>>13)|0)+(Oe>>>26)|0,Oe&=67108863,r=Math.imul(U,Q),i=(i=Math.imul(U,ee))+Math.imul(B,Q)|0,o=Math.imul(B,ee),r=r+Math.imul(L,ne)|0,i=(i=i+Math.imul(L,re)|0)+Math.imul(j,ne)|0,o=o+Math.imul(j,re)|0,r=r+Math.imul(P,oe)|0,i=(i=i+Math.imul(P,se)|0)+Math.imul(N,oe)|0,o=o+Math.imul(N,se)|0,r=r+Math.imul(x,ue)|0,i=(i=i+Math.imul(x,ce)|0)+Math.imul(C,ue)|0,o=o+Math.imul(C,ce)|0,r=r+Math.imul(I,le)|0,i=(i=i+Math.imul(I,de)|0)+Math.imul(k,le)|0,o=o+Math.imul(k,de)|0;var xe=(c+(r=r+Math.imul(E,pe)|0)|0)+((8191&(i=(i=i+Math.imul(E,ve)|0)+Math.imul(M,pe)|0))<<13)|0;c=((o=o+Math.imul(M,ve)|0)+(i>>>13)|0)+(xe>>>26)|0,xe&=67108863,r=Math.imul(U,ne),i=(i=Math.imul(U,re))+Math.imul(B,ne)|0,o=Math.imul(B,re),r=r+Math.imul(L,oe)|0,i=(i=i+Math.imul(L,se)|0)+Math.imul(j,oe)|0,o=o+Math.imul(j,se)|0,r=r+Math.imul(P,ue)|0,i=(i=i+Math.imul(P,ce)|0)+Math.imul(N,ue)|0,o=o+Math.imul(N,ce)|0,r=r+Math.imul(x,le)|0,i=(i=i+Math.imul(x,de)|0)+Math.imul(C,le)|0,o=o+Math.imul(C,de)|0;var Ce=(c+(r=r+Math.imul(I,pe)|0)|0)+((8191&(i=(i=i+Math.imul(I,ve)|0)+Math.imul(k,pe)|0))<<13)|0;c=((o=o+Math.imul(k,ve)|0)+(i>>>13)|0)+(Ce>>>26)|0,Ce&=67108863,r=Math.imul(U,oe),i=(i=Math.imul(U,se))+Math.imul(B,oe)|0,o=Math.imul(B,se),r=r+Math.imul(L,ue)|0,i=(i=i+Math.imul(L,ce)|0)+Math.imul(j,ue)|0,o=o+Math.imul(j,ce)|0,r=r+Math.imul(P,le)|0,i=(i=i+Math.imul(P,de)|0)+Math.imul(N,le)|0,o=o+Math.imul(N,de)|0;var Te=(c+(r=r+Math.imul(x,pe)|0)|0)+((8191&(i=(i=i+Math.imul(x,ve)|0)+Math.imul(C,pe)|0))<<13)|0;c=((o=o+Math.imul(C,ve)|0)+(i>>>13)|0)+(Te>>>26)|0,Te&=67108863,r=Math.imul(U,ue),i=(i=Math.imul(U,ce))+Math.imul(B,ue)|0,o=Math.imul(B,ce),r=r+Math.imul(L,le)|0,i=(i=i+Math.imul(L,de)|0)+Math.imul(j,le)|0,o=o+Math.imul(j,de)|0;var Pe=(c+(r=r+Math.imul(P,pe)|0)|0)+((8191&(i=(i=i+Math.imul(P,ve)|0)+Math.imul(N,pe)|0))<<13)|0;c=((o=o+Math.imul(N,ve)|0)+(i>>>13)|0)+(Pe>>>26)|0,Pe&=67108863,r=Math.imul(U,le),i=(i=Math.imul(U,de))+Math.imul(B,le)|0,o=Math.imul(B,de);var Ne=(c+(r=r+Math.imul(L,pe)|0)|0)+((8191&(i=(i=i+Math.imul(L,ve)|0)+Math.imul(j,pe)|0))<<13)|0;c=((o=o+Math.imul(j,ve)|0)+(i>>>13)|0)+(Ne>>>26)|0,Ne&=67108863;var Re=(c+(r=Math.imul(U,pe))|0)+((8191&(i=(i=Math.imul(U,ve))+Math.imul(B,pe)|0))<<13)|0;return c=((o=Math.imul(B,ve))+(i>>>13)|0)+(Re>>>26)|0,Re&=67108863,u[0]=ge,u[1]=me,u[2]=be,u[3]=ye,u[4]=we,u[5]=_e,u[6]=Se,u[7]=Ee,u[8]=Me,u[9]=Ae,u[10]=Ie,u[11]=ke,u[12]=Oe,u[13]=xe,u[14]=Ce,u[15]=Te,u[16]=Pe,u[17]=Ne,u[18]=Re,0!==c&&(u[19]=c,n.length++),n};function p(e,t,n){return(new v).mulp(e,t,n)}function v(e,t){this.x=e,this.y=t}Math.imul||(h=d),o.prototype.mulTo=function(e,t){var n=this.length+e.length;return 10===this.length&&10===e.length?h(this,e,t):n<63?d(this,e,t):n<1024?function(e,t,n){n.negative=t.negative^e.negative,n.length=e.length+t.length;for(var r=0,i=0,o=0;o<n.length-1;o++){var s=i;i=0;for(var a=67108863&r,u=Math.min(o,t.length-1),c=Math.max(0,o-e.length+1);c<=u;c++){var f=o-c,l=(0|e.words[f])*(0|t.words[c]),d=67108863&l;a=67108863&(d=d+a|0),i+=(s=(s=s+(l/67108864|0)|0)+(d>>>26)|0)>>>26,s&=67108863}n.words[o]=a,r=s,s=i}return 0!==r?n.words[o]=r:n.length--,n.strip()}(this,e,t):p(this,e,t)},v.prototype.makeRBT=function(e){for(var t=new Array(e),n=o.prototype._countBits(e)-1,r=0;r<e;r++)t[r]=this.revBin(r,n,e);return t},v.prototype.revBin=function(e,t,n){if(0===e||e===n-1)return e;for(var r=0,i=0;i<t;i++)r|=(1&e)<<t-i-1,e>>=1;return r},v.prototype.permute=function(e,t,n,r,i,o){for(var s=0;s<o;s++)r[s]=t[e[s]],i[s]=n[e[s]]},v.prototype.transform=function(e,t,n,r,i,o){this.permute(o,e,t,n,r,i);for(var s=1;s<i;s<<=1)for(var a=s<<1,u=Math.cos(2*Math.PI/a),c=Math.sin(2*Math.PI/a),f=0;f<i;f+=a)for(var l=u,d=c,h=0;h<s;h++){var p=n[f+h],v=r[f+h],g=n[f+h+s],m=r[f+h+s],b=l*g-d*m;m=l*m+d*g,g=b,n[f+h]=p+g,r[f+h]=v+m,n[f+h+s]=p-g,r[f+h+s]=v-m,h!==a&&(b=u*l-c*d,d=u*d+c*l,l=b)}},v.prototype.guessLen13b=function(e,t){var n=1|Math.max(t,e),r=1&n,i=0;for(n=n/2|0;n;n>>>=1)i++;return 1<<i+1+r},v.prototype.conjugate=function(e,t,n){if(!(n<=1))for(var r=0;r<n/2;r++){var i=e[r];e[r]=e[n-r-1],e[n-r-1]=i,i=t[r],t[r]=-t[n-r-1],t[n-r-1]=-i}},v.prototype.normalize13b=function(e,t){for(var n=0,r=0;r<t/2;r++){var i=8192*Math.round(e[2*r+1]/t)+Math.round(e[2*r]/t)+n;e[r]=67108863&i,n=i<67108864?0:i/67108864|0}return e},v.prototype.convert13b=function(e,t,n,i){for(var o=0,s=0;s<t;s++)o+=0|e[s],n[2*s]=8191&o,o>>>=13,n[2*s+1]=8191&o,o>>>=13;for(s=2*t;s<i;++s)n[s]=0;r(0===o),r(0==(-8192&o))},v.prototype.stub=function(e){for(var t=new Array(e),n=0;n<e;n++)t[n]=0;return t},v.prototype.mulp=function(e,t,n){var r=2*this.guessLen13b(e.length,t.length),i=this.makeRBT(r),o=this.stub(r),s=new Array(r),a=new Array(r),u=new Array(r),c=new Array(r),f=new Array(r),l=new Array(r),d=n.words;d.length=r,this.convert13b(e.words,e.length,s,r),this.convert13b(t.words,t.length,c,r),this.transform(s,o,a,u,r,i),this.transform(c,o,f,l,r,i);for(var h=0;h<r;h++){var p=a[h]*f[h]-u[h]*l[h];u[h]=a[h]*l[h]+u[h]*f[h],a[h]=p}return this.conjugate(a,u,r),this.transform(a,u,d,o,r,i),this.conjugate(d,o,r),this.normalize13b(d,r),n.negative=e.negative^t.negative,n.length=e.length+t.length,n.strip()},o.prototype.mul=function(e){var t=new o(null);return t.words=new Array(this.length+e.length),this.mulTo(e,t)},o.prototype.mulf=function(e){var t=new o(null);return t.words=new Array(this.length+e.length),p(this,e,t)},o.prototype.imul=function(e){return this.clone().mulTo(e,this)},o.prototype.imuln=function(e){r("number"==typeof e),r(e<67108864);for(var t=0,n=0;n<this.length;n++){var i=(0|this.words[n])*e,o=(67108863&i)+(67108863&t);t>>=26,t+=i/67108864|0,t+=o>>>26,this.words[n]=67108863&o}return 0!==t&&(this.words[n]=t,this.length++),this},o.prototype.muln=function(e){return this.clone().imuln(e)},o.prototype.sqr=function(){return this.mul(this)},o.prototype.isqr=function(){return this.imul(this.clone())},o.prototype.pow=function(e){var t=function(e){for(var t=new Array(e.bitLength()),n=0;n<t.length;n++){var r=n/26|0,i=n%26;t[n]=(e.words[r]&1<<i)>>>i}return t}(e);if(0===t.length)return new o(1);for(var n=this,r=0;r<t.length&&0===t[r];r++,n=n.sqr());if(++r<t.length)for(var i=n.sqr();r<t.length;r++,i=i.sqr())0!==t[r]&&(n=n.mul(i));return n},o.prototype.iushln=function(e){r("number"==typeof e&&e>=0);var t,n=e%26,i=(e-n)/26,o=67108863>>>26-n<<26-n;if(0!==n){var s=0;for(t=0;t<this.length;t++){var a=this.words[t]&o,u=(0|this.words[t])-a<<n;this.words[t]=u|s,s=a>>>26-n}s&&(this.words[t]=s,this.length++)}if(0!==i){for(t=this.length-1;t>=0;t--)this.words[t+i]=this.words[t];for(t=0;t<i;t++)this.words[t]=0;this.length+=i}return this.strip()},o.prototype.ishln=function(e){return r(0===this.negative),this.iushln(e)},o.prototype.iushrn=function(e,t,n){var i;r("number"==typeof e&&e>=0),i=t?(t-t%26)/26:0;var o=e%26,s=Math.min((e-o)/26,this.length),a=67108863^67108863>>>o<<o,u=n;if(i-=s,i=Math.max(0,i),u){for(var c=0;c<s;c++)u.words[c]=this.words[c];u.length=s}if(0===s);else if(this.length>s)for(this.length-=s,c=0;c<this.length;c++)this.words[c]=this.words[c+s];else this.words[0]=0,this.length=1;var f=0;for(c=this.length-1;c>=0&&(0!==f||c>=i);c--){var l=0|this.words[c];this.words[c]=f<<26-o|l>>>o,f=l&a}return u&&0!==f&&(u.words[u.length++]=f),0===this.length&&(this.words[0]=0,this.length=1),this.strip()},o.prototype.ishrn=function(e,t,n){return r(0===this.negative),this.iushrn(e,t,n)},o.prototype.shln=function(e){return this.clone().ishln(e)},o.prototype.ushln=function(e){return this.clone().iushln(e)},o.prototype.shrn=function(e){return this.clone().ishrn(e)},o.prototype.ushrn=function(e){return this.clone().iushrn(e)},o.prototype.testn=function(e){r("number"==typeof e&&e>=0);var t=e%26,n=(e-t)/26,i=1<<t;return!(this.length<=n)&&!!(this.words[n]&i)},o.prototype.imaskn=function(e){r("number"==typeof e&&e>=0);var t=e%26,n=(e-t)/26;if(r(0===this.negative,"imaskn works only with positive numbers"),this.length<=n)return this;if(0!==t&&n++,this.length=Math.min(n,this.length),0!==t){var i=67108863^67108863>>>t<<t;this.words[this.length-1]&=i}return this.strip()},o.prototype.maskn=function(e){return this.clone().imaskn(e)},o.prototype.iaddn=function(e){return r("number"==typeof e),r(e<67108864),e<0?this.isubn(-e):0!==this.negative?1===this.length&&(0|this.words[0])<e?(this.words[0]=e-(0|this.words[0]),this.negative=0,this):(this.negative=0,this.isubn(e),this.negative=1,this):this._iaddn(e)},o.prototype._iaddn=function(e){this.words[0]+=e;for(var t=0;t<this.length&&this.words[t]>=67108864;t++)this.words[t]-=67108864,t===this.length-1?this.words[t+1]=1:this.words[t+1]++;return this.length=Math.max(this.length,t+1),this},o.prototype.isubn=function(e){if(r("number"==typeof e),r(e<67108864),e<0)return this.iaddn(-e);if(0!==this.negative)return this.negative=0,this.iaddn(e),this.negative=1,this;if(this.words[0]-=e,1===this.length&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var t=0;t<this.length&&this.words[t]<0;t++)this.words[t]+=67108864,this.words[t+1]-=1;return this.strip()},o.prototype.addn=function(e){return this.clone().iaddn(e)},o.prototype.subn=function(e){return this.clone().isubn(e)},o.prototype.iabs=function(){return this.negative=0,this},o.prototype.abs=function(){return this.clone().iabs()},o.prototype._ishlnsubmul=function(e,t,n){var i,o,s=e.length+n;this._expand(s);var a=0;for(i=0;i<e.length;i++){o=(0|this.words[i+n])+a;var u=(0|e.words[i])*t;a=((o-=67108863&u)>>26)-(u/67108864|0),this.words[i+n]=67108863&o}for(;i<this.length-n;i++)a=(o=(0|this.words[i+n])+a)>>26,this.words[i+n]=67108863&o;if(0===a)return this.strip();for(r(-1===a),a=0,i=0;i<this.length;i++)a=(o=-(0|this.words[i])+a)>>26,this.words[i]=67108863&o;return this.negative=1,this.strip()},o.prototype._wordDiv=function(e,t){var n=(this.length,e.length),r=this.clone(),i=e,s=0|i.words[i.length-1];0!==(n=26-this._countBits(s))&&(i=i.ushln(n),r.iushln(n),s=0|i.words[i.length-1]);var a,u=r.length-i.length;if("mod"!==t){(a=new o(null)).length=u+1,a.words=new Array(a.length);for(var c=0;c<a.length;c++)a.words[c]=0}var f=r.clone()._ishlnsubmul(i,1,u);0===f.negative&&(r=f,a&&(a.words[u]=1));for(var l=u-1;l>=0;l--){var d=67108864*(0|r.words[i.length+l])+(0|r.words[i.length+l-1]);for(d=Math.min(d/s|0,67108863),r._ishlnsubmul(i,d,l);0!==r.negative;)d--,r.negative=0,r._ishlnsubmul(i,1,l),r.isZero()||(r.negative^=1);a&&(a.words[l]=d)}return a&&a.strip(),r.strip(),"div"!==t&&0!==n&&r.iushrn(n),{div:a||null,mod:r}},o.prototype.divmod=function(e,t,n){return r(!e.isZero()),this.isZero()?{div:new o(0),mod:new o(0)}:0!==this.negative&&0===e.negative?(a=this.neg().divmod(e,t),"mod"!==t&&(i=a.div.neg()),"div"!==t&&(s=a.mod.neg(),n&&0!==s.negative&&s.iadd(e)),{div:i,mod:s}):0===this.negative&&0!==e.negative?(a=this.divmod(e.neg(),t),"mod"!==t&&(i=a.div.neg()),{div:i,mod:a.mod}):0!=(this.negative&e.negative)?(a=this.neg().divmod(e.neg(),t),"div"!==t&&(s=a.mod.neg(),n&&0!==s.negative&&s.isub(e)),{div:a.div,mod:s}):e.length>this.length||this.cmp(e)<0?{div:new o(0),mod:this}:1===e.length?"div"===t?{div:this.divn(e.words[0]),mod:null}:"mod"===t?{div:null,mod:new o(this.modn(e.words[0]))}:{div:this.divn(e.words[0]),mod:new o(this.modn(e.words[0]))}:this._wordDiv(e,t);var i,s,a},o.prototype.div=function(e){return this.divmod(e,"div",!1).div},o.prototype.mod=function(e){return this.divmod(e,"mod",!1).mod},o.prototype.umod=function(e){return this.divmod(e,"mod",!0).mod},o.prototype.divRound=function(e){var t=this.divmod(e);if(t.mod.isZero())return t.div;var n=0!==t.div.negative?t.mod.isub(e):t.mod,r=e.ushrn(1),i=e.andln(1),o=n.cmp(r);return o<0||1===i&&0===o?t.div:0!==t.div.negative?t.div.isubn(1):t.div.iaddn(1)},o.prototype.modn=function(e){r(e<=67108863);for(var t=(1<<26)%e,n=0,i=this.length-1;i>=0;i--)n=(t*n+(0|this.words[i]))%e;return n},o.prototype.idivn=function(e){r(e<=67108863);for(var t=0,n=this.length-1;n>=0;n--){var i=(0|this.words[n])+67108864*t;this.words[n]=i/e|0,t=i%e}return this.strip()},o.prototype.divn=function(e){return this.clone().idivn(e)},o.prototype.egcd=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i=new o(1),s=new o(0),a=new o(0),u=new o(1),c=0;t.isEven()&&n.isEven();)t.iushrn(1),n.iushrn(1),++c;for(var f=n.clone(),l=t.clone();!t.isZero();){for(var d=0,h=1;0==(t.words[0]&h)&&d<26;++d,h<<=1);if(d>0)for(t.iushrn(d);d-- >0;)(i.isOdd()||s.isOdd())&&(i.iadd(f),s.isub(l)),i.iushrn(1),s.iushrn(1);for(var p=0,v=1;0==(n.words[0]&v)&&p<26;++p,v<<=1);if(p>0)for(n.iushrn(p);p-- >0;)(a.isOdd()||u.isOdd())&&(a.iadd(f),u.isub(l)),a.iushrn(1),u.iushrn(1);t.cmp(n)>=0?(t.isub(n),i.isub(a),s.isub(u)):(n.isub(t),a.isub(i),u.isub(s))}return{a:a,b:u,gcd:n.iushln(c)}},o.prototype._invmp=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i,s=new o(1),a=new o(0),u=n.clone();t.cmpn(1)>0&&n.cmpn(1)>0;){for(var c=0,f=1;0==(t.words[0]&f)&&c<26;++c,f<<=1);if(c>0)for(t.iushrn(c);c-- >0;)s.isOdd()&&s.iadd(u),s.iushrn(1);for(var l=0,d=1;0==(n.words[0]&d)&&l<26;++l,d<<=1);if(l>0)for(n.iushrn(l);l-- >0;)a.isOdd()&&a.iadd(u),a.iushrn(1);t.cmp(n)>=0?(t.isub(n),s.isub(a)):(n.isub(t),a.isub(s))}return(i=0===t.cmpn(1)?s:a).cmpn(0)<0&&i.iadd(e),i},o.prototype.gcd=function(e){if(this.isZero())return e.abs();if(e.isZero())return this.abs();var t=this.clone(),n=e.clone();t.negative=0,n.negative=0;for(var r=0;t.isEven()&&n.isEven();r++)t.iushrn(1),n.iushrn(1);for(;;){for(;t.isEven();)t.iushrn(1);for(;n.isEven();)n.iushrn(1);var i=t.cmp(n);if(i<0){var o=t;t=n,n=o}else if(0===i||0===n.cmpn(1))break;t.isub(n)}return n.iushln(r)},o.prototype.invm=function(e){return this.egcd(e).a.umod(e)},o.prototype.isEven=function(){return 0==(1&this.words[0])},o.prototype.isOdd=function(){return 1==(1&this.words[0])},o.prototype.andln=function(e){return this.words[0]&e},o.prototype.bincn=function(e){r("number"==typeof e);var t=e%26,n=(e-t)/26,i=1<<t;if(this.length<=n)return this._expand(n+1),this.words[n]|=i,this;for(var o=i,s=n;0!==o&&s<this.length;s++){var a=0|this.words[s];o=(a+=o)>>>26,a&=67108863,this.words[s]=a}return 0!==o&&(this.words[s]=o,this.length++),this},o.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},o.prototype.cmpn=function(e){var t,n=e<0;if(0!==this.negative&&!n)return-1;if(0===this.negative&&n)return 1;if(this.strip(),this.length>1)t=1;else{n&&(e=-e),r(e<=67108863,"Number is too big");var i=0|this.words[0];t=i===e?0:i<e?-1:1}return 0!==this.negative?0|-t:t},o.prototype.cmp=function(e){if(0!==this.negative&&0===e.negative)return-1;if(0===this.negative&&0!==e.negative)return 1;var t=this.ucmp(e);return 0!==this.negative?0|-t:t},o.prototype.ucmp=function(e){if(this.length>e.length)return 1;if(this.length<e.length)return-1;for(var t=0,n=this.length-1;n>=0;n--){var r=0|this.words[n],i=0|e.words[n];if(r!==i){r<i?t=-1:r>i&&(t=1);break}}return t},o.prototype.gtn=function(e){return 1===this.cmpn(e)},o.prototype.gt=function(e){return 1===this.cmp(e)},o.prototype.gten=function(e){return this.cmpn(e)>=0},o.prototype.gte=function(e){return this.cmp(e)>=0},o.prototype.ltn=function(e){return-1===this.cmpn(e)},o.prototype.lt=function(e){return-1===this.cmp(e)},o.prototype.lten=function(e){return this.cmpn(e)<=0},o.prototype.lte=function(e){return this.cmp(e)<=0},o.prototype.eqn=function(e){return 0===this.cmpn(e)},o.prototype.eq=function(e){return 0===this.cmp(e)},o.red=function(e){return new S(e)},o.prototype.toRed=function(e){return r(!this.red,"Already a number in reduction context"),r(0===this.negative,"red works only with positives"),e.convertTo(this)._forceRed(e)},o.prototype.fromRed=function(){return r(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},o.prototype._forceRed=function(e){return this.red=e,this},o.prototype.forceRed=function(e){return r(!this.red,"Already a number in reduction context"),this._forceRed(e)},o.prototype.redAdd=function(e){return r(this.red,"redAdd works only with red numbers"),this.red.add(this,e)},o.prototype.redIAdd=function(e){return r(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,e)},o.prototype.redSub=function(e){return r(this.red,"redSub works only with red numbers"),this.red.sub(this,e)},o.prototype.redISub=function(e){return r(this.red,"redISub works only with red numbers"),this.red.isub(this,e)},o.prototype.redShl=function(e){return r(this.red,"redShl works only with red numbers"),this.red.shl(this,e)},o.prototype.redMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.mul(this,e)},o.prototype.redIMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.imul(this,e)},o.prototype.redSqr=function(){return r(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},o.prototype.redISqr=function(){return r(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},o.prototype.redSqrt=function(){return r(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},o.prototype.redInvm=function(){return r(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},o.prototype.redNeg=function(){return r(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},o.prototype.redPow=function(e){return r(this.red&&!e.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,e)};var g={k256:null,p224:null,p192:null,p25519:null};function m(e,t){this.name=e,this.p=new o(t,16),this.n=this.p.bitLength(),this.k=new o(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function b(){m.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function y(){m.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function w(){m.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function _(){m.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function S(e){if("string"==typeof e){var t=o._prime(e);this.m=t.p,this.prime=t}else r(e.gtn(1),"modulus must be greater than 1"),this.m=e,this.prime=null}function E(e){S.call(this,e),this.shift=this.m.bitLength(),this.shift%26!=0&&(this.shift+=26-this.shift%26),this.r=new o(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}m.prototype._tmp=function(){var e=new o(null);return e.words=new Array(Math.ceil(this.n/13)),e},m.prototype.ireduce=function(e){var t,n=e;do{this.split(n,this.tmp),t=(n=(n=this.imulK(n)).iadd(this.tmp)).bitLength()}while(t>this.n);var r=t<this.n?-1:n.ucmp(this.p);return 0===r?(n.words[0]=0,n.length=1):r>0?n.isub(this.p):void 0!==n.strip?n.strip():n._strip(),n},m.prototype.split=function(e,t){e.iushrn(this.n,0,t)},m.prototype.imulK=function(e){return e.imul(this.k)},i(b,m),b.prototype.split=function(e,t){for(var n=Math.min(e.length,9),r=0;r<n;r++)t.words[r]=e.words[r];if(t.length=n,e.length<=9)return e.words[0]=0,void(e.length=1);var i=e.words[9];for(t.words[t.length++]=4194303&i,r=10;r<e.length;r++){var o=0|e.words[r];e.words[r-10]=(4194303&o)<<4|i>>>22,i=o}i>>>=22,e.words[r-10]=i,0===i&&e.length>10?e.length-=10:e.length-=9},b.prototype.imulK=function(e){e.words[e.length]=0,e.words[e.length+1]=0,e.length+=2;for(var t=0,n=0;n<e.length;n++){var r=0|e.words[n];t+=977*r,e.words[n]=67108863&t,t=64*r+(t/67108864|0)}return 0===e.words[e.length-1]&&(e.length--,0===e.words[e.length-1]&&e.length--),e},i(y,m),i(w,m),i(_,m),_.prototype.imulK=function(e){for(var t=0,n=0;n<e.length;n++){var r=19*(0|e.words[n])+t,i=67108863&r;r>>>=26,e.words[n]=i,t=r}return 0!==t&&(e.words[e.length++]=t),e},o._prime=function(e){if(g[e])return g[e];var t;if("k256"===e)t=new b;else if("p224"===e)t=new y;else if("p192"===e)t=new w;else{if("p25519"!==e)throw new Error("Unknown prime "+e);t=new _}return g[e]=t,t},S.prototype._verify1=function(e){r(0===e.negative,"red works only with positives"),r(e.red,"red works only with red numbers")},S.prototype._verify2=function(e,t){r(0==(e.negative|t.negative),"red works only with positives"),r(e.red&&e.red===t.red,"red works only with red numbers")},S.prototype.imod=function(e){return this.prime?this.prime.ireduce(e)._forceRed(this):e.umod(this.m)._forceRed(this)},S.prototype.neg=function(e){return e.isZero()?e.clone():this.m.sub(e)._forceRed(this)},S.prototype.add=function(e,t){this._verify2(e,t);var n=e.add(t);return n.cmp(this.m)>=0&&n.isub(this.m),n._forceRed(this)},S.prototype.iadd=function(e,t){this._verify2(e,t);var n=e.iadd(t);return n.cmp(this.m)>=0&&n.isub(this.m),n},S.prototype.sub=function(e,t){this._verify2(e,t);var n=e.sub(t);return n.cmpn(0)<0&&n.iadd(this.m),n._forceRed(this)},S.prototype.isub=function(e,t){this._verify2(e,t);var n=e.isub(t);return n.cmpn(0)<0&&n.iadd(this.m),n},S.prototype.shl=function(e,t){return this._verify1(e),this.imod(e.ushln(t))},S.prototype.imul=function(e,t){return this._verify2(e,t),this.imod(e.imul(t))},S.prototype.mul=function(e,t){return this._verify2(e,t),this.imod(e.mul(t))},S.prototype.isqr=function(e){return this.imul(e,e.clone())},S.prototype.sqr=function(e){return this.mul(e,e)},S.prototype.sqrt=function(e){if(e.isZero())return e.clone();var t=this.m.andln(3);if(r(t%2==1),3===t){var n=this.m.add(new o(1)).iushrn(2);return this.pow(e,n)}for(var i=this.m.subn(1),s=0;!i.isZero()&&0===i.andln(1);)s++,i.iushrn(1);r(!i.isZero());var a=new o(1).toRed(this),u=a.redNeg(),c=this.m.subn(1).iushrn(1),f=this.m.bitLength();for(f=new o(2*f*f).toRed(this);0!==this.pow(f,c).cmp(u);)f.redIAdd(u);for(var l=this.pow(f,i),d=this.pow(e,i.addn(1).iushrn(1)),h=this.pow(e,i),p=s;0!==h.cmp(a);){for(var v=h,g=0;0!==v.cmp(a);g++)v=v.redSqr();r(g<p);var m=this.pow(l,new o(1).iushln(p-g-1));d=d.redMul(m),l=m.redSqr(),h=h.redMul(l),p=g}return d},S.prototype.invm=function(e){var t=e._invmp(this.m);return 0!==t.negative?(t.negative=0,this.imod(t).redNeg()):this.imod(t)},S.prototype.pow=function(e,t){if(t.isZero())return new o(1).toRed(this);if(0===t.cmpn(1))return e.clone();var n=new Array(16);n[0]=new o(1).toRed(this),n[1]=e;for(var r=2;r<n.length;r++)n[r]=this.mul(n[r-1],e);var i=n[0],s=0,a=0,u=t.bitLength()%26;for(0===u&&(u=26),r=t.length-1;r>=0;r--){for(var c=t.words[r],f=u-1;f>=0;f--){var l=c>>f&1;i!==n[0]&&(i=this.sqr(i)),0!==l||0!==s?(s<<=1,s|=l,(4===++a||0===r&&0===f)&&(i=this.mul(i,n[s]),a=0,s=0)):a=0}u=26}return i},S.prototype.convertTo=function(e){var t=e.umod(this.m);return t===e?t.clone():t},S.prototype.convertFrom=function(e){var t=e.clone();return t.red=null,t},o.mont=function(e){return new E(e)},i(E,S),E.prototype.convertTo=function(e){return this.imod(e.ushln(this.shift))},E.prototype.convertFrom=function(e){var t=this.imod(e.mul(this.rinv));return t.red=null,t},E.prototype.imul=function(e,t){if(e.isZero()||t.isZero())return e.words[0]=0,e.length=1,e;var n=e.imul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),o=i;return i.cmp(this.m)>=0?o=i.isub(this.m):i.cmpn(0)<0&&(o=i.iadd(this.m)),o._forceRed(this)},E.prototype.mul=function(e,t){if(e.isZero()||t.isZero())return new o(0)._forceRed(this);var n=e.mul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),s=i;return i.cmp(this.m)>=0?s=i.isub(this.m):i.cmpn(0)<0&&(s=i.iadd(this.m)),s._forceRed(this)},E.prototype.invm=function(e){return this.imod(e._invmp(this.m).mul(this.r2))._forceRed(this)}}(e,this)}).call(this,n(57)(e))},function(e,t,n){"use strict";n.d(t,"a",(function(){return r})),n.d(t,"b",(function(){return C})),n.d(t,"c",(function(){return P})),n.d(t,"d",(function(){return N})),n.d(t,"e",(function(){return V})),n.d(t,"f",(function(){return F})),n.d(t,"g",(function(){return te})),n.d(t,"h",(function(){return j})),n.d(t,"i",(function(){return re})); -/*! - * Copyright 2016 Amazon.com, - * Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Amazon Software License (the "License"). - * You may not use this file except in compliance with the - * License. A copy of the License is located at - * - * http://aws.amazon.com/asl/ - * - * or in the "license" file accompanying this file. This file is - * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, express or implied. See the License - * for the specific language governing permissions and - * limitations under the License. - */ -var r=function(){function e(e){var t=e||{},n=t.ValidationData,r=t.Username,i=t.Password,o=t.AuthParameters,s=t.ClientMetadata;this.validationData=n||{},this.authParameters=o||{},this.clientMetadata=s||{},this.username=r,this.password=i}var t=e.prototype;return t.getUsername=function(){return this.username},t.getPassword=function(){return this.password},t.getValidationData=function(){return this.validationData},t.getAuthParameters=function(){return this.authParameters},t.getClientMetadata=function(){return this.clientMetadata},e}(),i=n(6),o=n(32),s=n.n(o),a=(n(161),n(87)),u=n.n(a),c=n(75),f=n.n(c),l=n(250);var d,h=function(){function e(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:4*e.length}var t=e.prototype;return t.random=function(t){for(var n=[],r=0;r<t;r+=4)n.push(Object(l.a)());return new e(n,t)},t.toString=function(){return function(e){for(var t=e.words,n=e.sigBytes,r=[],i=0;i<n;i++){var o=t[i>>>2]>>>24-i%4*8&255;r.push((o>>>4).toString(16)),r.push((15&o).toString(16))}return r.join("")}(this)},e}(),p=v;function v(e,t){null!=e&&this.fromString(e,t)}function g(){return new v(null)}var m="undefined"!=typeof navigator;m&&"Microsoft Internet Explorer"==navigator.appName?(v.prototype.am=function(e,t,n,r,i,o){for(var s=32767&t,a=t>>15;--o>=0;){var u=32767&this[e],c=this[e++]>>15,f=a*u+c*s;i=((u=s*u+((32767&f)<<15)+n[r]+(1073741823&i))>>>30)+(f>>>15)+a*c+(i>>>30),n[r++]=1073741823&u}return i},d=30):m&&"Netscape"!=navigator.appName?(v.prototype.am=function(e,t,n,r,i,o){for(;--o>=0;){var s=t*this[e++]+n[r]+i;i=Math.floor(s/67108864),n[r++]=67108863&s}return i},d=26):(v.prototype.am=function(e,t,n,r,i,o){for(var s=16383&t,a=t>>14;--o>=0;){var u=16383&this[e],c=this[e++]>>14,f=a*u+c*s;i=((u=s*u+((16383&f)<<14)+n[r]+i)>>28)+(f>>14)+a*c,n[r++]=268435455&u}return i},d=28),v.prototype.DB=d,v.prototype.DM=(1<<d)-1,v.prototype.DV=1<<d;v.prototype.FV=Math.pow(2,52),v.prototype.F1=52-d,v.prototype.F2=2*d-52;var b,y,w=new Array;for(b="0".charCodeAt(0),y=0;y<=9;++y)w[b++]=y;for(b="a".charCodeAt(0),y=10;y<36;++y)w[b++]=y;for(b="A".charCodeAt(0),y=10;y<36;++y)w[b++]=y;function _(e){return"0123456789abcdefghijklmnopqrstuvwxyz".charAt(e)}function S(e,t){var n=w[e.charCodeAt(t)];return null==n?-1:n}function E(e){var t=g();return t.fromInt(e),t}function M(e){var t,n=1;return 0!=(t=e>>>16)&&(e=t,n+=16),0!=(t=e>>8)&&(e=t,n+=8),0!=(t=e>>4)&&(e=t,n+=4),0!=(t=e>>2)&&(e=t,n+=2),0!=(t=e>>1)&&(e=t,n+=1),n}function A(e){this.m=e,this.mp=e.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<<e.DB-15)-1,this.mt2=2*e.t}A.prototype.convert=function(e){var t=g();return e.abs().dlShiftTo(this.m.t,t),t.divRemTo(this.m,null,t),e.s<0&&t.compareTo(v.ZERO)>0&&this.m.subTo(t,t),t},A.prototype.revert=function(e){var t=g();return e.copyTo(t),this.reduce(t),t},A.prototype.reduce=function(e){for(;e.t<=this.mt2;)e[e.t++]=0;for(var t=0;t<this.m.t;++t){var n=32767&e[t],r=n*this.mpl+((n*this.mph+(e[t]>>15)*this.mpl&this.um)<<15)&e.DM;for(e[n=t+this.m.t]+=this.m.am(0,r,e,t,0,this.m.t);e[n]>=e.DV;)e[n]-=e.DV,e[++n]++}e.clamp(),e.drShiftTo(this.m.t,e),e.compareTo(this.m)>=0&&e.subTo(this.m,e)},A.prototype.mulTo=function(e,t,n){e.multiplyTo(t,n),this.reduce(n)},A.prototype.sqrTo=function(e,t){e.squareTo(t),this.reduce(t)},v.prototype.copyTo=function(e){for(var t=this.t-1;t>=0;--t)e[t]=this[t];e.t=this.t,e.s=this.s},v.prototype.fromInt=function(e){this.t=1,this.s=e<0?-1:0,e>0?this[0]=e:e<-1?this[0]=e+this.DV:this.t=0},v.prototype.fromString=function(e,t){var n;if(16==t)n=4;else if(8==t)n=3;else if(2==t)n=1;else if(32==t)n=5;else{if(4!=t)throw new Error("Only radix 2, 4, 8, 16, 32 are supported");n=2}this.t=0,this.s=0;for(var r=e.length,i=!1,o=0;--r>=0;){var s=S(e,r);s<0?"-"==e.charAt(r)&&(i=!0):(i=!1,0==o?this[this.t++]=s:o+n>this.DB?(this[this.t-1]|=(s&(1<<this.DB-o)-1)<<o,this[this.t++]=s>>this.DB-o):this[this.t-1]|=s<<o,(o+=n)>=this.DB&&(o-=this.DB))}this.clamp(),i&&v.ZERO.subTo(this,this)},v.prototype.clamp=function(){for(var e=this.s&this.DM;this.t>0&&this[this.t-1]==e;)--this.t},v.prototype.dlShiftTo=function(e,t){var n;for(n=this.t-1;n>=0;--n)t[n+e]=this[n];for(n=e-1;n>=0;--n)t[n]=0;t.t=this.t+e,t.s=this.s},v.prototype.drShiftTo=function(e,t){for(var n=e;n<this.t;++n)t[n-e]=this[n];t.t=Math.max(this.t-e,0),t.s=this.s},v.prototype.lShiftTo=function(e,t){var n,r=e%this.DB,i=this.DB-r,o=(1<<i)-1,s=Math.floor(e/this.DB),a=this.s<<r&this.DM;for(n=this.t-1;n>=0;--n)t[n+s+1]=this[n]>>i|a,a=(this[n]&o)<<r;for(n=s-1;n>=0;--n)t[n]=0;t[s]=a,t.t=this.t+s+1,t.s=this.s,t.clamp()},v.prototype.rShiftTo=function(e,t){t.s=this.s;var n=Math.floor(e/this.DB);if(n>=this.t)t.t=0;else{var r=e%this.DB,i=this.DB-r,o=(1<<r)-1;t[0]=this[n]>>r;for(var s=n+1;s<this.t;++s)t[s-n-1]|=(this[s]&o)<<i,t[s-n]=this[s]>>r;r>0&&(t[this.t-n-1]|=(this.s&o)<<i),t.t=this.t-n,t.clamp()}},v.prototype.subTo=function(e,t){for(var n=0,r=0,i=Math.min(e.t,this.t);n<i;)r+=this[n]-e[n],t[n++]=r&this.DM,r>>=this.DB;if(e.t<this.t){for(r-=e.s;n<this.t;)r+=this[n],t[n++]=r&this.DM,r>>=this.DB;r+=this.s}else{for(r+=this.s;n<e.t;)r-=e[n],t[n++]=r&this.DM,r>>=this.DB;r-=e.s}t.s=r<0?-1:0,r<-1?t[n++]=this.DV+r:r>0&&(t[n++]=r),t.t=n,t.clamp()},v.prototype.multiplyTo=function(e,t){var n=this.abs(),r=e.abs(),i=n.t;for(t.t=i+r.t;--i>=0;)t[i]=0;for(i=0;i<r.t;++i)t[i+n.t]=n.am(0,r[i],t,i,0,n.t);t.s=0,t.clamp(),this.s!=e.s&&v.ZERO.subTo(t,t)},v.prototype.squareTo=function(e){for(var t=this.abs(),n=e.t=2*t.t;--n>=0;)e[n]=0;for(n=0;n<t.t-1;++n){var r=t.am(n,t[n],e,2*n,0,1);(e[n+t.t]+=t.am(n+1,2*t[n],e,2*n+1,r,t.t-n-1))>=t.DV&&(e[n+t.t]-=t.DV,e[n+t.t+1]=1)}e.t>0&&(e[e.t-1]+=t.am(n,t[n],e,2*n,0,1)),e.s=0,e.clamp()},v.prototype.divRemTo=function(e,t,n){var r=e.abs();if(!(r.t<=0)){var i=this.abs();if(i.t<r.t)return null!=t&&t.fromInt(0),void(null!=n&&this.copyTo(n));null==n&&(n=g());var o=g(),s=this.s,a=e.s,u=this.DB-M(r[r.t-1]);u>0?(r.lShiftTo(u,o),i.lShiftTo(u,n)):(r.copyTo(o),i.copyTo(n));var c=o.t,f=o[c-1];if(0!=f){var l=f*(1<<this.F1)+(c>1?o[c-2]>>this.F2:0),d=this.FV/l,h=(1<<this.F1)/l,p=1<<this.F2,m=n.t,b=m-c,y=null==t?g():t;for(o.dlShiftTo(b,y),n.compareTo(y)>=0&&(n[n.t++]=1,n.subTo(y,n)),v.ONE.dlShiftTo(c,y),y.subTo(o,o);o.t<c;)o[o.t++]=0;for(;--b>=0;){var w=n[--m]==f?this.DM:Math.floor(n[m]*d+(n[m-1]+p)*h);if((n[m]+=o.am(0,w,n,b,0,c))<w)for(o.dlShiftTo(b,y),n.subTo(y,n);n[m]<--w;)n.subTo(y,n)}null!=t&&(n.drShiftTo(c,t),s!=a&&v.ZERO.subTo(t,t)),n.t=c,n.clamp(),u>0&&n.rShiftTo(u,n),s<0&&v.ZERO.subTo(n,n)}}},v.prototype.invDigit=function(){if(this.t<1)return 0;var e=this[0];if(0==(1&e))return 0;var t=3&e;return(t=(t=(t=(t=t*(2-(15&e)*t)&15)*(2-(255&e)*t)&255)*(2-((65535&e)*t&65535))&65535)*(2-e*t%this.DV)%this.DV)>0?this.DV-t:-t},v.prototype.addTo=function(e,t){for(var n=0,r=0,i=Math.min(e.t,this.t);n<i;)r+=this[n]+e[n],t[n++]=r&this.DM,r>>=this.DB;if(e.t<this.t){for(r+=e.s;n<this.t;)r+=this[n],t[n++]=r&this.DM,r>>=this.DB;r+=this.s}else{for(r+=this.s;n<e.t;)r+=e[n],t[n++]=r&this.DM,r>>=this.DB;r+=e.s}t.s=r<0?-1:0,r>0?t[n++]=r:r<-1&&(t[n++]=this.DV+r),t.t=n,t.clamp()},v.prototype.toString=function(e){if(this.s<0)return"-"+this.negate().toString(e);var t;if(16==e)t=4;else if(8==e)t=3;else if(2==e)t=1;else if(32==e)t=5;else{if(4!=e)throw new Error("Only radix 2, 4, 8, 16, 32 are supported");t=2}var n,r=(1<<t)-1,i=!1,o="",s=this.t,a=this.DB-s*this.DB%t;if(s-- >0)for(a<this.DB&&(n=this[s]>>a)>0&&(i=!0,o=_(n));s>=0;)a<t?(n=(this[s]&(1<<a)-1)<<t-a,n|=this[--s]>>(a+=this.DB-t)):(n=this[s]>>(a-=t)&r,a<=0&&(a+=this.DB,--s)),n>0&&(i=!0),i&&(o+=_(n));return i?o:"0"},v.prototype.negate=function(){var e=g();return v.ZERO.subTo(this,e),e},v.prototype.abs=function(){return this.s<0?this.negate():this},v.prototype.compareTo=function(e){var t=this.s-e.s;if(0!=t)return t;var n=this.t;if(0!=(t=n-e.t))return this.s<0?-t:t;for(;--n>=0;)if(0!=(t=this[n]-e[n]))return t;return 0},v.prototype.bitLength=function(){return this.t<=0?0:this.DB*(this.t-1)+M(this[this.t-1]^this.s&this.DM)},v.prototype.mod=function(e){var t=g();return this.abs().divRemTo(e,null,t),this.s<0&&t.compareTo(v.ZERO)>0&&e.subTo(t,t),t},v.prototype.equals=function(e){return 0==this.compareTo(e)},v.prototype.add=function(e){var t=g();return this.addTo(e,t),t},v.prototype.subtract=function(e){var t=g();return this.subTo(e,t),t},v.prototype.multiply=function(e){var t=g();return this.multiplyTo(e,t),t},v.prototype.divide=function(e){var t=g();return this.divRemTo(e,t,null),t},v.prototype.modPow=function(e,t,n){var r,i=e.bitLength(),o=E(1),s=new A(t);if(i<=0)return o;r=i<18?1:i<48?3:i<144?4:i<768?5:6;var a=new Array,u=3,c=r-1,f=(1<<r)-1;if(a[1]=s.convert(this),r>1){var l=g();for(s.sqrTo(a[1],l);u<=f;)a[u]=g(),s.mulTo(l,a[u-2],a[u]),u+=2}var d,h,p=e.t-1,v=!0,m=g();for(i=M(e[p])-1;p>=0;){for(i>=c?d=e[p]>>i-c&f:(d=(e[p]&(1<<i+1)-1)<<c-i,p>0&&(d|=e[p-1]>>this.DB+i-c)),u=r;0==(1&d);)d>>=1,--u;if((i-=u)<0&&(i+=this.DB,--p),v)a[d].copyTo(o),v=!1;else{for(;u>1;)s.sqrTo(o,m),s.sqrTo(m,o),u-=2;u>0?s.sqrTo(o,m):(h=o,o=m,m=h),s.mulTo(m,a[d],o)}for(;p>=0&&0==(e[p]&1<<i);)s.sqrTo(o,m),h=o,o=m,m=h,--i<0&&(i=this.DB-1,--p)}var b=s.revert(o);return n(null,b),b},v.ZERO=E(0),v.ONE=E(1); -/*! - * Copyright 2016 Amazon.com, - * Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Amazon Software License (the "License"). - * You may not use this file except in compliance with the - * License. A copy of the License is located at - * - * http://aws.amazon.com/asl/ - * - * or in the "license" file accompanying this file. This file is - * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, express or implied. See the License - * for the specific language governing permissions and - * limitations under the License. - */ -var I=function(e){return i.Buffer.from((new h).random(e).toString(),"hex")},k=function(){function e(e){this.N=new p("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",16),this.g=new p("2",16),this.k=new p(this.hexHash("00"+this.N.toString(16)+"0"+this.g.toString(16)),16),this.smallAValue=this.generateRandomSmallA(),this.getLargeAValue((function(){})),this.infoBits=i.Buffer.from("Caldera Derived Key","utf8"),this.poolName=e}var t=e.prototype;return t.getSmallAValue=function(){return this.smallAValue},t.getLargeAValue=function(e){var t=this;this.largeAValue?e(null,this.largeAValue):this.calculateA(this.smallAValue,(function(n,r){n&&e(n,null),t.largeAValue=r,e(null,t.largeAValue)}))},t.generateRandomSmallA=function(){var e=I(128).toString("hex");return new p(e,16).mod(this.N)},t.generateRandomString=function(){return I(40).toString("base64")},t.getRandomPassword=function(){return this.randomPassword},t.getSaltDevices=function(){return this.SaltToHashDevices},t.getVerifierDevices=function(){return this.verifierDevices},t.generateHashDevice=function(e,t,n){var r=this;this.randomPassword=this.generateRandomString();var i=""+e+t+":"+this.randomPassword,o=this.hash(i),s=I(16).toString("hex");this.SaltToHashDevices=this.padHex(new p(s,16)),this.g.modPow(new p(this.hexHash(this.SaltToHashDevices+o),16),this.N,(function(e,t){e&&n(e,null),r.verifierDevices=r.padHex(t),n(null,null)}))},t.calculateA=function(e,t){var n=this;this.g.modPow(e,this.N,(function(e,r){e&&t(e,null),r.mod(n.N).equals(p.ZERO)&&t(new Error("Illegal paramater. A mod N cannot be 0."),null),t(null,r)}))},t.calculateU=function(e,t){return this.UHexHash=this.hexHash(this.padHex(e)+this.padHex(t)),new p(this.UHexHash,16)},t.hash=function(e){var t=e instanceof i.Buffer?s.a.lib.WordArray.create(e):e,n=u()(t).toString();return new Array(64-n.length).join("0")+n},t.hexHash=function(e){return this.hash(i.Buffer.from(e,"hex"))},t.computehkdf=function(e,t){var n=s.a.lib.WordArray.create(i.Buffer.concat([this.infoBits,i.Buffer.from(String.fromCharCode(1),"utf8")])),r=e instanceof i.Buffer?s.a.lib.WordArray.create(e):e,o=t instanceof i.Buffer?s.a.lib.WordArray.create(t):t,a=f()(r,o),u=f()(n,a);return i.Buffer.from(u.toString(),"hex").slice(0,16)},t.getPasswordAuthenticationKey=function(e,t,n,r,o){var s=this;if(n.mod(this.N).equals(p.ZERO))throw new Error("B cannot be zero.");if(this.UValue=this.calculateU(this.largeAValue,n),this.UValue.equals(p.ZERO))throw new Error("U cannot be zero.");var a=""+this.poolName+e+":"+t,u=this.hash(a),c=new p(this.hexHash(this.padHex(r)+u),16);this.calculateS(c,n,(function(e,t){e&&o(e,null);var n=s.computehkdf(i.Buffer.from(s.padHex(t),"hex"),i.Buffer.from(s.padHex(s.UValue.toString(16)),"hex"));o(null,n)}))},t.calculateS=function(e,t,n){var r=this;this.g.modPow(e,this.N,(function(i,o){i&&n(i,null),t.subtract(r.k.multiply(o)).modPow(r.smallAValue.add(r.UValue.multiply(e)),r.N,(function(e,t){e&&n(e,null),n(null,t.mod(r.N))}))}))},t.getNewPasswordRequiredChallengeUserAttributePrefix=function(){return"userAttributes."},t.padHex=function(e){var t=e.toString(16);return t.length%2==1?t="0"+t:-1!=="89ABCDEFabcdef".indexOf(t[0])&&(t="00"+t),t},e}(),O=function(){function e(e){this.jwtToken=e||"",this.payload=this.decodePayload()}var t=e.prototype;return t.getJwtToken=function(){return this.jwtToken},t.getExpiration=function(){return this.payload.exp},t.getIssuedAt=function(){return this.payload.iat},t.decodePayload=function(){var e=this.jwtToken.split(".")[1];try{return JSON.parse(i.Buffer.from(e,"base64").toString("utf8"))}catch(e){return{}}},e}();function x(e,t){return(x=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}var C=function(e){var t,n;function r(t){var n=(void 0===t?{}:t).AccessToken;return e.call(this,n||"")||this}return n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,x(t,n),r}(O);function T(e,t){return(T=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)} -/*! - * Copyright 2016 Amazon.com, - * Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Amazon Software License (the "License"). - * You may not use this file except in compliance with the - * License. A copy of the License is located at - * - * http://aws.amazon.com/asl/ - * - * or in the "license" file accompanying this file. This file is - * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, express or implied. See the License - * for the specific language governing permissions and - * limitations under the License. - */var P=function(e){var t,n;function r(t){var n=(void 0===t?{}:t).IdToken;return e.call(this,n||"")||this}return n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,T(t,n),r}(O),N=function(){function e(e){var t=(void 0===e?{}:e).RefreshToken;this.token=t||""}return e.prototype.getToken=function(){return this.token},e}(),R=n(90),L=n.n(R),j=function(){function e(e){var t=void 0===e?{}:e,n=t.IdToken,r=t.RefreshToken,i=t.AccessToken,o=t.ClockDrift;if(null==i||null==n)throw new Error("Id token and Access Token must be present.");this.idToken=n,this.refreshToken=r,this.accessToken=i,this.clockDrift=void 0===o?this.calculateClockDrift():o}var t=e.prototype;return t.getIdToken=function(){return this.idToken},t.getRefreshToken=function(){return this.refreshToken},t.getAccessToken=function(){return this.accessToken},t.getClockDrift=function(){return this.clockDrift},t.calculateClockDrift=function(){return Math.floor(new Date/1e3)-Math.min(this.accessToken.getIssuedAt(),this.idToken.getIssuedAt())},t.isValid=function(){var e=Math.floor(new Date/1e3)-this.clockDrift;return e<this.accessToken.getExpiration()&&e<this.idToken.getExpiration()},e}(),D=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],U=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],B=function(){function e(){}return e.prototype.getNowString=function(){var e=new Date,t=U[e.getUTCDay()],n=D[e.getUTCMonth()],r=e.getUTCDate(),i=e.getUTCHours();i<10&&(i="0"+i);var o=e.getUTCMinutes();o<10&&(o="0"+o);var s=e.getUTCSeconds();return s<10&&(s="0"+s),t+" "+n+" "+r+" "+i+":"+o+":"+s+" UTC "+e.getUTCFullYear()},e}(),F=function(){function e(e){var t=void 0===e?{}:e,n=t.Name,r=t.Value;this.Name=n||"",this.Value=r||""}var t=e.prototype;return t.getValue=function(){return this.Value},t.setValue=function(e){return this.Value=e,this},t.getName=function(){return this.Name},t.setName=function(e){return this.Name=e,this},t.toString=function(){return JSON.stringify(this)},t.toJSON=function(){return{Name:this.Name,Value:this.Value}},e}(),z={},q=function(){function e(){}return e.setItem=function(e,t){return z[e]=t,z[e]},e.getItem=function(e){return Object.prototype.hasOwnProperty.call(z,e)?z[e]:void 0},e.removeItem=function(e){return delete z[e]},e.clear=function(){return z={}},e}(),K=function(){function e(){try{this.storageWindow=window.localStorage,this.storageWindow.setItem("aws.cognito.test-ls",1),this.storageWindow.removeItem("aws.cognito.test-ls")}catch(e){this.storageWindow=q}}return e.prototype.getStorage=function(){return this.storageWindow},e}(),H="undefined"!=typeof navigator?navigator.userAgent:"nodejs",V=function(){function e(e){if(null==e||null==e.Username||null==e.Pool)throw new Error("Username and Pool information are required.");this.username=e.Username||"",this.pool=e.Pool,this.Session=null,this.client=e.Pool.client,this.signInUserSession=null,this.authenticationFlowType="USER_SRP_AUTH",this.storage=e.Storage||(new K).getStorage(),this.keyPrefix="CognitoIdentityServiceProvider."+this.pool.getClientId(),this.userDataKey=this.keyPrefix+"."+this.username+".userData"}var t=e.prototype;return t.setSignInUserSession=function(e){this.clearCachedUserData(),this.signInUserSession=e,this.cacheTokens()},t.getSignInUserSession=function(){return this.signInUserSession},t.getUsername=function(){return this.username},t.getAuthenticationFlowType=function(){return this.authenticationFlowType},t.setAuthenticationFlowType=function(e){this.authenticationFlowType=e},t.initiateAuth=function(e,t){var n=this,r=e.getAuthParameters();r.USERNAME=this.username;var i=0!==Object.keys(e.getValidationData()).length?e.getValidationData():e.getClientMetadata(),o={AuthFlow:"CUSTOM_AUTH",ClientId:this.pool.getClientId(),AuthParameters:r,ClientMetadata:i};this.getUserContextData()&&(o.UserContextData=this.getUserContextData()),this.client.request("InitiateAuth",o,(function(e,r){if(e)return t.onFailure(e);var i=r.ChallengeName,o=r.ChallengeParameters;return"CUSTOM_CHALLENGE"===i?(n.Session=r.Session,t.customChallenge(o)):(n.signInUserSession=n.getCognitoUserSession(r.AuthenticationResult),n.cacheTokens(),t.onSuccess(n.signInUserSession))}))},t.authenticateUser=function(e,t){return"USER_PASSWORD_AUTH"===this.authenticationFlowType?this.authenticateUserPlainUsernamePassword(e,t):"USER_SRP_AUTH"===this.authenticationFlowType||"CUSTOM_AUTH"===this.authenticationFlowType?this.authenticateUserDefaultAuth(e,t):t.onFailure(new Error("Authentication flow type is invalid."))},t.authenticateUserDefaultAuth=function(e,t){var n,r,o=this,a=new k(this.pool.getUserPoolId().split("_")[1]),u=new B,c={};null!=this.deviceKey&&(c.DEVICE_KEY=this.deviceKey),c.USERNAME=this.username,a.getLargeAValue((function(l,d){l&&t.onFailure(l),c.SRP_A=d.toString(16),"CUSTOM_AUTH"===o.authenticationFlowType&&(c.CHALLENGE_NAME="SRP_A");var h=0!==Object.keys(e.getValidationData()).length?e.getValidationData():e.getClientMetadata(),v={AuthFlow:o.authenticationFlowType,ClientId:o.pool.getClientId(),AuthParameters:c,ClientMetadata:h};o.getUserContextData(o.username)&&(v.UserContextData=o.getUserContextData(o.username)),o.client.request("InitiateAuth",v,(function(c,l){if(c)return t.onFailure(c);var d=l.ChallengeParameters;o.username=d.USER_ID_FOR_SRP,n=new p(d.SRP_B,16),r=new p(d.SALT,16),o.getCachedDeviceKeyAndPassword(),a.getPasswordAuthenticationKey(o.username,e.getPassword(),n,r,(function(e,n){e&&t.onFailure(e);var r=u.getNowString(),c=s.a.lib.WordArray.create(i.Buffer.concat([i.Buffer.from(o.pool.getUserPoolId().split("_")[1],"utf8"),i.Buffer.from(o.username,"utf8"),i.Buffer.from(d.SECRET_BLOCK,"base64"),i.Buffer.from(r,"utf8")])),p=s.a.lib.WordArray.create(n),v=L.a.stringify(f()(c,p)),g={};g.USERNAME=o.username,g.PASSWORD_CLAIM_SECRET_BLOCK=d.SECRET_BLOCK,g.TIMESTAMP=r,g.PASSWORD_CLAIM_SIGNATURE=v,null!=o.deviceKey&&(g.DEVICE_KEY=o.deviceKey);var m={ChallengeName:"PASSWORD_VERIFIER",ClientId:o.pool.getClientId(),ChallengeResponses:g,Session:l.Session,ClientMetadata:h};o.getUserContextData()&&(m.UserContextData=o.getUserContextData()),function e(t,n){return o.client.request("RespondToAuthChallenge",t,(function(r,i){return r&&"ResourceNotFoundException"===r.code&&-1!==r.message.toLowerCase().indexOf("device")?(g.DEVICE_KEY=null,o.deviceKey=null,o.randomPassword=null,o.deviceGroupKey=null,o.clearCachedDeviceKeyAndPassword(),e(t,n)):n(r,i)}))}(m,(function(e,n){return e?t.onFailure(e):o.authenticateUserInternal(n,a,t)}))}))}))}))},t.authenticateUserPlainUsernamePassword=function(e,t){var n=this,r={};if(r.USERNAME=this.username,r.PASSWORD=e.getPassword(),r.PASSWORD){var i=new k(this.pool.getUserPoolId().split("_")[1]);this.getCachedDeviceKeyAndPassword(),null!=this.deviceKey&&(r.DEVICE_KEY=this.deviceKey);var o=0!==Object.keys(e.getValidationData()).length?e.getValidationData():e.getClientMetadata(),s={AuthFlow:"USER_PASSWORD_AUTH",ClientId:this.pool.getClientId(),AuthParameters:r,ClientMetadata:o};this.getUserContextData(this.username)&&(s.UserContextData=this.getUserContextData(this.username)),this.client.request("InitiateAuth",s,(function(e,r){return e?t.onFailure(e):n.authenticateUserInternal(r,i,t)}))}else t.onFailure(new Error("PASSWORD parameter is required"))},t.authenticateUserInternal=function(e,t,n){var r=this,o=e.ChallengeName,s=e.ChallengeParameters;if("SMS_MFA"===o)return this.Session=e.Session,n.mfaRequired(o,s);if("SELECT_MFA_TYPE"===o)return this.Session=e.Session,n.selectMFAType(o,s);if("MFA_SETUP"===o)return this.Session=e.Session,n.mfaSetup(o,s);if("SOFTWARE_TOKEN_MFA"===o)return this.Session=e.Session,n.totpRequired(o,s);if("CUSTOM_CHALLENGE"===o)return this.Session=e.Session,n.customChallenge(s);if("NEW_PASSWORD_REQUIRED"===o){this.Session=e.Session;var a=null,u=null,c=[],f=t.getNewPasswordRequiredChallengeUserAttributePrefix();if(s&&(a=JSON.parse(e.ChallengeParameters.userAttributes),u=JSON.parse(e.ChallengeParameters.requiredAttributes)),u)for(var l=0;l<u.length;l++)c[l]=u[l].substr(f.length);return n.newPasswordRequired(a,c)}if("DEVICE_SRP_AUTH"!==o){this.signInUserSession=this.getCognitoUserSession(e.AuthenticationResult),this.challengeName=o,this.cacheTokens();var d=e.AuthenticationResult.NewDeviceMetadata;if(null==d)return n.onSuccess(this.signInUserSession);t.generateHashDevice(e.AuthenticationResult.NewDeviceMetadata.DeviceGroupKey,e.AuthenticationResult.NewDeviceMetadata.DeviceKey,(function(o){if(o)return n.onFailure(o);var s={Salt:i.Buffer.from(t.getSaltDevices(),"hex").toString("base64"),PasswordVerifier:i.Buffer.from(t.getVerifierDevices(),"hex").toString("base64")};r.verifierDevices=s.PasswordVerifier,r.deviceGroupKey=d.DeviceGroupKey,r.randomPassword=t.getRandomPassword(),r.client.request("ConfirmDevice",{DeviceKey:d.DeviceKey,AccessToken:r.signInUserSession.getAccessToken().getJwtToken(),DeviceSecretVerifierConfig:s,DeviceName:H},(function(t,i){return t?n.onFailure(t):(r.deviceKey=e.AuthenticationResult.NewDeviceMetadata.DeviceKey,r.cacheDeviceKeyAndPassword(),!0===i.UserConfirmationNecessary?n.onSuccess(r.signInUserSession,i.UserConfirmationNecessary):n.onSuccess(r.signInUserSession))}))}))}else this.getDeviceResponse(n)},t.completeNewPasswordChallenge=function(e,t,n,r){var i=this;if(!e)return n.onFailure(new Error("New password is required."));var o=new k(this.pool.getUserPoolId().split("_")[1]),s=o.getNewPasswordRequiredChallengeUserAttributePrefix(),a={};t&&Object.keys(t).forEach((function(e){a[s+e]=t[e]})),a.NEW_PASSWORD=e,a.USERNAME=this.username;var u={ChallengeName:"NEW_PASSWORD_REQUIRED",ClientId:this.pool.getClientId(),ChallengeResponses:a,Session:this.Session,ClientMetadata:r};this.getUserContextData()&&(u.UserContextData=this.getUserContextData()),this.client.request("RespondToAuthChallenge",u,(function(e,t){return e?n.onFailure(e):i.authenticateUserInternal(t,o,n)}))},t.getDeviceResponse=function(e,t){var n=this,r=new k(this.deviceGroupKey),o=new B,a={};a.USERNAME=this.username,a.DEVICE_KEY=this.deviceKey,r.getLargeAValue((function(u,c){u&&e.onFailure(u),a.SRP_A=c.toString(16);var l={ChallengeName:"DEVICE_SRP_AUTH",ClientId:n.pool.getClientId(),ChallengeResponses:a,ClientMetadata:t};n.getUserContextData()&&(l.UserContextData=n.getUserContextData()),n.client.request("RespondToAuthChallenge",l,(function(t,a){if(t)return e.onFailure(t);var u=a.ChallengeParameters,c=new p(u.SRP_B,16),l=new p(u.SALT,16);r.getPasswordAuthenticationKey(n.deviceKey,n.randomPassword,c,l,(function(t,r){if(t)return e.onFailure(t);var c=o.getNowString(),l=s.a.lib.WordArray.create(i.Buffer.concat([i.Buffer.from(n.deviceGroupKey,"utf8"),i.Buffer.from(n.deviceKey,"utf8"),i.Buffer.from(u.SECRET_BLOCK,"base64"),i.Buffer.from(c,"utf8")])),d=s.a.lib.WordArray.create(r),h=L.a.stringify(f()(l,d)),p={};p.USERNAME=n.username,p.PASSWORD_CLAIM_SECRET_BLOCK=u.SECRET_BLOCK,p.TIMESTAMP=c,p.PASSWORD_CLAIM_SIGNATURE=h,p.DEVICE_KEY=n.deviceKey;var v={ChallengeName:"DEVICE_PASSWORD_VERIFIER",ClientId:n.pool.getClientId(),ChallengeResponses:p,Session:a.Session};n.getUserContextData()&&(v.UserContextData=n.getUserContextData()),n.client.request("RespondToAuthChallenge",v,(function(t,r){return t?e.onFailure(t):(n.signInUserSession=n.getCognitoUserSession(r.AuthenticationResult),n.cacheTokens(),e.onSuccess(n.signInUserSession))}))}))}))}))},t.confirmRegistration=function(e,t,n,r){var i={ClientId:this.pool.getClientId(),ConfirmationCode:e,Username:this.username,ForceAliasCreation:t,ClientMetadata:r};this.getUserContextData()&&(i.UserContextData=this.getUserContextData()),this.client.request("ConfirmSignUp",i,(function(e){return e?n(e,null):n(null,"SUCCESS")}))},t.sendCustomChallengeAnswer=function(e,t,n){var r=this,i={};i.USERNAME=this.username,i.ANSWER=e;var o=new k(this.pool.getUserPoolId().split("_")[1]);this.getCachedDeviceKeyAndPassword(),null!=this.deviceKey&&(i.DEVICE_KEY=this.deviceKey);var s={ChallengeName:"CUSTOM_CHALLENGE",ChallengeResponses:i,ClientId:this.pool.getClientId(),Session:this.Session,ClientMetadata:n};this.getUserContextData()&&(s.UserContextData=this.getUserContextData()),this.client.request("RespondToAuthChallenge",s,(function(e,n){return e?t.onFailure(e):r.authenticateUserInternal(n,o,t)}))},t.sendMFACode=function(e,t,n,r){var o=this,s={};s.USERNAME=this.username,s.SMS_MFA_CODE=e;var a=n||"SMS_MFA";"SOFTWARE_TOKEN_MFA"===a&&(s.SOFTWARE_TOKEN_MFA_CODE=e),null!=this.deviceKey&&(s.DEVICE_KEY=this.deviceKey);var u={ChallengeName:a,ChallengeResponses:s,ClientId:this.pool.getClientId(),Session:this.Session,ClientMetadata:r};this.getUserContextData()&&(u.UserContextData=this.getUserContextData()),this.client.request("RespondToAuthChallenge",u,(function(e,n){if(e)return t.onFailure(e);if("DEVICE_SRP_AUTH"!==n.ChallengeName){if(o.signInUserSession=o.getCognitoUserSession(n.AuthenticationResult),o.cacheTokens(),null==n.AuthenticationResult.NewDeviceMetadata)return t.onSuccess(o.signInUserSession);var r=new k(o.pool.getUserPoolId().split("_")[1]);r.generateHashDevice(n.AuthenticationResult.NewDeviceMetadata.DeviceGroupKey,n.AuthenticationResult.NewDeviceMetadata.DeviceKey,(function(e){if(e)return t.onFailure(e);var s={Salt:i.Buffer.from(r.getSaltDevices(),"hex").toString("base64"),PasswordVerifier:i.Buffer.from(r.getVerifierDevices(),"hex").toString("base64")};o.verifierDevices=s.PasswordVerifier,o.deviceGroupKey=n.AuthenticationResult.NewDeviceMetadata.DeviceGroupKey,o.randomPassword=r.getRandomPassword(),o.client.request("ConfirmDevice",{DeviceKey:n.AuthenticationResult.NewDeviceMetadata.DeviceKey,AccessToken:o.signInUserSession.getAccessToken().getJwtToken(),DeviceSecretVerifierConfig:s,DeviceName:H},(function(e,r){return e?t.onFailure(e):(o.deviceKey=n.AuthenticationResult.NewDeviceMetadata.DeviceKey,o.cacheDeviceKeyAndPassword(),!0===r.UserConfirmationNecessary?t.onSuccess(o.signInUserSession,r.UserConfirmationNecessary):t.onSuccess(o.signInUserSession))}))}))}else o.getDeviceResponse(t)}))},t.changePassword=function(e,t,n,r){if(null==this.signInUserSession||!this.signInUserSession.isValid())return n(new Error("User is not authenticated"),null);this.client.request("ChangePassword",{PreviousPassword:e,ProposedPassword:t,AccessToken:this.signInUserSession.getAccessToken().getJwtToken(),ClientMetadata:r},(function(e){return e?n(e,null):n(null,"SUCCESS")}))},t.enableMFA=function(e){if(null==this.signInUserSession||!this.signInUserSession.isValid())return e(new Error("User is not authenticated"),null);var t=[];t.push({DeliveryMedium:"SMS",AttributeName:"phone_number"}),this.client.request("SetUserSettings",{MFAOptions:t,AccessToken:this.signInUserSession.getAccessToken().getJwtToken()},(function(t){return t?e(t,null):e(null,"SUCCESS")}))},t.setUserMfaPreference=function(e,t,n){if(null==this.signInUserSession||!this.signInUserSession.isValid())return n(new Error("User is not authenticated"),null);this.client.request("SetUserMFAPreference",{SMSMfaSettings:e,SoftwareTokenMfaSettings:t,AccessToken:this.signInUserSession.getAccessToken().getJwtToken()},(function(e){return e?n(e,null):n(null,"SUCCESS")}))},t.disableMFA=function(e){if(null==this.signInUserSession||!this.signInUserSession.isValid())return e(new Error("User is not authenticated"),null);this.client.request("SetUserSettings",{MFAOptions:[],AccessToken:this.signInUserSession.getAccessToken().getJwtToken()},(function(t){return t?e(t,null):e(null,"SUCCESS")}))},t.deleteUser=function(e,t){var n=this;if(null==this.signInUserSession||!this.signInUserSession.isValid())return e(new Error("User is not authenticated"),null);this.client.request("DeleteUser",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken(),ClientMetadata:t},(function(t){return t?e(t,null):(n.clearCachedUser(),e(null,"SUCCESS"))}))},t.updateAttributes=function(e,t,n){var r=this;if(null==this.signInUserSession||!this.signInUserSession.isValid())return t(new Error("User is not authenticated"),null);this.client.request("UpdateUserAttributes",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken(),UserAttributes:e,ClientMetadata:n},(function(e){return e?t(e,null):r.getUserData((function(){return t(null,"SUCCESS")}),{bypassCache:!0})}))},t.getUserAttributes=function(e){if(null==this.signInUserSession||!this.signInUserSession.isValid())return e(new Error("User is not authenticated"),null);this.client.request("GetUser",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken()},(function(t,n){if(t)return e(t,null);for(var r=[],i=0;i<n.UserAttributes.length;i++){var o={Name:n.UserAttributes[i].Name,Value:n.UserAttributes[i].Value},s=new F(o);r.push(s)}return e(null,r)}))},t.getMFAOptions=function(e){if(null==this.signInUserSession||!this.signInUserSession.isValid())return e(new Error("User is not authenticated"),null);this.client.request("GetUser",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken()},(function(t,n){return t?e(t,null):e(null,n.MFAOptions)}))},t.createGetUserRequest=function(){return this.client.promisifyRequest("GetUser",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken()})},t.refreshSessionIfPossible=function(e){var t=this;return void 0===e&&(e={}),new Promise((function(n){var r=t.signInUserSession.getRefreshToken();r&&r.getToken()?t.refreshSession(r,n,e.clientMetadata):n()}))},t.getUserData=function(e,t){var n=this;if(null==this.signInUserSession||!this.signInUserSession.isValid())return this.clearCachedUserData(),e(new Error("User is not authenticated"),null);var r=this.getUserDataFromCache();if(r)if(this.isFetchUserDataAndTokenRequired(t))this.fetchUserData().then((function(e){return n.refreshSessionIfPossible(t).then((function(){return e}))})).then((function(t){return e(null,t)})).catch(e);else try{return void e(null,JSON.parse(r))}catch(t){return this.clearCachedUserData(),void e(t,null)}else this.fetchUserData().then((function(t){e(null,t)})).catch(e)},t.getUserDataFromCache=function(){return this.storage.getItem(this.userDataKey)},t.isFetchUserDataAndTokenRequired=function(e){var t=(e||{}).bypassCache;return void 0!==t&&t},t.fetchUserData=function(){var e=this;return this.createGetUserRequest().then((function(t){return e.cacheUserData(t),t}))},t.deleteAttributes=function(e,t){if(null==this.signInUserSession||!this.signInUserSession.isValid())return t(new Error("User is not authenticated"),null);this.client.request("DeleteUserAttributes",{UserAttributeNames:e,AccessToken:this.signInUserSession.getAccessToken().getJwtToken()},(function(e){return e?t(e,null):t(null,"SUCCESS")}))},t.resendConfirmationCode=function(e,t){var n={ClientId:this.pool.getClientId(),Username:this.username,ClientMetadata:t};this.client.request("ResendConfirmationCode",n,(function(t,n){return t?e(t,null):e(null,n)}))},t.getSession=function(e,t){if(void 0===t&&(t={}),null==this.username)return e(new Error("Username is null. Cannot retrieve a new session"),null);if(null!=this.signInUserSession&&this.signInUserSession.isValid())return e(null,this.signInUserSession);var n="CognitoIdentityServiceProvider."+this.pool.getClientId()+"."+this.username,r=n+".idToken",i=n+".accessToken",o=n+".refreshToken",s=n+".clockDrift";if(this.storage.getItem(r)){var a=new P({IdToken:this.storage.getItem(r)}),u=new C({AccessToken:this.storage.getItem(i)}),c=new N({RefreshToken:this.storage.getItem(o)}),f=parseInt(this.storage.getItem(s),0)||0,l=new j({IdToken:a,AccessToken:u,RefreshToken:c,ClockDrift:f});if(l.isValid())return this.signInUserSession=l,e(null,this.signInUserSession);if(!c.getToken())return e(new Error("Cannot retrieve a new session. Please authenticate."),null);this.refreshSession(c,e,t.clientMetadata)}else e(new Error("Local storage is missing an ID Token, Please authenticate"),null)},t.refreshSession=function(e,t,n){var r=this,i=this.pool.wrapRefreshSessionCallback?this.pool.wrapRefreshSessionCallback(t):t,o={};o.REFRESH_TOKEN=e.getToken();var s="CognitoIdentityServiceProvider."+this.pool.getClientId(),a=s+".LastAuthUser";if(this.storage.getItem(a)){this.username=this.storage.getItem(a);var u=s+"."+this.username+".deviceKey";this.deviceKey=this.storage.getItem(u),o.DEVICE_KEY=this.deviceKey}var c={ClientId:this.pool.getClientId(),AuthFlow:"REFRESH_TOKEN_AUTH",AuthParameters:o,ClientMetadata:n};this.getUserContextData()&&(c.UserContextData=this.getUserContextData()),this.client.request("InitiateAuth",c,(function(t,n){if(t)return"NotAuthorizedException"===t.code&&r.clearCachedUser(),i(t,null);if(n){var o=n.AuthenticationResult;return Object.prototype.hasOwnProperty.call(o,"RefreshToken")||(o.RefreshToken=e.getToken()),r.signInUserSession=r.getCognitoUserSession(o),r.cacheTokens(),i(null,r.signInUserSession)}}))},t.cacheTokens=function(){var e="CognitoIdentityServiceProvider."+this.pool.getClientId(),t=e+"."+this.username+".idToken",n=e+"."+this.username+".accessToken",r=e+"."+this.username+".refreshToken",i=e+"."+this.username+".clockDrift",o=e+".LastAuthUser";this.storage.setItem(t,this.signInUserSession.getIdToken().getJwtToken()),this.storage.setItem(n,this.signInUserSession.getAccessToken().getJwtToken()),this.storage.setItem(r,this.signInUserSession.getRefreshToken().getToken()),this.storage.setItem(i,""+this.signInUserSession.getClockDrift()),this.storage.setItem(o,this.username)},t.cacheUserData=function(e){this.storage.setItem(this.userDataKey,JSON.stringify(e))},t.clearCachedUserData=function(){this.storage.removeItem(this.userDataKey)},t.clearCachedUser=function(){this.clearCachedTokens(),this.clearCachedUserData()},t.cacheDeviceKeyAndPassword=function(){var e="CognitoIdentityServiceProvider."+this.pool.getClientId()+"."+this.username,t=e+".deviceKey",n=e+".randomPasswordKey",r=e+".deviceGroupKey";this.storage.setItem(t,this.deviceKey),this.storage.setItem(n,this.randomPassword),this.storage.setItem(r,this.deviceGroupKey)},t.getCachedDeviceKeyAndPassword=function(){var e="CognitoIdentityServiceProvider."+this.pool.getClientId()+"."+this.username,t=e+".deviceKey",n=e+".randomPasswordKey",r=e+".deviceGroupKey";this.storage.getItem(t)&&(this.deviceKey=this.storage.getItem(t),this.randomPassword=this.storage.getItem(n),this.deviceGroupKey=this.storage.getItem(r))},t.clearCachedDeviceKeyAndPassword=function(){var e="CognitoIdentityServiceProvider."+this.pool.getClientId()+"."+this.username,t=e+".deviceKey",n=e+".randomPasswordKey",r=e+".deviceGroupKey";this.storage.removeItem(t),this.storage.removeItem(n),this.storage.removeItem(r)},t.clearCachedTokens=function(){var e="CognitoIdentityServiceProvider."+this.pool.getClientId(),t=e+"."+this.username+".idToken",n=e+"."+this.username+".accessToken",r=e+"."+this.username+".refreshToken",i=e+".LastAuthUser",o=e+"."+this.username+".clockDrift";this.storage.removeItem(t),this.storage.removeItem(n),this.storage.removeItem(r),this.storage.removeItem(i),this.storage.removeItem(o)},t.getCognitoUserSession=function(e){var t=new P(e),n=new C(e),r=new N(e);return new j({IdToken:t,AccessToken:n,RefreshToken:r})},t.forgotPassword=function(e,t){var n={ClientId:this.pool.getClientId(),Username:this.username,ClientMetadata:t};this.getUserContextData()&&(n.UserContextData=this.getUserContextData()),this.client.request("ForgotPassword",n,(function(t,n){return t?e.onFailure(t):"function"==typeof e.inputVerificationCode?e.inputVerificationCode(n):e.onSuccess(n)}))},t.confirmPassword=function(e,t,n,r){var i={ClientId:this.pool.getClientId(),Username:this.username,ConfirmationCode:e,Password:t,ClientMetadata:r};this.getUserContextData()&&(i.UserContextData=this.getUserContextData()),this.client.request("ConfirmForgotPassword",i,(function(e){return e?n.onFailure(e):n.onSuccess()}))},t.getAttributeVerificationCode=function(e,t,n){if(null==this.signInUserSession||!this.signInUserSession.isValid())return t.onFailure(new Error("User is not authenticated"));this.client.request("GetUserAttributeVerificationCode",{AttributeName:e,AccessToken:this.signInUserSession.getAccessToken().getJwtToken(),ClientMetadata:n},(function(e,n){return e?t.onFailure(e):"function"==typeof t.inputVerificationCode?t.inputVerificationCode(n):t.onSuccess()}))},t.verifyAttribute=function(e,t,n){if(null==this.signInUserSession||!this.signInUserSession.isValid())return n.onFailure(new Error("User is not authenticated"));this.client.request("VerifyUserAttribute",{AttributeName:e,Code:t,AccessToken:this.signInUserSession.getAccessToken().getJwtToken()},(function(e){return e?n.onFailure(e):n.onSuccess("SUCCESS")}))},t.getDevice=function(e){if(null==this.signInUserSession||!this.signInUserSession.isValid())return e.onFailure(new Error("User is not authenticated"));this.client.request("GetDevice",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken(),DeviceKey:this.deviceKey},(function(t,n){return t?e.onFailure(t):e.onSuccess(n)}))},t.forgetSpecificDevice=function(e,t){if(null==this.signInUserSession||!this.signInUserSession.isValid())return t.onFailure(new Error("User is not authenticated"));this.client.request("ForgetDevice",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken(),DeviceKey:e},(function(e){return e?t.onFailure(e):t.onSuccess("SUCCESS")}))},t.forgetDevice=function(e){var t=this;this.forgetSpecificDevice(this.deviceKey,{onFailure:e.onFailure,onSuccess:function(n){return t.deviceKey=null,t.deviceGroupKey=null,t.randomPassword=null,t.clearCachedDeviceKeyAndPassword(),e.onSuccess(n)}})},t.setDeviceStatusRemembered=function(e){if(null==this.signInUserSession||!this.signInUserSession.isValid())return e.onFailure(new Error("User is not authenticated"));this.client.request("UpdateDeviceStatus",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken(),DeviceKey:this.deviceKey,DeviceRememberedStatus:"remembered"},(function(t){return t?e.onFailure(t):e.onSuccess("SUCCESS")}))},t.setDeviceStatusNotRemembered=function(e){if(null==this.signInUserSession||!this.signInUserSession.isValid())return e.onFailure(new Error("User is not authenticated"));this.client.request("UpdateDeviceStatus",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken(),DeviceKey:this.deviceKey,DeviceRememberedStatus:"not_remembered"},(function(t){return t?e.onFailure(t):e.onSuccess("SUCCESS")}))},t.listDevices=function(e,t,n){if(null==this.signInUserSession||!this.signInUserSession.isValid())return n.onFailure(new Error("User is not authenticated"));var r={AccessToken:this.signInUserSession.getAccessToken().getJwtToken(),Limit:e};t&&(r.PaginationToken=t),this.client.request("ListDevices",r,(function(e,t){return e?n.onFailure(e):n.onSuccess(t)}))},t.globalSignOut=function(e){var t=this;if(null==this.signInUserSession||!this.signInUserSession.isValid())return e.onFailure(new Error("User is not authenticated"));this.client.request("GlobalSignOut",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken()},(function(n){return n?e.onFailure(n):(t.clearCachedUser(),e.onSuccess("SUCCESS"))}))},t.signOut=function(){this.signInUserSession=null,this.clearCachedUser()},t.sendMFASelectionAnswer=function(e,t){var n=this,r={};r.USERNAME=this.username,r.ANSWER=e;var i={ChallengeName:"SELECT_MFA_TYPE",ChallengeResponses:r,ClientId:this.pool.getClientId(),Session:this.Session};this.getUserContextData()&&(i.UserContextData=this.getUserContextData()),this.client.request("RespondToAuthChallenge",i,(function(r,i){return r?t.onFailure(r):(n.Session=i.Session,"SMS_MFA"===e?t.mfaRequired(i.ChallengeName,i.ChallengeParameters):"SOFTWARE_TOKEN_MFA"===e?t.totpRequired(i.ChallengeName,i.ChallengeParameters):void 0)}))},t.getUserContextData=function(){return this.pool.getUserContextData(this.username)},t.associateSoftwareToken=function(e){var t=this;null!=this.signInUserSession&&this.signInUserSession.isValid()?this.client.request("AssociateSoftwareToken",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken()},(function(t,n){return t?e.onFailure(t):e.associateSecretCode(n.SecretCode)})):this.client.request("AssociateSoftwareToken",{Session:this.Session},(function(n,r){return n?e.onFailure(n):(t.Session=r.Session,e.associateSecretCode(r.SecretCode))}))},t.verifySoftwareToken=function(e,t,n){var r=this;null!=this.signInUserSession&&this.signInUserSession.isValid()?this.client.request("VerifySoftwareToken",{AccessToken:this.signInUserSession.getAccessToken().getJwtToken(),UserCode:e,FriendlyDeviceName:t},(function(e,t){return e?n.onFailure(e):n.onSuccess(t)})):this.client.request("VerifySoftwareToken",{Session:this.Session,UserCode:e,FriendlyDeviceName:t},(function(e,t){if(e)return n.onFailure(e);r.Session=t.Session;var i={};i.USERNAME=r.username;var o={ChallengeName:"MFA_SETUP",ClientId:r.pool.getClientId(),ChallengeResponses:i,Session:r.Session};r.getUserContextData()&&(o.UserContextData=r.getUserContextData()),r.client.request("RespondToAuthChallenge",o,(function(e,t){return e?n.onFailure(e):(r.signInUserSession=r.getCognitoUserSession(t.AuthenticationResult),r.cacheTokens(),n.onSuccess(r.signInUserSession))}))}))},e}(); -/*! - * Copyright 2016 Amazon.com, - * Inc. or its affiliates. All Rights Reserved. - * - * Licensed under the Amazon Software License (the "License"). - * You may not use this file except in compliance with the - * License. A copy of the License is located at - * - * http://aws.amazon.com/asl/ - * - * or in the "license" file accompanying this file. This file is - * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, express or implied. See the License - * for the specific language governing permissions and - * limitations under the License. - */n(365);function G(){}G.prototype.userAgent="aws-amplify/0.1.x js";var W=G;function $(e){var t="function"==typeof Map?new Map:void 0;return($=function(e){if(null===e||(n=e,-1===Function.toString.call(n).indexOf("[native code]")))return e;var n;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return Y(e,arguments,X(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),Z(r,e)})(e)}function Y(e,t,n){return(Y=J()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&Z(i,n.prototype),i}).apply(null,arguments)}function J(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(e){return!1}}function Z(e,t){return(Z=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function X(e){return(X=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}var Q=function(e){var t,n;function r(t,n,r,i){var o;return(o=e.call(this,t)||this).code=n,o.name=r,o.statusCode=i,o}return n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,Z(t,n),r}($(Error)),ee=function(){function e(e,t,n){this.endpoint=t||"https://cognito-idp."+e+".amazonaws.com/";var r=(n||{}).credentials;this.fetchOptions=r?{credentials:r}:{}}var t=e.prototype;return t.promisifyRequest=function(e,t){var n=this;return new Promise((function(r,i){n.request(e,t,(function(e,t){e?i(new Q(e.message,e.code,e.name,e.statusCode)):r(t)}))}))},t.request=function(e,t,n){var r,i={"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":"AWSCognitoIdentityProviderService."+e,"X-Amz-User-Agent":W.prototype.userAgent},o=Object.assign({},this.fetchOptions,{headers:i,method:"POST",mode:"cors",cache:"no-cache",body:JSON.stringify(t)});fetch(this.endpoint,o).then((function(e){return r=e,e}),(function(e){if(e instanceof TypeError)throw new Error("Network error");throw e})).then((function(e){return e.json().catch((function(){return{}}))})).then((function(e){if(r.ok)return n(null,e);e;var t=(e.__type||e.code).split("#").pop(),i={code:t,name:t,message:e.message||e.Message||null};return n(i)})).catch((function(e){if(!(r&&r.headers&&r.headers.get("x-amzn-errortype"))){if(e instanceof Error&&"Network error"===e.message){var t={code:"NetworkError",name:e.name,message:e.message};return n(t)}return n(e)}try{var i=r.headers.get("x-amzn-errortype").split(":")[0],o={code:i,name:i,statusCode:r.status,message:r.status?r.status.toString():null};return n(o)}catch(t){return n(e)}}))},e}(),te=function(){function e(e,t){var n=e||{},r=n.UserPoolId,i=n.ClientId,o=n.endpoint,s=n.fetchOptions,a=n.AdvancedSecurityDataCollectionFlag;if(!r||!i)throw new Error("Both UserPoolId and ClientId are required.");if(!/^[\w-]+_.+$/.test(r))throw new Error("Invalid UserPoolId format.");var u=r.split("_")[0];this.userPoolId=r,this.clientId=i,this.client=new ee(u,o,s),this.advancedSecurityDataCollectionFlag=!1!==a,this.storage=e.Storage||(new K).getStorage(),t&&(this.wrapRefreshSessionCallback=t)}var t=e.prototype;return t.getUserPoolId=function(){return this.userPoolId},t.getClientId=function(){return this.clientId},t.signUp=function(e,t,n,r,i,o){var s=this,a={ClientId:this.clientId,Username:e,Password:t,UserAttributes:n,ValidationData:r,ClientMetadata:o};this.getUserContextData(e)&&(a.UserContextData=this.getUserContextData(e)),this.client.request("SignUp",a,(function(t,n){if(t)return i(t,null);var r={Username:e,Pool:s,Storage:s.storage},o={user:new V(r),userConfirmed:n.UserConfirmed,userSub:n.UserSub,codeDeliveryDetails:n.CodeDeliveryDetails};return i(null,o)}))},t.getCurrentUser=function(){var e="CognitoIdentityServiceProvider."+this.clientId+".LastAuthUser",t=this.storage.getItem(e);if(t){var n={Username:t,Pool:this,Storage:this.storage};return new V(n)}return null},t.getUserContextData=function(e){if("undefined"!=typeof AmazonCognitoAdvancedSecurityData){var t=AmazonCognitoAdvancedSecurityData;if(this.advancedSecurityDataCollectionFlag){var n=t.getData(e,this.userPoolId,this.clientId);if(n)return{EncodedData:n}}return{}}},e}(),ne=n(65),re=function(){function e(e){if(!e.domain)throw new Error("The domain of cookieStorage can not be undefined.");if(this.domain=e.domain,e.path?this.path=e.path:this.path="/",Object.prototype.hasOwnProperty.call(e,"expires")?this.expires=e.expires:this.expires=365,Object.prototype.hasOwnProperty.call(e,"secure")?this.secure=e.secure:this.secure=!0,Object.prototype.hasOwnProperty.call(e,"sameSite")){if(!["strict","lax","none"].includes(e.sameSite))throw new Error('The sameSite value of cookieStorage must be "lax", "strict" or "none".');if("none"===e.sameSite&&!this.secure)throw new Error("sameSite = None requires the Secure attribute in latest browser versions.");this.sameSite=e.sameSite}else this.sameSite=null}var t=e.prototype;return t.setItem=function(e,t){var n={path:this.path,expires:this.expires,domain:this.domain,secure:this.secure};return this.sameSite&&(n.sameSite=this.sameSite),ne.set(e,t,n),ne.get(e)},t.getItem=function(e){return ne.get(e)},t.removeItem=function(e){var t={path:this.path,expires:this.expires,domain:this.domain,secure:this.secure};return this.sameSite&&(t.sameSite=this.sameSite),ne.remove(e,t)},t.clear=function(){var e,t=ne.get();for(e=0;e<t.length;++e)ne.remove(t[e]);return{}},e}()},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t,n){var r;e.exports=(r=r||function(e,t){var n=Object.create||function(){function e(){}return function(t){var n;return e.prototype=t,n=new e,e.prototype=null,n}}(),r={},i=r.lib={},o=i.Base={extend:function(e){var t=n(this);return e&&t.mixIn(e),t.hasOwnProperty("init")&&this.init!==t.init||(t.init=function(){t.$super.init.apply(this,arguments)}),t.init.prototype=t,t.$super=this,t},create:function(){var e=this.extend();return e.init.apply(e,arguments),e},init:function(){},mixIn:function(e){for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);e.hasOwnProperty("toString")&&(this.toString=e.toString)},clone:function(){return this.init.prototype.extend(this)}},s=i.WordArray=o.extend({init:function(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:4*e.length},toString:function(e){return(e||u).stringify(this)},concat:function(e){var t=this.words,n=e.words,r=this.sigBytes,i=e.sigBytes;if(this.clamp(),r%4)for(var o=0;o<i;o++){var s=n[o>>>2]>>>24-o%4*8&255;t[r+o>>>2]|=s<<24-(r+o)%4*8}else for(o=0;o<i;o+=4)t[r+o>>>2]=n[o>>>2];return this.sigBytes+=i,this},clamp:function(){var t=this.words,n=this.sigBytes;t[n>>>2]&=4294967295<<32-n%4*8,t.length=e.ceil(n/4)},clone:function(){var e=o.clone.call(this);return e.words=this.words.slice(0),e},random:function(t){for(var n,r=[],i=function(t){t=t;var n=987654321,r=4294967295;return function(){var i=((n=36969*(65535&n)+(n>>16)&r)<<16)+(t=18e3*(65535&t)+(t>>16)&r)&r;return i/=4294967296,(i+=.5)*(e.random()>.5?1:-1)}},o=0;o<t;o+=4){var a=i(4294967296*(n||e.random()));n=987654071*a(),r.push(4294967296*a()|0)}return new s.init(r,t)}}),a=r.enc={},u=a.Hex={stringify:function(e){for(var t=e.words,n=e.sigBytes,r=[],i=0;i<n;i++){var o=t[i>>>2]>>>24-i%4*8&255;r.push((o>>>4).toString(16)),r.push((15&o).toString(16))}return r.join("")},parse:function(e){for(var t=e.length,n=[],r=0;r<t;r+=2)n[r>>>3]|=parseInt(e.substr(r,2),16)<<24-r%8*4;return new s.init(n,t/2)}},c=a.Latin1={stringify:function(e){for(var t=e.words,n=e.sigBytes,r=[],i=0;i<n;i++){var o=t[i>>>2]>>>24-i%4*8&255;r.push(String.fromCharCode(o))}return r.join("")},parse:function(e){for(var t=e.length,n=[],r=0;r<t;r++)n[r>>>2]|=(255&e.charCodeAt(r))<<24-r%4*8;return new s.init(n,t)}},f=a.Utf8={stringify:function(e){try{return decodeURIComponent(escape(c.stringify(e)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(e){return c.parse(unescape(encodeURIComponent(e)))}},l=i.BufferedBlockAlgorithm=o.extend({reset:function(){this._data=new s.init,this._nDataBytes=0},_append:function(e){"string"==typeof e&&(e=f.parse(e)),this._data.concat(e),this._nDataBytes+=e.sigBytes},_process:function(t){var n=this._data,r=n.words,i=n.sigBytes,o=this.blockSize,a=i/(4*o),u=(a=t?e.ceil(a):e.max((0|a)-this._minBufferSize,0))*o,c=e.min(4*u,i);if(u){for(var f=0;f<u;f+=o)this._doProcessBlock(r,f);var l=r.splice(0,u);n.sigBytes-=c}return new s.init(l,c)},clone:function(){var e=o.clone.call(this);return e._data=this._data.clone(),e},_minBufferSize:0}),d=(i.Hasher=l.extend({cfg:o.extend(),init:function(e){this.cfg=this.cfg.extend(e),this.reset()},reset:function(){l.reset.call(this),this._doReset()},update:function(e){return this._append(e),this._process(),this},finalize:function(e){return e&&this._append(e),this._doFinalize()},blockSize:16,_createHelper:function(e){return function(t,n){return new e.init(n).finalize(t)}},_createHmacHelper:function(e){return function(t,n){return new d.HMAC.init(e,n).finalize(t)}}}),r.algo={});return r}(Math),r)},function(e,t,n){"use strict";(function(e){n.d(t,"d",(function(){return f})),n.d(t,"c",(function(){return l})),n.d(t,"b",(function(){return d})),n.d(t,"a",(function(){return g}));var r=[{type:"text/plain",ext:"txt"},{type:"text/html",ext:"html"},{type:"text/javascript",ext:"js"},{type:"text/css",ext:"css"},{type:"text/csv",ext:"csv"},{type:"text/yaml",ext:"yml"},{type:"text/yaml",ext:"yaml"},{type:"text/calendar",ext:"ics"},{type:"text/calendar",ext:"ical"},{type:"image/apng",ext:"apng"},{type:"image/bmp",ext:"bmp"},{type:"image/gif",ext:"gif"},{type:"image/x-icon",ext:"ico"},{type:"image/x-icon",ext:"cur"},{type:"image/jpeg",ext:"jpg"},{type:"image/jpeg",ext:"jpeg"},{type:"image/jpeg",ext:"jfif"},{type:"image/jpeg",ext:"pjp"},{type:"image/jpeg",ext:"pjpeg"},{type:"image/png",ext:"png"},{type:"image/svg+xml",ext:"svg"},{type:"image/tiff",ext:"tif"},{type:"image/tiff",ext:"tiff"},{type:"image/webp",ext:"webp"},{type:"application/json",ext:"json"},{type:"application/xml",ext:"xml"},{type:"application/x-sh",ext:"sh"},{type:"application/zip",ext:"zip"},{type:"application/x-rar-compressed",ext:"rar"},{type:"application/x-tar",ext:"tar"},{type:"application/x-bzip",ext:"bz"},{type:"application/x-bzip2",ext:"bz2"},{type:"application/pdf",ext:"pdf"},{type:"application/java-archive",ext:"jar"},{type:"application/msword",ext:"doc"},{type:"application/vnd.ms-excel",ext:"xls"},{type:"application/vnd.ms-excel",ext:"xlsx"},{type:"message/rfc822",ext:"eml"}],i=function(e){return void 0===e&&(e={}),0===Object.keys(e).length},o=function(e,t,n){if(!e||!e.sort)return!1;var r=n&&"desc"===n?-1:1;return e.sort((function(e,n){var i=e[t],o=n[t];return void 0===o?void 0===i?0:1*r:void 0===i||i<o?-1*r:i>o?1*r:0})),!0},s=function(e,t){var n=Object.assign({},e);return t&&("string"==typeof t?delete n[t]:t.forEach((function(e){delete n[e]}))),n},a=function(e,t){void 0===t&&(t="application/octet-stream");var n=e.toLowerCase(),i=r.filter((function(e){return n.endsWith("."+e.ext)}));return i.length>0?i[0].type:t},u=function(e){var t=e.toLowerCase();return!!t.startsWith("text/")||("application/json"===t||"application/xml"===t||"application/sh"===t)},c=function(){for(var e="",t="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",n=32;n>0;n-=1)e+=t[Math.floor(Math.random()*t.length)];return e},f=function(e){if(e.isResolved)return e;var t=!0,n=!1,r=!1,i=e.then((function(e){return r=!0,t=!1,e}),(function(e){throw n=!0,t=!1,e}));return i.isFullfilled=function(){return r},i.isPending=function(){return t},i.isRejected=function(){return n},i},l=function(){if("undefined"==typeof self)return!1;var e=self;return void 0!==e.WorkerGlobalScope&&self instanceof e.WorkerGlobalScope},d=function(){return{isBrowser:"undefined"!=typeof window&&void 0!==window.document,isNode:void 0!==e&&null!=e.versions&&null!=e.versions.node}},h=function e(t,n,r){if(void 0===n&&(n=[]),void 0===r&&(r=[]),!v(t))return t;var i={};for(var o in t){if(t.hasOwnProperty(o))i[n.includes(o)?o:o[0].toLowerCase()+o.slice(1)]=r.includes(o)?t[o]:e(t[o],n,r)}return i},p=function e(t,n,r){if(void 0===n&&(n=[]),void 0===r&&(r=[]),!v(t))return t;var i={};for(var o in t){if(t.hasOwnProperty(o))i[n.includes(o)?o:o[0].toUpperCase()+o.slice(1)]=r.includes(o)?t[o]:e(t[o],n,r)}return i},v=function(e){return!(!(e instanceof Object)||e instanceof Array||e instanceof Function||e instanceof Number||e instanceof String||e instanceof Boolean)},g=function(){function e(){}return e.isEmpty=i,e.sortByField=o,e.objectLessAttributes=s,e.filenameToContentType=a,e.isTextFile=u,e.generateRandomString=c,e.makeQuerablePromise=f,e.isWebWorker=l,e.browserOrNode=d,e.transferKeyToLowerCase=h,e.transferKeyToUpperCase=p,e.isStrictObject=v,e}()}).call(this,n(20))},function(e,t,n){"use strict";n.d(t,"a",(function(){return r}));var r,i=n(105);!function(e){e.CONNECTION_CLOSED="Connection closed",e.TIMEOUT_DISCONNECT="Timeout disconnect",e.SUBSCRIPTION_ACK="Subscription ack"}(r||(r={})),t.b=i.a},function(e,t,n){"use strict";var r;n.d(t,"a",(function(){return r})),function(e){e.DEFAULT_MSG="Authentication Error",e.EMPTY_USERNAME="Username cannot be empty",e.INVALID_USERNAME="The username should either be a string or one of the sign in types",e.EMPTY_PASSWORD="Password cannot be empty",e.EMPTY_CODE="Confirmation code cannot be empty",e.SIGN_UP_ERROR="Error creating account",e.NO_MFA="No valid MFA method provided",e.INVALID_MFA="Invalid MFA type",e.EMPTY_CHALLENGE="Challenge response cannot be empty",e.NO_USER_SESSION="Failed to get the session because the user is empty"}(r||(r={}))},function(e,t,n){var r=n(228),i=n(230),o=n(231),s=n(61),a=n(232),u=n(138),c=n(229),f=n(139),l=Object.prototype.hasOwnProperty;e.exports=function(e){if(null==e)return!0;if(a(e)&&(s(e)||"string"==typeof e||"function"==typeof e.splice||u(e)||f(e)||o(e)))return!e.length;var t=i(e);if("[object Map]"==t||"[object Set]"==t)return!e.size;if(c(e))return!r(e).length;for(var n in e)if(l.call(e,n))return!1;return!0}},function(e,t,n){"use strict";n.d(t,"a",(function(){return s}));var r=n(1),i=n(2);var o={step:"build",tags:["SET_CONTENT_LENGTH","CONTENT_LENGTH"],name:"contentLengthMiddleware"},s=function(e){return{applyToStack:function(t){t.add(function(e){var t=this;return function(n){return function(o){return Object(r.__awaiter)(t,void 0,void 0,(function(){var t,s,a,u,c;return Object(r.__generator)(this,(function(f){return t=o.request,i.a.isInstance(t)&&(s=t.body,a=t.headers,s&&-1===Object.keys(a).map((function(e){return e.toLowerCase()})).indexOf("content-length")&&void 0!==(u=e(s))&&(t.headers=Object(r.__assign)(Object(r.__assign)({},t.headers),((c={})["content-length"]=String(u),c)))),[2,n(Object(r.__assign)(Object(r.__assign)({},o),{request:t}))]}))}))}}}(e.bodyLengthChecker),o)}}}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.WebCryptoSha256=t.Ie11Sha256=void 0,n(1).__exportStar(n(373),t);var r=n(216);Object.defineProperty(t,"Ie11Sha256",{enumerable:!0,get:function(){return r.Sha256}});var i=n(219);Object.defineProperty(t,"WebCryptoSha256",{enumerable:!0,get:function(){return i.Sha256}})},function(e,t,n){"use strict";n.d(t,"a",(function(){return i}));var r=n(106),i=function(e){var t,n=new URL(e),i=n.hostname,o=n.pathname,s=n.port,a=n.protocol,u=n.search;return u&&(t=Object(r.a)(u)),{hostname:i,port:s?parseInt(s):void 0,protocol:a,path:o,query:t}}},function(e,t,n){"use strict";function r(e){if("string"==typeof e){for(var t=e.length,n=t-1;n>=0;n--){var r=e.charCodeAt(n);r>127&&r<=2047?t++:r>2047&&r<=65535&&(t+=2)}return t}return"number"==typeof e.byteLength?e.byteLength:"number"==typeof e.size?e.size:void 0}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";function r(e,t){return"aws-sdk-js-v3-"+e+"/"+t+" "+("undefined"!=typeof navigator&&"string"==typeof navigator.userAgent?navigator.userAgent:"")}n.d(t,"a",(function(){return r}))},function(e,t,n){"use strict";var r=n(63);n(30);t.a=r.a},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=n(1),i={name:"loggerMiddleware",tags:["LOGGER"],step:"initialize"},o=function(e){return{applyToStack:function(e){e.add((function(e,t){return function(n){return Object(r.__awaiter)(void 0,void 0,void 0,(function(){var i,o,s,a;return Object(r.__generator)(this,(function(r){switch(r.label){case 0:return i=t.logger,[4,e(n)];case 1:return o=r.sent(),i?(s=o.response,"function"==typeof i.info&&i.info({metadata:{statusCode:s.statusCode,requestId:null!==(a=s.headers["x-amzn-requestid"])&&void 0!==a?a:s.headers["x-amzn-request-id"],extendedRequestId:s.headers["x-amz-id-2"],cfId:s.headers["x-amz-cf-id"]}}),[2,o]):[2,o]}}))}))}}),i)}}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return s}));var r=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},i=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(r(arguments[t]));return e},o={VERBOSE:1,DEBUG:2,INFO:3,WARN:4,ERROR:5},s=function(){function e(e,t){void 0===t&&(t="WARN"),this.name=e,this.level=t}return e.prototype._padding=function(e){return e<10?"0"+e:""+e},e.prototype._ts=function(){var e=new Date;return[this._padding(e.getMinutes()),this._padding(e.getSeconds())].join(":")+"."+e.getMilliseconds()},e.prototype._log=function(t){for(var n=[],r=1;r<arguments.length;r++)n[r-1]=arguments[r];var i=this.level;e.LOG_LEVEL&&(i=e.LOG_LEVEL),"undefined"!=typeof window&&window.LOG_LEVEL&&(i=window.LOG_LEVEL);var s=o[i],a=o[t];if(a>=s){var u=console.log.bind(console);"ERROR"===t&&console.error&&(u=console.error.bind(console)),"WARN"===t&&console.warn&&(u=console.warn.bind(console));var c="["+t+"] "+this._ts()+" "+this.name;if(1===n.length&&"string"==typeof n[0])u(c+" - "+n[0]);else if(1===n.length)u(c,n[0]);else if("string"==typeof n[0]){var f=n.slice(1);1===f.length&&(f=f[0]),u(c+" - "+n[0],f)}else u(c,n)}},e.prototype.log=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];this._log.apply(this,i(["INFO"],e))},e.prototype.info=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];this._log.apply(this,i(["INFO"],e))},e.prototype.warn=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];this._log.apply(this,i(["WARN"],e))},e.prototype.error=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];this._log.apply(this,i(["ERROR"],e))},e.prototype.debug=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];this._log.apply(this,i(["DEBUG"],e))},e.prototype.verbose=function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];this._log.apply(this,i(["VERBOSE"],e))},e.LOG_LEVEL=null,e}()},function(e,t,n){"use strict";var r=n(235),i=Object.prototype.toString;function o(e){return"[object Array]"===i.call(e)}function s(e){return void 0===e}function a(e){return null!==e&&"object"==typeof e}function u(e){if("[object Object]"!==i.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function c(e){return"[object Function]"===i.call(e)}function f(e,t){if(null!=e)if("object"!=typeof e&&(e=[e]),o(e))for(var n=0,r=e.length;n<r;n++)t.call(null,e[n],n,e);else for(var i in e)Object.prototype.hasOwnProperty.call(e,i)&&t.call(null,e[i],i,e)}e.exports={isArray:o,isArrayBuffer:function(e){return"[object ArrayBuffer]"===i.call(e)},isBuffer:function(e){return null!==e&&!s(e)&&null!==e.constructor&&!s(e.constructor)&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)},isFormData:function(e){return"undefined"!=typeof FormData&&e instanceof FormData},isArrayBufferView:function(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer},isString:function(e){return"string"==typeof e},isNumber:function(e){return"number"==typeof e},isObject:a,isPlainObject:u,isUndefined:s,isDate:function(e){return"[object Date]"===i.call(e)},isFile:function(e){return"[object File]"===i.call(e)},isBlob:function(e){return"[object Blob]"===i.call(e)},isFunction:c,isStream:function(e){return a(e)&&c(e.pipe)},isURLSearchParams:function(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams},isStandardBrowserEnv:function(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)},forEach:f,merge:function e(){var t={};function n(n,r){u(t[r])&&u(n)?t[r]=e(t[r],n):u(n)?t[r]=e({},n):o(n)?t[r]=n.slice():t[r]=n}for(var r=0,i=arguments.length;r<i;r++)f(arguments[r],n);return t},extend:function(e,t,n){return f(t,(function(t,i){e[i]=n&&"function"==typeof t?r(t,n):t})),e},trim:function(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")},stripBOM:function(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e}}},function(e,t){function n(e,t){if(!e)throw new Error(t||"Assertion failed")}e.exports=n,n.equal=function(e,t,n){if(e!=t)throw new Error(n||"Assertion failed: "+e+" != "+t)}},function(e,t,n){"use strict";var r=t,i=n(29),o=n(46),s=n(198);r.assert=o,r.toArray=s.toArray,r.zero2=s.zero2,r.toHex=s.toHex,r.encode=s.encode,r.getNAF=function(e,t,n){var r=new Array(Math.max(e.bitLength(),n)+1);r.fill(0);for(var i=1<<t+1,o=e.clone(),s=0;s<r.length;s++){var a,u=o.andln(i-1);o.isOdd()?(a=u>(i>>1)-1?(i>>1)-u:u,o.isubn(a)):a=0,r[s]=a,o.iushrn(1)}return r},r.getJSF=function(e,t){var n=[[],[]];e=e.clone(),t=t.clone();for(var r,i=0,o=0;e.cmpn(-i)>0||t.cmpn(-o)>0;){var s,a,u=e.andln(3)+i&3,c=t.andln(3)+o&3;3===u&&(u=-1),3===c&&(c=-1),s=0==(1&u)?0:3!==(r=e.andln(7)+i&7)&&5!==r||2!==c?u:-u,n[0].push(s),a=0==(1&c)?0:3!==(r=t.andln(7)+o&7)&&5!==r||2!==u?c:-c,n[1].push(a),2*i===s+1&&(i=1-i),2*o===a+1&&(o=1-o),e.iushrn(1),t.iushrn(1)}return n},r.cachedProperty=function(e,t,n){var r="_"+t;e.prototype[t]=function(){return void 0!==this[r]?this[r]:this[r]=n.call(this)}},r.parseBytes=function(e){return"string"==typeof e?r.toArray(e,"hex"):e},r.intFromLE=function(e){return new i(e,"hex","le")}},,function(e,t,n){"use strict";var r,i="object"==typeof Reflect?Reflect:null,o=i&&"function"==typeof i.apply?i.apply:function(e,t,n){return Function.prototype.apply.call(e,t,n)};r=i&&"function"==typeof i.ownKeys?i.ownKeys:Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:function(e){return Object.getOwnPropertyNames(e)};var s=Number.isNaN||function(e){return e!=e};function a(){a.init.call(this)}e.exports=a,e.exports.once=function(e,t){return new Promise((function(n,r){function i(){void 0!==o&&e.removeListener("error",o),n([].slice.call(arguments))}var o;"error"!==t&&(o=function(n){e.removeListener(t,i),r(n)},e.once("error",o)),e.once(t,i)}))},a.EventEmitter=a,a.prototype._events=void 0,a.prototype._eventsCount=0,a.prototype._maxListeners=void 0;var u=10;function c(e){if("function"!=typeof e)throw new TypeError('The "listener" argument must be of type Function. Received type '+typeof e)}function f(e){return void 0===e._maxListeners?a.defaultMaxListeners:e._maxListeners}function l(e,t,n,r){var i,o,s,a;if(c(n),void 0===(o=e._events)?(o=e._events=Object.create(null),e._eventsCount=0):(void 0!==o.newListener&&(e.emit("newListener",t,n.listener?n.listener:n),o=e._events),s=o[t]),void 0===s)s=o[t]=n,++e._eventsCount;else if("function"==typeof s?s=o[t]=r?[n,s]:[s,n]:r?s.unshift(n):s.push(n),(i=f(e))>0&&s.length>i&&!s.warned){s.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(t)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=e,u.type=t,u.count=s.length,a=u,console&&console.warn&&console.warn(a)}return e}function d(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function h(e,t,n){var r={fired:!1,wrapFn:void 0,target:e,type:t,listener:n},i=d.bind(r);return i.listener=n,r.wrapFn=i,i}function p(e,t,n){var r=e._events;if(void 0===r)return[];var i=r[t];return void 0===i?[]:"function"==typeof i?n?[i.listener||i]:[i]:n?function(e){for(var t=new Array(e.length),n=0;n<t.length;++n)t[n]=e[n].listener||e[n];return t}(i):g(i,i.length)}function v(e){var t=this._events;if(void 0!==t){var n=t[e];if("function"==typeof n)return 1;if(void 0!==n)return n.length}return 0}function g(e,t){for(var n=new Array(t),r=0;r<t;++r)n[r]=e[r];return n}Object.defineProperty(a,"defaultMaxListeners",{enumerable:!0,get:function(){return u},set:function(e){if("number"!=typeof e||e<0||s(e))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+e+".");u=e}}),a.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},a.prototype.setMaxListeners=function(e){if("number"!=typeof e||e<0||s(e))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+e+".");return this._maxListeners=e,this},a.prototype.getMaxListeners=function(){return f(this)},a.prototype.emit=function(e){for(var t=[],n=1;n<arguments.length;n++)t.push(arguments[n]);var r="error"===e,i=this._events;if(void 0!==i)r=r&&void 0===i.error;else if(!r)return!1;if(r){var s;if(t.length>0&&(s=t[0]),s instanceof Error)throw s;var a=new Error("Unhandled error."+(s?" ("+s.message+")":""));throw a.context=s,a}var u=i[e];if(void 0===u)return!1;if("function"==typeof u)o(u,this,t);else{var c=u.length,f=g(u,c);for(n=0;n<c;++n)o(f[n],this,t)}return!0},a.prototype.addListener=function(e,t){return l(this,e,t,!1)},a.prototype.on=a.prototype.addListener,a.prototype.prependListener=function(e,t){return l(this,e,t,!0)},a.prototype.once=function(e,t){return c(t),this.on(e,h(this,e,t)),this},a.prototype.prependOnceListener=function(e,t){return c(t),this.prependListener(e,h(this,e,t)),this},a.prototype.removeListener=function(e,t){var n,r,i,o,s;if(c(t),void 0===(r=this._events))return this;if(void 0===(n=r[e]))return this;if(n===t||n.listener===t)0==--this._eventsCount?this._events=Object.create(null):(delete r[e],r.removeListener&&this.emit("removeListener",e,n.listener||t));else if("function"!=typeof n){for(i=-1,o=n.length-1;o>=0;o--)if(n[o]===t||n[o].listener===t){s=n[o].listener,i=o;break}if(i<0)return this;0===i?n.shift():function(e,t){for(;t+1<e.length;t++)e[t]=e[t+1];e.pop()}(n,i),1===n.length&&(r[e]=n[0]),void 0!==r.removeListener&&this.emit("removeListener",e,s||t)}return this},a.prototype.off=a.prototype.removeListener,a.prototype.removeAllListeners=function(e){var t,n,r;if(void 0===(n=this._events))return this;if(void 0===n.removeListener)return 0===arguments.length?(this._events=Object.create(null),this._eventsCount=0):void 0!==n[e]&&(0==--this._eventsCount?this._events=Object.create(null):delete n[e]),this;if(0===arguments.length){var i,o=Object.keys(n);for(r=0;r<o.length;++r)"removeListener"!==(i=o[r])&&this.removeAllListeners(i);return this.removeAllListeners("removeListener"),this._events=Object.create(null),this._eventsCount=0,this}if("function"==typeof(t=n[e]))this.removeListener(e,t);else if(void 0!==t)for(r=t.length-1;r>=0;r--)this.removeListener(e,t[r]);return this},a.prototype.listeners=function(e){return p(this,e,!0)},a.prototype.rawListeners=function(e){return p(this,e,!1)},a.listenerCount=function(e,t){return"function"==typeof e.listenerCount?e.listenerCount(t):v.call(e,t)},a.prototype.listenerCount=v,a.prototype.eventNames=function(){return this._eventsCount>0?r(this._events):[]}},function(e,t,n){"use strict";n.d(t,"a",(function(){return r})),n.d(t,"b",(function(){return i}));var r={userAgent:"aws-amplify/3.8.12 js",product:"",navigator:null,isReactNative:!1};if("undefined"!=typeof navigator&&navigator.product)switch(r.product=navigator.product||"",r.navigator=navigator||null,navigator.product){case"ReactNative":r.userAgent="aws-amplify/3.8.12 react-native",r.isReactNative=!0;break;default:r.userAgent="aws-amplify/3.8.12 js",r.isReactNative=!1}var i=function(){return r.userAgent}},function(e,t,n){"use strict";var r=n(46),i=n(7);function o(e,t){return 55296==(64512&e.charCodeAt(t))&&(!(t<0||t+1>=e.length)&&56320==(64512&e.charCodeAt(t+1)))}function s(e){return(e>>>24|e>>>8&65280|e<<8&16711680|(255&e)<<24)>>>0}function a(e){return 1===e.length?"0"+e:e}function u(e){return 7===e.length?"0"+e:6===e.length?"00"+e:5===e.length?"000"+e:4===e.length?"0000"+e:3===e.length?"00000"+e:2===e.length?"000000"+e:1===e.length?"0000000"+e:e}t.inherits=i,t.toArray=function(e,t){if(Array.isArray(e))return e.slice();if(!e)return[];var n=[];if("string"==typeof e)if(t){if("hex"===t)for((e=e.replace(/[^a-z0-9]+/gi,"")).length%2!=0&&(e="0"+e),i=0;i<e.length;i+=2)n.push(parseInt(e[i]+e[i+1],16))}else for(var r=0,i=0;i<e.length;i++){var s=e.charCodeAt(i);s<128?n[r++]=s:s<2048?(n[r++]=s>>6|192,n[r++]=63&s|128):o(e,i)?(s=65536+((1023&s)<<10)+(1023&e.charCodeAt(++i)),n[r++]=s>>18|240,n[r++]=s>>12&63|128,n[r++]=s>>6&63|128,n[r++]=63&s|128):(n[r++]=s>>12|224,n[r++]=s>>6&63|128,n[r++]=63&s|128)}else for(i=0;i<e.length;i++)n[i]=0|e[i];return n},t.toHex=function(e){for(var t="",n=0;n<e.length;n++)t+=a(e[n].toString(16));return t},t.htonl=s,t.toHex32=function(e,t){for(var n="",r=0;r<e.length;r++){var i=e[r];"little"===t&&(i=s(i)),n+=u(i.toString(16))}return n},t.zero2=a,t.zero8=u,t.join32=function(e,t,n,i){var o=n-t;r(o%4==0);for(var s=new Array(o/4),a=0,u=t;a<s.length;a++,u+=4){var c;c="big"===i?e[u]<<24|e[u+1]<<16|e[u+2]<<8|e[u+3]:e[u+3]<<24|e[u+2]<<16|e[u+1]<<8|e[u],s[a]=c>>>0}return s},t.split32=function(e,t){for(var n=new Array(4*e.length),r=0,i=0;r<e.length;r++,i+=4){var o=e[r];"big"===t?(n[i]=o>>>24,n[i+1]=o>>>16&255,n[i+2]=o>>>8&255,n[i+3]=255&o):(n[i+3]=o>>>24,n[i+2]=o>>>16&255,n[i+1]=o>>>8&255,n[i]=255&o)}return n},t.rotr32=function(e,t){return e>>>t|e<<32-t},t.rotl32=function(e,t){return e<<t|e>>>32-t},t.sum32=function(e,t){return e+t>>>0},t.sum32_3=function(e,t,n){return e+t+n>>>0},t.sum32_4=function(e,t,n,r){return e+t+n+r>>>0},t.sum32_5=function(e,t,n,r,i){return e+t+n+r+i>>>0},t.sum64=function(e,t,n,r){var i=e[t],o=r+e[t+1]>>>0,s=(o<r?1:0)+n+i;e[t]=s>>>0,e[t+1]=o},t.sum64_hi=function(e,t,n,r){return(t+r>>>0<t?1:0)+e+n>>>0},t.sum64_lo=function(e,t,n,r){return t+r>>>0},t.sum64_4_hi=function(e,t,n,r,i,o,s,a){var u=0,c=t;return u+=(c=c+r>>>0)<t?1:0,u+=(c=c+o>>>0)<o?1:0,e+n+i+s+(u+=(c=c+a>>>0)<a?1:0)>>>0},t.sum64_4_lo=function(e,t,n,r,i,o,s,a){return t+r+o+a>>>0},t.sum64_5_hi=function(e,t,n,r,i,o,s,a,u,c){var f=0,l=t;return f+=(l=l+r>>>0)<t?1:0,f+=(l=l+o>>>0)<o?1:0,f+=(l=l+a>>>0)<a?1:0,e+n+i+s+u+(f+=(l=l+c>>>0)<c?1:0)>>>0},t.sum64_5_lo=function(e,t,n,r,i,o,s,a,u,c){return t+r+o+a+c>>>0},t.rotr64_hi=function(e,t,n){return(t<<32-n|e>>>n)>>>0},t.rotr64_lo=function(e,t,n){return(e<<32-n|t>>>n)>>>0},t.shr64_hi=function(e,t,n){return e>>>n},t.shr64_lo=function(e,t,n){return(e<<32-n|t>>>n)>>>0}},function(e,t,n){"use strict";var r=n(62);t.a=r.a},function(e,t,n){var r=n(223),i="object"==typeof self&&self&&self.Object===Object&&self,o=r||i||Function("return this")();e.exports=o},function(e,t,n){"use strict";const r=":A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD",i="["+r+"][:A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*",o=new RegExp("^"+i+"$");t.isExist=function(e){return void 0!==e},t.isEmptyObject=function(e){return 0===Object.keys(e).length},t.merge=function(e,t,n){if(t){const r=Object.keys(t),i=r.length;for(let o=0;o<i;o++)e[r[o]]="strict"===n?[t[r[o]]]:t[r[o]]}},t.getValue=function(e){return t.isExist(e)?e:""},t.buildOptions=function(e,t,n){var r={};if(!e)return t;for(let i=0;i<n.length;i++)void 0!==e[n[i]]?r[n[i]]=e[n[i]]:r[n[i]]=t[n[i]];return r},t.isTagNameInArrayMode=function(e,t,n){return!1!==t&&(t instanceof RegExp?t.test(e):"function"==typeof t?!!t(e,n):"strict"===t)},t.isName=function(e){const t=o.exec(e);return!(null==t)},t.getAllMatches=function(e,t){const n=[];let r=t.exec(e);for(;r;){const i=[],o=r.length;for(let e=0;e<o;e++)i.push(r[e]);n.push(i),r=t.exec(e)}return n},t.nameRegexp=i},function(e,t,n){"use strict";n.d(t,"a",(function(){return r}));var r=function(e){return encodeURIComponent(e).replace(/[!'()*]/g,i)},i=function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}},function(e,t,n){var r=n(8).Buffer,i=n(285).Transform,o=n(59).StringDecoder;function s(e){i.call(this),this.hashMode="string"==typeof e,this.hashMode?this[e]=this._finalOrDigest:this.final=this._finalOrDigest,this._final&&(this.__final=this._final,this._final=null),this._decoder=null,this._encoding=null}n(7)(s,i),s.prototype.update=function(e,t,n){"string"==typeof e&&(e=r.from(e,t));var i=this._update(e);return this.hashMode?this:(n&&(i=this._toString(i,n)),i)},s.prototype.setAutoPadding=function(){},s.prototype.getAuthTag=function(){throw new Error("trying to get auth tag in unsupported state")},s.prototype.setAuthTag=function(){throw new Error("trying to set auth tag in unsupported state")},s.prototype.setAAD=function(){throw new Error("trying to set aad in unsupported state")},s.prototype._transform=function(e,t,n){var r;try{this.hashMode?this._update(e):this.push(this._update(e))}catch(e){r=e}finally{n(r)}},s.prototype._flush=function(e){var t;try{this.push(this.__final())}catch(e){t=e}e(t)},s.prototype._finalOrDigest=function(e){var t=this.__final()||r.alloc(0);return e&&(t=this._toString(t,e,!0)),t},s.prototype._toString=function(e,t,n){if(this._decoder||(this._decoder=new o(t),this._encoding=t),this._encoding!==t)throw new Error("can't switch encodings");var r=this._decoder.write(e);return n&&(r+=this._decoder.end()),r},e.exports=s},function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},function(e,t,n){"use strict";var r;n.d(t,"a",(function(){return r})),function(e){e.API_KEY="API_KEY",e.AWS_IAM="AWS_IAM",e.OPENID_CONNECT="OPENID_CONNECT",e.AMAZON_COGNITO_USER_POOLS="AMAZON_COGNITO_USER_POOLS"}(r||(r={}))},function(e,t,n){"use strict";var r=n(8).Buffer,i=r.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function o(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(r.isEncoding===i||!i(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=u,this.end=c,t=4;break;case"utf8":this.fillLast=a,t=4;break;case"base64":this.text=f,this.end=l,t=3;break;default:return this.write=d,void(this.end=h)}this.lastNeed=0,this.lastTotal=0,this.lastChar=r.allocUnsafe(t)}function s(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function a(e){var t=this.lastTotal-this.lastNeed,n=function(e,t,n){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if(128!=(192&t[1]))return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&128!=(192&t[2]))return e.lastNeed=2,"�"}}(this,e);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):(e.copy(this.lastChar,t,0,e.length),void(this.lastNeed-=e.length))}function u(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function c(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function f(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function l(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function d(e){return e.toString(this.encoding)}function h(e){return e&&e.length?this.write(e):""}t.StringDecoder=o,o.prototype.write=function(e){if(0===e.length)return"";var t,n;if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return n<e.length?t?t+this.text(e,n):this.text(e,n):t||""},o.prototype.end=function(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t},o.prototype.text=function(e,t){var n=function(e,t,n){var r=t.length-1;if(r<n)return 0;var i=s(t[r]);if(i>=0)return i>0&&(e.lastNeed=i-1),i;if(--r<n||-2===i)return 0;if((i=s(t[r]))>=0)return i>0&&(e.lastNeed=i-2),i;if(--r<n||-2===i)return 0;if((i=s(t[r]))>=0)return i>0&&(2===i?i=0:e.lastNeed=i-3),i;return 0}(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)},o.prototype.fillLast=function(e){if(this.lastNeed<=e.length)return e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal);e.copy(this.lastChar,this.lastTotal-this.lastNeed,0,e.length),this.lastNeed-=e.length}},function(e,t,n){"use strict";var r=n(92),i=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=l;var o=Object.create(n(80));o.inherits=n(7);var s=n(171),a=n(120);o.inherits(l,s);for(var u=i(a.prototype),c=0;c<u.length;c++){var f=u[c];l.prototype[f]||(l.prototype[f]=a.prototype[f])}function l(e){if(!(this instanceof l))return new l(e);s.call(this,e),a.call(this,e),e&&!1===e.readable&&(this.readable=!1),e&&!1===e.writable&&(this.writable=!1),this.allowHalfOpen=!0,e&&!1===e.allowHalfOpen&&(this.allowHalfOpen=!1),this.once("end",d)}function d(){this.allowHalfOpen||this._writableState.ended||r.nextTick(h,this)}function h(e){e.end()}Object.defineProperty(l.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Object.defineProperty(l.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set:function(e){void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed=e,this._writableState.destroyed=e)}}),l.prototype._destroy=function(e,t){this.push(null),this.end(),r.nextTick(t,e)}},function(e,t){var n=Array.isArray;e.exports=n},function(e,t,n){"use strict";n.d(t,"b",(function(){return _})),n.d(t,"a",(function(){return S}));var r=n(63),i=n(26),o=n(254),s=n(44),a=n(89),u=n(19),c=function(){return(c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},f=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},l=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},d=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n},h=new s.a("RestAPI"),p=function(){function e(e){this._api=null,this.Credentials=a.a,this._options=e,h.debug("API Options",this._options)}return e.prototype.getModuleName=function(){return"RestAPI"},e.prototype.configure=function(e){var t=e||{},n=t.API,r=void 0===n?{}:n,i=d(t,["API"]),o=c(c({},i),r);if(h.debug("configure Rest API",{opt:o}),o.aws_project_region){if(o.aws_cloud_logic_custom){var s=o.aws_cloud_logic_custom;o.endpoints="string"==typeof s?JSON.parse(s):s}o=Object.assign({},o,{region:o.aws_project_region,header:{}})}return Array.isArray(o.endpoints)?o.endpoints.forEach((function(e){void 0!==e.custom_header&&"function"!=typeof e.custom_header&&(h.warn("Rest API "+e.name+", custom_header should be a function"),e.custom_header=void 0)})):this._options&&Array.isArray(this._options.endpoints)?o.endpoints=this._options.endpoints:o.endpoints=[],this._options=Object.assign({},this._options,o),this.createInstance(),this._options},e.prototype.createInstance=function(){return h.debug("create Rest API instance"),this._api=new o.a(this._options),this._api.Credentials=this.Credentials,!0},e.prototype.get=function(e,t,n){try{var r=this.getEndpointInfo(e,t),i=this._api.getCancellableToken(),o=Object.assign({},n);o.cancellableToken=i;var s=this._api.get(r,o);return this._api.updateRequestToBeCancellable(s,i),s}catch(e){return Promise.reject(e.message)}},e.prototype.post=function(e,t,n){try{var r=this.getEndpointInfo(e,t),i=this._api.getCancellableToken(),o=Object.assign({},n);o.cancellableToken=i;var s=this._api.post(r,o);return this._api.updateRequestToBeCancellable(s,i),s}catch(e){return Promise.reject(e.message)}},e.prototype.put=function(e,t,n){try{var r=this.getEndpointInfo(e,t),i=this._api.getCancellableToken(),o=Object.assign({},n);o.cancellableToken=i;var s=this._api.put(r,o);return this._api.updateRequestToBeCancellable(s,i),s}catch(e){return Promise.reject(e.message)}},e.prototype.patch=function(e,t,n){try{var r=this.getEndpointInfo(e,t),i=this._api.getCancellableToken(),o=Object.assign({},n);o.cancellableToken=i;var s=this._api.patch(r,o);return this._api.updateRequestToBeCancellable(s,i),s}catch(e){return Promise.reject(e.message)}},e.prototype.del=function(e,t,n){try{var r=this.getEndpointInfo(e,t),i=this._api.getCancellableToken(),o=Object.assign({},n);o.cancellableToken=i;var s=this._api.del(r,o);return this._api.updateRequestToBeCancellable(s,i),s}catch(e){return Promise.reject(e.message)}},e.prototype.head=function(e,t,n){try{var r=this.getEndpointInfo(e,t),i=this._api.getCancellableToken(),o=Object.assign({},n);o.cancellableToken=i;var s=this._api.head(r,o);return this._api.updateRequestToBeCancellable(s,i),s}catch(e){return Promise.reject(e.message)}},e.prototype.isCancel=function(e){return this._api.isCancel(e)},e.prototype.cancel=function(e,t){return this._api.cancel(e,t)},e.prototype.endpoint=function(e){return f(this,void 0,void 0,(function(){return l(this,(function(t){return[2,this._api.endpoint(e)]}))}))},e.prototype.getEndpointInfo=function(e,t){var n=this._options.endpoints;if(!Array.isArray(n))throw new Error("API category not configured");var r=n.find((function(t){return t.name===e}));if(!r)throw new Error("API "+e+" does not exist");var i={endpoint:r.endpoint+t};return"string"==typeof r.region?i.region=r.region:"string"==typeof this._options.region&&(i.region=this._options.region),"string"==typeof r.service?i.service=r.service||"execute-api":i.service="execute-api","function"==typeof r.custom_header?i.custom_header=r.custom_header:i.custom_header=void 0,i},e}(),v=new p(null);u.a.register(v);var g=n(248),m=function(){return(m=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},b=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},y=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},w=new s.a("API"),_=function(){function e(e){this.Auth=r.a,this.Cache=i.a,this.Credentials=a.a,this._options=e,this._restApi=new p(e),this._graphqlApi=new g.a(e),w.debug("API Options",this._options)}return e.prototype.getModuleName=function(){return"API"},e.prototype.configure=function(e){this._options=Object.assign({},this._options,e),this._restApi.Credentials=this.Credentials,this._graphqlApi.Auth=this.Auth,this._graphqlApi.Cache=this.Cache,this._graphqlApi.Credentials=this.Credentials;var t=this._restApi.configure(this._options),n=this._graphqlApi.configure(this._options);return m(m({},t),n)},e.prototype.get=function(e,t,n){return this._restApi.get(e,t,n)},e.prototype.post=function(e,t,n){return this._restApi.post(e,t,n)},e.prototype.put=function(e,t,n){return this._restApi.put(e,t,n)},e.prototype.patch=function(e,t,n){return this._restApi.patch(e,t,n)},e.prototype.del=function(e,t,n){return this._restApi.del(e,t,n)},e.prototype.head=function(e,t,n){return this._restApi.head(e,t,n)},e.prototype.isCancel=function(e){return this._restApi.isCancel(e)},e.prototype.cancel=function(e,t){return this._restApi.cancel(e,t)},e.prototype.endpoint=function(e){return b(this,void 0,void 0,(function(){return y(this,(function(t){return[2,this._restApi.endpoint(e)]}))}))},e.prototype.getGraphqlOperationType=function(e){return this._graphqlApi.getGraphqlOperationType(e)},e.prototype.graphql=function(e,t){return this._graphqlApi.graphql(e,t)},e}(),S=new _(null);u.a.register(S)},function(e,t,n){"use strict";n.d(t,"a",(function(){return q}));var r=n(12),i=n(44),o=n(88),s=n(89),a=n(221),u=n(146),c=n(86),f=n(33);var l,d=n(19),h=n(30),p=n(16),v=function(e){var t=window.open(e,"_self");return t?Promise.resolve(t):Promise.reject()},g=n(87),m=n.n(g),b=n(90),y=n.n(b),w=function(){return(w=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},_=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},S=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},E=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},M="undefined"!=typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("amplify_default"):"@@amplify_default",A=function(e,t,n){o.a.dispatch("auth",{event:e,data:t,message:n},"Auth",M)},I=new i.a("OAuth"),k=function(){function e(e){var t=e.config,n=e.cognitoClientId,r=e.scopes,i=void 0===r?[]:r;if(this._urlOpener=t.urlOpener||v,this._config=t,this._cognitoClientId=n,!this.isValidScopes(i))throw Error("scopes must be a String Array");this._scopes=i}return e.prototype.isValidScopes=function(e){return Array.isArray(e)&&e.every((function(e){return"string"==typeof e}))},e.prototype.oauthSignIn=function(e,t,n,i,o,s){void 0===e&&(e="code"),void 0===o&&(o=r.b.Cognito);var a=this._generateState(32),u=s?a+"-"+s.split("").map((function(e){return e.charCodeAt(0).toString(16).padStart(2,"0")})).join(""):a;!function(e){window.sessionStorage.setItem("oauth_state",e)}(u);var c,f=this._generateRandom(128);c=f,window.sessionStorage.setItem("ouath_pkce_key",c);var l=this._generateChallenge(f),d=this._scopes.join(" "),h="https://"+t+"/oauth2/authorize?"+Object.entries(w(w({redirect_uri:n,response_type:e,client_id:i,identity_provider:o,scope:d,state:u},"code"===e?{code_challenge:l}:{}),"code"===e?{code_challenge_method:"S256"}:{})).map((function(e){var t=E(e,2),n=t[0],r=t[1];return encodeURIComponent(n)+"="+encodeURIComponent(r)})).join("&");I.debug("Redirecting to "+h),this._urlOpener(h,n)},e.prototype._handleCodeFlow=function(e){return _(this,void 0,void 0,(function(){var t,n,i,o,s,a,u,c,f,l,d,h;return S(this,(function(v){switch(v.label){case 0:return(t=(Object(p.parse)(e).query||"").split("&").map((function(e){return e.split("=")})).reduce((function(e,t){var n,r=E(t,2),i=r[0],o=r[1];return w(w({},e),((n={})[i]=o,n))}),{code:void 0}).code)&&Object(p.parse)(e).pathname===Object(p.parse)(this._config.redirectSignIn).pathname?(n="https://"+this._config.domain+"/oauth2/token",A("codeFlow",{},"Retrieving tokens from "+n),i=Object(r.d)(this._config)?this._cognitoClientId:this._config.clientID,o=Object(r.d)(this._config)?this._config.redirectSignIn:this._config.redirectUri,g=window.sessionStorage.getItem("ouath_pkce_key"),window.sessionStorage.removeItem("ouath_pkce_key"),a=w({grant_type:"authorization_code",code:t,client_id:i,redirect_uri:o},(s=g)?{code_verifier:s}:{}),I.debug("Calling token endpoint: "+n+" with",a),u=Object.entries(a).map((function(e){var t=E(e,2),n=t[0],r=t[1];return encodeURIComponent(n)+"="+encodeURIComponent(r)})).join("&"),[4,fetch(n,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:u})]):[2];case 1:return[4,v.sent().json()];case 2:if(c=v.sent(),f=c.access_token,l=c.refresh_token,d=c.id_token,h=c.error)throw new Error(h);return[2,{accessToken:f,refreshToken:l,idToken:d}]}var g}))}))},e.prototype._handleImplicitFlow=function(e){return _(this,void 0,void 0,(function(){var t,n,r;return S(this,(function(i){return t=(Object(p.parse)(e).hash||"#").substr(1).split("&").map((function(e){return e.split("=")})).reduce((function(e,t){var n,r=E(t,2),i=r[0],o=r[1];return w(w({},e),((n={})[i]=o,n))}),{id_token:void 0,access_token:void 0}),n=t.id_token,r=t.access_token,A("implicitFlow",{},"Got tokens from "+e),I.debug("Retrieving implicit tokens from "+e+" with"),[2,{accessToken:r,idToken:n,refreshToken:null}]}))}))},e.prototype.handleAuthResponse=function(e){return _(this,void 0,void 0,(function(){var t,n,r,i,o,s,a;return S(this,(function(u){switch(u.label){case 0:if(u.trys.push([0,5,,6]),t=e?w(w({},(Object(p.parse)(e).hash||"#").substr(1).split("&").map((function(e){return e.split("=")})).reduce((function(e,t){var n=E(t,2),r=n[0],i=n[1];return e[r]=i,e}),{})),(Object(p.parse)(e).query||"").split("&").map((function(e){return e.split("=")})).reduce((function(e,t){var n=E(t,2),r=n[0],i=n[1];return e[r]=i,e}),{})):{},n=t.error,r=t.error_description,n)throw new Error(r);return i=this._validateState(t),I.debug("Starting "+this._config.responseType+" flow with "+e),"code"!==this._config.responseType?[3,2]:(o=[{}],[4,this._handleCodeFlow(e)]);case 1:return[2,w.apply(void 0,[w.apply(void 0,o.concat([u.sent()])),{state:i}])];case 2:return s=[{}],[4,this._handleImplicitFlow(e)];case 3:return[2,w.apply(void 0,[w.apply(void 0,s.concat([u.sent()])),{state:i}])];case 4:return[3,6];case 5:throw a=u.sent(),I.error("Error handling auth response.",a),a;case 6:return[2]}}))}))},e.prototype._validateState=function(e){if(e){var t,n=(t=window.sessionStorage.getItem("oauth_state"),window.sessionStorage.removeItem("oauth_state"),t),r=e.state;if(n&&n!==r)throw new Error("Invalid state in OAuth flow");return r}},e.prototype.signOut=function(){return _(this,void 0,void 0,(function(){var e,t,n;return S(this,(function(i){return e="https://"+this._config.domain+"/logout?",t=Object(r.d)(this._config)?this._cognitoClientId:this._config.oauth.clientID,n=Object(r.d)(this._config)?this._config.redirectSignOut:this._config.returnTo,e+=Object.entries({client_id:t,logout_uri:encodeURIComponent(n)}).map((function(e){var t=E(e,2);return t[0]+"="+t[1]})).join("&"),A("oAuthSignOut",{oAuth:"signOut"},"Signing out from "+e),I.debug("Signing out from "+e),[2,this._urlOpener(e)]}))}))},e.prototype._generateState=function(e){for(var t="",n=e,r="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";n>0;--n)t+=r[Math.round(Math.random()*(r.length-1))];return t},e.prototype._generateChallenge=function(e){return this._base64URL(m()(e))},e.prototype._base64URL=function(e){return e.toString(y.a).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")},e.prototype._generateRandom=function(e){var t=new Uint8Array(e);if("undefined"!=typeof window&&window.crypto)window.crypto.getRandomValues(t);else for(var n=0;n<e;n+=1)t[n]=Math.random()*"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~".length|0;return this._bufferToString(t)},e.prototype._bufferToString=function(e){for(var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",n=[],r=0;r<e.byteLength;r+=1){var i=e[r]%t.length;n.push(t[i])}return n.join("")},e}(),O=n(35),x=(l=function(e,t){return(l=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}l(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),C=new i.a("AuthError"),T=function(e){function t(n){var r=this,i=N[n],o=i.message,s=i.log;return(r=e.call(this,o)||this).constructor=t,Object.setPrototypeOf(r,t.prototype),r.name="AuthError",r.log=s||o,C.error(r.log),r}return x(t,e),t}(Error),P=function(e){function t(n){var r=e.call(this,n)||this;return r.constructor=t,Object.setPrototypeOf(r,t.prototype),r.name="NoUserPoolError",r}return x(t,e),t}(T),N={noConfig:{message:O.a.DEFAULT_MSG,log:"\n Error: Amplify has not been configured correctly.\n This error is typically caused by one of the following scenarios:\n\n 1. Make sure you're passing the awsconfig object to Amplify.configure() in your app's entry point\n See https://aws-amplify.github.io/docs/js/authentication#configure-your-app for more information\n \n 2. There might be multiple conflicting versions of aws-amplify or amplify packages in your node_modules.\n Try deleting your node_modules folder and reinstalling the dependencies with `yarn install`\n "},missingAuthConfig:{message:O.a.DEFAULT_MSG,log:"\n Error: Amplify has not been configured correctly. \n The configuration object is missing required auth properties. \n Did you run `amplify push` after adding auth via `amplify add auth`?\n See https://aws-amplify.github.io/docs/js/authentication#amplify-project-setup for more information\n "},emptyUsername:{message:O.a.EMPTY_USERNAME},invalidUsername:{message:O.a.INVALID_USERNAME},emptyPassword:{message:O.a.EMPTY_PASSWORD},emptyCode:{message:O.a.EMPTY_CODE},signUpError:{message:O.a.SIGN_UP_ERROR,log:"The first parameter should either be non-null string or object"},noMFA:{message:O.a.NO_MFA},invalidMFA:{message:O.a.INVALID_MFA},emptyChallengeResponse:{message:O.a.EMPTY_CHALLENGE},noUserSession:{message:O.a.NO_USER_SESSION},default:{message:O.a.DEFAULT_MSG}};function R(e){return(R="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var L=function(){return(L=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},j=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},D=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},U=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},B=new i.a("AuthClass"),F="undefined"!=typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("amplify_default"):"@@amplify_default",z=function(e,t,n){o.a.dispatch("auth",{event:e,data:t,message:n},"Auth",F)},q=new(function(){function e(e){var t=this;this.userPool=null,this.user=null,this.oAuthFlowInProgress=!1,this.Credentials=s.a,this.wrapRefreshSessionCallback=function(e){return function(t,n){return n?z("tokenRefresh",void 0,"New token retrieved"):z("tokenRefresh_failure",t,"Failed to retrieve new token"),e(t,n)}},this.configure(e),this.currentCredentials=this.currentCredentials.bind(this),this.currentUserCredentials=this.currentUserCredentials.bind(this),o.a.listen("auth",(function(e){switch(e.payload.event){case"signIn":t._storage.setItem("amplify-signin-with-hostedUI","false");break;case"signOut":t._storage.removeItem("amplify-signin-with-hostedUI");break;case"cognitoHostedUI":t._storage.setItem("amplify-signin-with-hostedUI","true")}}))}return e.prototype.getModuleName=function(){return"Auth"},e.prototype.configure=function(e){var t=this;if(!e)return this._config||{};B.debug("configure Auth");var n=Object.assign({},this._config,a.a.parseMobilehubConfig(e).Auth,e);this._config=n;var i=this._config,o=i.userPoolId,s=i.userPoolWebClientId,l=i.cookieStorage,d=i.oauth,p=i.region,v=i.identityPoolId,g=i.mandatorySignIn,m=i.refreshHandlers,b=i.identityPoolRegion,y=i.clientMetadata,w=i.endpoint;if(this._config.storage){if(!this._isValidAuthStorage(this._config.storage))throw B.error("The storage in the Auth config is not valid!"),new Error("Empty storage object");this._storage=this._config.storage}else this._storage=l?new h.i(l):e.ssr?new u.a:(new c.a).getStorage();if(this._storageSync=Promise.resolve(),"function"==typeof this._storage.sync&&(this._storageSync=this._storage.sync()),o){var _={UserPoolId:o,ClientId:s,endpoint:w};_.Storage=this._storage,this.userPool=new h.g(_,this.wrapRefreshSessionCallback)}this.Credentials.configure({mandatorySignIn:g,region:b||p,userPoolId:o,identityPoolId:v,refreshHandlers:m,storage:this._storage});var S=d?Object(r.d)(this._config.oauth)?d:d.awsCognito:void 0;if(S){var E=Object.assign({cognitoClientId:s,UserPoolId:o,domain:S.domain,scopes:S.scope,redirectSignIn:S.redirectSignIn,redirectSignOut:S.redirectSignOut,responseType:S.responseType,Storage:this._storage,urlOpener:S.urlOpener,clientMetadata:y},S.options);this._oAuthHandler=new k({scopes:E.scopes,config:E,cognitoClientId:E.cognitoClientId});var M={};!function(e){if(f.a.browserOrNode().isBrowser&&window.location)e({url:window.location.href});else if(!f.a.browserOrNode().isNode)throw new Error("Not supported")}((function(e){var n=e.url;M[n]||(M[n]=!0,t._handleAuthResponse(n))}))}return z("configured",null,"The Auth category has been configured successfully"),this._config},e.prototype.signUp=function(e){for(var t=this,n=[],i=1;i<arguments.length;i++)n[i-1]=arguments[i];if(!this.userPool)return this.rejectNoUserPool();var o,s=null,a=null,u=[],c=null;if(e&&"string"==typeof e){s=e,a=n?n[0]:null;var f=n?n[1]:null,l=n?n[2]:null;f&&u.push(new h.f({Name:"email",Value:f})),l&&u.push(new h.f({Name:"phone_number",Value:l}))}else{if(!e||"object"!==R(e))return this.rejectAuthError(r.a.SignUpError);s=e.username,a=e.password,e&&e.clientMetadata?o=e.clientMetadata:this._config.clientMetadata&&(o=this._config.clientMetadata);var d=e.attributes;d&&Object.keys(d).map((function(e){u.push(new h.f({Name:e,Value:d[e]}))}));var p=e.validationData;p&&(c=[],Object.keys(p).map((function(e){c.push(new h.f({Name:e,Value:d[e]}))})))}return s?a?(B.debug("signUp attrs:",u),B.debug("signUp validation data:",c),new Promise((function(e,n){t.userPool.signUp(s,a,u,c,(function(t,r){t?(z("signUp_failure",t,s+" failed to signup"),n(t)):(z("signUp",r,s+" has signed up successfully"),e(r))}),o)}))):this.rejectAuthError(r.a.EmptyPassword):this.rejectAuthError(r.a.EmptyUsername)},e.prototype.confirmSignUp=function(e,t,n){if(!this.userPool)return this.rejectNoUserPool();if(!e)return this.rejectAuthError(r.a.EmptyUsername);if(!t)return this.rejectAuthError(r.a.EmptyCode);var i,o=this.createCognitoUser(e),s=!n||"boolean"!=typeof n.forceAliasCreation||n.forceAliasCreation;return n&&n.clientMetadata?i=n.clientMetadata:this._config.clientMetadata&&(i=this._config.clientMetadata),new Promise((function(e,n){o.confirmRegistration(t,s,(function(t,r){t?n(t):e(r)}),i)}))},e.prototype.resendSignUp=function(e,t){if(void 0===t&&(t=this._config.clientMetadata),!this.userPool)return this.rejectNoUserPool();if(!e)return this.rejectAuthError(r.a.EmptyUsername);var n=this.createCognitoUser(e);return new Promise((function(e,r){n.resendConfirmationCode((function(t,n){t?r(t):e(n)}),t)}))},e.prototype.signIn=function(e,t,n){if(void 0===n&&(n=this._config.clientMetadata),!this.userPool)return this.rejectNoUserPool();var i=null,o=null,s={};if("string"==typeof e)i=e,o=t;else{if(!Object(r.g)(e))return this.rejectAuthError(r.a.InvalidUsername);void 0!==t&&B.warn("The password should be defined under the first parameter object!"),i=e.username,o=e.password,s=e.validationData}if(!i)return this.rejectAuthError(r.a.EmptyUsername);var a=new h.a({Username:i,Password:o,ValidationData:s,ClientMetadata:n});return o?this.signInWithPassword(a):this.signInWithoutPassword(a)},e.prototype.authCallbacks=function(e,t,n){var r=this,i=this;return{onSuccess:function(o){return j(r,void 0,void 0,(function(){var r,s,a,u;return D(this,(function(c){switch(c.label){case 0:B.debug(o),delete e.challengeName,delete e.challengeParam,c.label=1;case 1:return c.trys.push([1,4,5,9]),[4,this.Credentials.clear()];case 2:return c.sent(),[4,this.Credentials.set(o,"session")];case 3:return r=c.sent(),B.debug("succeed to get cognito credentials",r),[3,9];case 4:return s=c.sent(),B.debug("cannot get cognito credentials",s),[3,9];case 5:return c.trys.push([5,7,,8]),[4,this.currentUserPoolUser()];case 6:return a=c.sent(),i.user=a,z("signIn",a,"A user "+e.getUsername()+" has been signed in"),t(a),[3,8];case 7:return u=c.sent(),B.error("Failed to get the signed in user",u),n(u),[3,8];case 8:return[7];case 9:return[2]}}))}))},onFailure:function(t){B.debug("signIn failure",t),z("signIn_failure",t,e.getUsername()+" failed to signin"),n(t)},customChallenge:function(n){B.debug("signIn custom challenge answer required"),e.challengeName="CUSTOM_CHALLENGE",e.challengeParam=n,t(e)},mfaRequired:function(n,r){B.debug("signIn MFA required"),e.challengeName=n,e.challengeParam=r,t(e)},mfaSetup:function(n,r){B.debug("signIn mfa setup",n),e.challengeName=n,e.challengeParam=r,t(e)},newPasswordRequired:function(n,r){B.debug("signIn new password"),e.challengeName="NEW_PASSWORD_REQUIRED",e.challengeParam={userAttributes:n,requiredAttributes:r},t(e)},totpRequired:function(n,r){B.debug("signIn totpRequired"),e.challengeName=n,e.challengeParam=r,t(e)},selectMFAType:function(n,r){B.debug("signIn selectMFAType",n),e.challengeName=n,e.challengeParam=r,t(e)}}},e.prototype.signInWithPassword=function(e){var t=this;if(this.pendingSignIn)throw new Error("Pending sign-in attempt already in progress");var n=this.createCognitoUser(e.getUsername());return this.pendingSignIn=new Promise((function(r,i){n.authenticateUser(e,t.authCallbacks(n,(function(e){t.pendingSignIn=null,r(e)}),(function(e){t.pendingSignIn=null,i(e)})))})),this.pendingSignIn},e.prototype.signInWithoutPassword=function(e){var t=this,n=this.createCognitoUser(e.getUsername());return n.setAuthenticationFlowType("CUSTOM_AUTH"),new Promise((function(r,i){n.initiateAuth(e,t.authCallbacks(n,r,i))}))},e.prototype.getMFAOptions=function(e){return new Promise((function(t,n){e.getMFAOptions((function(e,r){if(e)return B.debug("get MFA Options failed",e),void n(e);B.debug("get MFA options success",r),t(r)}))}))},e.prototype.getPreferredMFA=function(e,t){var n=this,r=this;return new Promise((function(i,o){var s=n._config.clientMetadata,a=!!t&&t.bypassCache;e.getUserData((function(e,t){if(e)return B.debug("getting preferred mfa failed",e),void o(e);var n=r._getMfaTypeFromUserData(t);return n?void i(n):void o("invalid MFA Type")}),{bypassCache:a,clientMetadata:s})}))},e.prototype._getMfaTypeFromUserData=function(e){var t=null,n=e.PreferredMfaSetting;if(n)t=n;else{var r=e.UserMFASettingList;if(r)0===r.length?t="NOMFA":B.debug("invalid case for getPreferredMFA",e);else t=e.MFAOptions?"SMS_MFA":"NOMFA"}return t},e.prototype._getUserData=function(e,t){return new Promise((function(n,r){e.getUserData((function(e,t){return e?(B.debug("getting user data failed",e),void r(e)):void n(t)}),t)}))},e.prototype.setPreferredMFA=function(e,t){return j(this,void 0,void 0,(function(){var n,i,o,s,a,u;return D(this,(function(c){switch(c.label){case 0:return n=this._config.clientMetadata,[4,this._getUserData(e,{bypassCache:!0,clientMetadata:n})];case 1:switch(i=c.sent(),o=null,s=null,t){case"TOTP":return[3,2];case"SMS":return[3,3];case"NOMFA":return[3,4]}return[3,6];case 2:return s={PreferredMfa:!0,Enabled:!0},[3,7];case 3:return o={PreferredMfa:!0,Enabled:!0},[3,7];case 4:return a=i.UserMFASettingList,[4,this._getMfaTypeFromUserData(i)];case 5:if("NOMFA"===(u=c.sent()))return[2,Promise.resolve("No change for mfa type")];if("SMS_MFA"===u)o={PreferredMfa:!1,Enabled:!1};else{if("SOFTWARE_TOKEN_MFA"!==u)return[2,this.rejectAuthError(r.a.InvalidMFA)];s={PreferredMfa:!1,Enabled:!1}}return a&&0!==a.length&&a.forEach((function(e){"SMS_MFA"===e?o={PreferredMfa:!1,Enabled:!1}:"SOFTWARE_TOKEN_MFA"===e&&(s={PreferredMfa:!1,Enabled:!1})})),[3,7];case 6:return B.debug("no validmfa method provided"),[2,this.rejectAuthError(r.a.NoMFA)];case 7:return this,[2,new Promise((function(t,r){e.setUserMfaPreference(o,s,(function(i,o){if(i)return B.debug("Set user mfa preference error",i),r(i);B.debug("Set user mfa success",o),B.debug("Caching the latest user data into local"),e.getUserData((function(e,n){return e?(B.debug("getting user data failed",e),r(e)):t(o)}),{bypassCache:!0,clientMetadata:n})}))}))]}}))}))},e.prototype.disableSMS=function(e){return new Promise((function(t,n){e.disableMFA((function(e,r){if(e)return B.debug("disable mfa failed",e),void n(e);B.debug("disable mfa succeed",r),t(r)}))}))},e.prototype.enableSMS=function(e){return new Promise((function(t,n){e.enableMFA((function(e,r){if(e)return B.debug("enable mfa failed",e),void n(e);B.debug("enable mfa succeed",r),t(r)}))}))},e.prototype.setupTOTP=function(e){return new Promise((function(t,n){e.associateSoftwareToken({onFailure:function(e){B.debug("associateSoftwareToken failed",e),n(e)},associateSecretCode:function(e){B.debug("associateSoftwareToken sucess",e),t(e)}})}))},e.prototype.verifyTotpToken=function(e,t){return B.debug("verification totp token",e,t),new Promise((function(n,r){e.verifySoftwareToken(t,"My TOTP device",{onFailure:function(e){B.debug("verifyTotpToken failed",e),r(e)},onSuccess:function(t){z("signIn",e,"A user "+e.getUsername()+" has been signed in"),B.debug("verifyTotpToken success",t),n(t)}})}))},e.prototype.confirmSignIn=function(e,t,n,i){var o=this;if(void 0===i&&(i=this._config.clientMetadata),!t)return this.rejectAuthError(r.a.EmptyCode);var s=this;return new Promise((function(r,a){e.sendMFACode(t,{onSuccess:function(t){return j(o,void 0,void 0,(function(){var n,i;return D(this,(function(o){switch(o.label){case 0:B.debug(t),o.label=1;case 1:return o.trys.push([1,4,5,6]),[4,this.Credentials.clear()];case 2:return o.sent(),[4,this.Credentials.set(t,"session")];case 3:return n=o.sent(),B.debug("succeed to get cognito credentials",n),[3,6];case 4:return i=o.sent(),B.debug("cannot get cognito credentials",i),[3,6];case 5:return s.user=e,z("signIn",e,"A user "+e.getUsername()+" has been signed in"),r(e),[7];case 6:return[2]}}))}))},onFailure:function(e){B.debug("confirm signIn failure",e),a(e)}},n,i)}))},e.prototype.completeNewPassword=function(e,t,n,i){var o=this;if(void 0===n&&(n={}),void 0===i&&(i=this._config.clientMetadata),!t)return this.rejectAuthError(r.a.EmptyPassword);var s=this;return new Promise((function(r,a){e.completeNewPasswordChallenge(t,n,{onSuccess:function(t){return j(o,void 0,void 0,(function(){var n,i;return D(this,(function(o){switch(o.label){case 0:B.debug(t),o.label=1;case 1:return o.trys.push([1,4,5,6]),[4,this.Credentials.clear()];case 2:return o.sent(),[4,this.Credentials.set(t,"session")];case 3:return n=o.sent(),B.debug("succeed to get cognito credentials",n),[3,6];case 4:return i=o.sent(),B.debug("cannot get cognito credentials",i),[3,6];case 5:return s.user=e,z("signIn",e,"A user "+e.getUsername()+" has been signed in"),r(e),[7];case 6:return[2]}}))}))},onFailure:function(e){B.debug("completeNewPassword failure",e),z("completeNewPassword_failure",e,o.user+" failed to complete the new password flow"),a(e)},mfaRequired:function(t,n){B.debug("signIn MFA required"),e.challengeName=t,e.challengeParam=n,r(e)},mfaSetup:function(t,n){B.debug("signIn mfa setup",t),e.challengeName=t,e.challengeParam=n,r(e)},totpRequired:function(t,n){B.debug("signIn mfa setup",t),e.challengeName=t,e.challengeParam=n,r(e)}},i)}))},e.prototype.sendCustomChallengeAnswer=function(e,t,n){var i=this;if(void 0===n&&(n=this._config.clientMetadata),!this.userPool)return this.rejectNoUserPool();if(!t)return this.rejectAuthError(r.a.EmptyChallengeResponse);return new Promise((function(r,o){e.sendCustomChallengeAnswer(t,i.authCallbacks(e,r,o),n)}))},e.prototype.updateUserAttributes=function(e,t,n){void 0===n&&(n=this._config.clientMetadata);var r=[],i=this;return new Promise((function(o,s){i.userSession(e).then((function(i){for(var a in t)if("sub"!==a&&a.indexOf("_verified")<0){var u={Name:a,Value:t[a]};r.push(u)}e.updateAttributes(r,(function(e,t){return e?s(e):o(t)}),n)}))}))},e.prototype.userAttributes=function(e){var t=this;return new Promise((function(n,r){t.userSession(e).then((function(t){e.getUserAttributes((function(e,t){e?r(e):n(t)}))}))}))},e.prototype.verifiedContact=function(e){var t=this;return this.userAttributes(e).then((function(e){var n=t.attributesToObject(e),r={},i={};return n.email&&(n.email_verified?i.email=n.email:r.email=n.email),n.phone_number&&(n.phone_number_verified?i.phone_number=n.phone_number:r.phone_number=n.phone_number),{verified:i,unverified:r}}))},e.prototype.currentUserPoolUser=function(e){var t=this;return this.userPool?new Promise((function(n,r){t._storageSync.then((function(){return j(t,void 0,void 0,(function(){var t,i,s=this;return D(this,(function(a){switch(a.label){case 0:return this.isOAuthInProgress()?(B.debug("OAuth signIn in progress, waiting for resolution..."),[4,new Promise((function(e){var t=setTimeout((function(){B.debug("OAuth signIn in progress timeout"),o.a.remove("auth",n),e()}),1e4);function n(r){var i=r.payload.event;"cognitoHostedUI"!==i&&"cognitoHostedUI_failure"!==i||(B.debug("OAuth signIn resolved: "+i),clearTimeout(t),o.a.remove("auth",n),e())}o.a.listen("auth",n)}))]):[3,2];case 1:a.sent(),a.label=2;case 2:return(t=this.userPool.getCurrentUser())?(i=this._config.clientMetadata,t.getSession((function(i,o){return j(s,void 0,void 0,(function(){var s,a,u,c=this;return D(this,(function(f){switch(f.label){case 0:return i?(B.debug("Failed to get the user session",i),r(i),[2]):(s=!!e&&e.bypassCache)?[4,this.Credentials.clear()]:[3,2];case 1:f.sent(),f.label=2;case 2:return a=this._config.clientMetadata,u=o.getAccessToken().decodePayload().scope,(void 0===u?"":u).split(" ").includes("aws.cognito.signin.user.admin")?(t.getUserData((function(e,i){if(e)return B.debug("getting user data failed",e),void("User is disabled."===e.message||"User does not exist."===e.message||"Access Token has been revoked"===e.message?r(e):n(t));for(var o=i.PreferredMfaSetting||"NOMFA",s=[],a=0;a<i.UserAttributes.length;a++){var u={Name:i.UserAttributes[a].Name,Value:i.UserAttributes[a].Value},f=new h.f(u);s.push(f)}var l=c.attributesToObject(s);return Object.assign(t,{attributes:l,preferredMFA:o}),n(t)}),{bypassCache:s,clientMetadata:a}),[2]):(B.debug("Unable to get the user data because the aws.cognito.signin.user.admin is not in the scopes of the access token"),[2,n(t)])}}))}))}),{clientMetadata:i}),[2]):(B.debug("Failed to get user from user pool"),r("No current user"),[2])}}))}))})).catch((function(e){return B.debug("Failed to sync cache info into memory",e),r(e)}))})):this.rejectNoUserPool()},e.prototype.isOAuthInProgress=function(){return this.oAuthFlowInProgress},e.prototype.currentAuthenticatedUser=function(e){return j(this,void 0,void 0,(function(){var t,n,r,i,o;return D(this,(function(s){switch(s.label){case 0:B.debug("getting current authenticated user"),t=null,s.label=1;case 1:return s.trys.push([1,3,,4]),[4,this._storageSync];case 2:return s.sent(),[3,4];case 3:throw n=s.sent(),B.debug("Failed to sync cache info into memory",n),n;case 4:try{(r=JSON.parse(this._storage.getItem("aws-amplify-federatedInfo")))&&(t=L(L({},r.user),{token:r.token}))}catch(e){B.debug("cannot load federated user from auth storage")}return t?(this.user=t,B.debug("get current authenticated federated user",this.user),[2,this.user]):[3,5];case 5:B.debug("get current authenticated userpool user"),i=null,s.label=6;case 6:return s.trys.push([6,8,,9]),[4,this.currentUserPoolUser(e)];case 7:return i=s.sent(),[3,9];case 8:return"No userPool"===(o=s.sent())&&B.error("Cannot get the current user because the user pool is missing. Please make sure the Auth module is configured with a valid Cognito User Pool ID"),B.debug("The user is not authenticated by the error",o),[2,Promise.reject("The user is not authenticated")];case 9:return this.user=i,[2,this.user]}}))}))},e.prototype.currentSession=function(){var e=this;return B.debug("Getting current session"),this.userPool?new Promise((function(t,n){e.currentUserPoolUser().then((function(r){e.userSession(r).then((function(e){t(e)})).catch((function(e){B.debug("Failed to get the current session",e),n(e)}))})).catch((function(e){B.debug("Failed to get the current user",e),n(e)}))})):Promise.reject()},e.prototype.userSession=function(e){if(!e)return B.debug("the user is null"),this.rejectAuthError(r.a.NoUserSession);var t=this._config.clientMetadata;return new Promise((function(n,r){B.debug("Getting the session from this user:",e),e.getSession((function(t,i){return t?(B.debug("Failed to get the session from user",e),void r(t)):(B.debug("Succeed to get the user session",i),void n(i))}),{clientMetadata:t})}))},e.prototype.currentUserCredentials=function(){return j(this,void 0,void 0,(function(){var e,t,n=this;return D(this,(function(r){switch(r.label){case 0:B.debug("Getting current user credentials"),r.label=1;case 1:return r.trys.push([1,3,,4]),[4,this._storageSync];case 2:return r.sent(),[3,4];case 3:throw e=r.sent(),B.debug("Failed to sync cache info into memory",e),e;case 4:t=null;try{t=JSON.parse(this._storage.getItem("aws-amplify-federatedInfo"))}catch(e){B.debug("failed to get or parse item aws-amplify-federatedInfo",e)}return t?[2,this.Credentials.refreshFederatedToken(t)]:[2,this.currentSession().then((function(e){return B.debug("getting session success",e),n.Credentials.set(e,"session")})).catch((function(e){return B.debug("getting session failed",e),n.Credentials.set(null,"guest")}))]}}))}))},e.prototype.currentCredentials=function(){return B.debug("getting current credentials"),this.Credentials.get()},e.prototype.verifyUserAttribute=function(e,t,n){return void 0===n&&(n=this._config.clientMetadata),new Promise((function(r,i){e.getAttributeVerificationCode(t,{onSuccess:function(){return r()},onFailure:function(e){return i(e)}},n)}))},e.prototype.verifyUserAttributeSubmit=function(e,t,n){return n?new Promise((function(r,i){e.verifyAttribute(t,n,{onSuccess:function(e){r(e)},onFailure:function(e){i(e)}})})):this.rejectAuthError(r.a.EmptyCode)},e.prototype.verifyCurrentUserAttribute=function(e){var t=this;return t.currentUserPoolUser().then((function(n){return t.verifyUserAttribute(n,e)}))},e.prototype.verifyCurrentUserAttributeSubmit=function(e,t){var n=this;return n.currentUserPoolUser().then((function(r){return n.verifyUserAttributeSubmit(r,e,t)}))},e.prototype.cognitoIdentitySignOut=function(e,t){return j(this,void 0,void 0,(function(){var n,r,i=this;return D(this,(function(o){switch(o.label){case 0:return o.trys.push([0,2,,3]),[4,this._storageSync];case 1:return o.sent(),[3,3];case 2:throw n=o.sent(),B.debug("Failed to sync cache info into memory",n),n;case 3:return r=this._oAuthHandler&&"true"===this._storage.getItem("amplify-signin-with-hostedUI"),[2,new Promise((function(n,o){if(e&&e.global){B.debug("user global sign out",t);var s=i._config.clientMetadata;t.getSession((function(e,s){if(e)return B.debug("failed to get the user session",e),o(e);t.globalSignOut({onSuccess:function(e){if(B.debug("global sign out success"),!r)return n();i.oAuthSignOutRedirect(n,o)},onFailure:function(e){return B.debug("global sign out failed",e),o(e)}})}),{clientMetadata:s})}else{if(B.debug("user sign out",t),t.signOut(),!r)return n();i.oAuthSignOutRedirect(n,o)}}))]}}))}))},e.prototype.oAuthSignOutRedirect=function(e,t){f.a.browserOrNode().isBrowser?this.oAuthSignOutRedirectOrReject(t):this.oAuthSignOutAndResolve(e)},e.prototype.oAuthSignOutAndResolve=function(e){this._oAuthHandler.signOut(),e()},e.prototype.oAuthSignOutRedirectOrReject=function(e){this._oAuthHandler.signOut(),setTimeout((function(){return e("Signout timeout fail")}),3e3)},e.prototype.signOut=function(e){return j(this,void 0,void 0,(function(){var t;return D(this,(function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,this.cleanCachedItems()];case 1:return n.sent(),[3,3];case 2:return n.sent(),B.debug("failed to clear cached items"),[3,3];case 3:return this.userPool?(t=this.userPool.getCurrentUser())?[4,this.cognitoIdentitySignOut(e,t)]:[3,5]:[3,7];case 4:return n.sent(),[3,6];case 5:B.debug("no current Cognito user"),n.label=6;case 6:return[3,8];case 7:B.debug("no Congito User pool"),n.label=8;case 8:return z("signOut",this.user,"A user has been signed out"),this.user=null,[2]}}))}))},e.prototype.cleanCachedItems=function(){return j(this,void 0,void 0,(function(){return D(this,(function(e){switch(e.label){case 0:return[4,this.Credentials.clear()];case 1:return e.sent(),[2]}}))}))},e.prototype.changePassword=function(e,t,n,r){var i=this;return void 0===r&&(r=this._config.clientMetadata),new Promise((function(o,s){i.userSession(e).then((function(i){e.changePassword(t,n,(function(e,t){return e?(B.debug("change password failure",e),s(e)):o(t)}),r)}))}))},e.prototype.forgotPassword=function(e,t){if(void 0===t&&(t=this._config.clientMetadata),!this.userPool)return this.rejectNoUserPool();if(!e)return this.rejectAuthError(r.a.EmptyUsername);var n=this.createCognitoUser(e);return new Promise((function(r,i){n.forgotPassword({onSuccess:function(){r()},onFailure:function(t){B.debug("forgot password failure",t),z("forgotPassword_failure",t,e+" forgotPassword failed"),i(t)},inputVerificationCode:function(t){z("forgotPassword",n,e+" has initiated forgot password flow"),r(t)}},t)}))},e.prototype.forgotPasswordSubmit=function(e,t,n,i){if(void 0===i&&(i=this._config.clientMetadata),!this.userPool)return this.rejectNoUserPool();if(!e)return this.rejectAuthError(r.a.EmptyUsername);if(!t)return this.rejectAuthError(r.a.EmptyCode);if(!n)return this.rejectAuthError(r.a.EmptyPassword);var o=this.createCognitoUser(e);return new Promise((function(r,s){o.confirmPassword(t,n,{onSuccess:function(){z("forgotPasswordSubmit",o,e+" forgotPasswordSubmit successful"),r()},onFailure:function(t){z("forgotPasswordSubmit_failure",t,e+" forgotPasswordSubmit failed"),s(t)}},i)}))},e.prototype.currentUserInfo=function(){return j(this,void 0,void 0,(function(){var e,t,n,r,i,o,s;return D(this,(function(a){switch(a.label){case 0:return(e=this.Credentials.getCredSource())&&"aws"!==e&&"userPool"!==e?[3,9]:[4,this.currentUserPoolUser().catch((function(e){return B.debug(e)}))];case 1:if(!(s=a.sent()))return[2,null];a.label=2;case 2:return a.trys.push([2,8,,9]),[4,this.userAttributes(s)];case 3:t=a.sent(),n=this.attributesToObject(t),r=null,a.label=4;case 4:return a.trys.push([4,6,,7]),[4,this.currentCredentials()];case 5:return r=a.sent(),[3,7];case 6:return i=a.sent(),B.debug("Failed to retrieve credentials while getting current user info",i),[3,7];case 7:return[2,{id:r?r.identityId:void 0,username:s.getUsername(),attributes:n}];case 8:return o=a.sent(),B.debug("currentUserInfo error",o),[2,{}];case 9:return"federated"===e?[2,(s=this.user)||{}]:[2]}}))}))},e.prototype.federatedSignIn=function(e,t,n){return j(this,void 0,void 0,(function(){var i,o,s,a,u,c,f,l,d,h,p;return D(this,(function(v){switch(v.label){case 0:if(!this._config.identityPoolId&&!this._config.userPoolId)throw new Error("Federation requires either a User Pool or Identity Pool in config");if(void 0===e&&this._config.identityPoolId&&!this._config.userPoolId)throw new Error("Federation with Identity Pools requires tokens passed as arguments");return Object(r.e)(e)||Object(r.f)(e)||Object(r.c)(e)||void 0===e?(i=e||{provider:r.b.Cognito},u=Object(r.e)(i)?i.provider:i.customProvider,Object(r.e)(i),o=i.customState,this._config.userPoolId&&(s=Object(r.d)(this._config.oauth)?this._config.userPoolWebClientId:this._config.oauth.clientID,a=Object(r.d)(this._config.oauth)?this._config.oauth.redirectSignIn:this._config.oauth.redirectUri,this._oAuthHandler.oauthSignIn(this._config.oauth.responseType,this._config.oauth.domain,a,s,u,o)),[3,4]):[3,1];case 1:u=e;try{(c=JSON.stringify(JSON.parse(this._storage.getItem("aws-amplify-federatedInfo")).user))&&B.warn("There is already a signed in user: "+c+" in your app.\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tYou should not call Auth.federatedSignIn method again as it may cause unexpected behavior.")}catch(e){}return f=t.token,l=t.identity_id,d=t.expires_at,[4,this.Credentials.set({provider:u,token:f,identity_id:l,user:n,expires_at:d},"federation")];case 2:return h=v.sent(),[4,this.currentAuthenticatedUser()];case 3:return p=v.sent(),z("signIn",p,"A user "+p.username+" has been signed in"),B.debug("federated sign in credentials",h),[2,h];case 4:return[2]}}))}))},e.prototype._handleAuthResponse=function(e){return j(this,void 0,void 0,(function(){var t,n,r,i,o,s,a,u,c,l,d,v,g,m;return D(this,(function(b){switch(b.label){case 0:if(this.oAuthFlowInProgress)return B.debug("Skipping URL "+e+" current flow in progress"),[2];b.label=1;case 1:if(b.trys.push([1,,8,9]),this.oAuthFlowInProgress=!0,!this._config.userPoolId)throw new Error("OAuth responses require a User Pool defined in config");if(z("parsingCallbackUrl",{url:e},"The callback url is being parsed"),t=e||(f.a.browserOrNode().isBrowser?window.location.href:""),n=!!(Object(p.parse)(t).query||"").split("&").map((function(e){return e.split("=")})).find((function(e){var t=U(e,1)[0];return"code"===t||"error"===t})),r=!!(Object(p.parse)(t).hash||"#").substr(1).split("&").map((function(e){return e.split("=")})).find((function(e){var t=U(e,1)[0];return"access_token"===t||"error"===t})),!n&&!r)return[3,7];this._storage.setItem("amplify-redirected-from-hosted-ui","true"),b.label=2;case 2:return b.trys.push([2,6,,7]),[4,this._oAuthHandler.handleAuthResponse(t)];case 3:return i=b.sent(),o=i.accessToken,s=i.idToken,a=i.refreshToken,u=i.state,c=new h.h({IdToken:new h.c({IdToken:s}),RefreshToken:new h.d({RefreshToken:a}),AccessToken:new h.b({AccessToken:o})}),l=void 0,this._config.identityPoolId?[4,this.Credentials.set(c,"session")]:[3,5];case 4:l=b.sent(),B.debug("AWS credentials",l),b.label=5;case 5:return d=/-/.test(u),(v=this.createCognitoUser(c.getIdToken().decodePayload()["cognito:username"])).setSignInUserSession(c),window&&void 0!==window.history&&window.history.replaceState({},null,this._config.oauth.redirectSignIn),z("signIn",v,"A user "+v.getUsername()+" has been signed in"),z("cognitoHostedUI",v,"A user "+v.getUsername()+" has been signed in via Cognito Hosted UI"),d&&(g=u.split("-").splice(1).join("-"),z("customOAuthState",g.match(/.{2}/g).map((function(e){return String.fromCharCode(parseInt(e,16))})).join(""),"State for user "+v.getUsername())),[2,l];case 6:return m=b.sent(),B.debug("Error in cognito hosted auth response",m),z("signIn_failure",m,"The OAuth response flow failed"),z("cognitoHostedUI_failure",m,"A failure occurred when returning to the Cognito Hosted UI"),z("customState_failure",m,"A failure occurred when returning state"),[3,7];case 7:return[3,9];case 8:return this.oAuthFlowInProgress=!1,[7];case 9:return[2]}}))}))},e.prototype.essentialCredentials=function(e){return{accessKeyId:e.accessKeyId,sessionToken:e.sessionToken,secretAccessKey:e.secretAccessKey,identityId:e.identityId,authenticated:e.authenticated}},e.prototype.attributesToObject=function(e){var t={};return e&&e.map((function(e){"email_verified"===e.Name||"phone_number_verified"===e.Name?t[e.Name]="true"===e.Value||!0===e.Value:t[e.Name]=e.Value})),t},e.prototype.createCognitoUser=function(e){var t={Username:e,Pool:this.userPool};t.Storage=this._storage;var n=this._config.authenticationFlowType,r=new h.e(t);return n&&r.setAuthenticationFlowType(n),r},e.prototype._isValidAuthStorage=function(e){return!!e&&"function"==typeof e.getItem&&"function"==typeof e.setItem&&"function"==typeof e.removeItem&&"function"==typeof e.clear},e.prototype.noUserPoolErrorHandler=function(e){return!e||e.userPoolId&&e.identityPoolId?r.a.NoConfig:r.a.MissingAuthConfig},e.prototype.rejectAuthError=function(e){return Promise.reject(new T(e))},e.prototype.rejectNoUserPool=function(){var e=this.noUserPoolErrorHandler(this._config);return Promise.reject(new P(e))},e}())(null);d.a.register(q)},function(e,t,n){e.exports=n(465)},function(e,t,n){var r,i; -/*! - * JavaScript Cookie v2.2.1 - * https://github.com/js-cookie/js-cookie - * - * Copyright 2006, 2015 Klaus Hartl & Fagner Brack - * Released under the MIT license - */!function(o){if(void 0===(i="function"==typeof(r=o)?r.call(t,n,t,e):r)||(e.exports=i),!0,e.exports=o(),!!0){var s=window.Cookies,a=window.Cookies=o();a.noConflict=function(){return window.Cookies=s,a}}}((function(){function e(){for(var e=0,t={};e<arguments.length;e++){var n=arguments[e];for(var r in n)t[r]=n[r]}return t}function t(e){return e.replace(/(%[0-9A-Z]{2})+/g,decodeURIComponent)}return function n(r){function i(){}function o(t,n,o){if("undefined"!=typeof document){"number"==typeof(o=e({path:"/"},i.defaults,o)).expires&&(o.expires=new Date(1*new Date+864e5*o.expires)),o.expires=o.expires?o.expires.toUTCString():"";try{var s=JSON.stringify(n);/^[\{\[]/.test(s)&&(n=s)}catch(e){}n=r.write?r.write(n,t):encodeURIComponent(String(n)).replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g,decodeURIComponent),t=encodeURIComponent(String(t)).replace(/%(23|24|26|2B|5E|60|7C)/g,decodeURIComponent).replace(/[\(\)]/g,escape);var a="";for(var u in o)o[u]&&(a+="; "+u,!0!==o[u]&&(a+="="+o[u].split(";")[0]));return document.cookie=t+"="+n+a}}function s(e,n){if("undefined"!=typeof document){for(var i={},o=document.cookie?document.cookie.split("; "):[],s=0;s<o.length;s++){var a=o[s].split("="),u=a.slice(1).join("=");n||'"'!==u.charAt(0)||(u=u.slice(1,-1));try{var c=t(a[0]);if(u=(r.read||r)(u,c)||t(u),n)try{u=JSON.parse(u)}catch(e){}if(i[c]=u,e===c)break}catch(e){}}return e?i[e]:i}}return i.set=o,i.get=function(e){return s(e,!1)},i.getJSON=function(e){return s(e,!0)},i.remove=function(t,n){o(t,"",e(n,{expires:-1}))},i.defaults={},i.withConverter=n,i}((function(){}))}))},function(e,t,n){"use strict";(function(t,r){var i=n(8).Buffer,o=t.crypto||t.msCrypto;o&&o.getRandomValues?e.exports=function(e,t){if(e>4294967295)throw new RangeError("requested too many random bytes");var n=i.allocUnsafe(e);if(e>0)if(e>65536)for(var s=0;s<e;s+=65536)o.getRandomValues(n.slice(s,s+65536));else o.getRandomValues(n);if("function"==typeof t)return r.nextTick((function(){t(null,n)}));return n}:e.exports=function(){throw new Error("Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11")}}).call(this,n(31),n(20))},function(e,t,n){"use strict";var r={};function i(e,t,n){n||(n=Error);var i=function(e){var n,r;function i(n,r,i){return e.call(this,function(e,n,r){return"string"==typeof t?t:t(e,n,r)}(n,r,i))||this}return r=e,(n=i).prototype=Object.create(r.prototype),n.prototype.constructor=n,n.__proto__=r,i}(n);i.prototype.name=n.name,i.prototype.code=e,r[e]=i}function o(e,t){if(Array.isArray(e)){var n=e.length;return e=e.map((function(e){return String(e)})),n>2?"one of ".concat(t," ").concat(e.slice(0,n-1).join(", "),", or ")+e[n-1]:2===n?"one of ".concat(t," ").concat(e[0]," or ").concat(e[1]):"of ".concat(t," ").concat(e[0])}return"of ".concat(t," ").concat(String(e))}i("ERR_INVALID_OPT_VALUE",(function(e,t){return'The value "'+t+'" is invalid for option "'+e+'"'}),TypeError),i("ERR_INVALID_ARG_TYPE",(function(e,t,n){var r,i,s,a;if("string"==typeof t&&(i="not ",t.substr(!s||s<0?0:+s,i.length)===i)?(r="must not be",t=t.replace(/^not /,"")):r="must be",function(e,t,n){return(void 0===n||n>e.length)&&(n=e.length),e.substring(n-t.length,n)===t}(e," argument"))a="The ".concat(e," ").concat(r," ").concat(o(t,"type"));else{var u=function(e,t,n){return"number"!=typeof n&&(n=0),!(n+t.length>e.length)&&-1!==e.indexOf(t,n)}(e,".")?"property":"argument";a='The "'.concat(e,'" ').concat(u," ").concat(r," ").concat(o(t,"type"))}return a+=". Received type ".concat(typeof n)}),TypeError),i("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF"),i("ERR_METHOD_NOT_IMPLEMENTED",(function(e){return"The "+e+" method is not implemented"})),i("ERR_STREAM_PREMATURE_CLOSE","Premature close"),i("ERR_STREAM_DESTROYED",(function(e){return"Cannot call "+e+" after a stream was destroyed"})),i("ERR_MULTIPLE_CALLBACK","Callback called multiple times"),i("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable"),i("ERR_STREAM_WRITE_AFTER_END","write after end"),i("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError),i("ERR_UNKNOWN_ENCODING",(function(e){return"Unknown encoding: "+e}),TypeError),i("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event"),e.exports.codes=r},function(e,t,n){"use strict";(function(t){var r=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=c;var i=n(163),o=n(167);n(7)(c,i);for(var s=r(o.prototype),a=0;a<s.length;a++){var u=s[a];c.prototype[u]||(c.prototype[u]=o.prototype[u])}function c(e){if(!(this instanceof c))return new c(e);i.call(this,e),o.call(this,e),this.allowHalfOpen=!0,e&&(!1===e.readable&&(this.readable=!1),!1===e.writable&&(this.writable=!1),!1===e.allowHalfOpen&&(this.allowHalfOpen=!1,this.once("end",f)))}function f(){this._writableState.ended||t.nextTick(l,this)}function l(e){e.end()}Object.defineProperty(c.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Object.defineProperty(c.prototype,"writableBuffer",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}}),Object.defineProperty(c.prototype,"writableLength",{enumerable:!1,get:function(){return this._writableState.length}}),Object.defineProperty(c.prototype,"destroyed",{enumerable:!1,get:function(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set:function(e){void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed=e,this._writableState.destroyed=e)}})}).call(this,n(20))},function(e,t,n){var r=n(8).Buffer;function i(e,t){this._block=r.alloc(e),this._finalSize=t,this._blockSize=e,this._len=0}i.prototype.update=function(e,t){"string"==typeof e&&(t=t||"utf8",e=r.from(e,t));for(var n=this._block,i=this._blockSize,o=e.length,s=this._len,a=0;a<o;){for(var u=s%i,c=Math.min(o-a,i-u),f=0;f<c;f++)n[u+f]=e[a+f];a+=c,(s+=c)%i==0&&this._update(n)}return this._len+=o,this},i.prototype.digest=function(e){var t=this._len%this._blockSize;this._block[t]=128,this._block.fill(0,t+1),t>=this._finalSize&&(this._update(this._block),this._block.fill(0));var n=8*this._len;if(n<=4294967295)this._block.writeUInt32BE(n,this._blockSize-4);else{var r=(4294967295&n)>>>0,i=(n-r)/4294967296;this._block.writeUInt32BE(i,this._blockSize-8),this._block.writeUInt32BE(r,this._blockSize-4)}this._update(this._block);var o=this._hash();return e?o.toString(e):o},i.prototype._update=function(){throw new Error("_update must be implemented by subclass")},e.exports=i},function(e,t,n){"use strict";var r={};function i(e,t,n){n||(n=Error);var i=function(e){var n,r;function i(n,r,i){return e.call(this,function(e,n,r){return"string"==typeof t?t:t(e,n,r)}(n,r,i))||this}return r=e,(n=i).prototype=Object.create(r.prototype),n.prototype.constructor=n,n.__proto__=r,i}(n);i.prototype.name=n.name,i.prototype.code=e,r[e]=i}function o(e,t){if(Array.isArray(e)){var n=e.length;return e=e.map((function(e){return String(e)})),n>2?"one of ".concat(t," ").concat(e.slice(0,n-1).join(", "),", or ")+e[n-1]:2===n?"one of ".concat(t," ").concat(e[0]," or ").concat(e[1]):"of ".concat(t," ").concat(e[0])}return"of ".concat(t," ").concat(String(e))}i("ERR_INVALID_OPT_VALUE",(function(e,t){return'The value "'+t+'" is invalid for option "'+e+'"'}),TypeError),i("ERR_INVALID_ARG_TYPE",(function(e,t,n){var r,i,s,a;if("string"==typeof t&&(i="not ",t.substr(!s||s<0?0:+s,i.length)===i)?(r="must not be",t=t.replace(/^not /,"")):r="must be",function(e,t,n){return(void 0===n||n>e.length)&&(n=e.length),e.substring(n-t.length,n)===t}(e," argument"))a="The ".concat(e," ").concat(r," ").concat(o(t,"type"));else{var u=function(e,t,n){return"number"!=typeof n&&(n=0),!(n+t.length>e.length)&&-1!==e.indexOf(t,n)}(e,".")?"property":"argument";a='The "'.concat(e,'" ').concat(u," ").concat(r," ").concat(o(t,"type"))}return a+=". Received type ".concat(typeof n)}),TypeError),i("ERR_STREAM_PUSH_AFTER_EOF","stream.push() after EOF"),i("ERR_METHOD_NOT_IMPLEMENTED",(function(e){return"The "+e+" method is not implemented"})),i("ERR_STREAM_PREMATURE_CLOSE","Premature close"),i("ERR_STREAM_DESTROYED",(function(e){return"Cannot call "+e+" after a stream was destroyed"})),i("ERR_MULTIPLE_CALLBACK","Callback called multiple times"),i("ERR_STREAM_CANNOT_PIPE","Cannot pipe, not readable"),i("ERR_STREAM_WRITE_AFTER_END","write after end"),i("ERR_STREAM_NULL_VALUES","May not write null values to stream",TypeError),i("ERR_UNKNOWN_ENCODING",(function(e){return"Unknown encoding: "+e}),TypeError),i("ERR_STREAM_UNSHIFT_AFTER_END_EVENT","stream.unshift() after end event"),e.exports.codes=r},function(e,t,n){"use strict";(function(t){var r=Object.keys||function(e){var t=[];for(var n in e)t.push(n);return t};e.exports=c;var i=n(192),o=n(196);n(7)(c,i);for(var s=r(o.prototype),a=0;a<s.length;a++){var u=s[a];c.prototype[u]||(c.prototype[u]=o.prototype[u])}function c(e){if(!(this instanceof c))return new c(e);i.call(this,e),o.call(this,e),this.allowHalfOpen=!0,e&&(!1===e.readable&&(this.readable=!1),!1===e.writable&&(this.writable=!1),!1===e.allowHalfOpen&&(this.allowHalfOpen=!1,this.once("end",f)))}function f(){this._writableState.ended||t.nextTick(l,this)}function l(e){e.end()}Object.defineProperty(c.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Object.defineProperty(c.prototype,"writableBuffer",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}}),Object.defineProperty(c.prototype,"writableLength",{enumerable:!1,get:function(){return this._writableState.length}}),Object.defineProperty(c.prototype,"destroyed",{enumerable:!1,get:function(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set:function(e){void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed=e,this._writableState.destroyed=e)}})}).call(this,n(20))},function(e,t,n){var r=n(398),i=n(401);e.exports=function(e,t){var n=i(e,t);return r(n)?n:void 0}},function(e,t,n){"use strict";n.d(t,"b",(function(){return g})),n.d(t,"a",(function(){return m}));var r=n(44),i=n(33),o=n(514),s=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},a=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},u=new r.a("CognitoCredentials"),c=new Promise((function(e,t){return Object(i.b)().isBrowser?(window.gapi&&window.gapi.auth2?window.gapi.auth2:null)?(u.debug("google api already loaded"),e()):void setTimeout((function(){return e()}),2e3):(u.debug("not in the browser, directly resolved"),e())})),f=function(){function e(){this.initialized=!1,this.refreshGoogleToken=this.refreshGoogleToken.bind(this),this._refreshGoogleTokenImpl=this._refreshGoogleTokenImpl.bind(this)}return e.prototype.refreshGoogleToken=function(){return s(this,void 0,void 0,(function(){return a(this,(function(e){switch(e.label){case 0:return this.initialized?[3,2]:(u.debug("need to wait for the Google SDK loaded"),[4,c]);case 1:e.sent(),this.initialized=!0,u.debug("finish waiting"),e.label=2;case 2:return[2,this._refreshGoogleTokenImpl()]}}))}))},e.prototype._refreshGoogleTokenImpl=function(){var e=null;return Object(i.b)().isBrowser&&(e=window.gapi&&window.gapi.auth2?window.gapi.auth2:null),e?new Promise((function(t,n){e.getAuthInstance().then((function(e){e||(u.debug("google Auth undefined"),n(new o.a("google Auth undefined")));var r=e.currentUser.get();r.isSignedIn()?(u.debug("refreshing the google access token"),r.reloadAuthResponse().then((function(e){var n=e.id_token,r=e.expires_at;t({token:n,expires_at:r})})).catch((function(e){e&&"network_error"===e.error?n("Network error reloading google auth response"):n(new o.a("Failed to reload google auth response"))}))):n(new o.a("User is not signed in with Google"))})).catch((function(e){u.debug("Failed to refresh google token",e),n(new o.a("Failed to refresh google token"))}))})):(u.debug("no gapi auth2 available"),Promise.reject("no gapi auth2 available"))},e}(),l=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},d=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},h=new r.a("CognitoCredentials"),p=new Promise((function(e,t){return Object(i.b)().isBrowser?window.FB?(h.debug("FB SDK already loaded"),e()):void setTimeout((function(){return e()}),2e3):(h.debug("not in the browser, directly resolved"),e())})),v=function(){function e(){this.initialized=!1,this.refreshFacebookToken=this.refreshFacebookToken.bind(this),this._refreshFacebookTokenImpl=this._refreshFacebookTokenImpl.bind(this)}return e.prototype.refreshFacebookToken=function(){return l(this,void 0,void 0,(function(){return d(this,(function(e){switch(e.label){case 0:return this.initialized?[3,2]:(h.debug("need to wait for the Facebook SDK loaded"),[4,p]);case 1:e.sent(),this.initialized=!0,h.debug("finish waiting"),e.label=2;case 2:return[2,this._refreshFacebookTokenImpl()]}}))}))},e.prototype._refreshFacebookTokenImpl=function(){var e=null;if(Object(i.b)().isBrowser&&(e=window.FB),!e){return h.debug("no fb sdk available"),Promise.reject(new o.a("no fb sdk available"))}return new Promise((function(t,n){e.getLoginStatus((function(e){if(e&&e.authResponse){var r=e.authResponse,i=r.accessToken,s=1e3*r.expiresIn+(new Date).getTime();if(!i){a="the jwtToken is undefined";h.debug(a),n(new o.a(a))}t({token:i,expires_at:s})}else{var a="no response from facebook when refreshing the jwt token";h.debug(a),n(new o.a(a))}}),{scope:"public_profile,email"})}))},e}(),g=new f,m=new v},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=n(1),i=n(55);function o(e){var t,n,o=[];try{for(var s=Object(r.__values)(Object.keys(e).sort()),a=s.next();!a.done;a=s.next()){var u=a.value,c=e[u];if(u=Object(i.a)(u),Array.isArray(c))for(var f=0,l=c.length;f<l;f++)o.push(u+"="+Object(i.a)(c[f]));else{var d=u;(c||"string"==typeof c)&&(d+="="+Object(i.a)(c)),o.push(d)}}}catch(e){t={error:e}}finally{try{a&&!a.done&&(n=s.return)&&n.call(s)}finally{if(t)throw t.error}}return o.join("&")}},function(e,t,n){var r;e.exports=(r=n(32),n(87),n(271),r.HmacSHA256)},function(e,t,n){"use strict"; -/*! - * cookie - * Copyright(c) 2012-2014 Roman Shtylman - * Copyright(c) 2015 Douglas Christopher Wilson - * MIT Licensed - */t.parse=function(e,t){if("string"!=typeof e)throw new TypeError("argument str must be a string");for(var n={},i=t||{},s=e.split(o),u=i.decode||r,c=0;c<s.length;c++){var f=s[c],l=f.indexOf("=");if(!(l<0)){var d=f.substr(0,l).trim(),h=f.substr(++l,f.length).trim();'"'==h[0]&&(h=h.slice(1,-1)),null==n[d]&&(n[d]=a(h,u))}}return n},t.serialize=function(e,t,n){var r=n||{},o=r.encode||i;if("function"!=typeof o)throw new TypeError("option encode is invalid");if(!s.test(e))throw new TypeError("argument name is invalid");var a=o(t);if(a&&!s.test(a))throw new TypeError("argument val is invalid");var u=e+"="+a;if(null!=r.maxAge){var c=r.maxAge-0;if(isNaN(c)||!isFinite(c))throw new TypeError("option maxAge is invalid");u+="; Max-Age="+Math.floor(c)}if(r.domain){if(!s.test(r.domain))throw new TypeError("option domain is invalid");u+="; Domain="+r.domain}if(r.path){if(!s.test(r.path))throw new TypeError("option path is invalid");u+="; Path="+r.path}if(r.expires){if("function"!=typeof r.expires.toUTCString)throw new TypeError("option expires is invalid");u+="; Expires="+r.expires.toUTCString()}r.httpOnly&&(u+="; HttpOnly");r.secure&&(u+="; Secure");if(r.sameSite){switch("string"==typeof r.sameSite?r.sameSite.toLowerCase():r.sameSite){case!0:u+="; SameSite=Strict";break;case"lax":u+="; SameSite=Lax";break;case"strict":u+="; SameSite=Strict";break;case"none":u+="; SameSite=None";break;default:throw new TypeError("option sameSite is invalid")}}return u};var r=decodeURIComponent,i=encodeURIComponent,o=/; */,s=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;function a(e,t){try{return t(e)}catch(t){return e}}},function(e,t,n){"use strict";n.d(t,"a",(function(){return i}));var r=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},i={clockOffset:0,getDateWithClockOffset:function(){return i.clockOffset?new Date((new Date).getTime()+i.clockOffset):new Date},getClockOffset:function(){return i.clockOffset},getHeaderStringFromDate:function(e){return void 0===e&&(e=i.getDateWithClockOffset()),e.toISOString().replace(/[:\-]|\.\d{3}/g,"")},getDateFromHeaderString:function(e){var t=r(e.match(/^(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2}).+/),7),n=t[1],i=t[2],o=t[3],s=t[4],a=t[5],u=t[6];return new Date(Date.UTC(Number(n),Number(i)-1,Number(o),Number(s),Number(a),Number(u)))},isClockSkewed:function(e){return Math.abs(e.getTime()-i.getDateWithClockOffset().getTime())>=3e5},isClockSkewError:function(e){if(!e.response||!e.response.headers)return!1;var t=e.response.headers;return Boolean("BadRequestException"===t["x-amzn-errortype"]&&(t.date||t.Date))},setClockOffset:function(e){i.clockOffset=e}}},,function(e,t,n){"use strict";var r=n(7),i=n(113),o=n(116),s=n(117),a=n(56);function u(e){a.call(this,"digest"),this._hash=e}r(u,a),u.prototype._update=function(e){this._hash.update(e)},u.prototype._final=function(){return this._hash.digest()},e.exports=function(e){return"md5"===(e=e.toLowerCase())?new i:"rmd160"===e||"ripemd160"===e?new o:new u(s(e))}},function(e,t,n){(function(e){function n(e){return Object.prototype.toString.call(e)}t.isArray=function(e){return Array.isArray?Array.isArray(e):"[object Array]"===n(e)},t.isBoolean=function(e){return"boolean"==typeof e},t.isNull=function(e){return null===e},t.isNullOrUndefined=function(e){return null==e},t.isNumber=function(e){return"number"==typeof e},t.isString=function(e){return"string"==typeof e},t.isSymbol=function(e){return"symbol"==typeof e},t.isUndefined=function(e){return void 0===e},t.isRegExp=function(e){return"[object RegExp]"===n(e)},t.isObject=function(e){return"object"==typeof e&&null!==e},t.isDate=function(e){return"[object Date]"===n(e)},t.isError=function(e){return"[object Error]"===n(e)||e instanceof Error},t.isFunction=function(e){return"function"==typeof e},t.isPrimitive=function(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e},t.isBuffer=e.isBuffer}).call(this,n(6).Buffer)},function(e,t,n){(function(t){e.exports=function(e,n){for(var r=Math.min(e.length,n.length),i=new t(r),o=0;o<r;++o)i[o]=e[o]^n[o];return i}}).call(this,n(6).Buffer)},function(e,t,n){"use strict";var r=n(51),i=n(46);function o(){this.pending=null,this.pendingTotal=0,this.blockSize=this.constructor.blockSize,this.outSize=this.constructor.outSize,this.hmacStrength=this.constructor.hmacStrength,this.padLength=this.constructor.padLength/8,this.endian="big",this._delta8=this.blockSize/8,this._delta32=this.blockSize/32}t.BlockHash=o,o.prototype.update=function(e,t){if(e=r.toArray(e,t),this.pending?this.pending=this.pending.concat(e):this.pending=e,this.pendingTotal+=e.length,this.pending.length>=this._delta8){var n=(e=this.pending).length%this._delta8;this.pending=e.slice(e.length-n,e.length),0===this.pending.length&&(this.pending=null),e=r.join32(e,0,e.length-n,this.endian);for(var i=0;i<e.length;i+=this._delta32)this._update(e,i,i+this._delta32)}return this},o.prototype.digest=function(e){return this.update(this._pad()),i(null===this.pending),this._digest(e)},o.prototype._pad=function(){var e=this.pendingTotal,t=this._delta8,n=t-(e+this.padLength)%t,r=new Array(n+this.padLength);r[0]=128;for(var i=1;i<n;i++)r[i]=0;if(e<<=3,"big"===this.endian){for(var o=8;o<this.padLength;o++)r[i++]=0;r[i++]=0,r[i++]=0,r[i++]=0,r[i++]=0,r[i++]=e>>>24&255,r[i++]=e>>>16&255,r[i++]=e>>>8&255,r[i++]=255&e}else for(r[i++]=255&e,r[i++]=e>>>8&255,r[i++]=e>>>16&255,r[i++]=e>>>24&255,r[i++]=0,r[i++]=0,r[i++]=0,r[i++]=0,o=8;o<this.padLength;o++)r[i++]=0;return r}},function(e,t,n){"use strict";const r=n(7),i=n(132).Reporter,o=n(130).Buffer;function s(e,t){i.call(this,t),o.isBuffer(e)?(this.base=e,this.offset=0,this.length=e.length):this.error("Input not Buffer")}function a(e,t){if(Array.isArray(e))this.length=0,this.value=e.map((function(e){return a.isEncoderBuffer(e)||(e=new a(e,t)),this.length+=e.length,e}),this);else if("number"==typeof e){if(!(0<=e&&e<=255))return t.error("non-byte EncoderBuffer value");this.value=e,this.length=1}else if("string"==typeof e)this.value=e,this.length=o.byteLength(e);else{if(!o.isBuffer(e))return t.error("Unsupported type: "+typeof e);this.value=e,this.length=e.length}}r(s,i),t.DecoderBuffer=s,s.isDecoderBuffer=function(e){if(e instanceof s)return!0;return"object"==typeof e&&o.isBuffer(e.base)&&"DecoderBuffer"===e.constructor.name&&"number"==typeof e.offset&&"number"==typeof e.length&&"function"==typeof e.save&&"function"==typeof e.restore&&"function"==typeof e.isEmpty&&"function"==typeof e.readUInt8&&"function"==typeof e.skip&&"function"==typeof e.raw},s.prototype.save=function(){return{offset:this.offset,reporter:i.prototype.save.call(this)}},s.prototype.restore=function(e){const t=new s(this.base);return t.offset=e.offset,t.length=this.offset,this.offset=e.offset,i.prototype.restore.call(this,e.reporter),t},s.prototype.isEmpty=function(){return this.offset===this.length},s.prototype.readUInt8=function(e){return this.offset+1<=this.length?this.base.readUInt8(this.offset++,!0):this.error(e||"DecoderBuffer overrun")},s.prototype.skip=function(e,t){if(!(this.offset+e<=this.length))return this.error(t||"DecoderBuffer overrun");const n=new s(this.base);return n._reporterState=this._reporterState,n.offset=this.offset,n.length=this.offset+e,this.offset+=e,n},s.prototype.raw=function(e){return this.base.slice(e?e.offset:this.offset,this.length)},t.EncoderBuffer=a,a.isEncoderBuffer=function(e){if(e instanceof a)return!0;return"object"==typeof e&&"EncoderBuffer"===e.constructor.name&&"number"==typeof e.length&&"function"==typeof e.join},a.prototype.join=function(e,t){return e||(e=o.alloc(this.length)),t||(t=0),0===this.length||(Array.isArray(this.value)?this.value.forEach((function(n){n.join(e,t),t+=n.length})):("number"==typeof this.value?e[t]=this.value:"string"==typeof this.value?e.write(this.value,t):o.isBuffer(this.value)&&this.value.copy(e,t),t+=this.length)),e}},function(e,t,n){var r=n(97),i=n(390),o=n(391),s=r?r.toStringTag:void 0;e.exports=function(e){return null==e?void 0===e?"[object Undefined]":"[object Null]":s&&s in Object(e)?i(e):o(e)}},function(e,t){e.exports=function(e){return null!=e&&"object"==typeof e}},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r={},i=function(){function e(){}return e.setItem=function(e,t){return r[e]=t,r[e]},e.getItem=function(e){return Object.prototype.hasOwnProperty.call(r,e)?r[e]:void 0},e.removeItem=function(e){return delete r[e]},e.clear=function(){return r={}},e}(),o=function(){function e(){try{this.storageWindow=window.localStorage,this.storageWindow.setItem("aws.amplify.test-ls",1),this.storageWindow.removeItem("aws.amplify.test-ls")}catch(e){this.storageWindow=i}}return e.prototype.getStorage=function(){return this.storageWindow},e}()},function(e,t,n){var r;e.exports=(r=n(32),function(e){var t=r,n=t.lib,i=n.WordArray,o=n.Hasher,s=t.algo,a=[],u=[];!function(){function t(t){for(var n=e.sqrt(t),r=2;r<=n;r++)if(!(t%r))return!1;return!0}function n(e){return 4294967296*(e-(0|e))|0}for(var r=2,i=0;i<64;)t(r)&&(i<8&&(a[i]=n(e.pow(r,.5))),u[i]=n(e.pow(r,1/3)),i++),r++}();var c=[],f=s.SHA256=o.extend({_doReset:function(){this._hash=new i.init(a.slice(0))},_doProcessBlock:function(e,t){for(var n=this._hash.words,r=n[0],i=n[1],o=n[2],s=n[3],a=n[4],f=n[5],l=n[6],d=n[7],h=0;h<64;h++){if(h<16)c[h]=0|e[t+h];else{var p=c[h-15],v=(p<<25|p>>>7)^(p<<14|p>>>18)^p>>>3,g=c[h-2],m=(g<<15|g>>>17)^(g<<13|g>>>19)^g>>>10;c[h]=v+c[h-7]+m+c[h-16]}var b=r&i^r&o^i&o,y=(r<<30|r>>>2)^(r<<19|r>>>13)^(r<<10|r>>>22),w=d+((a<<26|a>>>6)^(a<<21|a>>>11)^(a<<7|a>>>25))+(a&f^~a&l)+u[h]+c[h];d=l,l=f,f=a,a=s+w|0,s=o,o=i,i=r,r=w+(y+b)|0}n[0]=n[0]+r|0,n[1]=n[1]+i|0,n[2]=n[2]+o|0,n[3]=n[3]+s|0,n[4]=n[4]+a|0,n[5]=n[5]+f|0,n[6]=n[6]+l|0,n[7]=n[7]+d|0},_doFinalize:function(){var t=this._data,n=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return n[i>>>5]|=128<<24-i%32,n[14+(i+64>>>9<<4)]=e.floor(r/4294967296),n[15+(i+64>>>9<<4)]=r,t.sigBytes=4*n.length,this._process(),this._hash},clone:function(){var e=o.clone.call(this);return e._hash=this._hash.clone(),e}});t.SHA256=o._createHelper(f),t.HmacSHA256=o._createHmacHelper(f)}(Math),r.SHA256)},function(e,t,n){"use strict";n.d(t,"a",(function(){return c}));var r=n(44),i=function(){return(i=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},o=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},s=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(o(arguments[t]));return e},a=new r.a("Hub"),u="undefined"!=typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("amplify_default"):"@@amplify_default";var c=new(function(){function e(e){this.listeners=[],this.patterns=[],this.protectedChannels=["core","auth","api","analytics","interactions","pubsub","storage","xr"],this.name=e}return e.prototype.remove=function(e,t){if(e instanceof RegExp){var n=this.patterns.find((function(t){return t.pattern.source===e.source}));if(!n)return void a.warn("No listeners for "+e);this.patterns=s(this.patterns.filter((function(e){return e!==n})))}else{var r=this.listeners[e];if(!r)return void a.warn("No listeners for "+e);this.listeners[e]=s(r.filter((function(e){return e.callback!==t})))}},e.prototype.dispatch=function(e,t,n,r){(void 0===n&&(n=""),this.protectedChannels.indexOf(e)>-1)&&(r===u||a.warn("WARNING: "+e+" is protected and dispatching on it can have unintended consequences"));var o={channel:e,payload:i({},t),source:n,patternInfo:[]};try{this._toListeners(o)}catch(e){a.error(e)}},e.prototype.listen=function(e,t,n){var r,i=this;if(void 0===n&&(n="noname"),function(e){return void 0!==e.onHubCapsule}(t))a.warn("WARNING onHubCapsule is Deprecated. Please pass in a callback."),r=t.onHubCapsule.bind(t);else{if("function"!=typeof t)throw new Error("No callback supplied to Hub");r=t}if(e instanceof RegExp)this.patterns.push({pattern:e,callback:r});else{var o=this.listeners[e];o||(o=[],this.listeners[e]=o),o.push({name:n,callback:r})}return function(){i.remove(e,r)}},e.prototype._toListeners=function(e){var t=e.channel,n=e.payload,r=this.listeners[t];if(r&&r.forEach((function(r){a.debug("Dispatching to "+t+" with ",n);try{r.callback(e)}catch(e){a.error(e)}})),this.patterns.length>0){if(!n.message)return void a.warn("Cannot perform pattern matching without a message key");var s=n.message;this.patterns.forEach((function(t){var n=s.match(t.pattern);if(n){var r=o(n).slice(1),u=i(i({},e),{patternInfo:r});try{t.callback(u)}catch(e){a.error(e)}}}))}},e}())("__default__")},function(e,t,n){"use strict";n.d(t,"a",(function(){return Lt}));var r=n(44),i=n(86),o=n(33),s=n(73),a=n(514),u=n(50),c=n(19),f=n(1),l=function(e,t){return(l=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function d(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}l(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var h=function(){return(h=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function p(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))}function v(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}}Object.create;function g(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s}var m,b,y,w,_,S,E,M,A,I,k,O,x,C,T,P,N,R,L,j,D,U,B,F,z,q,K,H,V,G,W,$,Y,J,Z,X,Q,ee,te,ne,re,ie,oe,se,ae,ue,ce,fe,le,de,he,pe,ve,ge,me,be,ye;Object.create;!function(e){e.AUTHENTICATED_ROLE="AuthenticatedRole",e.DENY="Deny"}(m||(m={})),(b||(b={})).filterSensitiveLog=function(e){return h({},e)},(y||(y={})).filterSensitiveLog=function(e){return h({},e)},(w||(w={})).filterSensitiveLog=function(e){return h({},e)},(_||(_={})).filterSensitiveLog=function(e){return h({},e)},(S||(S={})).filterSensitiveLog=function(e){return h({},e)},(E||(E={})).filterSensitiveLog=function(e){return h({},e)},(M||(M={})).filterSensitiveLog=function(e){return h({},e)},(A||(A={})).filterSensitiveLog=function(e){return h({},e)},(I||(I={})).filterSensitiveLog=function(e){return h({},e)},(k||(k={})).filterSensitiveLog=function(e){return h({},e)},function(e){e.ACCESS_DENIED="AccessDenied",e.INTERNAL_SERVER_ERROR="InternalServerError"}(O||(O={})),(x||(x={})).filterSensitiveLog=function(e){return h({},e)},(C||(C={})).filterSensitiveLog=function(e){return h({},e)},(T||(T={})).filterSensitiveLog=function(e){return h({},e)},(P||(P={})).filterSensitiveLog=function(e){return h({},e)},(N||(N={})).filterSensitiveLog=function(e){return h({},e)},(R||(R={})).filterSensitiveLog=function(e){return h({},e)},(L||(L={})).filterSensitiveLog=function(e){return h({},e)},(j||(j={})).filterSensitiveLog=function(e){return h({},e)},(D||(D={})).filterSensitiveLog=function(e){return h({},e)},(U||(U={})).filterSensitiveLog=function(e){return h({},e)},(B||(B={})).filterSensitiveLog=function(e){return h({},e)},(F||(F={})).filterSensitiveLog=function(e){return h({},e)},(z||(z={})).filterSensitiveLog=function(e){return h({},e)},(q||(q={})).filterSensitiveLog=function(e){return h({},e)},(K||(K={})).filterSensitiveLog=function(e){return h({},e)},function(e){e.CONTAINS="Contains",e.EQUALS="Equals",e.NOT_EQUAL="NotEqual",e.STARTS_WITH="StartsWith"}(H||(H={})),(V||(V={})).filterSensitiveLog=function(e){return h({},e)},(G||(G={})).filterSensitiveLog=function(e){return h({},e)},function(e){e.RULES="Rules",e.TOKEN="Token"}(W||(W={})),($||($={})).filterSensitiveLog=function(e){return h({},e)},(Y||(Y={})).filterSensitiveLog=function(e){return h({},e)},(J||(J={})).filterSensitiveLog=function(e){return h({},e)},(Z||(Z={})).filterSensitiveLog=function(e){return h({},e)},(X||(X={})).filterSensitiveLog=function(e){return h({},e)},(Q||(Q={})).filterSensitiveLog=function(e){return h({},e)},(ee||(ee={})).filterSensitiveLog=function(e){return h({},e)},(te||(te={})).filterSensitiveLog=function(e){return h({},e)},(ne||(ne={})).filterSensitiveLog=function(e){return h({},e)},(re||(re={})).filterSensitiveLog=function(e){return h({},e)},(ie||(ie={})).filterSensitiveLog=function(e){return h({},e)},(oe||(oe={})).filterSensitiveLog=function(e){return h({},e)},(se||(se={})).filterSensitiveLog=function(e){return h({},e)},(ae||(ae={})).filterSensitiveLog=function(e){return h({},e)},(ue||(ue={})).filterSensitiveLog=function(e){return h({},e)},(ce||(ce={})).filterSensitiveLog=function(e){return h({},e)},(fe||(fe={})).filterSensitiveLog=function(e){return h({},e)},(le||(le={})).filterSensitiveLog=function(e){return h({},e)},(de||(de={})).filterSensitiveLog=function(e){return h({},e)},(he||(he={})).filterSensitiveLog=function(e){return h({},e)},(pe||(pe={})).filterSensitiveLog=function(e){return h({},e)},(ve||(ve={})).filterSensitiveLog=function(e){return h({},e)},(ge||(ge={})).filterSensitiveLog=function(e){return h({},e)},(me||(me={})).filterSensitiveLog=function(e){return h({},e)},(be||(be={})).filterSensitiveLog=function(e){return h({},e)},(ye||(ye={})).filterSensitiveLog=function(e){return h({},e)};var we=n(2),_e=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,d,p,g,m,b,y;return v(this,(function(v){switch(v.label){case 0:return r=[h({},e)],y={},[4,Je(e.body,t)];case 1:switch(n=h.apply(void 0,r.concat([(y.body=v.sent(),y)])),o="UnknownError",s=n.body.__type.split("#"),o=void 0===s[1]?s[0]:s[1],o){case"ExternalServiceException":case"com.amazonaws.cognitoidentity#ExternalServiceException":return[3,2];case"InternalErrorException":case"com.amazonaws.cognitoidentity#InternalErrorException":return[3,4];case"InvalidIdentityPoolConfigurationException":case"com.amazonaws.cognitoidentity#InvalidIdentityPoolConfigurationException":return[3,6];case"InvalidParameterException":case"com.amazonaws.cognitoidentity#InvalidParameterException":return[3,8];case"NotAuthorizedException":case"com.amazonaws.cognitoidentity#NotAuthorizedException":return[3,10];case"ResourceConflictException":case"com.amazonaws.cognitoidentity#ResourceConflictException":return[3,12];case"ResourceNotFoundException":case"com.amazonaws.cognitoidentity#ResourceNotFoundException":return[3,14];case"TooManyRequestsException":case"com.amazonaws.cognitoidentity#TooManyRequestsException":return[3,16]}return[3,18];case 2:return a=[{}],[4,Ee(n,t)];case 3:return i=h.apply(void 0,[h.apply(void 0,a.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 4:return u=[{}],[4,Me(n,t)];case 5:return i=h.apply(void 0,[h.apply(void 0,u.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 6:return c=[{}],[4,Ae(n,t)];case 7:return i=h.apply(void 0,[h.apply(void 0,c.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 8:return f=[{}],[4,Ie(n,t)];case 9:return i=h.apply(void 0,[h.apply(void 0,f.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 10:return l=[{}],[4,Oe(n,t)];case 11:return i=h.apply(void 0,[h.apply(void 0,l.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 12:return d=[{}],[4,xe(n,t)];case 13:return i=h.apply(void 0,[h.apply(void 0,d.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 14:return p=[{}],[4,Ce(n,t)];case 15:return i=h.apply(void 0,[h.apply(void 0,p.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 16:return g=[{}],[4,Te(n,t)];case 17:return i=h.apply(void 0,[h.apply(void 0,g.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 18:m=n.body,o=m.code||m.Code||o,i=h(h({},m),{name:""+o,message:m.message||m.Message||o,$fault:"client",$metadata:We(e)}),v.label=19;case 19:return b=i.message||i.Message||o,i.message=b,delete i.Message,[2,Promise.reject(Object.assign(new Error(b),i))]}}))}))},Se=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,d,p,g,m,b,y;return v(this,(function(v){switch(v.label){case 0:return r=[h({},e)],y={},[4,Je(e.body,t)];case 1:switch(n=h.apply(void 0,r.concat([(y.body=v.sent(),y)])),o="UnknownError",s=n.body.__type.split("#"),o=void 0===s[1]?s[0]:s[1],o){case"ExternalServiceException":case"com.amazonaws.cognitoidentity#ExternalServiceException":return[3,2];case"InternalErrorException":case"com.amazonaws.cognitoidentity#InternalErrorException":return[3,4];case"InvalidParameterException":case"com.amazonaws.cognitoidentity#InvalidParameterException":return[3,6];case"LimitExceededException":case"com.amazonaws.cognitoidentity#LimitExceededException":return[3,8];case"NotAuthorizedException":case"com.amazonaws.cognitoidentity#NotAuthorizedException":return[3,10];case"ResourceConflictException":case"com.amazonaws.cognitoidentity#ResourceConflictException":return[3,12];case"ResourceNotFoundException":case"com.amazonaws.cognitoidentity#ResourceNotFoundException":return[3,14];case"TooManyRequestsException":case"com.amazonaws.cognitoidentity#TooManyRequestsException":return[3,16]}return[3,18];case 2:return a=[{}],[4,Ee(n,t)];case 3:return i=h.apply(void 0,[h.apply(void 0,a.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 4:return u=[{}],[4,Me(n,t)];case 5:return i=h.apply(void 0,[h.apply(void 0,u.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 6:return c=[{}],[4,Ie(n,t)];case 7:return i=h.apply(void 0,[h.apply(void 0,c.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 8:return f=[{}],[4,ke(n,t)];case 9:return i=h.apply(void 0,[h.apply(void 0,f.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 10:return l=[{}],[4,Oe(n,t)];case 11:return i=h.apply(void 0,[h.apply(void 0,l.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 12:return d=[{}],[4,xe(n,t)];case 13:return i=h.apply(void 0,[h.apply(void 0,d.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 14:return p=[{}],[4,Ce(n,t)];case 15:return i=h.apply(void 0,[h.apply(void 0,p.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 16:return g=[{}],[4,Te(n,t)];case 17:return i=h.apply(void 0,[h.apply(void 0,g.concat([v.sent()])),{name:o,$metadata:We(e)}]),[3,19];case 18:m=n.body,o=m.code||m.Code||o,i=h(h({},m),{name:""+o,message:m.message||m.Message||o,$fault:"client",$metadata:We(e)}),v.label=19;case 19:return b=i.message||i.Message||o,i.message=b,delete i.Message,[2,Promise.reject(Object.assign(new Error(b),i))]}}))}))},Ee=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n=e.body,r=je(n,t),[2,h({name:"ExternalServiceException",$fault:"client",$metadata:We(e)},r)]}))}))},Me=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n=e.body,r=Be(n,t),[2,h({name:"InternalErrorException",$fault:"server",$metadata:We(e)},r)]}))}))},Ae=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n=e.body,r=Fe(n,t),[2,h({name:"InvalidIdentityPoolConfigurationException",$fault:"client",$metadata:We(e)},r)]}))}))},Ie=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n=e.body,r=ze(n,t),[2,h({name:"InvalidParameterException",$fault:"client",$metadata:We(e)},r)]}))}))},ke=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n=e.body,r=qe(n,t),[2,h({name:"LimitExceededException",$fault:"client",$metadata:We(e)},r)]}))}))},Oe=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n=e.body,r=Ke(n,t),[2,h({name:"NotAuthorizedException",$fault:"client",$metadata:We(e)},r)]}))}))},xe=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n=e.body,r=He(n,t),[2,h({name:"ResourceConflictException",$fault:"client",$metadata:We(e)},r)]}))}))},Ce=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n=e.body,r=Ve(n,t),[2,h({name:"ResourceNotFoundException",$fault:"client",$metadata:We(e)},r)]}))}))},Te=function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n=e.body,r=Ge(n,t),[2,h({name:"TooManyRequestsException",$fault:"client",$metadata:We(e)},r)]}))}))},Pe=function(e,t){return h(h(h({},void 0!==e.CustomRoleArn&&{CustomRoleArn:e.CustomRoleArn}),void 0!==e.IdentityId&&{IdentityId:e.IdentityId}),void 0!==e.Logins&&{Logins:Re(e.Logins,t)})},Ne=function(e,t){return h(h(h({},void 0!==e.AccountId&&{AccountId:e.AccountId}),void 0!==e.IdentityPoolId&&{IdentityPoolId:e.IdentityPoolId}),void 0!==e.Logins&&{Logins:Re(e.Logins,t)})},Re=function(e,t){return Object.entries(e).reduce((function(e,t){var n,r=g(t,2),i=r[0],o=r[1];return h(h({},e),((n={})[i]=o,n))}),{})},Le=function(e,t){return{AccessKeyId:void 0!==e.AccessKeyId&&null!==e.AccessKeyId?e.AccessKeyId:void 0,Expiration:void 0!==e.Expiration&&null!==e.Expiration?new Date(Math.round(1e3*e.Expiration)):void 0,SecretKey:void 0!==e.SecretKey&&null!==e.SecretKey?e.SecretKey:void 0,SessionToken:void 0!==e.SessionToken&&null!==e.SessionToken?e.SessionToken:void 0}},je=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},De=function(e,t){return{Credentials:void 0!==e.Credentials&&null!==e.Credentials?Le(e.Credentials):void 0,IdentityId:void 0!==e.IdentityId&&null!==e.IdentityId?e.IdentityId:void 0}},Ue=function(e,t){return{IdentityId:void 0!==e.IdentityId&&null!==e.IdentityId?e.IdentityId:void 0}},Be=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},Fe=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},ze=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},qe=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},Ke=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},He=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},Ve=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},Ge=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},We=function(e){return{httpStatusCode:e.statusCode,httpHeaders:e.headers,requestId:e.headers["x-amzn-requestid"]}},$e=function(e,t){return void 0===e&&(e=new Uint8Array),e instanceof Uint8Array?Promise.resolve(e):t.streamCollector(e)||Promise.resolve(new Uint8Array)},Ye=function(e,t,n,r,i){return p(void 0,void 0,void 0,(function(){var o,s,a,u,c,f;return v(this,(function(l){switch(l.label){case 0:return[4,e.endpoint()];case 1:return o=l.sent(),s=o.hostname,a=o.protocol,u=void 0===a?"https":a,c=o.port,f={protocol:u,hostname:s,port:c,method:"POST",path:n,headers:t},void 0!==r&&(f.hostname=r),void 0!==i&&(f.body=i),[2,new we.a(f)]}}))}))},Je=function(e,t){return function(e,t){return $e(e,t).then((function(e){return t.utf8Encoder(e)}))}(e,t).then((function(e){return e.length?JSON.parse(e):{}}))},Ze=n(10),Xe=n(0),Qe=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return d(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Ze.a)(t,this.serialize,this.deserialize));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"CognitoIdentityClient",commandName:"GetCredentialsForIdentityCommand",inputFilterSensitiveLog:D.filterSensitiveLog,outputFilterSensitiveLog:B.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"CognitoIdentityClient",commandName:"GetCredentialsForIdentityCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n={"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":"AWSCognitoIdentityService.GetCredentialsForIdentity"},r=JSON.stringify(Pe(e,t)),[2,Ye(t,n,"/",void 0,r)]}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return p(void 0,void 0,void 0,(function(){var n,r,i;return v(this,(function(o){switch(o.label){case 0:return e.statusCode>=300?[2,_e(e,t)]:[4,Je(e.body,t)];case 1:return n=o.sent(),{},r=De(n,t),i=h({$metadata:We(e)},r),[2,Promise.resolve(i)]}}))}))}(e,t)},t}(Xe.b),et=function(e){function t(t,n){void 0===n&&(n=!0);var r=e.call(this,t)||this;return r.tryNextLink=n,r}return Object(f.__extends)(t,e),t}(Error);function tt(e){return Promise.all(Object.keys(e).reduce((function(t,n){var r=e[n];return"string"==typeof r?t.push([n,r]):t.push(r().then((function(e){return[n,e]}))),t}),[])).then((function(e){return e.reduce((function(e,t){var n=Object(f.__read)(t,2),r=n[0],i=n[1];return e[r]=i,e}),{})}))}function nt(e){var t=this;return function(){return Object(f.__awaiter)(t,void 0,void 0,(function(){var t,n,r,i,o,s,a,u,c,l,d,h,p;return Object(f.__generator)(this,(function(f){switch(f.label){case 0:return l=(c=e.client).send,d=Qe.bind,p={CustomRoleArn:e.customRoleArn,IdentityId:e.identityId},e.logins?[4,tt(e.logins)]:[3,2];case 1:return h=f.sent(),[3,3];case 2:h=void 0,f.label=3;case 3:return[4,l.apply(c,[new(d.apply(Qe,[void 0,(p.Logins=h,p)]))])];case 4:return t=f.sent().Credentials,n=void 0===t?function(){throw new et("Response from Amazon Cognito contained no credentials")}():t,r=n.AccessKeyId,i=void 0===r?function(){throw new et("Response from Amazon Cognito contained no access key ID")}():r,o=n.Expiration,s=n.SecretKey,a=void 0===s?function(){throw new et("Response from Amazon Cognito contained no secret key")}():s,u=n.SessionToken,[2,{identityId:e.identityId,accessKeyId:i,secretAccessKey:a,sessionToken:u,expiration:o}]}}))}))}}var rt=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return d(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Ze.a)(t,this.serialize,this.deserialize));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"CognitoIdentityClient",commandName:"GetIdCommand",inputFilterSensitiveLog:z.filterSensitiveLog,outputFilterSensitiveLog:q.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"CognitoIdentityClient",commandName:"GetIdCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return p(void 0,void 0,void 0,(function(){var n,r;return v(this,(function(i){return n={"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":"AWSCognitoIdentityService.GetId"},r=JSON.stringify(Ne(e,t)),[2,Ye(t,n,"/",void 0,r)]}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return p(void 0,void 0,void 0,(function(){var n,r,i;return v(this,(function(o){switch(o.label){case 0:return e.statusCode>=300?[2,Se(e,t)]:[4,Je(e.body,t)];case 1:return n=o.sent(),{},r=Ue(n,t),i=h({$metadata:We(e)},r),[2,Promise.resolve(i)]}}))}))}(e,t)},t}(Xe.b),it=function(){function e(e){void 0===e&&(e="aws:cognito-identity-ids"),this.dbName=e}return e.prototype.getItem=function(e){return this.withObjectStore("readonly",(function(t){var n=t.get(e);return new Promise((function(e){n.onerror=function(){return e(null)},n.onsuccess=function(){return e(n.result?n.result.value:null)}}))})).catch((function(){return null}))},e.prototype.removeItem=function(e){return this.withObjectStore("readwrite",(function(t){var n=t.delete(e);return new Promise((function(e,t){n.onerror=function(){return t(n.error)},n.onsuccess=function(){return e()}}))}))},e.prototype.setItem=function(e,t){return this.withObjectStore("readwrite",(function(n){var r=n.put({id:e,value:t});return new Promise((function(e,t){r.onerror=function(){return t(r.error)},r.onsuccess=function(){return e()}}))}))},e.prototype.getDb=function(){var e=self.indexedDB.open(this.dbName,1);return new Promise((function(t,n){e.onsuccess=function(){t(e.result)},e.onerror=function(){n(e.error)},e.onblocked=function(){n(new Error("Unable to access DB"))},e.onupgradeneeded=function(){var t=e.result;t.onerror=function(){n(new Error("Failed to create object store"))},t.createObjectStore("IdentityIds",{keyPath:"id"})}}))},e.prototype.withObjectStore=function(e,t){return this.getDb().then((function(n){var r=n.transaction("IdentityIds",e);return r.oncomplete=function(){return n.close()},new Promise((function(e,n){r.onerror=function(){return n(r.error)},e(t(r.objectStore("IdentityIds")))})).catch((function(e){throw n.close(),e}))}))},e}(),ot=new(function(){function e(e){void 0===e&&(e={}),this.store=e}return e.prototype.getItem=function(e){return e in this.store?this.store[e]:null},e.prototype.removeItem=function(e){delete this.store[e]},e.prototype.setItem=function(e,t){this.store[e]=t},e}());function st(e){var t=this,n=e.accountId,r=e.cache,i=void 0===r?"object"==typeof self&&self.indexedDB?new it:"object"==typeof window&&window.localStorage?window.localStorage:ot:r,o=e.client,s=e.customRoleArn,a=e.identityPoolId,u=e.logins,c=e.userIdentifier,l=void 0===c?u&&0!==Object.keys(u).length?void 0:"ANONYMOUS":c,d=l?"aws:cognito-identity-credentials:"+a+":"+l:void 0,h=function(){return Object(f.__awaiter)(t,void 0,void 0,(function(){var e,t,r,c,l,p,v,g,m;return Object(f.__generator)(this,(function(f){switch(f.label){case 0:return(t=d)?[4,i.getItem(d)]:[3,2];case 1:t=f.sent(),f.label=2;case 2:return(e=t)?[3,7]:(p=(l=o).send,v=rt.bind,m={AccountId:n,IdentityPoolId:a},u?[4,tt(u)]:[3,4]);case 3:return g=f.sent(),[3,5];case 4:g=void 0,f.label=5;case 5:return[4,p.apply(l,[new(v.apply(rt,[void 0,(m.Logins=g,m)]))])];case 6:r=f.sent().IdentityId,c=void 0===r?function(){throw new et("Response from Amazon Cognito contained no identity ID")}():r,e=c,d&&Promise.resolve(i.setItem(d,e)).catch((function(){})),f.label=7;case 7:return[2,(h=nt({client:o,customRoleArn:s,logins:u,identityId:e}))()]}}))}))};return function(){return h().catch((function(e){return Object(f.__awaiter)(t,void 0,void 0,(function(){return Object(f.__generator)(this,(function(t){throw d&&Promise.resolve(i.removeItem(d)).catch((function(){})),e}))}))}))}}var at=n(147),ut=n(38),ct=n(18),ft=n(24),lt=n(11),dt=n(39),ht=n(17),pt=n(40),vt=n(41),gt=n(15),mt="cognito-identity.{region}.amazonaws.com",bt=new Set(["ap-east-1","ap-northeast-1","ap-northeast-2","ap-south-1","ap-southeast-1","ap-southeast-2","ca-central-1","eu-central-1","eu-north-1","eu-west-1","eu-west-2","eu-west-3","me-south-1","sa-east-1","us-east-1","us-east-2","us-west-1","us-west-2"]),yt=new Set(["cn-north-1","cn-northwest-1"]),wt=new Set(["us-iso-east-1"]),_t=new Set(["us-isob-east-1"]),St=new Set(["us-gov-east-1","us-gov-west-1"]),Et=h(h({},{apiVersion:"2014-06-30",disableHostPrefix:!1,logger:{},regionInfoProvider:function(e,t){var n=void 0;switch(e){case"ap-northeast-1":n={hostname:"cognito-identity.ap-northeast-1.amazonaws.com",partition:"aws"};break;case"ap-northeast-2":n={hostname:"cognito-identity.ap-northeast-2.amazonaws.com",partition:"aws"};break;case"ap-south-1":n={hostname:"cognito-identity.ap-south-1.amazonaws.com",partition:"aws"};break;case"ap-southeast-1":n={hostname:"cognito-identity.ap-southeast-1.amazonaws.com",partition:"aws"};break;case"ap-southeast-2":n={hostname:"cognito-identity.ap-southeast-2.amazonaws.com",partition:"aws"};break;case"ca-central-1":n={hostname:"cognito-identity.ca-central-1.amazonaws.com",partition:"aws"};break;case"cn-north-1":n={hostname:"cognito-identity.cn-north-1.amazonaws.com.cn",partition:"aws-cn"};break;case"eu-central-1":n={hostname:"cognito-identity.eu-central-1.amazonaws.com",partition:"aws"};break;case"eu-west-1":n={hostname:"cognito-identity.eu-west-1.amazonaws.com",partition:"aws"};break;case"eu-west-2":n={hostname:"cognito-identity.eu-west-2.amazonaws.com",partition:"aws"};break;case"us-east-1":n={hostname:"cognito-identity.us-east-1.amazonaws.com",partition:"aws"};break;case"us-east-2":n={hostname:"cognito-identity.us-east-2.amazonaws.com",partition:"aws"};break;case"us-west-2":n={hostname:"cognito-identity.us-west-2.amazonaws.com",partition:"aws"};break;default:bt.has(e)&&(n={hostname:mt.replace("{region}",e),partition:"aws"}),yt.has(e)&&(n={hostname:"cognito-identity.{region}.amazonaws.com.cn".replace("{region}",e),partition:"aws-cn"}),wt.has(e)&&(n={hostname:"cognito-identity.{region}.c2s.ic.gov".replace("{region}",e),partition:"aws-iso"}),_t.has(e)&&(n={hostname:"cognito-identity.{region}.sc2s.sgov.gov".replace("{region}",e),partition:"aws-iso-b"}),St.has(e)&&(n={hostname:"cognito-identity.{region}.amazonaws.com".replace("{region}",e),partition:"aws-us-gov"}),void 0===n&&(n={hostname:mt.replace("{region}",e),partition:"aws"})}return Promise.resolve(n)},signingName:"cognito-identity"}),{runtime:"browser",base64Decoder:ht.a,base64Encoder:ht.b,bodyLengthChecker:pt.a,credentialDefaultProvider:function(){},defaultUserAgent:Object(vt.a)(at.name,at.version),maxAttempts:lt.a,region:Object(ft.a)("Region is missing"),requestHandler:new ct.a,sha256:ut.Sha256,streamCollector:ct.b,urlParser:dt.a,utf8Decoder:gt.a,utf8Encoder:gt.b}),Mt=n(22),At=n(37),It=n(21),kt=n(43),Ot=n(25),xt=n(23),Ct=function(e){function t(t){var n=this,r=h(h({},Et),t),i=Object(Mt.b)(r),o=Object(Mt.a)(i),s=Object(Ot.b)(o),a=Object(lt.c)(s),u=Object(xt.b)(a),c=Object(It.b)(u);return(n=e.call(this,c)||this).config=c,n.middlewareStack.use(Object(lt.b)(n.config)),n.middlewareStack.use(Object(xt.a)(n.config)),n.middlewareStack.use(Object(At.a)(n.config)),n.middlewareStack.use(Object(It.a)(n.config)),n.middlewareStack.use(Object(kt.a)(n.config)),n}return d(t,e),t.prototype.destroy=function(){e.prototype.destroy.call(this)},t}(Xe.a),Tt=function(){return(Tt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},Pt=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},Nt=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},Rt=new r.a("Credentials"),Lt=new(function(){function e(e){this._gettingCredPromise=null,this._refreshHandlers={},this.Auth=void 0,this.configure(e),this._refreshHandlers.google=s.b.refreshGoogleToken,this._refreshHandlers.facebook=s.a.refreshFacebookToken}return e.prototype.getModuleName=function(){return"Credentials"},e.prototype.getCredSource=function(){return this._credentials_source},e.prototype.configure=function(e){if(!e)return this._config||{};this._config=Object.assign({},this._config,e);var t=this._config.refreshHandlers;return t&&(this._refreshHandlers=Tt(Tt({},this._refreshHandlers),t)),this._storage=this._config.storage,this._storage||(this._storage=(new i.a).getStorage()),this._storageSync=Promise.resolve(),"function"==typeof this._storage.sync&&(this._storageSync=this._storage.sync()),this._config},e.prototype.get=function(){return Rt.debug("getting credentials"),this._pickupCredentials()},e.prototype._pickupCredentials=function(){return Rt.debug("picking up credentials"),this._gettingCredPromise&&this._gettingCredPromise.isPending()?Rt.debug("getting old cred promise"):(Rt.debug("getting new cred promise"),this._gettingCredPromise=Object(o.d)(this._keepAlive())),this._gettingCredPromise},e.prototype._keepAlive=function(){return Pt(this,void 0,void 0,(function(){var e,t,n,r,i,o,s;return Nt(this,(function(a){switch(a.label){case 0:if(Rt.debug("checking if credentials exists and not expired"),(e=this._credentials)&&!this._isExpired(e)&&!this._isPastTTL())return Rt.debug("credentials not changed and not expired, directly return"),[2,Promise.resolve(e)];if(Rt.debug("need to get a new credential or refresh the existing one"),t=this.Auth,!(n=void 0===t?c.a.Auth:t)||"function"!=typeof n.currentUserCredentials)return[2,Promise.reject("No Auth module registered in Amplify")];if(this._isExpired(e)||!this._isPastTTL())return[3,6];Rt.debug("ttl has passed but token is not yet expired"),a.label=1;case 1:return a.trys.push([1,5,,6]),[4,n.currentUserPoolUser()];case 2:return r=a.sent(),[4,n.currentSession()];case 3:return i=a.sent(),o=i.refreshToken,[4,new Promise((function(e,t){r.refreshSession(o,(function(n,r){return n?t(n):e(r)}))}))];case 4:return a.sent(),[3,6];case 5:return s=a.sent(),Rt.debug("Error attempting to refreshing the session",s),[3,6];case 6:return[2,n.currentUserCredentials()]}}))}))},e.prototype.refreshFederatedToken=function(e){Rt.debug("Getting federated credentials");var t=e.provider,n=e.user,r=e.token,i=e.identity_id,o=e.expires_at;o=1970===new Date(o).getFullYear()?1e3*o:o;return Rt.debug("checking if federated jwt token expired"),o>(new Date).getTime()?(Rt.debug("token not expired"),this._setCredentialsFromFederation({provider:t,token:r,user:n,identity_id:i,expires_at:o})):this._refreshHandlers[t]&&"function"==typeof this._refreshHandlers[t]?(Rt.debug("getting refreshed jwt token from federation provider"),this._providerRefreshWithRetry({refreshHandler:this._refreshHandlers[t],provider:t,user:n})):(Rt.debug("no refresh handler for provider:",t),this.clear(),Promise.reject("no refresh handler for provider"))},e.prototype._providerRefreshWithRetry=function(e){var t=this,n=e.refreshHandler,r=e.provider,i=e.user;return Object(a.b)(n,[],1e4).then((function(e){return Rt.debug("refresh federated token sucessfully",e),t._setCredentialsFromFederation({provider:r,token:e.token,user:i,identity_id:e.identity_id,expires_at:e.expires_at})})).catch((function(e){return"string"==typeof e&&0===e.toLowerCase().lastIndexOf("network error",e.length)||t.clear(),Rt.debug("refresh federated token failed",e),Promise.reject("refreshing federation token failed: "+e)}))},e.prototype._isExpired=function(e){if(!e)return Rt.debug("no credentials for expiration check"),!0;Rt.debug("are these credentials expired?",e);var t=Date.now();return e.expiration.getTime()<=t},e.prototype._isPastTTL=function(){return this._nextCredentialsRefresh<=Date.now()},e.prototype._setCredentialsForGuest=function(){return Pt(this,void 0,void 0,(function(){var e,t,n,r,i,o,s,a=this;return Nt(this,(function(c){switch(c.label){case 0:if(Rt.debug("setting credentials for guest"),e=this._config,t=e.identityPoolId,n=e.region,e.mandatorySignIn)return[2,Promise.reject("cannot get guest credentials when mandatory signin enabled")];if(!t)return Rt.debug("No Cognito Identity pool provided for unauthenticated access"),[2,Promise.reject("No Cognito Identity pool provided for unauthenticated access")];if(!n)return Rt.debug("region is not configured for getting the credentials"),[2,Promise.reject("region is not configured for getting the credentials")];r=void 0,c.label=1;case 1:return c.trys.push([1,3,,4]),[4,this._storageSync];case 2:return c.sent(),r=this._storage.getItem("CognitoIdentityId-"+t),this._identityId=r,[3,4];case 3:return i=c.sent(),Rt.debug("Failed to get the cached identityId",i),[3,4];case 4:return o=new Ct({region:n,customUserAgent:Object(u.b)()}),s=void 0,s=r?nt({identityId:r,client:o})():function(){return Pt(a,void 0,void 0,(function(){var e;return Nt(this,(function(n){switch(n.label){case 0:return[4,o.send(new rt({IdentityPoolId:t}))];case 1:return e=n.sent().IdentityId,this._identityId=e,[2,nt({client:o,identityId:e})()]}}))}))}().catch((function(e){return Pt(a,void 0,void 0,(function(){return Nt(this,(function(t){throw e}))}))})),[2,this._loadCredentials(s,"guest",!1,null).then((function(e){return e})).catch((function(e){return Pt(a,void 0,void 0,(function(){var n=this;return Nt(this,(function(i){return"ResourceNotFoundException"===e.name&&e.message==="Identity '"+r+"' not found."?(Rt.debug("Failed to load guest credentials"),this._storage.removeItem("CognitoIdentityId-"+t),s=function(){return Pt(n,void 0,void 0,(function(){var e;return Nt(this,(function(n){switch(n.label){case 0:return[4,o.send(new rt({IdentityPoolId:t}))];case 1:return e=n.sent().IdentityId,this._identityId=e,[2,nt({client:o,identityId:e})()]}}))}))}().catch((function(e){return Pt(n,void 0,void 0,(function(){return Nt(this,(function(t){throw e}))}))})),[2,this._loadCredentials(s,"guest",!1,null)]):[2,e]}))}))}))]}}))}))},e.prototype._setCredentialsFromFederation=function(e){var t=e.provider,n=e.token,r=e.identity_id,i={google:"accounts.google.com",facebook:"graph.facebook.com",amazon:"www.amazon.com",developer:"cognito-identity.amazonaws.com"}[t]||t;if(!i)return Promise.reject("You must specify a federated provider");var o={};o[i]=n;var s=this._config,a=s.identityPoolId,c=s.region;if(!a)return Rt.debug("No Cognito Federated Identity pool provided"),Promise.reject("No Cognito Federated Identity pool provided");if(!c)return Rt.debug("region is not configured for getting the credentials"),Promise.reject("region is not configured for getting the credentials");var f=new Ct({region:c,customUserAgent:Object(u.b)()}),l=void 0;r?l=nt({identityId:r,logins:o,client:f})():l=st({logins:o,identityPoolId:a,client:f})();return this._loadCredentials(l,"federated",!0,e)},e.prototype._setCredentialsFromSession=function(e){var t=this;Rt.debug("set credentials from session");var n=e.getIdToken().getJwtToken(),r=this._config,i=r.region,o=r.userPoolId,s=r.identityPoolId;if(!s)return Rt.debug("No Cognito Federated Identity pool provided"),Promise.reject("No Cognito Federated Identity pool provided");if(!i)return Rt.debug("region is not configured for getting the credentials"),Promise.reject("region is not configured for getting the credentials");var a={};a["cognito-idp."+i+".amazonaws.com/"+o]=n;var c=new Ct({region:i,customUserAgent:Object(u.b)()}),f=Pt(t,void 0,void 0,(function(){var e;return Nt(this,(function(t){switch(t.label){case 0:return[4,c.send(new rt({IdentityPoolId:s,Logins:a}))];case 1:return e=t.sent().IdentityId,this._identityId=e,[2,nt({client:c,logins:a,identityId:e})()]}}))})).catch((function(e){return Pt(t,void 0,void 0,(function(){return Nt(this,(function(t){throw e}))}))}));return this._loadCredentials(f,"userPool",!0,null)},e.prototype._loadCredentials=function(e,t,n,r){var i=this,o=this,s=this._config.identityPoolId;return new Promise((function(a,u){e.then((function(e){return Pt(i,void 0,void 0,(function(){var i,u,c,f,l,d;return Nt(this,(function(h){switch(h.label){case 0:if(Rt.debug("Load credentials successfully",e),this._identityId&&!e.identityId&&(e.identityId=this._identityId),o._credentials=e,o._credentials.authenticated=n,o._credentials_source=t,o._nextCredentialsRefresh=(new Date).getTime()+3e6,"federated"===t){i=Object.assign({id:this._credentials.identityId},r.user),u=r.provider,c=r.token,f=r.expires_at,l=r.identity_id;try{this._storage.setItem("aws-amplify-federatedInfo",JSON.stringify({provider:u,token:c,user:i,expires_at:f,identity_id:l}))}catch(e){Rt.debug("Failed to put federated info into auth storage",e)}}if("guest"!==t)return[3,4];h.label=1;case 1:return h.trys.push([1,3,,4]),[4,this._storageSync];case 2:return h.sent(),this._storage.setItem("CognitoIdentityId-"+s,e.identityId),[3,4];case 3:return d=h.sent(),Rt.debug("Failed to cache identityId",d),[3,4];case 4:return a(o._credentials),[2]}}))}))})).catch((function(t){if(t)return Rt.debug("Failed to load credentials",e),Rt.debug("Error loading credentials",t),void u(t)}))}))},e.prototype.set=function(e,t){return"session"===t?this._setCredentialsFromSession(e):"federation"===t?this._setCredentialsFromFederation(e):"guest"===t?this._setCredentialsForGuest():(Rt.debug("no source specified for setting credentials"),Promise.reject("invalid source"))},e.prototype.clear=function(){return Pt(this,void 0,void 0,(function(){return Nt(this,(function(e){return this._credentials=null,this._credentials_source=null,Rt.debug("removing aws-amplify-federatedInfo from storage"),this._storage.removeItem("aws-amplify-federatedInfo"),[2]}))}))},e.prototype.shear=function(e){return{accessKeyId:e.accessKeyId,sessionToken:e.sessionToken,secretAccessKey:e.secretAccessKey,identityId:e.identityId,authenticated:e.authenticated}},e}())(null);c.a.register(Lt)},function(e,t,n){var r,i,o;e.exports=(o=n(32),i=(r=o).lib.WordArray,r.enc.Base64={stringify:function(e){var t=e.words,n=e.sigBytes,r=this._map;e.clamp();for(var i=[],o=0;o<n;o+=3)for(var s=(t[o>>>2]>>>24-o%4*8&255)<<16|(t[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|t[o+2>>>2]>>>24-(o+2)%4*8&255,a=0;a<4&&o+.75*a<n;a++)i.push(r.charAt(s>>>6*(3-a)&63));var u=r.charAt(64);if(u)for(;i.length%4;)i.push(u);return i.join("")},parse:function(e){var t=e.length,n=this._map,r=this._reverseMap;if(!r){r=this._reverseMap=[];for(var o=0;o<n.length;o++)r[n.charCodeAt(o)]=o}var s=n.charAt(64);if(s){var a=e.indexOf(s);-1!==a&&(t=a)}return function(e,t,n){for(var r=[],o=0,s=0;s<t;s++)if(s%4){var a=n[e.charCodeAt(s-1)]<<s%4*2,u=n[e.charCodeAt(s)]>>>6-s%4*2;r[o>>>2]|=(a|u)<<24-o%4*8,o++}return i.create(r,o)}(e,t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},o.enc.Base64)},function(e,t,n){"use strict";function r(e,t){for(var n,r=/\r\n|[\n\r]/g,i=1,o=t+1;(n=r.exec(e.body))&&n.index<t;)i+=1,o=t+1-(n.index+n[0].length);return{line:i,column:o}}function i(e,t){var n=e.locationOffset.column-1,r=o(n)+e.body,i=t.line-1,s=e.locationOffset.line-1,a=t.line+s,u=1===t.line?n:0,c=t.column+u,f=r.split(/\r\n|[\n\r]/g);return"".concat(e.name," (").concat(a,":").concat(c,")\n")+function(e){var t=e.filter((function(e){e[0];return void 0!==e[1]})),n=0,r=!0,i=!1,s=void 0;try{for(var a,u=t[Symbol.iterator]();!(r=(a=u.next()).done);r=!0){var c=a.value[0];n=Math.max(n,c.length)}}catch(e){i=!0,s=e}finally{try{r||null==u.return||u.return()}finally{if(i)throw s}}return t.map((function(e){var t,r=e[0],i=e[1];return o(n-(t=r).length)+t+i})).join("\n")}([["".concat(a-1,": "),f[i-1]],["".concat(a,": "),f[i]],["",o(c-1)+"^"],["".concat(a+1,": "),f[i+1]]])}function o(e){return Array(e+1).join(" ")}function s(e,t,n,i,o,a,u){var c=Array.isArray(t)?0!==t.length?t:void 0:t?[t]:void 0,f=n;if(!f&&c){var l=c[0];f=l&&l.loc&&l.loc.source}var d,h=i;!h&&c&&(h=c.reduce((function(e,t){return t.loc&&e.push(t.loc.start),e}),[])),h&&0===h.length&&(h=void 0),i&&n?d=i.map((function(e){return r(n,e)})):c&&(d=c.reduce((function(e,t){return t.loc&&e.push(r(t.loc.source,t.loc.start)),e}),[]));var p=u||a&&a.extensions;Object.defineProperties(this,{message:{value:e,enumerable:!0,writable:!0},locations:{value:d||void 0,enumerable:Boolean(d)},path:{value:o||void 0,enumerable:Boolean(o)},nodes:{value:c||void 0},source:{value:f||void 0},positions:{value:h||void 0},originalError:{value:a},extensions:{value:p||void 0,enumerable:Boolean(p)}}),a&&a.stack?Object.defineProperty(this,"stack",{value:a.stack,writable:!0,configurable:!0}):Error.captureStackTrace?Error.captureStackTrace(this,s):Object.defineProperty(this,"stack",{value:Error().stack,writable:!0,configurable:!0})}n.d(t,"a",(function(){return s})),s.prototype=Object.create(Error.prototype,{constructor:{value:s},name:{value:"GraphQLError"},toString:{value:function(){return function(e){var t=[];if(e.nodes){var n=!0,o=!1,s=void 0;try{for(var a,u=e.nodes[Symbol.iterator]();!(n=(a=u.next()).done);n=!0){var c=a.value;c.loc&&t.push(i(c.loc.source,r(c.loc.source,c.loc.start)))}}catch(e){o=!0,s=e}finally{try{n||null==u.return||u.return()}finally{if(o)throw s}}}else if(e.source&&e.locations){var f=e.source,l=!0,d=!1,h=void 0;try{for(var p,v=e.locations[Symbol.iterator]();!(l=(p=v.next()).done);l=!0){var g=p.value;t.push(i(f,g))}}catch(e){d=!0,h=e}finally{try{l||null==v.return||v.return()}finally{if(d)throw h}}}return 0===t.length?e.message:[e.message].concat(t).join("\n\n")+"\n"}(this)}}})},function(e,t,n){"use strict";(function(t){void 0===t||!t.version||0===t.version.indexOf("v0.")||0===t.version.indexOf("v1.")&&0!==t.version.indexOf("v1.8.")?e.exports={nextTick:function(e,n,r,i){if("function"!=typeof e)throw new TypeError('"callback" argument must be a function');var o,s,a=arguments.length;switch(a){case 0:case 1:return t.nextTick(e);case 2:return t.nextTick((function(){e.call(null,n)}));case 3:return t.nextTick((function(){e.call(null,n,r)}));case 4:return t.nextTick((function(){e.call(null,n,r,i)}));default:for(o=new Array(a-1),s=0;s<o.length;)o[s++]=arguments[s];return t.nextTick((function(){e.apply(null,o)}))}}}:e.exports=t}).call(this,n(20))},function(e,t,n){var r=n(8).Buffer;function i(e){r.isBuffer(e)||(e=r.from(e));for(var t=e.length/4|0,n=new Array(t),i=0;i<t;i++)n[i]=e.readUInt32BE(4*i);return n}function o(e){for(;0<e.length;e++)e[0]=0}function s(e,t,n,r,i){for(var o,s,a,u,c=n[0],f=n[1],l=n[2],d=n[3],h=e[0]^t[0],p=e[1]^t[1],v=e[2]^t[2],g=e[3]^t[3],m=4,b=1;b<i;b++)o=c[h>>>24]^f[p>>>16&255]^l[v>>>8&255]^d[255&g]^t[m++],s=c[p>>>24]^f[v>>>16&255]^l[g>>>8&255]^d[255&h]^t[m++],a=c[v>>>24]^f[g>>>16&255]^l[h>>>8&255]^d[255&p]^t[m++],u=c[g>>>24]^f[h>>>16&255]^l[p>>>8&255]^d[255&v]^t[m++],h=o,p=s,v=a,g=u;return o=(r[h>>>24]<<24|r[p>>>16&255]<<16|r[v>>>8&255]<<8|r[255&g])^t[m++],s=(r[p>>>24]<<24|r[v>>>16&255]<<16|r[g>>>8&255]<<8|r[255&h])^t[m++],a=(r[v>>>24]<<24|r[g>>>16&255]<<16|r[h>>>8&255]<<8|r[255&p])^t[m++],u=(r[g>>>24]<<24|r[h>>>16&255]<<16|r[p>>>8&255]<<8|r[255&v])^t[m++],[o>>>=0,s>>>=0,a>>>=0,u>>>=0]}var a=[0,1,2,4,8,16,32,64,128,27,54],u=function(){for(var e=new Array(256),t=0;t<256;t++)e[t]=t<128?t<<1:t<<1^283;for(var n=[],r=[],i=[[],[],[],[]],o=[[],[],[],[]],s=0,a=0,u=0;u<256;++u){var c=a^a<<1^a<<2^a<<3^a<<4;c=c>>>8^255&c^99,n[s]=c,r[c]=s;var f=e[s],l=e[f],d=e[l],h=257*e[c]^16843008*c;i[0][s]=h<<24|h>>>8,i[1][s]=h<<16|h>>>16,i[2][s]=h<<8|h>>>24,i[3][s]=h,h=16843009*d^65537*l^257*f^16843008*s,o[0][c]=h<<24|h>>>8,o[1][c]=h<<16|h>>>16,o[2][c]=h<<8|h>>>24,o[3][c]=h,0===s?s=a=1:(s=f^e[e[e[d^f]]],a^=e[e[a]])}return{SBOX:n,INV_SBOX:r,SUB_MIX:i,INV_SUB_MIX:o}}();function c(e){this._key=i(e),this._reset()}c.blockSize=16,c.keySize=32,c.prototype.blockSize=c.blockSize,c.prototype.keySize=c.keySize,c.prototype._reset=function(){for(var e=this._key,t=e.length,n=t+6,r=4*(n+1),i=[],o=0;o<t;o++)i[o]=e[o];for(o=t;o<r;o++){var s=i[o-1];o%t==0?(s=s<<8|s>>>24,s=u.SBOX[s>>>24]<<24|u.SBOX[s>>>16&255]<<16|u.SBOX[s>>>8&255]<<8|u.SBOX[255&s],s^=a[o/t|0]<<24):t>6&&o%t==4&&(s=u.SBOX[s>>>24]<<24|u.SBOX[s>>>16&255]<<16|u.SBOX[s>>>8&255]<<8|u.SBOX[255&s]),i[o]=i[o-t]^s}for(var c=[],f=0;f<r;f++){var l=r-f,d=i[l-(f%4?0:4)];c[f]=f<4||l<=4?d:u.INV_SUB_MIX[0][u.SBOX[d>>>24]]^u.INV_SUB_MIX[1][u.SBOX[d>>>16&255]]^u.INV_SUB_MIX[2][u.SBOX[d>>>8&255]]^u.INV_SUB_MIX[3][u.SBOX[255&d]]}this._nRounds=n,this._keySchedule=i,this._invKeySchedule=c},c.prototype.encryptBlockRaw=function(e){return s(e=i(e),this._keySchedule,u.SUB_MIX,u.SBOX,this._nRounds)},c.prototype.encryptBlock=function(e){var t=this.encryptBlockRaw(e),n=r.allocUnsafe(16);return n.writeUInt32BE(t[0],0),n.writeUInt32BE(t[1],4),n.writeUInt32BE(t[2],8),n.writeUInt32BE(t[3],12),n},c.prototype.decryptBlock=function(e){var t=(e=i(e))[1];e[1]=e[3],e[3]=t;var n=s(e,this._invKeySchedule,u.INV_SUB_MIX,u.INV_SBOX,this._nRounds),o=r.allocUnsafe(16);return o.writeUInt32BE(n[0],0),o.writeUInt32BE(n[3],4),o.writeUInt32BE(n[2],8),o.writeUInt32BE(n[1],12),o},c.prototype.scrub=function(){o(this._keySchedule),o(this._invKeySchedule),o(this._key)},e.exports.AES=c},function(e,t,n){var r=n(8).Buffer,i=n(113);e.exports=function(e,t,n,o){if(r.isBuffer(e)||(e=r.from(e,"binary")),t&&(r.isBuffer(t)||(t=r.from(t,"binary")),8!==t.length))throw new RangeError("salt should be Buffer with 8 byte length");for(var s=n/8,a=r.alloc(s),u=r.alloc(o||0),c=r.alloc(0);s>0||o>0;){var f=new i;f.update(c),f.update(e),t&&f.update(t),c=f.digest();var l=0;if(s>0){var d=a.length-s;l=Math.min(s,c.length),c.copy(a,d,0,l),s-=l}if(l<c.length&&o>0){var h=u.length-o,p=Math.min(o,c.length-l);c.copy(u,h,l,l+p),o-=p}}return c.fill(0),{key:a,iv:u}}},function(e,t,n){"use strict";var r=n(29),i=n(47),o=i.getNAF,s=i.getJSF,a=i.assert;function u(e,t){this.type=e,this.p=new r(t.p,16),this.red=t.prime?r.red(t.prime):r.mont(this.p),this.zero=new r(0).toRed(this.red),this.one=new r(1).toRed(this.red),this.two=new r(2).toRed(this.red),this.n=t.n&&new r(t.n,16),this.g=t.g&&this.pointFromJSON(t.g,t.gRed),this._wnafT1=new Array(4),this._wnafT2=new Array(4),this._wnafT3=new Array(4),this._wnafT4=new Array(4),this._bitLength=this.n?this.n.bitLength():0;var n=this.n&&this.p.div(this.n);!n||n.cmpn(100)>0?this.redN=null:(this._maxwellTrick=!0,this.redN=this.n.toRed(this.red))}function c(e,t){this.curve=e,this.type=t,this.precomputed=null}e.exports=u,u.prototype.point=function(){throw new Error("Not implemented")},u.prototype.validate=function(){throw new Error("Not implemented")},u.prototype._fixedNafMul=function(e,t){a(e.precomputed);var n=e._getDoubles(),r=o(t,1,this._bitLength),i=(1<<n.step+1)-(n.step%2==0?2:1);i/=3;var s,u,c=[];for(s=0;s<r.length;s+=n.step){u=0;for(var f=s+n.step-1;f>=s;f--)u=(u<<1)+r[f];c.push(u)}for(var l=this.jpoint(null,null,null),d=this.jpoint(null,null,null),h=i;h>0;h--){for(s=0;s<c.length;s++)(u=c[s])===h?d=d.mixedAdd(n.points[s]):u===-h&&(d=d.mixedAdd(n.points[s].neg()));l=l.add(d)}return l.toP()},u.prototype._wnafMul=function(e,t){var n=4,r=e._getNAFPoints(n);n=r.wnd;for(var i=r.points,s=o(t,n,this._bitLength),u=this.jpoint(null,null,null),c=s.length-1;c>=0;c--){for(var f=0;c>=0&&0===s[c];c--)f++;if(c>=0&&f++,u=u.dblp(f),c<0)break;var l=s[c];a(0!==l),u="affine"===e.type?l>0?u.mixedAdd(i[l-1>>1]):u.mixedAdd(i[-l-1>>1].neg()):l>0?u.add(i[l-1>>1]):u.add(i[-l-1>>1].neg())}return"affine"===e.type?u.toP():u},u.prototype._wnafMulAdd=function(e,t,n,r,i){var a,u,c,f=this._wnafT1,l=this._wnafT2,d=this._wnafT3,h=0;for(a=0;a<r;a++){var p=(c=t[a])._getNAFPoints(e);f[a]=p.wnd,l[a]=p.points}for(a=r-1;a>=1;a-=2){var v=a-1,g=a;if(1===f[v]&&1===f[g]){var m=[t[v],null,null,t[g]];0===t[v].y.cmp(t[g].y)?(m[1]=t[v].add(t[g]),m[2]=t[v].toJ().mixedAdd(t[g].neg())):0===t[v].y.cmp(t[g].y.redNeg())?(m[1]=t[v].toJ().mixedAdd(t[g]),m[2]=t[v].add(t[g].neg())):(m[1]=t[v].toJ().mixedAdd(t[g]),m[2]=t[v].toJ().mixedAdd(t[g].neg()));var b=[-3,-1,-5,-7,0,7,5,1,3],y=s(n[v],n[g]);for(h=Math.max(y[0].length,h),d[v]=new Array(h),d[g]=new Array(h),u=0;u<h;u++){var w=0|y[0][u],_=0|y[1][u];d[v][u]=b[3*(w+1)+(_+1)],d[g][u]=0,l[v]=m}}else d[v]=o(n[v],f[v],this._bitLength),d[g]=o(n[g],f[g],this._bitLength),h=Math.max(d[v].length,h),h=Math.max(d[g].length,h)}var S=this.jpoint(null,null,null),E=this._wnafT4;for(a=h;a>=0;a--){for(var M=0;a>=0;){var A=!0;for(u=0;u<r;u++)E[u]=0|d[u][a],0!==E[u]&&(A=!1);if(!A)break;M++,a--}if(a>=0&&M++,S=S.dblp(M),a<0)break;for(u=0;u<r;u++){var I=E[u];0!==I&&(I>0?c=l[u][I-1>>1]:I<0&&(c=l[u][-I-1>>1].neg()),S="affine"===c.type?S.mixedAdd(c):S.add(c))}}for(a=0;a<r;a++)l[a]=null;return i?S:S.toP()},u.BasePoint=c,c.prototype.eq=function(){throw new Error("Not implemented")},c.prototype.validate=function(){return this.curve.validate(this)},u.prototype.decodePoint=function(e,t){e=i.toArray(e,t);var n=this.p.byteLength();if((4===e[0]||6===e[0]||7===e[0])&&e.length-1==2*n)return 6===e[0]?a(e[e.length-1]%2==0):7===e[0]&&a(e[e.length-1]%2==1),this.point(e.slice(1,1+n),e.slice(1+n,1+2*n));if((2===e[0]||3===e[0])&&e.length-1===n)return this.pointFromX(e.slice(1,1+n),3===e[0]);throw new Error("Unknown point format")},c.prototype.encodeCompressed=function(e){return this.encode(e,!0)},c.prototype._encode=function(e){var t=this.curve.p.byteLength(),n=this.getX().toArray("be",t);return e?[this.getY().isEven()?2:3].concat(n):[4].concat(n,this.getY().toArray("be",t))},c.prototype.encode=function(e,t){return i.encode(this._encode(t),e)},c.prototype.precompute=function(e){if(this.precomputed)return this;var t={doubles:null,naf:null,beta:null};return t.naf=this._getNAFPoints(8),t.doubles=this._getDoubles(4,e),t.beta=this._getBeta(),this.precomputed=t,this},c.prototype._hasDoubles=function(e){if(!this.precomputed)return!1;var t=this.precomputed.doubles;return!!t&&t.points.length>=Math.ceil((e.bitLength()+1)/t.step)},c.prototype._getDoubles=function(e,t){if(this.precomputed&&this.precomputed.doubles)return this.precomputed.doubles;for(var n=[this],r=this,i=0;i<t;i+=e){for(var o=0;o<e;o++)r=r.dbl();n.push(r)}return{step:e,points:n}},c.prototype._getNAFPoints=function(e){if(this.precomputed&&this.precomputed.naf)return this.precomputed.naf;for(var t=[this],n=(1<<e)-1,r=1===n?null:this.dbl(),i=1;i<n;i++)t[i]=t[i-1].add(r);return{wnd:e,points:t}},c.prototype._getBeta=function(){return null},c.prototype.dblp=function(e){for(var t=this,n=0;n<e;n++)t=t.dbl();return t}},function(e,t,n){var r=n(350),i=n(357),o=n(358),s=n(122),a=n(178),u=n(8).Buffer;function c(e){var t;"object"!=typeof e||u.isBuffer(e)||(t=e.passphrase,e=e.key),"string"==typeof e&&(e=u.from(e));var n,c,f=o(e,t),l=f.tag,d=f.data;switch(l){case"CERTIFICATE":c=r.certificate.decode(d,"der").tbsCertificate.subjectPublicKeyInfo;case"PUBLIC KEY":switch(c||(c=r.PublicKey.decode(d,"der")),n=c.algorithm.algorithm.join(".")){case"1.2.840.113549.1.1.1":return r.RSAPublicKey.decode(c.subjectPublicKey.data,"der");case"1.2.840.10045.2.1":return c.subjectPrivateKey=c.subjectPublicKey,{type:"ec",data:c};case"1.2.840.10040.4.1":return c.algorithm.params.pub_key=r.DSAparam.decode(c.subjectPublicKey.data,"der"),{type:"dsa",data:c.algorithm.params};default:throw new Error("unknown key id "+n)}case"ENCRYPTED PRIVATE KEY":d=function(e,t){var n=e.algorithm.decrypt.kde.kdeparams.salt,r=parseInt(e.algorithm.decrypt.kde.kdeparams.iters.toString(),10),o=i[e.algorithm.decrypt.cipher.algo.join(".")],c=e.algorithm.decrypt.cipher.iv,f=e.subjectPrivateKey,l=parseInt(o.split("-")[1],10)/8,d=a.pbkdf2Sync(t,n,r,l,"sha1"),h=s.createDecipheriv(o,d,c),p=[];return p.push(h.update(f)),p.push(h.final()),u.concat(p)}(d=r.EncryptedPrivateKey.decode(d,"der"),t);case"PRIVATE KEY":switch(n=(c=r.PrivateKey.decode(d,"der")).algorithm.algorithm.join(".")){case"1.2.840.113549.1.1.1":return r.RSAPrivateKey.decode(c.subjectPrivateKey,"der");case"1.2.840.10045.2.1":return{curve:c.algorithm.curve,privateKey:r.ECPrivateKey.decode(c.subjectPrivateKey,"der").privateKey};case"1.2.840.10040.4.1":return c.algorithm.params.priv_key=r.DSAparam.decode(c.subjectPrivateKey,"der"),{type:"dsa",params:c.algorithm.params};default:throw new Error("unknown key id "+n)}case"RSA PUBLIC KEY":return r.RSAPublicKey.decode(d,"der");case"RSA PRIVATE KEY":return r.RSAPrivateKey.decode(d,"der");case"DSA PRIVATE KEY":return{type:"dsa",params:r.DSAPrivateKey.decode(d,"der")};case"EC PRIVATE KEY":return{curve:(d=r.ECPrivateKey.decode(d,"der")).parameters.value,privateKey:d.privateKey};default:throw new Error("unknown key type "+l)}}e.exports=c,c.signature=r.signature},function(e,t,n){var r=n(53).Symbol;e.exports=r},function(e,t,n){var r=n(72)(Object,"create");e.exports=r},function(e,t,n){var r=n(406),i=n(407),o=n(408),s=n(409),a=n(410);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}u.prototype.clear=r,u.prototype.delete=i,u.prototype.get=o,u.prototype.has=s,u.prototype.set=a,e.exports=u},function(e,t,n){var r=n(227);e.exports=function(e,t){for(var n=e.length;n--;)if(r(e[n][0],t))return n;return-1}},function(e,t,n){var r=n(412);e.exports=function(e,t){var n=e.__data__;return r(t)?n["string"==typeof t?"string":"hash"]:n.map}},function(e,t,n){"use strict";const r=n(54),i=n(54).buildOptions,o=n(460);"<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\/)(NAME)\\s*>))([^<]*)".replace(/NAME/g,r.nameRegexp);!Number.parseInt&&window.parseInt&&(Number.parseInt=window.parseInt),!Number.parseFloat&&window.parseFloat&&(Number.parseFloat=window.parseFloat);const s={attributeNamePrefix:"@_",attrNodeName:!1,textNodeName:"#text",ignoreAttributes:!0,ignoreNameSpace:!1,allowBooleanAttributes:!1,parseNodeValue:!0,parseAttributeValue:!1,arrayMode:!1,trimValues:!0,cdataTagName:!1,cdataPositionChar:"\\c",tagValueProcessor:function(e,t){return e},attrValueProcessor:function(e,t){return e},stopNodes:[]};t.defaultOptions=s;const a=["attributeNamePrefix","attrNodeName","textNodeName","ignoreAttributes","ignoreNameSpace","allowBooleanAttributes","parseNodeValue","parseAttributeValue","arrayMode","trimValues","cdataTagName","cdataPositionChar","tagValueProcessor","attrValueProcessor","parseTrueNumberOnly","stopNodes"];function u(e,t,n){return t&&(n.trimValues&&(t=t.trim()),t=f(t=n.tagValueProcessor(t,e),n.parseNodeValue,n.parseTrueNumberOnly)),t}function c(e,t){if(t.ignoreNameSpace){const t=e.split(":"),n="/"===e.charAt(0)?"/":"";if("xmlns"===t[0])return"";2===t.length&&(e=n+t[1])}return e}function f(e,t,n){if(t&&"string"==typeof e){let t;return""===e.trim()||isNaN(e)?t="true"===e||"false"!==e&&e:(-1!==e.indexOf("0x")?t=Number.parseInt(e,16):-1!==e.indexOf(".")?(t=Number.parseFloat(e),e=e.replace(/\.?0+$/,"")):t=Number.parseInt(e,10),n&&(t=String(t)===e?t:e)),t}return r.isExist(e)?e:""}t.props=a;const l=new RegExp("([^\\s=]+)\\s*(=\\s*(['\"])(.*?)\\3)?","g");function d(e,t){if(!t.ignoreAttributes&&"string"==typeof e){e=e.replace(/\r?\n/g," ");const n=r.getAllMatches(e,l),i=n.length,o={};for(let e=0;e<i;e++){const r=c(n[e][1],t);r.length&&(void 0!==n[e][4]?(t.trimValues&&(n[e][4]=n[e][4].trim()),n[e][4]=t.attrValueProcessor(n[e][4],r),o[t.attributeNamePrefix+r]=f(n[e][4],t.parseAttributeValue,t.parseTrueNumberOnly)):t.allowBooleanAttributes&&(o[t.attributeNamePrefix+r]=!0))}if(!Object.keys(o).length)return;if(t.attrNodeName){const e={};return e[t.attrNodeName]=o,e}return o}}function h(e,t){let n,r="";for(let i=t;i<e.length;i++){let t=e[i];if(n)t===n&&(n="");else if('"'===t||"'"===t)n=t;else{if(">"===t)return{data:r,index:i};"\t"===t&&(t=" ")}r+=t}}function p(e,t,n,r){const i=e.indexOf(t,n);if(-1===i)throw new Error(r);return i+t.length-1}t.getTraversalObj=function(e,t){e=e.replace(/\r\n?/g,"\n"),t=i(t,s,a);const n=new o("!xml");let c=n,f="";for(let n=0;n<e.length;n++){if("<"===e[n])if("/"===e[n+1]){const i=p(e,">",n,"Closing Tag is not closed.");let o=e.substring(n+2,i).trim();if(t.ignoreNameSpace){const e=o.indexOf(":");-1!==e&&(o=o.substr(e+1))}c&&(c.val?c.val=r.getValue(c.val)+""+u(o,f,t):c.val=u(o,f,t)),t.stopNodes.length&&t.stopNodes.includes(c.tagname)&&(c.child=[],null==c.attrsMap&&(c.attrsMap={}),c.val=e.substr(c.startIndex+1,n-c.startIndex-1)),c=c.parent,f="",n=i}else if("?"===e[n+1])n=p(e,"?>",n,"Pi Tag is not closed.");else if("!--"===e.substr(n+1,3))n=p(e,"--\x3e",n,"Comment is not closed.");else if("!D"===e.substr(n+1,2)){const t=p(e,">",n,"DOCTYPE is not closed.");n=e.substring(n,t).indexOf("[")>=0?e.indexOf("]>",n)+1:t}else if("!["===e.substr(n+1,2)){const i=p(e,"]]>",n,"CDATA is not closed.")-2,s=e.substring(n+9,i);if(f&&(c.val=r.getValue(c.val)+""+u(c.tagname,f,t),f=""),t.cdataTagName){const e=new o(t.cdataTagName,c,s);c.addChild(e),c.val=r.getValue(c.val)+t.cdataPositionChar,s&&(e.val=s)}else c.val=(c.val||"")+(s||"");n=i+2}else{const i=h(e,n+1);let s=i.data;const a=i.index,l=s.indexOf(" ");let p=s;if(-1!==l&&(p=s.substr(0,l).replace(/\s\s*$/,""),s=s.substr(l+1)),t.ignoreNameSpace){const e=p.indexOf(":");-1!==e&&(p=p.substr(e+1))}if(c&&f&&"!xml"!==c.tagname&&(c.val=r.getValue(c.val)+""+u(c.tagname,f,t)),s.length>0&&s.lastIndexOf("/")===s.length-1){"/"===p[p.length-1]?(p=p.substr(0,p.length-1),s=p):s=s.substr(0,s.length-1);const e=new o(p,c,"");p!==s&&(e.attrsMap=d(s,t)),c.addChild(e)}else{const e=new o(p,c);t.stopNodes.length&&t.stopNodes.includes(e.tagname)&&(e.startIndex=a),p!==s&&(e.attrsMap=d(s,t)),c.addChild(e),c=e}f="",n=a}else f+=e[n]}return n}},function(e,t,n){"use strict";n.d(t,"a",(function(){return i})),n.d(t,"b",(function(){return o})),n.d(t,"c",(function(){return s}));var r="undefined"!=typeof Symbol&&"function"==typeof Symbol.for,i=r?Symbol.for("INTERNAL_AWS_APPSYNC_PUBSUB_PROVIDER"):"@@INTERNAL_AWS_APPSYNC_PUBSUB_PROVIDER",o=r?Symbol.for("INTERNAL_AWS_APPSYNC_REALTIME_PUBSUB_PROVIDER"):"@@INTERNAL_AWS_APPSYNC_REALTIME_PUBSUB_PROVIDER",s="x-amz-user-agent"},function(e,t,n){"use strict";n.d(t,"a",(function(){return _}));var r=n(44),i=n(148),o=n(28),s=n(16),a=n(77);function u(e){return(u="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var c=function(){return(c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},f=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n},l=new r.a("Signer"),d=function(e,t){var n=new i.Sha256(e);return n.update(t),n.digestSync()},h=function(e){var t=e||"",n=new i.Sha256;return n.update(t),Object(o.b)(n.digestSync())},p=function(e){return Object.keys(e).map((function(e){return e.toLowerCase()})).sort().join(";")},v=function(e){var t,n,r=Object(s.parse)(e.url);return[e.method||"/",encodeURIComponent(r.pathname).replace(/%2F/gi,"/"),(n=r.query,n&&0!==n.length?n.split("&").map((function(e){var t=e.split("=");if(1===t.length)return e;var n=t[1].replace(/[!'()*]/g,(function(e){return"%"+e.charCodeAt(0).toString(16).toUpperCase()}));return t[0]+"="+n})).sort((function(e,t){var n=e.split("=")[0],r=t.split("=")[0];return n===r?e<t?-1:1:n<r?-1:1})).join("&"):""),(t=e.headers,t&&0!==Object.keys(t).length?Object.keys(t).map((function(e){return{key:e.toLowerCase(),value:t[e]?t[e].trim().replace(/\s+/g," "):""}})).sort((function(e,t){return e.key<t.key?-1:1})).map((function(e){return e.key+":"+e.value})).join("\n")+"\n":""),p(e.headers),h(e.data)].join("\n")},g=function(e){var t=(Object(s.parse)(e.url).host.match(/([^\.]+)\.(?:([^\.]*)\.)?amazonaws\.com$/)||[]).slice(1,3);return"es"===t[1]&&(t=t.reverse()),{service:e.service||t[0],region:e.region||t[1]}},m=function(e,t,n){return[e,t,n,"aws4_request"].join("/")},b=function(e,t,n,r){return[e,n,r,h(t)].join("\n")},y=function(e,t,n){l.debug(n);var r=d("AWS4"+e,t),i=d(r,n.region),o=d(i,n.service);return d(o,"aws4_request")},w=function(e,t){return Object(o.b)(d(e,t))},_=function(){function e(){}return e.sign=function(e,t,n){void 0===n&&(n=null),e.headers=e.headers||{};var r=a.a.getDateWithClockOffset().toISOString().replace(/[:\-]|\.\d{3}/g,""),i=r.substr(0,8),o=Object(s.parse)(e.url);e.headers.host=o.host,e.headers["x-amz-date"]=r,t.session_token&&(e.headers["X-Amz-Security-Token"]=t.session_token);var u=v(e);l.debug(u);var c=n||g(e),f=m(i,c.region,c.service),d=b("AWS4-HMAC-SHA256",u,r,f),h=y(t.secret_key,i,c),_=w(h,d),S=function(e,t,n,r,i){return[e+" Credential="+t+"/"+n,"SignedHeaders="+r,"Signature="+i].join(", ")}("AWS4-HMAC-SHA256",t.access_key,f,p(e.headers),_);return e.headers.Authorization=S,e},e.signUrl=function(e,t,n,r){var i="object"===u(e)?e.url:e,o="object"===u(e)?e.method:"GET",l="object"===u(e)?e.body:void 0,d=a.a.getDateWithClockOffset().toISOString().replace(/[:\-]|\.\d{3}/g,""),h=d.substr(0,8),p=Object(s.parse)(i,!0,!0),_=(p.search,f(p,["search"])),S={host:_.host},E=n||g({url:Object(s.format)(_)}),M=E.region,A=E.service,I=m(h,M,A),k=t.session_token&&"iotdevicegateway"!==A,O=c(c(c({"X-Amz-Algorithm":"AWS4-HMAC-SHA256","X-Amz-Credential":[t.access_key,I].join("/"),"X-Amz-Date":d.substr(0,16)},k?{"X-Amz-Security-Token":""+t.session_token}:{}),r?{"X-Amz-Expires":""+r}:{}),{"X-Amz-SignedHeaders":Object.keys(S).join(",")}),x=v({method:o,url:Object(s.format)(c(c({},_),{query:c(c({},_.query),O)})),headers:S,data:l}),C=b("AWS4-HMAC-SHA256",x,d,I),T=y(t.secret_key,h,{region:M,service:A}),P=w(T,C),N=c({"X-Amz-Signature":P},t.session_token&&{"X-Amz-Security-Token":t.session_token});return Object(s.format)({protocol:_.protocol,slashes:!0,hostname:_.hostname,port:_.port,pathname:_.pathname,query:c(c(c({},_.query),O),N)})},e}()},function(e,t,n){"use strict";n.d(t,"a",(function(){return se}));var r=n(14),i=n(33),o=n(44),s=n(103),a=n(19),u=n(256),c=n(27),f=function(){return(f=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},l=new o.a("AbstractPubSubProvider"),d=function(){function e(e){void 0===e&&(e={}),this._config=e}return e.prototype.configure=function(e){return void 0===e&&(e={}),this._config=f(f({},e),this._config),l.debug("configure "+this.getProviderName(),this._config),this.options},e.prototype.getCategory=function(){return"PubSub"},Object.defineProperty(e.prototype,"options",{get:function(){return f({},this._config)},enumerable:!0,configurable:!0}),e}();function h(e){return(h="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var p,v=(p=function(e,t){return(p=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}p(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),g=function(){return(g=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},m=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},b=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},y=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n},w=new o.a("MqttOverWSProvider");var _,S,E,M=function(){function e(){this.promises=new Map}return e.prototype.get=function(e,t){return m(this,void 0,void 0,(function(){var n;return b(this,(function(r){return(n=this.promises.get(e))||(n=t(e),this.promises.set(e,n)),[2,n]}))}))},Object.defineProperty(e.prototype,"allClients",{get:function(){return Array.from(this.promises.keys())},enumerable:!0,configurable:!0}),e.prototype.remove=function(e){this.promises.delete(e)},e}(),A="undefined"!=typeof Symbol?Symbol("topic"):"@@topic",I=function(e){function t(t){void 0===t&&(t={});var n=e.call(this,g(g({},t),{clientId:t.clientId||Object(c.v4)()}))||this;return n._clientsQueue=new M,n._topicObservers=new Map,n._clientIdObservers=new Map,n}return v(t,e),Object.defineProperty(t.prototype,"clientId",{get:function(){return this.options.clientId},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"endpoint",{get:function(){return this.options.aws_pubsub_endpoint},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"clientsQueue",{get:function(){return this._clientsQueue},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isSSLEnabled",{get:function(){return!this.options.aws_appsync_dangerously_connect_to_http_endpoint_for_testing},enumerable:!0,configurable:!0}),t.prototype.getTopicForValue=function(e){return"object"===h(e)&&e[A]},t.prototype.getProviderName=function(){return"MqttOverWSProvider"},t.prototype.onDisconnect=function(e){var t=this,n=e.clientId,r=e.errorCode,i=y(e,["clientId","errorCode"]);if(0!==r){w.warn(n,JSON.stringify(g({errorCode:r},i),null,2));var o=[],s=this._clientIdObservers.get(n);if(!s)return;s.forEach((function(e){e.error("Disconnected, error code: "+r),t._topicObservers.forEach((function(t,n){t.delete(e),0===t.size&&o.push(n)}))})),this._clientIdObservers.delete(n),o.forEach((function(e){t._topicObservers.delete(e)}))}},t.prototype.newClient=function(e){var t=e.url,n=e.clientId;return m(this,void 0,void 0,(function(){var e,r=this;return b(this,(function(i){switch(i.label){case 0:return w.debug("Creating new MQTT client",n),(e=new u.Client(t,n)).onMessageArrived=function(e){var t=e.destinationName,n=e.payloadString;r._onMessage(t,n)},e.onConnectionLost=function(e){var t=e.errorCode,i=y(e,["errorCode"]);r.onDisconnect(g({clientId:n,errorCode:t},i))},[4,new Promise((function(t,n){e.connect({useSSL:r.isSSLEnabled,mqttVersion:3,onSuccess:function(){return t(e)},onFailure:n})}))];case 1:return i.sent(),[2,e]}}))}))},t.prototype.connect=function(e,t){return void 0===t&&(t={}),m(this,void 0,void 0,(function(){var n=this;return b(this,(function(r){switch(r.label){case 0:return[4,this.clientsQueue.get(e,(function(e){return n.newClient(g(g({},t),{clientId:e}))}))];case 1:return[2,r.sent()]}}))}))},t.prototype.disconnect=function(e){return m(this,void 0,void 0,(function(){var t;return b(this,(function(n){switch(n.label){case 0:return[4,this.clientsQueue.get(e,(function(){return null}))];case 1:return(t=n.sent())&&t.isConnected()&&t.disconnect(),this.clientsQueue.remove(e),[2]}}))}))},t.prototype.publish=function(e,t){return m(this,void 0,void 0,(function(){var n,r,i,o;return b(this,(function(s){switch(s.label){case 0:return n=[].concat(e),r=JSON.stringify(t),[4,this.endpoint];case 1:return i=s.sent(),[4,this.connect(this.clientId,{url:i})];case 2:return o=s.sent(),w.debug("Publishing to topic(s)",n.join(","),r),n.forEach((function(e){return o.send(e,r)})),[2]}}))}))},t.prototype._onMessage=function(e,t){try{var n=[];this._topicObservers.forEach((function(t,r){(function(e,t){for(var n=e.split("/"),r=n.length,i=t.split("/"),o=0;o<r;++o){var s=n[o],a=i[o];if("#"===s)return i.length>=r;if("+"!==s&&s!==a)return!1}return r===i.length})(r,e)&&n.push(t)}));var r=JSON.parse(t);"object"===h(r)&&(r[A]=e),n.forEach((function(e){e.forEach((function(e){return e.next(r)}))}))}catch(e){w.warn("Error handling message",e,t)}},t.prototype.subscribe=function(e,t){var n=this;void 0===t&&(t={});var i=[].concat(e);return w.debug("Subscribing to topic(s)",i.join(",")),new r.a((function(e){var r;i.forEach((function(t){var r=n._topicObservers.get(t);r||(r=new Set,n._topicObservers.set(t,r)),r.add(e)}));var o=t.clientId,s=void 0===o?n.clientId:o,a=n._clientIdObservers.get(s);return a||(a=new Set),a.add(e),n._clientIdObservers.set(s,a),m(n,void 0,void 0,(function(){var n,o,a,u;return b(this,(function(c){switch(c.label){case 0:return void 0!==(n=t.url)?[3,2]:[4,this.endpoint];case 1:return a=c.sent(),[3,3];case 2:a=n,c.label=3;case 3:o=a,c.label=4;case 4:return c.trys.push([4,6,,7]),[4,this.connect(s,{url:o})];case 5:return r=c.sent(),i.forEach((function(e){r.subscribe(e)})),[3,7];case 6:return u=c.sent(),e.error(u),[3,7];case 7:return[2]}}))})),function(){return w.debug("Unsubscribing from topic(s)",i.join(",")),r&&(n._clientIdObservers.get(s).delete(e),0===n._clientIdObservers.get(s).size&&(n.disconnect(s),n._clientIdObservers.delete(s)),i.forEach((function(t){var i=n._topicObservers.get(t)||new Set;i.delete(e),0===i.size&&(n._topicObservers.delete(t),r.isConnected()&&r.unsubscribe(t))}))),null}}))},t}(d),k=function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),O=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},x=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},C=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n},T=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},P=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(T(arguments[t]));return e},N=new o.a("AWSAppSyncProvider"),R=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t._topicClient=new Map,t._topicAlias=new Map,t}return k(t,e),Object.defineProperty(t.prototype,"endpoint",{get:function(){throw new Error("Not supported")},enumerable:!0,configurable:!0}),t.prototype.getProviderName=function(){return"AWSAppSyncProvider"},t.prototype.publish=function(e,t,n){return O(this,void 0,void 0,(function(){return x(this,(function(e){throw new Error("Operation not supported")}))}))},t.prototype._cleanUp=function(e){var t=this;Array.from(this._topicClient.entries()).filter((function(t){return T(t,2)[1].clientId===e})).map((function(e){return T(e,1)[0]})).forEach((function(e){return t._cleanUpForTopic(e)}))},t.prototype._cleanUpForTopic=function(e){this._topicClient.delete(e),this._topicAlias.delete(e)},t.prototype.onDisconnect=function(e){var t=this,n=e.clientId,r=e.errorCode,i=C(e,["clientId","errorCode"]);0!==r&&(Array.from(this._topicClient.entries()).filter((function(e){return T(e,2)[1].clientId===n})).map((function(e){return T(e,1)[0]})).forEach((function(e){t._topicObservers.has(e)&&(t._topicObservers.get(e).forEach((function(e){e.closed||e.error(i)})),t._topicObservers.delete(e))})),this._cleanUp(n))},t.prototype.disconnect=function(t){return O(this,void 0,void 0,(function(){return x(this,(function(n){switch(n.label){case 0:return[4,this.clientsQueue.get(t,(function(){return null}))];case 1:return n.sent(),[4,e.prototype.disconnect.call(this,t)];case 2:return n.sent(),this._cleanUp(t),[2]}}))}))},t.prototype.subscribe=function(e,t){var n=this;void 0===t&&(t={});var i=new r.a((function(r){var i=[].concat(e);return N.debug("Subscribing to topic(s)",i.join(",")),O(n,void 0,void 0,(function(){var e,n,o,s,a,u=this;return x(this,(function(c){switch(c.label){case 0:return i.forEach((function(e){u._topicObservers.has(e)||u._topicObservers.set(e,new Set),u._topicObservers.get(e).add(r)})),e=t.mqttConnections,n=void 0===e?[]:e,o=t.newSubscriptions,s=Object.entries(o).map((function(e){var t=T(e,2),n=t[0];return[t[1].topic,n]})),this._topicAlias=new Map(P(Array.from(this._topicAlias.entries()),s)),a=Object.entries(i.reduce((function(e,t){var r=n.find((function(e){return e.topics.indexOf(t)>-1}));if(r){var i=r.client,o=r.url;e[i]||(e[i]={url:o,topics:new Set}),e[i].topics.add(t)}return e}),{})),[4,Promise.all(a.map((function(e){var t=T(e,2),n=t[0],i=t[1],o=i.url,s=i.topics;return O(u,void 0,void 0,(function(){var e,t,i=this;return x(this,(function(a){switch(a.label){case 0:e=null,a.label=1;case 1:return a.trys.push([1,3,,4]),[4,this.connect(n,{clientId:n,url:o})];case 2:return e=a.sent(),[3,4];case 3:return t=a.sent(),r.error({message:"Failed to connect",error:t}),r.complete(),[2,void 0];case 4:return s.forEach((function(t){e.isConnected()&&(e.subscribe(t),i._topicClient.set(t,e))})),[2,e]}}))}))})))];case 1:return c.sent(),[2]}}))})),function(){N.debug("Unsubscribing from topic(s)",i.join(",")),i.forEach((function(e){var t=n._topicClient.get(e);t&&t.isConnected()&&(t.unsubscribe(e),n._topicClient.delete(e),Array.from(n._topicClient.values()).some((function(e){return e===t}))||n.disconnect(t.clientId)),n._topicObservers.delete(e)}))}}));return r.a.from(i).map((function(e){var t=n.getTopicForValue(e),r=n._topicAlias.get(t);return e.data=Object.entries(e.data).reduce((function(e,t){var n=T(t,2),i=n[0],o=n[1];return e[r||i]=o,e}),{}),e}))},t}(I),L=n(91),j=n(16),D=n(6),U=n(88),B=n(5),F=n(514),z=n(89),q=n(104),K=n(26),H=n(42),V=n(34),G=function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),W=function(){return(W=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},$=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},Y=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},J=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},Z=new o.a("AWSAppSyncRealTimeProvider"),X="undefined"!=typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("amplify_default"):"@@amplify_default",Q=[400,401,403];!function(e){e.GQL_CONNECTION_INIT="connection_init",e.GQL_CONNECTION_ERROR="connection_error",e.GQL_CONNECTION_ACK="connection_ack",e.GQL_START="start",e.GQL_START_ACK="start_ack",e.GQL_DATA="data",e.GQL_CONNECTION_KEEP_ALIVE="ka",e.GQL_STOP="stop",e.GQL_COMPLETE="complete",e.GQL_ERROR="error"}(_||(_={})),function(e){e[e.PENDING=0]="PENDING",e[e.CONNECTED=1]="CONNECTED",e[e.FAILED=2]="FAILED"}(S||(S={})),function(e){e[e.CLOSED=0]="CLOSED",e[e.READY=1]="READY",e[e.CONNECTING=2]="CONNECTING"}(E||(E={}));var ee={accept:"application/json, text/javascript","content-encoding":"amz-1.0","content-type":"application/json; charset=UTF-8"},te=function(e){function t(){var t=null!==e&&e.apply(this,arguments)||this;return t.socketStatus=E.CLOSED,t.keepAliveTimeout=3e5,t.subscriptionObserverMap=new Map,t.promiseArray=[],t}return G(t,e),t.prototype.getProviderName=function(){return"AWSAppSyncRealTimeProvider"},t.prototype.newClient=function(){throw new Error("Not used here")},t.prototype.publish=function(e,t,n){return $(this,void 0,void 0,(function(){return Y(this,(function(e){throw new Error("Operation not supported")}))}))},t.prototype.subscribe=function(e,t){var n=this,i=t.appSyncGraphqlEndpoint;return new r.a((function(e){if(i){var r=Object(c.v4)();return n._startSubscriptionWithAWSAppSyncRealTime({options:t,observer:e,subscriptionId:r}),function(){return $(n,void 0,void 0,(function(){var e,t;return Y(this,(function(n){switch(n.label){case 0:return n.trys.push([0,2,3,4]),[4,this._waitForSubscriptionToBeConnected(r)];case 1:if(n.sent(),!(e=(this.subscriptionObserverMap.get(r)||{}).subscriptionState))return[2];if(e!==S.CONNECTED)throw new Error("Subscription never connected");return this._sendUnsubscriptionMessage(r),[3,4];case 2:return t=n.sent(),Z.debug("Error while unsubscribing "+t),[3,4];case 3:return this._removeSubscriptionObserver(r),[7];case 4:return[2]}}))}))}}e.error({errors:[W({},new L.a("Subscribe only available for AWS AppSync endpoint"))]}),e.complete()}))},Object.defineProperty(t.prototype,"isSSLEnabled",{get:function(){return!this.options.aws_appsync_dangerously_connect_to_http_endpoint_for_testing},enumerable:!0,configurable:!0}),t.prototype._startSubscriptionWithAWSAppSyncRealTime=function(e){var t=e.options,n=e.observer,r=e.subscriptionId;return $(this,void 0,void 0,(function(){var e,i,o,a,u,c,f,l,d,h,p,v,g,m,b,y,w,E,M,A,I,k,O,x,C,T,P=this;return Y(this,(function(N){switch(N.label){case 0:return e=t.appSyncGraphqlEndpoint,i=t.authenticationType,o=t.query,a=t.variables,u=t.apiKey,c=t.region,f=t.graphql_headers,l=void 0===f?function(){return{}}:f,d=t.additionalHeaders,h=void 0===d?{}:d,p=S.PENDING,v={query:o,variables:a},this.subscriptionObserverMap.set(r,{observer:n,query:o,variables:a,subscriptionState:p,startAckTimeoutId:null}),g=JSON.stringify(v),b=[{}],[4,this._awsRealTimeHeaderBasedAuth({apiKey:u,appSyncGraphqlEndpoint:e,authenticationType:i,payload:g,canonicalUri:"",region:c})];case 1:return y=[W.apply(void 0,b.concat([N.sent()]))],[4,l()];case 2:m=W.apply(void 0,[W.apply(void 0,[W.apply(void 0,y.concat([N.sent()])),h]),(T={},T[s.c]=B.a.userAgent,T)]),w={id:r,payload:{data:g,extensions:{authorization:W({},m)}},type:_.GQL_START},E=JSON.stringify(w),N.label=3;case 3:return N.trys.push([3,5,,6]),[4,this._initializeWebSocketConnection({apiKey:u,appSyncGraphqlEndpoint:e,authenticationType:i,region:c})];case 4:return N.sent(),[3,6];case 5:return M=N.sent(),Z.debug({err:M}),A=M.message,I=void 0===A?"":A,n.error({errors:[W({},new L.a("Connection failed: "+I))]}),n.complete(),"function"==typeof(k=(this.subscriptionObserverMap.get(r)||{}).subscriptionFailedCallback)&&k(),[2];case 6:return O=this.subscriptionObserverMap.get(r),x=O.subscriptionFailedCallback,C=O.subscriptionReadyCallback,this.subscriptionObserverMap.set(r,{observer:n,subscriptionState:p,variables:a,query:o,subscriptionReadyCallback:C,subscriptionFailedCallback:x,startAckTimeoutId:setTimeout((function(){P._timeoutStartSubscriptionAck.call(P,r)}),15e3)}),this.awsRealTimeSocket&&this.awsRealTimeSocket.send(E),[2]}}))}))},t.prototype._waitForSubscriptionToBeConnected=function(e){return $(this,void 0,void 0,(function(){var t=this;return Y(this,(function(n){return this.subscriptionObserverMap.get(e).subscriptionState===S.PENDING?[2,new Promise((function(n,r){var i=t.subscriptionObserverMap.get(e),o=i.observer,s=i.subscriptionState,a=i.variables,u=i.query;t.subscriptionObserverMap.set(e,{observer:o,subscriptionState:s,variables:a,query:u,subscriptionReadyCallback:n,subscriptionFailedCallback:r})}))]:[2]}))}))},t.prototype._sendUnsubscriptionMessage=function(e){try{if(this.awsRealTimeSocket&&this.awsRealTimeSocket.readyState===WebSocket.OPEN&&this.socketStatus===E.READY){var t={id:e,type:_.GQL_STOP},n=JSON.stringify(t);this.awsRealTimeSocket.send(n)}}catch(e){Z.debug({err:e})}},t.prototype._removeSubscriptionObserver=function(e){this.subscriptionObserverMap.delete(e),setTimeout(this._closeSocketIfRequired.bind(this),1e3)},t.prototype._closeSocketIfRequired=function(){if(!(this.subscriptionObserverMap.size>0))if(this.awsRealTimeSocket)if(this.awsRealTimeSocket.bufferedAmount>0)setTimeout(this._closeSocketIfRequired.bind(this),1e3);else{Z.debug("closing WebSocket..."),clearTimeout(this.keepAliveTimeoutId);var e=this.awsRealTimeSocket;e.onclose=void 0,e.onerror=void 0,e.close(1e3),this.awsRealTimeSocket=null,this.socketStatus=E.CLOSED}else this.socketStatus=E.CLOSED},t.prototype._handleIncomingSubscriptionMessage=function(e){Z.debug("subscription message from AWS AppSync RealTime: "+e.data);var t=JSON.parse(e.data),n=t.id,r=void 0===n?"":n,i=t.payload,o=t.type,s=this.subscriptionObserverMap.get(r)||{},a=s.observer,u=void 0===a?null:a,c=s.query,f=void 0===c?"":c,l=s.variables,d=void 0===l?{}:l,h=s.startAckTimeoutId,p=s.subscriptionReadyCallback,v=s.subscriptionFailedCallback;if(Z.debug({id:r,observer:u,query:f,variables:d}),o===_.GQL_DATA&&i&&i.data)u?u.next(i):Z.debug("observer not found for id: "+r);else if(o!==_.GQL_START_ACK){if(o===_.GQL_CONNECTION_KEEP_ALIVE)return clearTimeout(this.keepAliveTimeoutId),void(this.keepAliveTimeoutId=setTimeout(this._errorDisconnect.bind(this,V.a.TIMEOUT_DISCONNECT),this.keepAliveTimeout));if(o===_.GQL_ERROR){g=S.FAILED;this.subscriptionObserverMap.set(r,{observer:u,query:f,variables:d,startAckTimeoutId:h,subscriptionReadyCallback:p,subscriptionFailedCallback:v,subscriptionState:g}),u.error({errors:[W({},new L.a("Connection failed: "+JSON.stringify(i)))]}),clearTimeout(h),u.complete(),"function"==typeof v&&v()}}else{Z.debug("subscription ready for "+JSON.stringify({query:f,variables:d})),"function"==typeof p&&p(),clearTimeout(h),function(e,t,n){U.a.dispatch("api",{event:e,data:t,message:n},"PubSub",X)}(V.a.SUBSCRIPTION_ACK,{query:f,variables:d},"Connection established for subscription");var g=S.CONNECTED;this.subscriptionObserverMap.set(r,{observer:u,query:f,variables:d,startAckTimeoutId:null,subscriptionState:g,subscriptionReadyCallback:p,subscriptionFailedCallback:v})}},t.prototype._errorDisconnect=function(e){Z.debug("Disconnect error: "+e),this.subscriptionObserverMap.forEach((function(t){var n=t.observer;n&&!n.closed&&n.error({errors:[W({},new L.a(e))]})})),this.subscriptionObserverMap.clear(),this.awsRealTimeSocket&&this.awsRealTimeSocket.close(),this.socketStatus=E.CLOSED},t.prototype._timeoutStartSubscriptionAck=function(e){var t=this.subscriptionObserverMap.get(e)||{},n=t.observer,r=t.query,i=t.variables;n&&(this.subscriptionObserverMap.set(e,{observer:n,query:r,variables:i,subscriptionState:S.FAILED}),n&&!n.closed&&(n.error({errors:[W({},new L.a("Subscription timeout "+JSON.stringify({query:r,variables:i})))]}),n.complete()),Z.debug("timeoutStartSubscription",JSON.stringify({query:r,variables:i})))},t.prototype._initializeWebSocketConnection=function(e){var t=this,n=e.appSyncGraphqlEndpoint,r=e.authenticationType,i=e.apiKey,o=e.region;if(this.socketStatus!==E.READY)return new Promise((function(e,s){return $(t,void 0,void 0,(function(){var t,a,u,c,f,l,d,h,p,v;return Y(this,(function(g){switch(g.label){case 0:if(this.promiseArray.push({res:e,rej:s}),this.socketStatus!==E.CLOSED)return[3,5];g.label=1;case 1:return g.trys.push([1,4,,5]),this.socketStatus=E.CONNECTING,t=this.isSSLEnabled?"wss://":"ws://",a=n.replace("https://",t).replace("http://",t).replace("appsync-api","appsync-realtime-api").replace("gogi-beta","grt-beta"),u="{}",l=(f=JSON).stringify,[4,this._awsRealTimeHeaderBasedAuth({authenticationType:r,payload:u,canonicalUri:"/connect",apiKey:i,appSyncGraphqlEndpoint:n,region:o})];case 2:return c=l.apply(f,[g.sent()]),d=D.Buffer.from(c).toString("base64"),h=D.Buffer.from(u).toString("base64"),p=a+"?header="+d+"&payload="+h,[4,this._initializeRetryableHandshake({awsRealTimeUrl:p})];case 3:return g.sent(),this.promiseArray.forEach((function(e){var t=e.res;Z.debug("Notifying connection successful"),t()})),this.socketStatus=E.READY,this.promiseArray=[],[3,5];case 4:return v=g.sent(),this.promiseArray.forEach((function(e){return(0,e.rej)(v)})),this.promiseArray=[],this.awsRealTimeSocket&&this.awsRealTimeSocket.readyState===WebSocket.OPEN&&this.awsRealTimeSocket.close(3001),this.awsRealTimeSocket=null,this.socketStatus=E.CLOSED,[3,5];case 5:return[2]}}))}))}))},t.prototype._initializeRetryableHandshake=function(e){var t=e.awsRealTimeUrl;return $(this,void 0,void 0,(function(){return Y(this,(function(e){switch(e.label){case 0:return Z.debug("Initializaling retryable Handshake"),[4,Object(F.b)(this._initializeHandshake.bind(this),[{awsRealTimeUrl:t}],5e3)];case 1:return e.sent(),[2]}}))}))},t.prototype._initializeHandshake=function(e){var t=e.awsRealTimeUrl;return $(this,void 0,void 0,(function(){var e,n,r,i=this;return Y(this,(function(o){switch(o.label){case 0:Z.debug("Initializing handshake "+t),o.label=1;case 1:return o.trys.push([1,4,,5]),[4,new Promise((function(e,n){var r=new WebSocket(t,"graphql-ws");r.onerror=function(){Z.debug("WebSocket connection error")},r.onclose=function(){n(new Error("Connection handshake error"))},r.onopen=function(){return i.awsRealTimeSocket=r,e()}}))];case 2:return o.sent(),[4,new Promise((function(e,t){var n=!1;i.awsRealTimeSocket.onerror=function(e){Z.debug("WebSocket error "+JSON.stringify(e))},i.awsRealTimeSocket.onclose=function(e){Z.debug("WebSocket closed "+e.reason),t(new Error(JSON.stringify(e)))},i.awsRealTimeSocket.onmessage=function(r){Z.debug("subscription message from AWS AppSyncRealTime: "+r.data+" ");var o=JSON.parse(r.data),s=o.type,a=o.payload,u=(void 0===a?{}:a).connectionTimeoutMs,c=void 0===u?3e5:u;if(s===_.GQL_CONNECTION_ACK)return n=!0,i.keepAliveTimeout=c,i.awsRealTimeSocket.onmessage=i._handleIncomingSubscriptionMessage.bind(i),i.awsRealTimeSocket.onerror=function(e){Z.debug(e),i._errorDisconnect(V.a.CONNECTION_CLOSED)},i.awsRealTimeSocket.onclose=function(e){Z.debug("WebSocket closed "+e.reason),i._errorDisconnect(V.a.CONNECTION_CLOSED)},void e("Cool, connected to AWS AppSyncRealTime");if(s===_.GQL_CONNECTION_ERROR){var f=o.payload,l=(void 0===f?{}:f).errors,d=J(void 0===l?[]:l,1)[0],h=void 0===d?{}:d,p=h.errorType,v=void 0===p?"":p,g=h.errorCode;t({errorType:v,errorCode:void 0===g?0:g})}};var r={type:_.GQL_CONNECTION_INIT};i.awsRealTimeSocket.send(JSON.stringify(r)),setTimeout(function(){n||t(new Error("Connection timeout: ack from AWSRealTime was not received on 15000 ms"))}.bind(i),15e3)}))];case 3:return o.sent(),[3,5];case 4:throw e=o.sent(),n=e.errorType,r=e.errorCode,Q.includes(r)?new F.a(n):n?new Error(n):e;case 5:return[2]}}))}))},t.prototype._awsRealTimeHeaderBasedAuth=function(e){var t=e.authenticationType,n=e.payload,r=e.canonicalUri,i=e.appSyncGraphqlEndpoint,o=e.apiKey,s=e.region;return $(this,void 0,void 0,(function(){var e,a,u;return Y(this,(function(c){switch(c.label){case 0:return e={API_KEY:this._awsRealTimeApiKeyHeader.bind(this),AWS_IAM:this._awsRealTimeIAMHeader.bind(this),OPENID_CONNECT:this._awsRealTimeOPENIDHeader.bind(this),AMAZON_COGNITO_USER_POOLS:this._awsRealTimeCUPHeader.bind(this)},"function"!=typeof(a=e[t])?(Z.debug("Authentication type "+t+" not supported"),[2,""]):(u=j.parse(i).host,[4,a({payload:n,canonicalUri:r,appSyncGraphqlEndpoint:i,apiKey:o,region:s,host:u})]);case 1:return[2,c.sent()]}}))}))},t.prototype._awsRealTimeCUPHeader=function(e){var t=e.host;return $(this,void 0,void 0,(function(){return Y(this,(function(e){switch(e.label){case 0:return[4,H.a.currentSession()];case 1:return[2,{Authorization:e.sent().getAccessToken().getJwtToken(),host:t}]}}))}))},t.prototype._awsRealTimeOPENIDHeader=function(e){var t=e.host;return $(this,void 0,void 0,(function(){var e,n,r;return Y(this,(function(i){switch(i.label){case 0:return[4,K.a.getItem("federatedInfo")];case 1:return(n=i.sent())?(e=n.token,[3,4]):[3,2];case 2:return[4,H.a.currentAuthenticatedUser()];case 3:(r=i.sent())&&(e=r.token),i.label=4;case 4:if(!e)throw new Error("No federated jwt");return[2,{Authorization:e,host:t}]}}))}))},t.prototype._awsRealTimeApiKeyHeader=function(e){var t=e.apiKey,n=e.host;return $(this,void 0,void 0,(function(){var e,r;return Y(this,(function(i){return e=new Date,r=e.toISOString().replace(/[:\-]|\.\d{3}/g,""),[2,{host:n,"x-amz-date":r,"x-api-key":t}]}))}))},t.prototype._awsRealTimeIAMHeader=function(e){var t=e.payload,n=e.canonicalUri,r=e.appSyncGraphqlEndpoint,i=e.region;return $(this,void 0,void 0,(function(){var e,o,s;return Y(this,(function(a){switch(a.label){case 0:return e={region:i,service:"appsync"},[4,this._ensureCredentials()];case 1:if(!a.sent())throw new Error("No credentials");return[4,z.a.get().then((function(e){return{secret_key:e.secretAccessKey,access_key:e.accessKeyId,session_token:e.sessionToken}}))];case 2:return o=a.sent(),s={url:""+r+n,data:t,method:"POST",headers:W({},ee)},[2,q.a.sign(s,o,e).headers]}}))}))},t.prototype._ensureCredentials=function(){return z.a.get().then((function(e){if(!e)return!1;var t=z.a.shear(e);return Z.debug("set credentials for AWSAppSyncRealTimeProvider",t),!0})).catch((function(e){return Z.warn("ensure credentials error",e),!1}))},t}(d),ne=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},re=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},ie=Object(i.b)().isNode,oe=new o.a("PubSub"),se=new(function(){function e(e){this._options=e,oe.debug("PubSub Options",this._options),this._pluggables=[],this.subscribe=this.subscribe.bind(this)}return Object.defineProperty(e.prototype,"awsAppSyncProvider",{get:function(){return this._awsAppSyncProvider||(this._awsAppSyncProvider=new R(this._options)),this._awsAppSyncProvider},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"awsAppSyncRealTimeProvider",{get:function(){return this._awsAppSyncRealTimeProvider||(this._awsAppSyncRealTimeProvider=new te(this._options)),this._awsAppSyncRealTimeProvider},enumerable:!0,configurable:!0}),e.prototype.getModuleName=function(){return"PubSub"},e.prototype.configure=function(e){var t=this,n=e?e.PubSub||e:{};return oe.debug("configure PubSub",{opt:n}),this._options=Object.assign({},this._options,n),this._pluggables.map((function(e){return e.configure(t._options)})),this._options},e.prototype.addPluggable=function(e){return ne(this,void 0,void 0,(function(){return re(this,(function(t){return e&&"PubSub"===e.getCategory()?(this._pluggables.push(e),[2,e.configure(this._options)]):[2]}))}))},e.prototype.getProviderByName=function(e){return e===s.a?this.awsAppSyncProvider:e===s.b?this.awsAppSyncRealTimeProvider:this._pluggables.find((function(t){return t.getProviderName()===e}))},e.prototype.getProviders=function(e){void 0===e&&(e={});var t=e.provider;if(!t)return this._pluggables;var n=this.getProviderByName(t);if(!n)throw new Error("Could not find provider named "+t);return[n]},e.prototype.publish=function(e,t,n){return ne(this,void 0,void 0,(function(){return re(this,(function(r){return[2,Promise.all(this.getProviders(n).map((function(r){return r.publish(e,t,n)})))]}))}))},e.prototype.subscribe=function(e,t){if(ie&&this._options&&this._options.ssr)throw new Error("Subscriptions are not supported for Server-Side Rendering (SSR)");oe.debug("subscribe options",t);var n=this.getProviders(t);return new r.a((function(r){var i=n.map((function(n){return{provider:n,observable:n.subscribe(e,t)}})).map((function(e){var t=e.provider;return e.observable.subscribe({start:console.error,next:function(e){return r.next({provider:t,value:e})},error:function(e){return r.error({provider:t,error:e})}})}));return function(){return i.forEach((function(e){return e.unsubscribe()}))}}))},e}())(null);a.a.register(se)},function(e,t,n){"use strict";n.d(t,"a",(function(){return i}));var r=n(1);function i(e){var t,n,i={};if(e=e.replace(/^\?/,""))try{for(var o=Object(r.__values)(e.split("&")),s=o.next();!s.done;s=o.next()){var a=s.value,u=Object(r.__read)(a.split("="),2),c=u[0],f=u[1],l=void 0===f?null:f;c=decodeURIComponent(c),l&&(l=decodeURIComponent(l)),c in i?Array.isArray(i[c])?i[c].push(l):i[c]=[i[c],l]:i[c]=l}}catch(e){t={error:e}}finally{try{s&&!s.done&&(n=o.return)&&n.call(o)}finally{if(t)throw t.error}}return i}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Crc32=t.crc32=void 0;var r=n(1);t.crc32=function(e){return(new i).update(e).digest()};var i=function(){function e(){this.checksum=4294967295}return e.prototype.update=function(e){var t,n;try{for(var i=r.__values(e),s=i.next();!s.done;s=i.next()){var a=s.value;this.checksum=this.checksum>>>8^o[255&(this.checksum^a)]}}catch(e){t={error:e}}finally{try{s&&!s.done&&(n=i.return)&&n.call(i)}finally{if(t)throw t.error}}return this},e.prototype.digest=function(){return(4294967295^this.checksum)>>>0},e}();t.Crc32=i;var o=Uint32Array.from([0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117])},function(e,t,n){var r=n(431);e.exports=function(e,t){return r(e,t)}},function(e,t,n){var r=n(483),i=n(484),o=i;o.v1=r,o.v4=i,e.exports=o},function(e,t,n){"use strict";n.d(t,"a",(function(){return M}));var r=n(107),i=n(1),o=n(28),s=function(){function e(e){if(this.bytes=e,8!==e.byteLength)throw new Error("Int64 buffers must be exactly 8 bytes")}return e.fromNumber=function(t){if(t>0x8000000000000000||t<-0x8000000000000000)throw new Error(t+" is too large (or, if negative, too small) to represent as an Int64");for(var n=new Uint8Array(8),r=7,i=Math.abs(Math.round(t));r>-1&&i>0;r--,i/=256)n[r]=i;return t<0&&a(n),new e(n)},e.prototype.valueOf=function(){var e=this.bytes.slice(0),t=128&e[0];return t&&a(e),parseInt(Object(o.b)(e),16)*(t?-1:1)},e.prototype.toString=function(){return String(this.valueOf())},e}();function a(e){for(var t=0;t<8;t++)e[t]^=255;for(t=7;t>-1&&(e[t]++,0===e[t]);t--);}var u,c=function(){function e(e,t){this.toUtf8=e,this.fromUtf8=t}return e.prototype.format=function(e){var t,n,r,o,s=[];try{for(var a=Object(i.__values)(Object.keys(e)),u=a.next();!u.done;u=a.next()){var c=u.value,f=this.fromUtf8(c);s.push(Uint8Array.from([f.byteLength]),f,this.formatHeaderValue(e[c]))}}catch(e){t={error:e}}finally{try{u&&!u.done&&(n=a.return)&&n.call(a)}finally{if(t)throw t.error}}var l=new Uint8Array(s.reduce((function(e,t){return e+t.byteLength}),0)),d=0;try{for(var h=Object(i.__values)(s),p=h.next();!p.done;p=h.next()){var v=p.value;l.set(v,d),d+=v.byteLength}}catch(e){r={error:e}}finally{try{p&&!p.done&&(o=h.return)&&o.call(h)}finally{if(r)throw r.error}}return l},e.prototype.formatHeaderValue=function(e){switch(e.type){case"boolean":return Uint8Array.from([e.value?0:1]);case"byte":return Uint8Array.from([2,e.value]);case"short":var t=new DataView(new ArrayBuffer(3));return t.setUint8(0,3),t.setInt16(1,e.value,!1),new Uint8Array(t.buffer);case"integer":var n=new DataView(new ArrayBuffer(5));return n.setUint8(0,4),n.setInt32(1,e.value,!1),new Uint8Array(n.buffer);case"long":var r=new Uint8Array(9);return r[0]=5,r.set(e.value.bytes,1),r;case"binary":var i=new DataView(new ArrayBuffer(3+e.value.byteLength));i.setUint8(0,6),i.setUint16(1,e.value.byteLength,!1);var a=new Uint8Array(i.buffer);return a.set(e.value,3),a;case"string":var u=this.fromUtf8(e.value),c=new DataView(new ArrayBuffer(3+u.byteLength));c.setUint8(0,7),c.setUint16(1,u.byteLength,!1);var f=new Uint8Array(c.buffer);return f.set(u,3),f;case"timestamp":var l=new Uint8Array(9);return l[0]=8,l.set(s.fromNumber(e.value.valueOf()).bytes,1),l;case"uuid":if(!y.test(e.value))throw new Error("Invalid UUID received: "+e.value);var d=new Uint8Array(17);return d[0]=9,d.set(Object(o.a)(e.value.replace(/\-/g,"")),1),d}},e.prototype.parse=function(e){for(var t={},n=0;n<e.byteLength;){var r=e.getUint8(n++),i=this.toUtf8(new Uint8Array(e.buffer,e.byteOffset+n,r));switch(n+=r,e.getUint8(n++)){case 0:t[i]={type:f,value:!0};break;case 1:t[i]={type:f,value:!1};break;case 2:t[i]={type:l,value:e.getInt8(n++)};break;case 3:t[i]={type:d,value:e.getInt16(n,!1)},n+=2;break;case 4:t[i]={type:h,value:e.getInt32(n,!1)},n+=4;break;case 5:t[i]={type:p,value:new s(new Uint8Array(e.buffer,e.byteOffset+n,8))},n+=8;break;case 6:var a=e.getUint16(n,!1);n+=2,t[i]={type:v,value:new Uint8Array(e.buffer,e.byteOffset+n,a)},n+=a;break;case 7:var u=e.getUint16(n,!1);n+=2,t[i]={type:g,value:this.toUtf8(new Uint8Array(e.buffer,e.byteOffset+n,u))},n+=u;break;case 8:t[i]={type:m,value:new Date(new s(new Uint8Array(e.buffer,e.byteOffset+n,8)).valueOf())},n+=8;break;case 9:var c=new Uint8Array(e.buffer,e.byteOffset+n,16);n+=16,t[i]={type:b,value:Object(o.b)(c.subarray(0,4))+"-"+Object(o.b)(c.subarray(4,6))+"-"+Object(o.b)(c.subarray(6,8))+"-"+Object(o.b)(c.subarray(8,10))+"-"+Object(o.b)(c.subarray(10))};break;default:throw new Error("Unrecognized header type tag")}}return t},e}();!function(e){e[e.boolTrue=0]="boolTrue",e[e.boolFalse=1]="boolFalse",e[e.byte=2]="byte",e[e.short=3]="short",e[e.integer=4]="integer",e[e.long=5]="long",e[e.byteArray=6]="byteArray",e[e.string=7]="string",e[e.timestamp=8]="timestamp",e[e.uuid=9]="uuid"}(u||(u={}));var f="boolean",l="byte",d="short",h="integer",p="long",v="binary",g="string",m="timestamp",b="uuid",y=/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/;var w=function(){function e(e,t){this.headerMarshaller=new c(e,t)}return e.prototype.marshall=function(e){var t=e.headers,n=e.body,i=this.headerMarshaller.format(t),o=i.byteLength+n.byteLength+16,s=new Uint8Array(o),a=new DataView(s.buffer,s.byteOffset,s.byteLength),u=new r.Crc32;return a.setUint32(0,o,!1),a.setUint32(4,i.byteLength,!1),a.setUint32(8,u.update(s.subarray(0,8)).digest(),!1),s.set(i,12),s.set(n,i.byteLength+12),a.setUint32(o-4,u.update(s.subarray(8,o-4)).digest(),!1),s},e.prototype.unmarshall=function(e){var t=function(e){var t=e.byteLength,n=e.byteOffset,i=e.buffer;if(t<16)throw new Error("Provided message too short to accommodate event stream message overhead");var o=new DataView(i,n,t),s=o.getUint32(0,!1);if(t!==s)throw new Error("Reported message length does not match received message length");var a=o.getUint32(4,!1),u=o.getUint32(8,!1),c=o.getUint32(t-4,!1),f=(new r.Crc32).update(new Uint8Array(i,n,8));if(u!==f.digest())throw new Error("The prelude checksum specified in the message ("+u+") does not match the calculated CRC32 checksum ("+f.digest()+")");if(f.update(new Uint8Array(i,n+8,t-12)),c!==f.digest())throw new Error("The message checksum ("+f.digest()+") did not match the expected value of "+c);return{headers:new DataView(i,n+8+4,a),body:new Uint8Array(i,n+8+4+a,s-a-16)}}(e),n=t.headers,i=t.body;return{headers:this.headerMarshaller.parse(n),body:i}},e.prototype.formatHeaders=function(e){return this.headerMarshaller.format(e)},e}();var _=function(){function e(e){var t=e.utf8Encoder,n=e.utf8Decoder;this.eventMarshaller=new w(t,n),this.utfEncoder=t}return e.prototype.deserialize=function(e,t){var n,r,o,s,a,u,c;return function(e,t){var n;return(n={})[Symbol.asyncIterator]=function(){return Object(i.__asyncGenerator)(this,arguments,(function(){var n,r,o,s,a,u,c,f,l,d,h,p,v,g,m,b,y;return Object(i.__generator)(this,(function(w){switch(w.label){case 0:w.trys.push([0,12,13,18]),n=Object(i.__asyncValues)(e),w.label=1;case 1:return[4,Object(i.__await)(n.next())];case 2:if((r=w.sent()).done)return[3,11];if(o=r.value,s=t.eventMarshaller.unmarshall(o),"error"!==(a=s.headers[":message-type"].value))return[3,3];throw(u=new Error(s.headers[":error-message"].value||"UnknownError")).name=s.headers[":error-code"].value,u;case 3:return"exception"!==a?[3,5]:(c=s.headers[":exception-type"].value,(g={})[c]=s,f=g,[4,Object(i.__await)(t.deserializer(f))]);case 4:if((l=w.sent()).$unknown)throw(d=new Error(t.toUtf8(s.body))).name=c,d;throw l[c];case 5:return"event"!==a?[3,9]:((m={})[s.headers[":event-type"].value]=s,h=m,[4,Object(i.__await)(t.deserializer(h))]);case 6:return(p=w.sent()).$unknown?[3,10]:[4,Object(i.__await)(p)];case 7:return[4,w.sent()];case 8:return w.sent(),[3,10];case 9:throw Error("Unrecognizable event type: "+s.headers[":event-type"].value);case 10:return[3,1];case 11:return[3,18];case 12:return v=w.sent(),b={error:v},[3,18];case 13:return w.trys.push([13,,16,17]),r&&!r.done&&(y=n.return)?[4,Object(i.__await)(y.call(n))]:[3,15];case 14:w.sent(),w.label=15;case 15:return[3,17];case 16:if(b)throw b.error;return[7];case 17:return[7];case 18:return[2]}}))}))},n}((n=e,o=0,s=0,a=null,u=null,c=function(e){if("number"!=typeof e)throw new Error("Attempted to allocate an event message where size was not a number: "+e);o=e,s=4,a=new Uint8Array(e),new DataView(a.buffer).setUint32(0,e,!1)},(r={})[Symbol.asyncIterator]=function(){return Object(i.__asyncGenerator)(this,arguments,(function(){var e,t,r,f,l,d,h,p;return Object(i.__generator)(this,(function(v){switch(v.label){case 0:e=n[Symbol.asyncIterator](),v.label=1;case 1:return[4,Object(i.__await)(e.next())];case 2:return t=v.sent(),r=t.value,t.done?o?[3,4]:[4,Object(i.__await)(void 0)]:[3,10];case 3:return[2,v.sent()];case 4:return o!==s?[3,7]:[4,Object(i.__await)(a)];case 5:return[4,v.sent()];case 6:return v.sent(),[3,8];case 7:throw new Error("Truncated event message received.");case 8:return[4,Object(i.__await)(void 0)];case 9:return[2,v.sent()];case 10:f=r.length,l=0,v.label=11;case 11:if(!(l<f))return[3,15];if(!a){if(d=f-l,u||(u=new Uint8Array(4)),h=Math.min(4-s,d),u.set(r.slice(l,l+h),s),l+=h,(s+=h)<4)return[3,15];c(new DataView(u.buffer).getUint32(0,!1)),u=null}return p=Math.min(o-s,f-l),a.set(r.slice(l,l+p),s),s+=p,l+=p,o&&o===s?[4,Object(i.__await)(a)]:[3,14];case 12:return[4,v.sent()];case 13:v.sent(),a=null,o=0,s=0,v.label=14;case 14:return[3,11];case 15:return[3,1];case 16:return[2]}}))}))},r),{eventMarshaller:this.eventMarshaller,deserializer:t,toUtf8:this.utfEncoder})},e.prototype.serialize=function(e,t){var n,r=this;return(n={})[Symbol.asyncIterator]=function(){return Object(i.__asyncGenerator)(this,arguments,(function(){var n,o,s,a,u,c,f;return Object(i.__generator)(this,(function(l){switch(l.label){case 0:l.trys.push([0,7,8,13]),n=Object(i.__asyncValues)(e),l.label=1;case 1:return[4,Object(i.__await)(n.next())];case 2:return(o=l.sent()).done?[3,6]:(s=o.value,a=r.eventMarshaller.marshall(t(s)),[4,Object(i.__await)(a)]);case 3:return[4,l.sent()];case 4:l.sent(),l.label=5;case 5:return[3,1];case 6:return[3,13];case 7:return u=l.sent(),c={error:u},[3,13];case 8:return l.trys.push([8,,11,12]),o&&!o.done&&(f=n.return)?[4,Object(i.__await)(f.call(n))]:[3,10];case 9:l.sent(),l.label=10;case 10:return[3,12];case 11:if(c)throw c.error;return[7];case 12:return[7];case 13:return[4,Object(i.__await)(new Uint8Array(0))];case 14:return[4,l.sent()];case 15:return l.sent(),[2]}}))}))},n},e}(),S=function(){function e(e){var t=e.utf8Encoder,n=e.utf8Decoder;this.eventMarshaller=new w(t,n),this.universalMarshaller=new _({utf8Decoder:n,utf8Encoder:t})}return e.prototype.deserialize=function(e,t){var n,r,o=E(e)?(n=e,(r={})[Symbol.asyncIterator]=function(){return Object(i.__asyncGenerator)(this,arguments,(function(){var e,t,r,o;return Object(i.__generator)(this,(function(s){switch(s.label){case 0:e=n.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,Object(i.__await)(e.read())];case 3:return t=s.sent(),r=t.done,o=t.value,r?[4,Object(i.__await)(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,Object(i.__await)(o)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return e.releaseLock(),[7];case 10:return[2]}}))}))},r):e;return this.universalMarshaller.deserialize(o,t)},e.prototype.serialize=function(e,t){var n,r=this.universalMarshaller.serialize(e,t);return"function"==typeof ReadableStream?(n=r[Symbol.asyncIterator](),new ReadableStream({pull:function(e){return Object(i.__awaiter)(this,void 0,void 0,(function(){var t,r,o;return Object(i.__generator)(this,(function(i){switch(i.label){case 0:return[4,n.next()];case 1:return t=i.sent(),r=t.done,o=t.value,r?[2,e.close()]:(e.enqueue(o),[2])}}))}))}})):r},e}(),E=function(e){return"function"==typeof ReadableStream&&e instanceof ReadableStream},M=function(e){return new S(e)}},function(e,t,n){"use strict";n.d(t,"a",(function(){return M}));var r=n(1),i="X-Amz-Date".toLowerCase(),o=["authorization",i,"date"],s="X-Amz-Signature".toLowerCase(),a="X-Amz-Security-Token".toLowerCase(),u={authorization:!0,"cache-control":!0,connection:!0,expect:!0,from:!0,"keep-alive":!0,"max-forwards":!0,pragma:!0,referer:!0,te:!0,trailer:!0,"transfer-encoding":!0,upgrade:!0,"user-agent":!0,"x-amzn-trace-id":!0},c=/^proxy-/,f=/^sec-/,l="AWS4-HMAC-SHA256-PAYLOAD",d={},h=[];function p(e,t,n){return e+"/"+t+"/"+n+"/aws4_request"}var v=n(28);function g(e,t,n){var i,o,s=e.headers,a={};try{for(var l=Object(r.__values)(Object.keys(s).sort()),d=l.next();!d.done;d=l.next()){var h=d.value,p=h.toLowerCase();(p in u||(null==t?void 0:t.has(p))||c.test(p)||f.test(p))&&(!n||n&&!n.has(p))||(a[p]=s[h].trim().replace(/\s+/g," "))}}catch(e){i={error:e}}finally{try{d&&!d.done&&(o=l.return)&&o.call(l)}finally{if(i)throw i.error}}return a}var m=n(55);var b=n(251);function y(e,t){var n=e.headers,i=e.body;return Object(r.__awaiter)(this,void 0,void 0,(function(){var e,o,s,a,u,c,f;return Object(r.__generator)(this,(function(l){switch(l.label){case 0:try{for(e=Object(r.__values)(Object.keys(n)),o=e.next();!o.done;o=e.next())if("x-amz-content-sha256"===(s=o.value).toLowerCase())return[2,n[s]]}catch(e){c={error:e}}finally{try{o&&!o.done&&(f=e.return)&&f.call(e)}finally{if(c)throw c.error}}return null!=i?[3,1]:[2,"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"];case 1:return"string"==typeof i||ArrayBuffer.isView(i)||Object(b.a)(i)?((a=new t).update(i),u=v.b,[4,a.digest()]):[3,3];case 2:return[2,u.apply(void 0,[l.sent()])];case 3:return[2,"UNSIGNED-PAYLOAD"]}}))}))}function w(e){var t=e.headers,n=e.query,i=Object(r.__rest)(e,["headers","query"]);return Object(r.__assign)(Object(r.__assign)({},i),{headers:Object(r.__assign)({},t),query:n?_(n):void 0})}function _(e){return Object.keys(e).reduce((function(t,n){var i,o=e[n];return Object(r.__assign)(Object(r.__assign)({},t),((i={})[n]=Array.isArray(o)?Object(r.__spread)(o):o,i))}),{})}function S(e){var t,n;e="function"==typeof e.clone?e.clone():w(e);try{for(var i=Object(r.__values)(Object.keys(e.headers)),s=i.next();!s.done;s=i.next()){var a=s.value;o.indexOf(a.toLowerCase())>-1&&delete e.headers[a]}}catch(e){t={error:e}}finally{try{s&&!s.done&&(n=i.return)&&n.call(i)}finally{if(t)throw t.error}}return e}function E(e){return function(e){if("number"==typeof e)return new Date(1e3*e);if("string"==typeof e)return Number(e)?new Date(1e3*Number(e)):new Date(e);return e}(e).toISOString().replace(/\.\d{3}Z$/,"Z")}var M=function(){function e(e){var t=e.applyChecksum,n=e.credentials,r=e.region,i=e.service,o=e.sha256,s=e.uriEscapePath,a=void 0===s||s;this.service=i,this.sha256=o,this.uriEscapePath=a,this.applyChecksum="boolean"!=typeof t||t,this.regionProvider=k(r),this.credentialProvider=O(n)}return e.prototype.presign=function(e,t){return void 0===t&&(t={}),Object(r.__awaiter)(this,void 0,void 0,(function(){var n,i,o,s,a,u,c,f,l,d,h,v,m,b,_,E,M,k,O,x,C,T,P;return Object(r.__generator)(this,(function(N){switch(N.label){case 0:return n=t.signingDate,i=void 0===n?new Date:n,o=t.expiresIn,s=void 0===o?3600:o,a=t.unsignableHeaders,u=t.signableHeaders,c=t.signingRegion,f=t.signingService,[4,this.credentialProvider()];case 1:return l=N.sent(),null==c?[3,2]:(h=c,[3,4]);case 2:return[4,this.regionProvider()];case 3:h=N.sent(),N.label=4;case 4:return d=h,v=A(i),m=v.longDate,b=v.shortDate,s>604800?[2,Promise.reject("Signature version 4 presigned URLs must have an expiration date less than one week in the future")]:(_=p(b,d,null!=f?f:this.service),E=function(e){var t,n,i="function"==typeof e.clone?e.clone():w(e),o=i.headers,s=i.query,a=void 0===s?{}:s;try{for(var u=Object(r.__values)(Object.keys(o)),c=u.next();!c.done;c=u.next()){var f=c.value;"x-amz-"===f.toLowerCase().substr(0,6)&&(a[f]=o[f],delete o[f])}}catch(e){t={error:e}}finally{try{c&&!c.done&&(n=u.return)&&n.call(u)}finally{if(t)throw t.error}}return Object(r.__assign)(Object(r.__assign)({},e),{headers:o,query:a})}(S(e)),l.sessionToken&&(E.query["X-Amz-Security-Token"]=l.sessionToken),E.query["X-Amz-Algorithm"]="AWS4-HMAC-SHA256",E.query["X-Amz-Credential"]=l.accessKeyId+"/"+_,E.query["X-Amz-Date"]=m,E.query["X-Amz-Expires"]=s.toString(10),M=g(E,a,u),E.query["X-Amz-SignedHeaders"]=I(M),k=E.query,O="X-Amz-Signature",x=this.getSignature,C=[m,_,this.getSigningKey(l,d,b,f)],T=this.createCanonicalRequest,P=[E,M],[4,y(e,this.sha256)]);case 5:return[4,x.apply(this,C.concat([T.apply(this,P.concat([N.sent()]))]))];case 6:return k[O]=N.sent(),[2,E]}}))}))},e.prototype.sign=function(e,t){return Object(r.__awaiter)(this,void 0,void 0,(function(){return Object(r.__generator)(this,(function(n){return"string"==typeof e?[2,this.signString(e,t)]:e.headers&&e.payload?[2,this.signEvent(e,t)]:[2,this.signRequest(e,t)]}))}))},e.prototype.signEvent=function(e,t){var n=e.headers,i=e.payload,o=t.signingDate,s=void 0===o?new Date:o,a=t.priorSignature,u=t.signingRegion,c=t.signingService;return Object(r.__awaiter)(this,void 0,void 0,(function(){var e,t,o,f,d,h,g,m,b,w,_;return Object(r.__generator)(this,(function(r){switch(r.label){case 0:return null==u?[3,1]:(t=u,[3,3]);case 1:return[4,this.regionProvider()];case 2:t=r.sent(),r.label=3;case 3:return e=t,o=A(s),f=o.shortDate,d=o.longDate,h=p(f,e,null!=c?c:this.service),[4,y({headers:{},body:i},this.sha256)];case 4:return g=r.sent(),(m=new this.sha256).update(n),w=v.b,[4,m.digest()];case 5:return b=w.apply(void 0,[r.sent()]),_=[l,d,h,a,b,g].join("\n"),[2,this.signString(_,{signingDate:s,signingRegion:e,signingService:c})]}}))}))},e.prototype.signString=function(e,t){var n=void 0===t?{}:t,i=n.signingDate,o=void 0===i?new Date:i,s=n.signingRegion,a=n.signingService;return Object(r.__awaiter)(this,void 0,void 0,(function(){var t,n,i,u,c,f,l,d;return Object(r.__generator)(this,(function(r){switch(r.label){case 0:return[4,this.credentialProvider()];case 1:return t=r.sent(),null==s?[3,2]:(i=s,[3,4]);case 2:return[4,this.regionProvider()];case 3:i=r.sent(),r.label=4;case 4:return n=i,u=A(o).shortDate,l=(f=this.sha256).bind,[4,this.getSigningKey(t,n,u,a)];case 5:return(c=new(l.apply(f,[void 0,r.sent()]))).update(e),d=v.b,[4,c.digest()];case 6:return[2,d.apply(void 0,[r.sent()])]}}))}))},e.prototype.signRequest=function(e,t){var n=void 0===t?{}:t,o=n.signingDate,s=void 0===o?new Date:o,u=n.signableHeaders,c=n.unsignableHeaders,f=n.signingRegion,l=n.signingService;return Object(r.__awaiter)(this,void 0,void 0,(function(){var t,n,o,d,h,v,m,b,w,_,E;return Object(r.__generator)(this,(function(M){switch(M.label){case 0:return[4,this.credentialProvider()];case 1:return t=M.sent(),null==f?[3,2]:(o=f,[3,4]);case 2:return[4,this.regionProvider()];case 3:o=M.sent(),M.label=4;case 4:return n=o,d=S(e),h=A(s),v=h.longDate,m=h.shortDate,b=p(m,n,null!=l?l:this.service),d.headers[i]=v,t.sessionToken&&(d.headers[a]=t.sessionToken),[4,y(d,this.sha256)];case 5:return w=M.sent(),!function(e,t){var n,i;e=e.toLowerCase();try{for(var o=Object(r.__values)(Object.keys(t)),s=o.next();!s.done;s=o.next()){if(e===s.value.toLowerCase())return!0}}catch(e){n={error:e}}finally{try{s&&!s.done&&(i=o.return)&&i.call(o)}finally{if(n)throw n.error}}return!1}("x-amz-content-sha256",d.headers)&&this.applyChecksum&&(d.headers["x-amz-content-sha256"]=w),_=g(d,c,u),[4,this.getSignature(v,b,this.getSigningKey(t,n,m,l),this.createCanonicalRequest(d,_,w))];case 6:return E=M.sent(),d.headers.authorization="AWS4-HMAC-SHA256 Credential="+t.accessKeyId+"/"+b+", SignedHeaders="+I(_)+", Signature="+E,[2,d]}}))}))},e.prototype.createCanonicalRequest=function(e,t,n){var i=Object.keys(t).sort();return e.method+"\n"+this.getCanonicalPath(e)+"\n"+function(e){var t,n,i=e.query,o=void 0===i?{}:i,a=[],u={},c=function(e){if(e.toLowerCase()===s)return"continue";a.push(e);var t=o[e];"string"==typeof t?u[e]=Object(m.a)(e)+"="+Object(m.a)(t):Array.isArray(t)&&(u[e]=t.slice(0).sort().reduce((function(t,n){return t.concat([Object(m.a)(e)+"="+Object(m.a)(n)])}),[]).join("&"))};try{for(var f=Object(r.__values)(Object.keys(o).sort()),l=f.next();!l.done;l=f.next()){c(l.value)}}catch(e){t={error:e}}finally{try{l&&!l.done&&(n=f.return)&&n.call(f)}finally{if(t)throw t.error}}return a.map((function(e){return u[e]})).filter((function(e){return e})).join("&")}(e)+"\n"+i.map((function(e){return e+":"+t[e]})).join("\n")+"\n\n"+i.join(";")+"\n"+n},e.prototype.createStringToSign=function(e,t,n){return Object(r.__awaiter)(this,void 0,void 0,(function(){var i,o;return Object(r.__generator)(this,(function(r){switch(r.label){case 0:return(i=new this.sha256).update(n),[4,i.digest()];case 1:return o=r.sent(),[2,"AWS4-HMAC-SHA256\n"+e+"\n"+t+"\n"+Object(v.b)(o)]}}))}))},e.prototype.getCanonicalPath=function(e){var t=e.path;return this.uriEscapePath?"/"+encodeURIComponent(t.replace(/^\//,"")).replace(/%2F/g,"/"):t},e.prototype.getSignature=function(e,t,n,i){return Object(r.__awaiter)(this,void 0,void 0,(function(){var o,s,a,u,c;return Object(r.__generator)(this,(function(r){switch(r.label){case 0:return[4,this.createStringToSign(e,t,i)];case 1:return o=r.sent(),u=(a=this.sha256).bind,[4,n];case 2:return(s=new(u.apply(a,[void 0,r.sent()]))).update(o),c=v.b,[4,s.digest()];case 3:return[2,c.apply(void 0,[r.sent()])]}}))}))},e.prototype.getSigningKey=function(e,t,n,i){return function(e,t,n,i,o){var s=n+":"+i+":"+o+":"+t.accessKeyId+":"+t.sessionToken;if(s in d)return d[s];for(h.push(s);h.length>50;)delete d[h.shift()];return d[s]=new Promise((function(a,u){var c,f,l=Promise.resolve("AWS4"+t.secretAccessKey),h=function(t){(l=l.then((function(n){return r=t,(i=new e(n)).update(r),i.digest();var r,i}))).catch((function(){}))};try{for(var p=Object(r.__values)([n,i,o,"aws4_request"]),v=p.next();!v.done;v=p.next()){h(v.value)}}catch(e){c={error:e}}finally{try{v&&!v.done&&(f=p.return)&&f.call(p)}finally{if(c)throw c.error}}l.then(a,(function(e){delete d[s],u(e)}))}))}(this.sha256,e,n,t,i||this.service)},e}(),A=function(e){var t=E(e).replace(/[\-:]/g,"");return{longDate:t,shortDate:t.substr(0,8)}},I=function(e){return Object.keys(e).sort().join(";")},k=function(e){if("string"==typeof e){var t=Promise.resolve(e);return function(){return t}}return e},O=function(e){if("object"==typeof e){var t=Promise.resolve(e);return function(){return t}}return e}},function(e,t,n){"use strict";n.d(t,"a",(function(){return i}));var r=n(1),i=function(e){return Object(r.__assign)(Object(r.__assign)({},e),{eventStreamMarshaller:e.eventStreamSerdeProvider(e)})}},function(e,t,n){"use strict";var r=n(7),i=n(162),o=n(8).Buffer,s=new Array(16);function a(){i.call(this,64),this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878}function u(e,t){return e<<t|e>>>32-t}function c(e,t,n,r,i,o,s){return u(e+(t&n|~t&r)+i+o|0,s)+t|0}function f(e,t,n,r,i,o,s){return u(e+(t&r|n&~r)+i+o|0,s)+t|0}function l(e,t,n,r,i,o,s){return u(e+(t^n^r)+i+o|0,s)+t|0}function d(e,t,n,r,i,o,s){return u(e+(n^(t|~r))+i+o|0,s)+t|0}r(a,i),a.prototype._update=function(){for(var e=s,t=0;t<16;++t)e[t]=this._block.readInt32LE(4*t);var n=this._a,r=this._b,i=this._c,o=this._d;n=c(n,r,i,o,e[0],3614090360,7),o=c(o,n,r,i,e[1],3905402710,12),i=c(i,o,n,r,e[2],606105819,17),r=c(r,i,o,n,e[3],3250441966,22),n=c(n,r,i,o,e[4],4118548399,7),o=c(o,n,r,i,e[5],1200080426,12),i=c(i,o,n,r,e[6],2821735955,17),r=c(r,i,o,n,e[7],4249261313,22),n=c(n,r,i,o,e[8],1770035416,7),o=c(o,n,r,i,e[9],2336552879,12),i=c(i,o,n,r,e[10],4294925233,17),r=c(r,i,o,n,e[11],2304563134,22),n=c(n,r,i,o,e[12],1804603682,7),o=c(o,n,r,i,e[13],4254626195,12),i=c(i,o,n,r,e[14],2792965006,17),n=f(n,r=c(r,i,o,n,e[15],1236535329,22),i,o,e[1],4129170786,5),o=f(o,n,r,i,e[6],3225465664,9),i=f(i,o,n,r,e[11],643717713,14),r=f(r,i,o,n,e[0],3921069994,20),n=f(n,r,i,o,e[5],3593408605,5),o=f(o,n,r,i,e[10],38016083,9),i=f(i,o,n,r,e[15],3634488961,14),r=f(r,i,o,n,e[4],3889429448,20),n=f(n,r,i,o,e[9],568446438,5),o=f(o,n,r,i,e[14],3275163606,9),i=f(i,o,n,r,e[3],4107603335,14),r=f(r,i,o,n,e[8],1163531501,20),n=f(n,r,i,o,e[13],2850285829,5),o=f(o,n,r,i,e[2],4243563512,9),i=f(i,o,n,r,e[7],1735328473,14),n=l(n,r=f(r,i,o,n,e[12],2368359562,20),i,o,e[5],4294588738,4),o=l(o,n,r,i,e[8],2272392833,11),i=l(i,o,n,r,e[11],1839030562,16),r=l(r,i,o,n,e[14],4259657740,23),n=l(n,r,i,o,e[1],2763975236,4),o=l(o,n,r,i,e[4],1272893353,11),i=l(i,o,n,r,e[7],4139469664,16),r=l(r,i,o,n,e[10],3200236656,23),n=l(n,r,i,o,e[13],681279174,4),o=l(o,n,r,i,e[0],3936430074,11),i=l(i,o,n,r,e[3],3572445317,16),r=l(r,i,o,n,e[6],76029189,23),n=l(n,r,i,o,e[9],3654602809,4),o=l(o,n,r,i,e[12],3873151461,11),i=l(i,o,n,r,e[15],530742520,16),n=d(n,r=l(r,i,o,n,e[2],3299628645,23),i,o,e[0],4096336452,6),o=d(o,n,r,i,e[7],1126891415,10),i=d(i,o,n,r,e[14],2878612391,15),r=d(r,i,o,n,e[5],4237533241,21),n=d(n,r,i,o,e[12],1700485571,6),o=d(o,n,r,i,e[3],2399980690,10),i=d(i,o,n,r,e[10],4293915773,15),r=d(r,i,o,n,e[1],2240044497,21),n=d(n,r,i,o,e[8],1873313359,6),o=d(o,n,r,i,e[15],4264355552,10),i=d(i,o,n,r,e[6],2734768916,15),r=d(r,i,o,n,e[13],1309151649,21),n=d(n,r,i,o,e[4],4149444226,6),o=d(o,n,r,i,e[11],3174756917,10),i=d(i,o,n,r,e[2],718787259,15),r=d(r,i,o,n,e[9],3951481745,21),this._a=this._a+n|0,this._b=this._b+r|0,this._c=this._c+i|0,this._d=this._d+o|0},a.prototype._digest=function(){this._block[this._blockOffset++]=128,this._blockOffset>56&&(this._block.fill(0,this._blockOffset,64),this._update(),this._blockOffset=0),this._block.fill(0,this._blockOffset,56),this._block.writeUInt32LE(this._length[0],56),this._block.writeUInt32LE(this._length[1],60),this._update();var e=o.allocUnsafe(16);return e.writeInt32LE(this._a,0),e.writeInt32LE(this._b,4),e.writeInt32LE(this._c,8),e.writeInt32LE(this._d,12),e},e.exports=a},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(e){return!1}var n=t.localStorage[e];return null!=n&&"true"===String(n).toLowerCase()}e.exports=function(e,t){if(n("noDeprecation"))return e;var r=!1;return function(){if(!r){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(31))},function(e,t,n){"use strict";var r=n(67).codes.ERR_STREAM_PREMATURE_CLOSE;function i(){}e.exports=function e(t,n,o){if("function"==typeof n)return e(t,null,n);n||(n={}),o=function(e){var t=!1;return function(){if(!t){t=!0;for(var n=arguments.length,r=new Array(n),i=0;i<n;i++)r[i]=arguments[i];e.apply(this,r)}}}(o||i);var s=n.readable||!1!==n.readable&&t.readable,a=n.writable||!1!==n.writable&&t.writable,u=function(){t.writable||f()},c=t._writableState&&t._writableState.finished,f=function(){a=!1,c=!0,s||o.call(t)},l=t._readableState&&t._readableState.endEmitted,d=function(){s=!1,l=!0,a||o.call(t)},h=function(e){o.call(t,e)},p=function(){var e;return s&&!l?(t._readableState&&t._readableState.ended||(e=new r),o.call(t,e)):a&&!c?(t._writableState&&t._writableState.ended||(e=new r),o.call(t,e)):void 0},v=function(){t.req.on("finish",f)};return!function(e){return e.setHeader&&"function"==typeof e.abort}(t)?a&&!t._writableState&&(t.on("end",u),t.on("close",u)):(t.on("complete",f),t.on("abort",p),t.req?v():t.on("request",v)),t.on("end",d),t.on("finish",f),!1!==n.error&&t.on("error",h),t.on("close",p),function(){t.removeListener("complete",f),t.removeListener("abort",p),t.removeListener("request",v),t.req&&t.req.removeListener("finish",f),t.removeListener("end",u),t.removeListener("close",u),t.removeListener("finish",f),t.removeListener("end",d),t.removeListener("error",h),t.removeListener("close",p)}}},function(e,t,n){"use strict";var r=n(6).Buffer,i=n(7),o=n(162),s=new Array(16),a=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13],u=[5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11],c=[11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6],f=[8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11],l=[0,1518500249,1859775393,2400959708,2840853838],d=[1352829926,1548603684,1836072691,2053994217,0];function h(){o.call(this,64),this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520}function p(e,t){return e<<t|e>>>32-t}function v(e,t,n,r,i,o,s,a){return p(e+(t^n^r)+o+s|0,a)+i|0}function g(e,t,n,r,i,o,s,a){return p(e+(t&n|~t&r)+o+s|0,a)+i|0}function m(e,t,n,r,i,o,s,a){return p(e+((t|~n)^r)+o+s|0,a)+i|0}function b(e,t,n,r,i,o,s,a){return p(e+(t&r|n&~r)+o+s|0,a)+i|0}function y(e,t,n,r,i,o,s,a){return p(e+(t^(n|~r))+o+s|0,a)+i|0}i(h,o),h.prototype._update=function(){for(var e=s,t=0;t<16;++t)e[t]=this._block.readInt32LE(4*t);for(var n=0|this._a,r=0|this._b,i=0|this._c,o=0|this._d,h=0|this._e,w=0|this._a,_=0|this._b,S=0|this._c,E=0|this._d,M=0|this._e,A=0;A<80;A+=1){var I,k;A<16?(I=v(n,r,i,o,h,e[a[A]],l[0],c[A]),k=y(w,_,S,E,M,e[u[A]],d[0],f[A])):A<32?(I=g(n,r,i,o,h,e[a[A]],l[1],c[A]),k=b(w,_,S,E,M,e[u[A]],d[1],f[A])):A<48?(I=m(n,r,i,o,h,e[a[A]],l[2],c[A]),k=m(w,_,S,E,M,e[u[A]],d[2],f[A])):A<64?(I=b(n,r,i,o,h,e[a[A]],l[3],c[A]),k=g(w,_,S,E,M,e[u[A]],d[3],f[A])):(I=y(n,r,i,o,h,e[a[A]],l[4],c[A]),k=v(w,_,S,E,M,e[u[A]],d[4],f[A])),n=h,h=o,o=p(i,10),i=r,r=I,w=M,M=E,E=p(S,10),S=_,_=k}var O=this._b+i+E|0;this._b=this._c+o+M|0,this._c=this._d+h+w|0,this._d=this._e+n+_|0,this._e=this._a+r+S|0,this._a=O},h.prototype._digest=function(){this._block[this._blockOffset++]=128,this._blockOffset>56&&(this._block.fill(0,this._blockOffset,64),this._update(),this._blockOffset=0),this._block.fill(0,this._blockOffset,56),this._block.writeUInt32LE(this._length[0],56),this._block.writeUInt32LE(this._length[1],60),this._update();var e=r.alloc?r.alloc(20):new r(20);return e.writeInt32LE(this._a,0),e.writeInt32LE(this._b,4),e.writeInt32LE(this._c,8),e.writeInt32LE(this._d,12),e.writeInt32LE(this._e,16),e},e.exports=h},function(e,t,n){(t=e.exports=function(e){e=e.toLowerCase();var n=t[e];if(!n)throw new Error(e+" is not supported (we accept pull requests)");return new n}).sha=n(281),t.sha1=n(282),t.sha224=n(283),t.sha256=n(169),t.sha384=n(284),t.sha512=n(170)},function(e,t,n){(t=e.exports=n(171)).Stream=t,t.Readable=t,t.Writable=n(120),t.Duplex=n(60),t.Transform=n(174),t.PassThrough=n(291)},function(e,t,n){var r=n(6),i=r.Buffer;function o(e,t){for(var n in e)t[n]=e[n]}function s(e,t,n){return i(e,t,n)}i.from&&i.alloc&&i.allocUnsafe&&i.allocUnsafeSlow?e.exports=r:(o(r,t),t.Buffer=s),o(i,s),s.from=function(e,t,n){if("number"==typeof e)throw new TypeError("Argument must not be a number");return i(e,t,n)},s.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError("Argument must be a number");var r=i(e);return void 0!==t?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r},s.allocUnsafe=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return i(e)},s.allocUnsafeSlow=function(e){if("number"!=typeof e)throw new TypeError("Argument must be a number");return r.SlowBuffer(e)}},function(e,t,n){"use strict";(function(t,r,i){var o=n(92);function s(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var i=r.callback;t.pendingcb--,i(n),r=r.next}t.corkedRequestsFree?t.corkedRequestsFree.next=e:t.corkedRequestsFree=e}(t,e)}}e.exports=b;var a,u=!t.browser&&["v0.10","v0.9."].indexOf(t.version.slice(0,5))>-1?r:o.nextTick;b.WritableState=m;var c=Object.create(n(80));c.inherits=n(7);var f={deprecate:n(114)},l=n(172),d=n(119).Buffer,h=i.Uint8Array||function(){};var p,v=n(173);function g(){}function m(e,t){a=a||n(60),e=e||{};var r=t instanceof a;this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.writableObjectMode);var i=e.highWaterMark,c=e.writableHighWaterMark,f=this.objectMode?16:16384;this.highWaterMark=i||0===i?i:r&&(c||0===c)?c:f,this.highWaterMark=Math.floor(this.highWaterMark),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var l=!1===e.decodeStrings;this.decodeStrings=!l,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,r=n.sync,i=n.writecb;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,r,i){--t.pendingcb,n?(o.nextTick(i,r),o.nextTick(M,e,t),e._writableState.errorEmitted=!0,e.emit("error",r)):(i(r),e._writableState.errorEmitted=!0,e.emit("error",r),M(e,t))}(e,n,r,t,i);else{var s=S(n);s||n.corked||n.bufferProcessing||!n.bufferedRequest||_(e,n),r?u(w,e,n,s,i):w(e,n,s,i)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.bufferedRequestCount=0,this.corkedRequestsFree=new s(this)}function b(e){if(a=a||n(60),!(p.call(b,this)||this instanceof a))return new b(e);this._writableState=new m(e,this),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),l.call(this)}function y(e,t,n,r,i,o,s){t.writelen=r,t.writecb=s,t.writing=!0,t.sync=!0,n?e._writev(i,t.onwrite):e._write(i,o,t.onwrite),t.sync=!1}function w(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),M(e,t)}function _(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,i=new Array(r),o=t.corkedRequestsFree;o.entry=n;for(var a=0,u=!0;n;)i[a]=n,n.isBuf||(u=!1),n=n.next,a+=1;i.allBuffers=u,y(e,t,!0,t.length,i,"",o.finish),t.pendingcb++,t.lastBufferedRequest=null,o.next?(t.corkedRequestsFree=o.next,o.next=null):t.corkedRequestsFree=new s(t),t.bufferedRequestCount=0}else{for(;n;){var c=n.chunk,f=n.encoding,l=n.callback;if(y(e,t,!1,t.objectMode?1:c.length,c,f,l),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function S(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function E(e,t){e._final((function(n){t.pendingcb--,n&&e.emit("error",n),t.prefinished=!0,e.emit("prefinish"),M(e,t)}))}function M(e,t){var n=S(t);return n&&(!function(e,t){t.prefinished||t.finalCalled||("function"==typeof e._final?(t.pendingcb++,t.finalCalled=!0,o.nextTick(E,e,t)):(t.prefinished=!0,e.emit("prefinish")))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"))),n}c.inherits(b,l),m.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(m.prototype,"buffer",{get:f.deprecate((function(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(p=Function.prototype[Symbol.hasInstance],Object.defineProperty(b,Symbol.hasInstance,{value:function(e){return!!p.call(this,e)||this===b&&(e&&e._writableState instanceof m)}})):p=function(e){return e instanceof this},b.prototype.pipe=function(){this.emit("error",new Error("Cannot pipe, not readable"))},b.prototype.write=function(e,t,n){var r,i=this._writableState,s=!1,a=!i.objectMode&&(r=e,d.isBuffer(r)||r instanceof h);return a&&!d.isBuffer(e)&&(e=function(e){return d.from(e)}(e)),"function"==typeof t&&(n=t,t=null),a?t="buffer":t||(t=i.defaultEncoding),"function"!=typeof n&&(n=g),i.ended?function(e,t){var n=new Error("write after end");e.emit("error",n),o.nextTick(t,n)}(this,n):(a||function(e,t,n,r){var i=!0,s=!1;return null===n?s=new TypeError("May not write null values to stream"):"string"==typeof n||void 0===n||t.objectMode||(s=new TypeError("Invalid non-string/buffer chunk")),s&&(e.emit("error",s),o.nextTick(r,s),i=!1),i}(this,i,e,n))&&(i.pendingcb++,s=function(e,t,n,r,i,o){if(!n){var s=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=d.from(t,n));return t}(t,r,i);r!==s&&(n=!0,i="buffer",r=s)}var a=t.objectMode?1:r.length;t.length+=a;var u=t.length<t.highWaterMark;u||(t.needDrain=!0);if(t.writing||t.corked){var c=t.lastBufferedRequest;t.lastBufferedRequest={chunk:r,encoding:i,isBuf:n,callback:o,next:null},c?c.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else y(e,t,!1,a,r,i,o);return u}(this,i,a,e,t,n)),s},b.prototype.cork=function(){this._writableState.corked++},b.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.finished||e.bufferProcessing||!e.bufferedRequest||_(this,e))},b.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new TypeError("Unknown encoding: "+e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(b.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),b.prototype._write=function(e,t,n){n(new Error("_write() is not implemented"))},b.prototype._writev=null,b.prototype.end=function(e,t,n){var r=this._writableState;"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),r.corked&&(r.corked=1,this.uncork()),r.ending||r.finished||function(e,t,n){t.ending=!0,M(e,t),n&&(t.finished?o.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,r,n)},Object.defineProperty(b.prototype,"destroyed",{get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),b.prototype.destroy=v.destroy,b.prototype._undestroy=v.undestroy,b.prototype._destroy=function(e,t){this.end(),t(e)}}).call(this,n(20),n(289).setImmediate,n(31))},function(e,t,n){"use strict";var r=n(46);function i(e){this.options=e,this.type=this.options.type,this.blockSize=8,this._init(),this.buffer=new Array(this.blockSize),this.bufferOff=0}e.exports=i,i.prototype._init=function(){},i.prototype.update=function(e){return 0===e.length?[]:"decrypt"===this.type?this._updateDecrypt(e):this._updateEncrypt(e)},i.prototype._buffer=function(e,t){for(var n=Math.min(this.buffer.length-this.bufferOff,e.length-t),r=0;r<n;r++)this.buffer[this.bufferOff+r]=e[t+r];return this.bufferOff+=n,n},i.prototype._flushBuffer=function(e,t){return this._update(this.buffer,0,e,t),this.bufferOff=0,this.blockSize},i.prototype._updateEncrypt=function(e){var t=0,n=0,r=(this.bufferOff+e.length)/this.blockSize|0,i=new Array(r*this.blockSize);0!==this.bufferOff&&(t+=this._buffer(e,t),this.bufferOff===this.buffer.length&&(n+=this._flushBuffer(i,n)));for(var o=e.length-(e.length-t)%this.blockSize;t<o;t+=this.blockSize)this._update(e,t,i,n),n+=this.blockSize;for(;t<e.length;t++,this.bufferOff++)this.buffer[this.bufferOff]=e[t];return i},i.prototype._updateDecrypt=function(e){for(var t=0,n=0,r=Math.ceil((this.bufferOff+e.length)/this.blockSize)-1,i=new Array(r*this.blockSize);r>0;r--)t+=this._buffer(e,t),n+=this._flushBuffer(i,n);return t+=this._buffer(e,t),i},i.prototype.final=function(e){var t,n;return e&&(t=this.update(e)),n="encrypt"===this.type?this._finalEncrypt():this._finalDecrypt(),t?t.concat(n):n},i.prototype._pad=function(e,t){if(0===t)return!1;for(;t<e.length;)e[t++]=0;return!0},i.prototype._finalEncrypt=function(){if(!this._pad(this.buffer,this.bufferOff))return[];var e=new Array(this.blockSize);return this._update(this.buffer,0,e,0),e},i.prototype._unpad=function(e){return e},i.prototype._finalDecrypt=function(){r.equal(this.bufferOff,this.blockSize,"Not enough data to decrypt");var e=new Array(this.blockSize);return this._flushBuffer(e,0),this._unpad(e)}},function(e,t,n){var r=n(304),i=n(312),o=n(187);t.createCipher=t.Cipher=r.createCipher,t.createCipheriv=t.Cipheriv=r.createCipheriv,t.createDecipher=t.Decipher=i.createDecipher,t.createDecipheriv=t.Decipheriv=i.createDecipheriv,t.listCiphers=t.getCiphers=function(){return Object.keys(o)}},function(e,t,n){var r={ECB:n(305),CBC:n(306),CFB:n(307),CFB8:n(308),CFB1:n(309),OFB:n(310),CTR:n(185),GCM:n(185)},i=n(187);for(var o in i)i[o].module=r[i[o].mode];e.exports=i},function(e,t,n){var r;function i(e){this.rand=e}if(e.exports=function(e){return r||(r=new i(null)),r.generate(e)},e.exports.Rand=i,i.prototype.generate=function(e){return this._rand(e)},i.prototype._rand=function(e){if(this.rand.getBytes)return this.rand.getBytes(e);for(var t=new Uint8Array(e),n=0;n<t.length;n++)t[n]=this.rand.getByte();return t},"object"==typeof self)self.crypto&&self.crypto.getRandomValues?i.prototype._rand=function(e){var t=new Uint8Array(e);return self.crypto.getRandomValues(t),t}:self.msCrypto&&self.msCrypto.getRandomValues?i.prototype._rand=function(e){var t=new Uint8Array(e);return self.msCrypto.getRandomValues(t),t}:"object"==typeof window&&(i.prototype._rand=function(){throw new Error("Not implemented yet")});else try{var o=n(316);if("function"!=typeof o.randomBytes)throw new Error("Not supported");i.prototype._rand=function(e){return o.randomBytes(e)}}catch(e){}},function(e,t,n){"use strict";var r=n(70).codes.ERR_STREAM_PREMATURE_CLOSE;function i(){}e.exports=function e(t,n,o){if("function"==typeof n)return e(t,null,n);n||(n={}),o=function(e){var t=!1;return function(){if(!t){t=!0;for(var n=arguments.length,r=new Array(n),i=0;i<n;i++)r[i]=arguments[i];e.apply(this,r)}}}(o||i);var s=n.readable||!1!==n.readable&&t.readable,a=n.writable||!1!==n.writable&&t.writable,u=function(){t.writable||f()},c=t._writableState&&t._writableState.finished,f=function(){a=!1,c=!0,s||o.call(t)},l=t._readableState&&t._readableState.endEmitted,d=function(){s=!1,l=!0,a||o.call(t)},h=function(e){o.call(t,e)},p=function(){var e;return s&&!l?(t._readableState&&t._readableState.ended||(e=new r),o.call(t,e)):a&&!c?(t._writableState&&t._writableState.ended||(e=new r),o.call(t,e)):void 0},v=function(){t.req.on("finish",f)};return!function(e){return e.setHeader&&"function"==typeof e.abort}(t)?a&&!t._writableState&&(t.on("end",u),t.on("close",u)):(t.on("complete",f),t.on("abort",p),t.req?v():t.on("request",v)),t.on("end",d),t.on("finish",f),!1!==n.error&&t.on("error",h),t.on("close",p),function(){t.removeListener("complete",f),t.removeListener("abort",p),t.removeListener("request",v),t.req&&t.req.removeListener("finish",f),t.removeListener("end",u),t.removeListener("close",u),t.removeListener("finish",f),t.removeListener("end",d),t.removeListener("error",h),t.removeListener("close",p)}}},function(e,t,n){(function(t){var r=n(329),i=n(66);function o(e){var t,n=e.modulus.byteLength();do{t=new r(i(n))}while(t.cmp(e.modulus)>=0||!t.umod(e.prime1)||!t.umod(e.prime2));return t}function s(e,n){var i=function(e){var t=o(e);return{blinder:t.toRed(r.mont(e.modulus)).redPow(new r(e.publicExponent)).fromRed(),unblinder:t.invm(e.modulus)}}(n),s=n.modulus.byteLength(),a=new r(e).mul(i.blinder).umod(n.modulus),u=a.toRed(r.mont(n.prime1)),c=a.toRed(r.mont(n.prime2)),f=n.coefficient,l=n.prime1,d=n.prime2,h=u.redPow(n.exponent1).fromRed(),p=c.redPow(n.exponent2).fromRed(),v=h.isub(p).imul(f).umod(l).imul(d);return p.iadd(v).imul(i.unblinder).umod(n.modulus).toArrayLike(t,"be",s)}s.getr=o,e.exports=s}).call(this,n(6).Buffer)},function(e,t,n){"use strict";var r=t;r.version=n(331).version,r.utils=n(47),r.rand=n(124),r.curve=n(199),r.curves=n(128),r.ec=n(342),r.eddsa=n(346)},function(e,t,n){"use strict";var r,i=t,o=n(129),s=n(199),a=n(47).assert;function u(e){"short"===e.type?this.curve=new s.short(e):"edwards"===e.type?this.curve=new s.edwards(e):this.curve=new s.mont(e),this.g=this.curve.g,this.n=this.curve.n,this.hash=e.hash,a(this.g.validate(),"Invalid curve"),a(this.g.mul(this.n).isInfinity(),"Invalid curve, G*N != O")}function c(e,t){Object.defineProperty(i,e,{configurable:!0,enumerable:!0,get:function(){var n=new u(t);return Object.defineProperty(i,e,{configurable:!0,enumerable:!0,value:n}),n}})}i.PresetCurve=u,c("p192",{type:"short",prime:"p192",p:"ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff",a:"ffffffff ffffffff ffffffff fffffffe ffffffff fffffffc",b:"64210519 e59c80e7 0fa7e9ab 72243049 feb8deec c146b9b1",n:"ffffffff ffffffff ffffffff 99def836 146bc9b1 b4d22831",hash:o.sha256,gRed:!1,g:["188da80e b03090f6 7cbf20eb 43a18800 f4ff0afd 82ff1012","07192b95 ffc8da78 631011ed 6b24cdd5 73f977a1 1e794811"]}),c("p224",{type:"short",prime:"p224",p:"ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001",a:"ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff fffffffe",b:"b4050a85 0c04b3ab f5413256 5044b0b7 d7bfd8ba 270b3943 2355ffb4",n:"ffffffff ffffffff ffffffff ffff16a2 e0b8f03e 13dd2945 5c5c2a3d",hash:o.sha256,gRed:!1,g:["b70e0cbd 6bb4bf7f 321390b9 4a03c1d3 56c21122 343280d6 115c1d21","bd376388 b5f723fb 4c22dfe6 cd4375a0 5a074764 44d58199 85007e34"]}),c("p256",{type:"short",prime:null,p:"ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff",a:"ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff fffffffc",b:"5ac635d8 aa3a93e7 b3ebbd55 769886bc 651d06b0 cc53b0f6 3bce3c3e 27d2604b",n:"ffffffff 00000000 ffffffff ffffffff bce6faad a7179e84 f3b9cac2 fc632551",hash:o.sha256,gRed:!1,g:["6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296","4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5"]}),c("p384",{type:"short",prime:null,p:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff 00000000 00000000 ffffffff",a:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff 00000000 00000000 fffffffc",b:"b3312fa7 e23ee7e4 988e056b e3f82d19 181d9c6e fe814112 0314088f 5013875a c656398d 8a2ed19d 2a85c8ed d3ec2aef",n:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff c7634d81 f4372ddf 581a0db2 48b0a77a ecec196a ccc52973",hash:o.sha384,gRed:!1,g:["aa87ca22 be8b0537 8eb1c71e f320ad74 6e1d3b62 8ba79b98 59f741e0 82542a38 5502f25d bf55296c 3a545e38 72760ab7","3617de4a 96262c6f 5d9e98bf 9292dc29 f8f41dbd 289a147c e9da3113 b5f0b8c0 0a60b1ce 1d7e819d 7a431d7c 90ea0e5f"]}),c("p521",{type:"short",prime:null,p:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff",a:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffc",b:"00000051 953eb961 8e1c9a1f 929a21a0 b68540ee a2da725b 99b315f3 b8b48991 8ef109e1 56193951 ec7e937b 1652c0bd 3bb1bf07 3573df88 3d2c34f1 ef451fd4 6b503f00",n:"000001ff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffa 51868783 bf2f966b 7fcc0148 f709a5d0 3bb5c9b8 899c47ae bb6fb71e 91386409",hash:o.sha512,gRed:!1,g:["000000c6 858e06b7 0404e9cd 9e3ecb66 2395b442 9c648139 053fb521 f828af60 6b4d3dba a14b5e77 efe75928 fe1dc127 a2ffa8de 3348b3c1 856a429b f97e7e31 c2e5bd66","00000118 39296a78 9a3bc004 5c8a5fb4 2c7d1bd9 98f54449 579b4468 17afbd17 273e662c 97ee7299 5ef42640 c550b901 3fad0761 353c7086 a272c240 88be9476 9fd16650"]}),c("curve25519",{type:"mont",prime:"p25519",p:"7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed",a:"76d06",b:"1",n:"1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed",hash:o.sha256,gRed:!1,g:["9"]}),c("ed25519",{type:"edwards",prime:"p25519",p:"7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed",a:"-1",c:"1",d:"52036cee2b6ffe73 8cc740797779e898 00700a4d4141d8ab 75eb4dca135978a3",n:"1000000000000000 0000000000000000 14def9dea2f79cd6 5812631a5cf5d3ed",hash:o.sha256,gRed:!1,g:["216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a","6666666666666666666666666666666666666666666666666666666666666658"]});try{r=n(341)}catch(e){r=void 0}c("secp256k1",{type:"short",prime:"k256",p:"ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f",a:"0",b:"7",n:"ffffffff ffffffff ffffffff fffffffe baaedce6 af48a03b bfd25e8c d0364141",h:"1",hash:o.sha256,beta:"7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee",lambda:"5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72",basis:[{a:"3086d221a7d46bcde86c90e49284eb15",b:"-e4437ed6010e88286f547fa90abfe4c3"},{a:"114ca50f7a8e2f3f657c1108d9d44cfd8",b:"3086d221a7d46bcde86c90e49284eb15"}],gRed:!1,g:["79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798","483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",r]})},function(e,t,n){var r=t;r.utils=n(51),r.common=n(82),r.sha=n(335),r.ripemd=n(339),r.hmac=n(340),r.sha1=r.sha.sha1,r.sha256=r.sha.sha256,r.sha224=r.sha.sha224,r.sha384=r.sha.sha384,r.sha512=r.sha.sha512,r.ripemd160=r.ripemd.ripemd160},function(e,t,n){"use strict";(function(t){var r,i=n(6),o=i.Buffer,s={};for(r in i)i.hasOwnProperty(r)&&"SlowBuffer"!==r&&"Buffer"!==r&&(s[r]=i[r]);var a=s.Buffer={};for(r in o)o.hasOwnProperty(r)&&"allocUnsafe"!==r&&"allocUnsafeSlow"!==r&&(a[r]=o[r]);if(s.Buffer.prototype=o.prototype,a.from&&a.from!==Uint8Array.from||(a.from=function(e,t,n){if("number"==typeof e)throw new TypeError('The "value" argument must not be of type number. Received type '+typeof e);if(e&&void 0===e.length)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof e);return o(e,t,n)}),a.alloc||(a.alloc=function(e,t,n){if("number"!=typeof e)throw new TypeError('The "size" argument must be of type number. Received type '+typeof e);if(e<0||e>=2*(1<<30))throw new RangeError('The value "'+e+'" is invalid for option "size"');var r=o(e);return t&&0!==t.length?"string"==typeof n?r.fill(t,n):r.fill(t):r.fill(0),r}),!s.kStringMaxLength)try{s.kStringMaxLength=t.binding("buffer").kStringMaxLength}catch(e){}s.constants||(s.constants={MAX_LENGTH:s.kMaxLength},s.kStringMaxLength&&(s.constants.MAX_STRING_LENGTH=s.kStringMaxLength)),e.exports=s}).call(this,n(20))},function(e,t,n){"use strict";const r=n(132).Reporter,i=n(83).EncoderBuffer,o=n(83).DecoderBuffer,s=n(46),a=["seq","seqof","set","setof","objid","bool","gentime","utctime","null_","enum","int","objDesc","bitstr","bmpstr","charstr","genstr","graphstr","ia5str","iso646str","numstr","octstr","printstr","t61str","unistr","utf8str","videostr"],u=["key","obj","use","optional","explicit","implicit","def","choice","any","contains"].concat(a);function c(e,t,n){const r={};this._baseState=r,r.name=n,r.enc=e,r.parent=t||null,r.children=null,r.tag=null,r.args=null,r.reverseArgs=null,r.choice=null,r.optional=!1,r.any=!1,r.obj=!1,r.use=null,r.useDecoder=null,r.key=null,r.default=null,r.explicit=null,r.implicit=null,r.contains=null,r.parent||(r.children=[],this._wrap())}e.exports=c;const f=["enc","parent","children","tag","args","reverseArgs","choice","optional","any","obj","use","alteredUse","key","default","explicit","implicit","contains"];c.prototype.clone=function(){const e=this._baseState,t={};f.forEach((function(n){t[n]=e[n]}));const n=new this.constructor(t.parent);return n._baseState=t,n},c.prototype._wrap=function(){const e=this._baseState;u.forEach((function(t){this[t]=function(){const n=new this.constructor(this);return e.children.push(n),n[t].apply(n,arguments)}}),this)},c.prototype._init=function(e){const t=this._baseState;s(null===t.parent),e.call(this),t.children=t.children.filter((function(e){return e._baseState.parent===this}),this),s.equal(t.children.length,1,"Root node can have only one child")},c.prototype._useArgs=function(e){const t=this._baseState,n=e.filter((function(e){return e instanceof this.constructor}),this);e=e.filter((function(e){return!(e instanceof this.constructor)}),this),0!==n.length&&(s(null===t.children),t.children=n,n.forEach((function(e){e._baseState.parent=this}),this)),0!==e.length&&(s(null===t.args),t.args=e,t.reverseArgs=e.map((function(e){if("object"!=typeof e||e.constructor!==Object)return e;const t={};return Object.keys(e).forEach((function(n){n==(0|n)&&(n|=0);const r=e[n];t[r]=n})),t})))},["_peekTag","_decodeTag","_use","_decodeStr","_decodeObjid","_decodeTime","_decodeNull","_decodeInt","_decodeBool","_decodeList","_encodeComposite","_encodeStr","_encodeObjid","_encodeTime","_encodeNull","_encodeInt","_encodeBool"].forEach((function(e){c.prototype[e]=function(){const t=this._baseState;throw new Error(e+" not implemented for encoding: "+t.enc)}})),a.forEach((function(e){c.prototype[e]=function(){const t=this._baseState,n=Array.prototype.slice.call(arguments);return s(null===t.tag),t.tag=e,this._useArgs(n),this}})),c.prototype.use=function(e){s(e);const t=this._baseState;return s(null===t.use),t.use=e,this},c.prototype.optional=function(){return this._baseState.optional=!0,this},c.prototype.def=function(e){const t=this._baseState;return s(null===t.default),t.default=e,t.optional=!0,this},c.prototype.explicit=function(e){const t=this._baseState;return s(null===t.explicit&&null===t.implicit),t.explicit=e,this},c.prototype.implicit=function(e){const t=this._baseState;return s(null===t.explicit&&null===t.implicit),t.implicit=e,this},c.prototype.obj=function(){const e=this._baseState,t=Array.prototype.slice.call(arguments);return e.obj=!0,0!==t.length&&this._useArgs(t),this},c.prototype.key=function(e){const t=this._baseState;return s(null===t.key),t.key=e,this},c.prototype.any=function(){return this._baseState.any=!0,this},c.prototype.choice=function(e){const t=this._baseState;return s(null===t.choice),t.choice=e,this._useArgs(Object.keys(e).map((function(t){return e[t]}))),this},c.prototype.contains=function(e){const t=this._baseState;return s(null===t.use),t.contains=e,this},c.prototype._decode=function(e,t){const n=this._baseState;if(null===n.parent)return e.wrapResult(n.children[0]._decode(e,t));let r,i=n.default,s=!0,a=null;if(null!==n.key&&(a=e.enterKey(n.key)),n.optional){let r=null;if(null!==n.explicit?r=n.explicit:null!==n.implicit?r=n.implicit:null!==n.tag&&(r=n.tag),null!==r||n.any){if(s=this._peekTag(e,r,n.any),e.isError(s))return s}else{const r=e.save();try{null===n.choice?this._decodeGeneric(n.tag,e,t):this._decodeChoice(e,t),s=!0}catch(e){s=!1}e.restore(r)}}if(n.obj&&s&&(r=e.enterObject()),s){if(null!==n.explicit){const t=this._decodeTag(e,n.explicit);if(e.isError(t))return t;e=t}const r=e.offset;if(null===n.use&&null===n.choice){let t;n.any&&(t=e.save());const r=this._decodeTag(e,null!==n.implicit?n.implicit:n.tag,n.any);if(e.isError(r))return r;n.any?i=e.raw(t):e=r}if(t&&t.track&&null!==n.tag&&t.track(e.path(),r,e.length,"tagged"),t&&t.track&&null!==n.tag&&t.track(e.path(),e.offset,e.length,"content"),n.any||(i=null===n.choice?this._decodeGeneric(n.tag,e,t):this._decodeChoice(e,t)),e.isError(i))return i;if(n.any||null!==n.choice||null===n.children||n.children.forEach((function(n){n._decode(e,t)})),n.contains&&("octstr"===n.tag||"bitstr"===n.tag)){const r=new o(i);i=this._getUse(n.contains,e._reporterState.obj)._decode(r,t)}}return n.obj&&s&&(i=e.leaveObject(r)),null===n.key||null===i&&!0!==s?null!==a&&e.exitKey(a):e.leaveKey(a,n.key,i),i},c.prototype._decodeGeneric=function(e,t,n){const r=this._baseState;return"seq"===e||"set"===e?null:"seqof"===e||"setof"===e?this._decodeList(t,e,r.args[0],n):/str$/.test(e)?this._decodeStr(t,e,n):"objid"===e&&r.args?this._decodeObjid(t,r.args[0],r.args[1],n):"objid"===e?this._decodeObjid(t,null,null,n):"gentime"===e||"utctime"===e?this._decodeTime(t,e,n):"null_"===e?this._decodeNull(t,n):"bool"===e?this._decodeBool(t,n):"objDesc"===e?this._decodeStr(t,e,n):"int"===e||"enum"===e?this._decodeInt(t,r.args&&r.args[0],n):null!==r.use?this._getUse(r.use,t._reporterState.obj)._decode(t,n):t.error("unknown tag: "+e)},c.prototype._getUse=function(e,t){const n=this._baseState;return n.useDecoder=this._use(e,t),s(null===n.useDecoder._baseState.parent),n.useDecoder=n.useDecoder._baseState.children[0],n.implicit!==n.useDecoder._baseState.implicit&&(n.useDecoder=n.useDecoder.clone(),n.useDecoder._baseState.implicit=n.implicit),n.useDecoder},c.prototype._decodeChoice=function(e,t){const n=this._baseState;let r=null,i=!1;return Object.keys(n.choice).some((function(o){const s=e.save(),a=n.choice[o];try{const n=a._decode(e,t);if(e.isError(n))return!1;r={type:o,value:n},i=!0}catch(t){return e.restore(s),!1}return!0}),this),i?r:e.error("Choice not matched")},c.prototype._createEncoderBuffer=function(e){return new i(e,this.reporter)},c.prototype._encode=function(e,t,n){const r=this._baseState;if(null!==r.default&&r.default===e)return;const i=this._encodeValue(e,t,n);return void 0===i||this._skipDefault(i,t,n)?void 0:i},c.prototype._encodeValue=function(e,t,n){const i=this._baseState;if(null===i.parent)return i.children[0]._encode(e,t||new r);let o=null;if(this.reporter=t,i.optional&&void 0===e){if(null===i.default)return;e=i.default}let s=null,a=!1;if(i.any)o=this._createEncoderBuffer(e);else if(i.choice)o=this._encodeChoice(e,t);else if(i.contains)s=this._getUse(i.contains,n)._encode(e,t),a=!0;else if(i.children)s=i.children.map((function(n){if("null_"===n._baseState.tag)return n._encode(null,t,e);if(null===n._baseState.key)return t.error("Child should have a key");const r=t.enterKey(n._baseState.key);if("object"!=typeof e)return t.error("Child expected, but input is not object");const i=n._encode(e[n._baseState.key],t,e);return t.leaveKey(r),i}),this).filter((function(e){return e})),s=this._createEncoderBuffer(s);else if("seqof"===i.tag||"setof"===i.tag){if(!i.args||1!==i.args.length)return t.error("Too many args for : "+i.tag);if(!Array.isArray(e))return t.error("seqof/setof, but data is not Array");const n=this.clone();n._baseState.implicit=null,s=this._createEncoderBuffer(e.map((function(n){const r=this._baseState;return this._getUse(r.args[0],e)._encode(n,t)}),n))}else null!==i.use?o=this._getUse(i.use,n)._encode(e,t):(s=this._encodePrimitive(i.tag,e),a=!0);if(!i.any&&null===i.choice){const e=null!==i.implicit?i.implicit:i.tag,n=null===i.implicit?"universal":"context";null===e?null===i.use&&t.error("Tag could be omitted only for .use()"):null===i.use&&(o=this._encodeComposite(e,a,n,s))}return null!==i.explicit&&(o=this._encodeComposite(i.explicit,!1,"context",o)),o},c.prototype._encodeChoice=function(e,t){const n=this._baseState,r=n.choice[e.type];return r||s(!1,e.type+" not found in "+JSON.stringify(Object.keys(n.choice))),r._encode(e.value,t)},c.prototype._encodePrimitive=function(e,t){const n=this._baseState;if(/str$/.test(e))return this._encodeStr(t,e);if("objid"===e&&n.args)return this._encodeObjid(t,n.reverseArgs[0],n.args[1]);if("objid"===e)return this._encodeObjid(t,null,null);if("gentime"===e||"utctime"===e)return this._encodeTime(t,e);if("null_"===e)return this._encodeNull();if("int"===e||"enum"===e)return this._encodeInt(t,n.args&&n.reverseArgs[0]);if("bool"===e)return this._encodeBool(t);if("objDesc"===e)return this._encodeStr(t,e);throw new Error("Unsupported tag: "+e)},c.prototype._isNumstr=function(e){return/^[0-9 ]*$/.test(e)},c.prototype._isPrintstr=function(e){return/^[A-Za-z0-9 '()+,-./:=?]*$/.test(e)}},function(e,t,n){"use strict";const r=n(7);function i(e){this._reporterState={obj:null,path:[],options:e||{},errors:[]}}function o(e,t){this.path=e,this.rethrow(t)}t.Reporter=i,i.prototype.isError=function(e){return e instanceof o},i.prototype.save=function(){const e=this._reporterState;return{obj:e.obj,pathLen:e.path.length}},i.prototype.restore=function(e){const t=this._reporterState;t.obj=e.obj,t.path=t.path.slice(0,e.pathLen)},i.prototype.enterKey=function(e){return this._reporterState.path.push(e)},i.prototype.exitKey=function(e){const t=this._reporterState;t.path=t.path.slice(0,e-1)},i.prototype.leaveKey=function(e,t,n){const r=this._reporterState;this.exitKey(e),null!==r.obj&&(r.obj[t]=n)},i.prototype.path=function(){return this._reporterState.path.join("/")},i.prototype.enterObject=function(){const e=this._reporterState,t=e.obj;return e.obj={},t},i.prototype.leaveObject=function(e){const t=this._reporterState,n=t.obj;return t.obj=e,n},i.prototype.error=function(e){let t;const n=this._reporterState,r=e instanceof o;if(t=r?e:new o(n.path.map((function(e){return"["+JSON.stringify(e)+"]"})).join(""),e.message||e,e.stack),!n.options.partial)throw t;return r||n.errors.push(t),t},i.prototype.wrapResult=function(e){const t=this._reporterState;return t.options.partial?{result:this.isError(e)?null:e,errors:t.errors}:e},r(o,Error),o.prototype.rethrow=function(e){if(this.message=e+" at: "+(this.path||"(shallow)"),Error.captureStackTrace&&Error.captureStackTrace(this,o),!this.stack)try{throw new Error(this.message)}catch(e){this.stack=e.stack}return this}},function(e,t,n){"use strict";function r(e){const t={};return Object.keys(e).forEach((function(n){(0|n)==n&&(n|=0);const r=e[n];t[r]=n})),t}t.tagClass={0:"universal",1:"application",2:"context",3:"private"},t.tagClassByName=r(t.tagClass),t.tag={0:"end",1:"bool",2:"int",3:"bitstr",4:"octstr",5:"null_",6:"objid",7:"objDesc",8:"external",9:"real",10:"enum",11:"embed",12:"utf8str",13:"relativeOid",16:"seq",17:"set",18:"numstr",19:"printstr",20:"t61str",21:"videostr",22:"ia5str",23:"utctime",24:"gentime",25:"graphstr",26:"iso646str",27:"genstr",28:"unistr",29:"charstr",30:"bmpstr"},t.tagByName=r(t.tag)},function(e,t,n){"use strict";n.r(t),n.d(t,"locateWindow",(function(){return i}));var r={};function i(){return"undefined"!=typeof window?window:"undefined"!=typeof self?self:r}},function(e,t,n){var r=n(84),i=n(85);e.exports=function(e){return"symbol"==typeof e||i(e)&&"[object Symbol]"==r(e)}},function(e,t,n){var r=n(395),i=n(411),o=n(413),s=n(414),a=n(415);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}u.prototype.clear=r,u.prototype.delete=i,u.prototype.get=o,u.prototype.has=s,u.prototype.set=a,e.exports=u},function(e,t,n){var r=n(72)(n(53),"Map");e.exports=r},function(e,t,n){(function(e){var r=n(53),i=n(427),o=t&&!t.nodeType&&t,s=o&&"object"==typeof e&&e&&!e.nodeType&&e,a=s&&s.exports===o?r.Buffer:void 0,u=(a?a.isBuffer:void 0)||i;e.exports=u}).call(this,n(57)(e))},function(e,t,n){var r=n(428),i=n(429),o=n(430),s=o&&o.isTypedArray,a=s?i(s):r;e.exports=a},function(e,t,n){"use strict";n.d(t,"a",(function(){return $s})),n.d(t,"b",(function(){return Ks}));var r=n(44),i=n(221),o=n(88),s=n(89),a=n(50),u=function(e,t){return(u=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function c(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}u(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var f=function(){return(f=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function l(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))}function d(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}}Object.create;Object.create;var h,p,v,g,m,b,y,w,_,S,E,M,A,I,k,O,x,C,T,P,N,R,L,j,D,U,B,F,z,q,K,H,V,G,W,$,Y,J,Z,X,Q,ee,te,ne,re,ie,oe,se,ae,ue,ce,fe,le,de,he,pe,ve,ge,me,be,ye,we,_e,Se,Ee,Me,Ae,Ie,ke,Oe,xe,Ce,Te,Pe,Ne,Re,Le,je,De,Ue,Be,Fe,ze,qe,Ke,He,Ve,Ge,We,$e,Ye,Je,Ze,Xe,Qe,et,tt,nt,rt,it,ot,st,at,ut,ct,ft,lt,dt,ht,pt,vt,gt,mt,bt,yt,wt,_t,St,Et,Mt,At,It,kt,Ot,xt,Ct,Tt,Pt,Nt,Rt,Lt,jt,Dt,Ut,Bt,Ft,zt,qt,Kt,Ht,Vt,Gt,Wt,$t,Yt,Jt,Zt,Xt,Qt,en,tn,nn,rn,on,sn,an,un,cn,fn,ln,dn,hn,pn,vn,gn,mn,bn,yn,wn,_n,Sn,En,Mn,An,In,kn,On,xn,Cn,Tn,Pn,Nn,Rn,Ln,jn,Dn,Un,Bn,Fn,zn,qn,Kn,Hn,Vn,Gn,Wn,$n,Yn,Jn,Zn,Xn,Qn,er,tr,nr,rr,ir,or,sr,ar,ur,cr,fr,lr,dr,hr,pr,vr,gr,mr,br,yr,wr,_r,Sr,Er,Mr,Ar,Ir,kr,Or,xr,Cr,Tr,Pr,Nr,Rr,Lr,jr,Dr,Ur,Br,Fr,zr,qr,Kr,Hr,Vr,Gr,Wr,$r,Yr,Jr,Zr=n(0);(h||(h={})).filterSensitiveLog=function(e){return f({},e)},(p||(p={})).filterSensitiveLog=function(e){return f({},e)},(v||(v={})).filterSensitiveLog=function(e){return f({},e)},(g||(g={})).filterSensitiveLog=function(e){return f({},e)},(m||(m={})).filterSensitiveLog=function(e){return f({},e)},(b||(b={})).filterSensitiveLog=function(e){return f({},e)},(y||(y={})).filterSensitiveLog=function(e){return f({},e)},(w||(w={})).filterSensitiveLog=function(e){return f({},e)},(_||(_={})).filterSensitiveLog=function(e){return f({},e)},(S||(S={})).filterSensitiveLog=function(e){return f({},e)},(E||(E={})).filterSensitiveLog=function(e){return f(f({},e),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d})},(M||(M={})).filterSensitiveLog=function(e){return f({},e)},(A||(A={})).filterSensitiveLog=function(e){return f({},e)},(I||(I={})).filterSensitiveLog=function(e){return f({},e)},(k||(k={})).filterSensitiveLog=function(e){return f({},e)},(O||(O={})).filterSensitiveLog=function(e){return f(f(f({},e),e.SSEKMSEncryptionContext&&{SSEKMSEncryptionContext:Zr.d}),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d})},(x||(x={})).filterSensitiveLog=function(e){return f(f(f(f(f({},e),e.SSEKMSEncryptionContext&&{SSEKMSEncryptionContext:Zr.d}),e.SSECustomerKey&&{SSECustomerKey:Zr.d}),e.CopySourceSSECustomerKey&&{CopySourceSSECustomerKey:Zr.d}),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d})},(C||(C={})).filterSensitiveLog=function(e){return f({},e)},(T||(T={})).filterSensitiveLog=function(e){return f({},e)},(P||(P={})).filterSensitiveLog=function(e){return f({},e)},(N||(N={})).filterSensitiveLog=function(e){return f({},e)},(R||(R={})).filterSensitiveLog=function(e){return f({},e)},(L||(L={})).filterSensitiveLog=function(e){return f({},e)},(j||(j={})).filterSensitiveLog=function(e){return f(f(f({},e),e.SSEKMSEncryptionContext&&{SSEKMSEncryptionContext:Zr.d}),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d})},(D||(D={})).filterSensitiveLog=function(e){return f(f(f(f({},e),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d}),e.SSEKMSEncryptionContext&&{SSEKMSEncryptionContext:Zr.d}),e.SSECustomerKey&&{SSECustomerKey:Zr.d})},(U||(U={})).filterSensitiveLog=function(e){return f({},e)},(B||(B={})).filterSensitiveLog=function(e){return f({},e)},(F||(F={})).filterSensitiveLog=function(e){return f({},e)},(z||(z={})).filterSensitiveLog=function(e){return f({},e)},(q||(q={})).filterSensitiveLog=function(e){return f({},e)},(K||(K={})).filterSensitiveLog=function(e){return f({},e)},(H||(H={})).filterSensitiveLog=function(e){return f({},e)},(V||(V={})).filterSensitiveLog=function(e){return f({},e)},(G||(G={})).filterSensitiveLog=function(e){return f({},e)},(W||(W={})).filterSensitiveLog=function(e){return f({},e)},($||($={})).filterSensitiveLog=function(e){return f({},e)},(Y||(Y={})).filterSensitiveLog=function(e){return f({},e)},(J||(J={})).filterSensitiveLog=function(e){return f({},e)},(Z||(Z={})).filterSensitiveLog=function(e){return f({},e)},(X||(X={})).filterSensitiveLog=function(e){return f({},e)},(Q||(Q={})).filterSensitiveLog=function(e){return f({},e)},(ee||(ee={})).filterSensitiveLog=function(e){return f({},e)},(te||(te={})).filterSensitiveLog=function(e){return f({},e)},(ne||(ne={})).filterSensitiveLog=function(e){return f({},e)},(re||(re={})).filterSensitiveLog=function(e){return f({},e)},(ie||(ie={})).filterSensitiveLog=function(e){return f({},e)},(oe||(oe={})).filterSensitiveLog=function(e){return f({},e)},(se||(se={})).filterSensitiveLog=function(e){return f({},e)},(ae||(ae={})).filterSensitiveLog=function(e){return f({},e)},(ue||(ue={})).filterSensitiveLog=function(e){return f({},e)},(ce||(ce={})).filterSensitiveLog=function(e){return f({},e)},(fe||(fe={})).filterSensitiveLog=function(e){return f({},e)},(le||(le={})).filterSensitiveLog=function(e){return f({},e)},(de||(de={})).filterSensitiveLog=function(e){return f({},e)},(he||(he={})).filterSensitiveLog=function(e){return f({},e)},(pe||(pe={})).filterSensitiveLog=function(e){return f({},e)},(ve||(ve={})).filterSensitiveLog=function(e){return f({},e)},(ge||(ge={})).filterSensitiveLog=function(e){return f({},e)},(me||(me={})).filterSensitiveLog=function(e){return f({},e)},(be||(be={})).filterSensitiveLog=function(e){return f({},e)},(ye||(ye={})).filterSensitiveLog=function(e){return f({},e)},(we||(we={})).filterSensitiveLog=function(e){return f({},e)},(_e||(_e={})).filterSensitiveLog=function(e){return f({},e)},(Se||(Se={})).filterSensitiveLog=function(e){return f({},e)},(Ee||(Ee={})).filterSensitiveLog=function(e){return f({},e)},(Me||(Me={})).filterSensitiveLog=function(e){return f(f({},e),e.KMSMasterKeyID&&{KMSMasterKeyID:Zr.d})},(Ae||(Ae={})).filterSensitiveLog=function(e){return f(f({},e),e.ApplyServerSideEncryptionByDefault&&{ApplyServerSideEncryptionByDefault:Me.filterSensitiveLog(e.ApplyServerSideEncryptionByDefault)})},(Ie||(Ie={})).filterSensitiveLog=function(e){return f(f({},e),e.Rules&&{Rules:e.Rules.map((function(e){return Ae.filterSensitiveLog(e)}))})},(ke||(ke={})).filterSensitiveLog=function(e){return f(f({},e),e.ServerSideEncryptionConfiguration&&{ServerSideEncryptionConfiguration:Ie.filterSensitiveLog(e.ServerSideEncryptionConfiguration)})},(Oe||(Oe={})).filterSensitiveLog=function(e){return f({},e)},(xe||(xe={})).filterSensitiveLog=function(e){return f(f({},e),e.KeyId&&{KeyId:Zr.d})},(Ce||(Ce={})).filterSensitiveLog=function(e){return f({},e)},(Te||(Te={})).filterSensitiveLog=function(e){return f(f({},e),e.SSEKMS&&{SSEKMS:xe.filterSensitiveLog(e.SSEKMS)})},(Pe||(Pe={})).filterSensitiveLog=function(e){return f(f({},e),e.Encryption&&{Encryption:Te.filterSensitiveLog(e.Encryption)})},(Ne||(Ne={})).filterSensitiveLog=function(e){return f(f({},e),e.S3BucketDestination&&{S3BucketDestination:Pe.filterSensitiveLog(e.S3BucketDestination)})},(Re||(Re={})).filterSensitiveLog=function(e){return f({},e)},(Le||(Le={})).filterSensitiveLog=function(e){return f({},e)},(je||(je={})).filterSensitiveLog=function(e){return f(f({},e),e.Destination&&{Destination:Ne.filterSensitiveLog(e.Destination)})},(De||(De={})).filterSensitiveLog=function(e){return f(f({},e),e.InventoryConfiguration&&{InventoryConfiguration:je.filterSensitiveLog(e.InventoryConfiguration)})},(Ue||(Ue={})).filterSensitiveLog=function(e){return f({},e)},(Be||(Be={})).filterSensitiveLog=function(e){return f({},e)},(Fe||(Fe={})).filterSensitiveLog=function(e){return f({},e)},(ze||(ze={})).filterSensitiveLog=function(e){return f({},e)},(qe||(qe={})).filterSensitiveLog=function(e){return f({},e)},(Ke||(Ke={})).filterSensitiveLog=function(e){return f({},e)},(He||(He={})).filterSensitiveLog=function(e){return f({},e)},(Ve||(Ve={})).filterSensitiveLog=function(e){return f({},e)},(Ge||(Ge={})).filterSensitiveLog=function(e){return f({},e)},(We||(We={})).filterSensitiveLog=function(e){return f({},e)},($e||($e={})).filterSensitiveLog=function(e){return f({},e)},(Ye||(Ye={})).filterSensitiveLog=function(e){return f({},e)},(Je||(Je={})).filterSensitiveLog=function(e){return f({},e)},(Ze||(Ze={})).filterSensitiveLog=function(e){return f({},e)},(Xe||(Xe={})).filterSensitiveLog=function(e){return f({},e)},(Qe||(Qe={})).filterSensitiveLog=function(e){return f({},e)},(et||(et={})).filterSensitiveLog=function(e){return f({},e)},(tt||(tt={})).filterSensitiveLog=function(e){return f({},e)},(nt||(nt={})).filterSensitiveLog=function(e){return f({},e)},(rt||(rt={})).filterSensitiveLog=function(e){return f({},e)},(it||(it={})).filterSensitiveLog=function(e){return f({},e)},(ot||(ot={})).filterSensitiveLog=function(e){return f({},e)},(st||(st={})).filterSensitiveLog=function(e){return f({},e)},(at||(at={})).filterSensitiveLog=function(e){return f({},e)},(ut||(ut={})).filterSensitiveLog=function(e){return f({},e)},(ct||(ct={})).filterSensitiveLog=function(e){return f({},e)},(ft||(ft={})).filterSensitiveLog=function(e){return f({},e)},(lt||(lt={})).filterSensitiveLog=function(e){return f({},e)},(dt||(dt={})).filterSensitiveLog=function(e){return f({},e)},(ht||(ht={})).filterSensitiveLog=function(e){return f({},e)},(pt||(pt={})).filterSensitiveLog=function(e){return f({},e)},(vt||(vt={})).filterSensitiveLog=function(e){return f({},e)},(gt||(gt={})).filterSensitiveLog=function(e){return f({},e)},(mt||(mt={})).filterSensitiveLog=function(e){return f({},e)},(bt||(bt={})).filterSensitiveLog=function(e){return f({},e)},(yt||(yt={})).filterSensitiveLog=function(e){return f({},e)},(wt||(wt={})).filterSensitiveLog=function(e){return f({},e)},(_t||(_t={})).filterSensitiveLog=function(e){return f({},e)},(St||(St={})).filterSensitiveLog=function(e){return f({},e)},(Et||(Et={})).filterSensitiveLog=function(e){return f({},e)},(Mt||(Mt={})).filterSensitiveLog=function(e){return f({},e)},(At||(At={})).filterSensitiveLog=function(e){return f({},e)},(It||(It={})).filterSensitiveLog=function(e){return f({},e)},(kt||(kt={})).filterSensitiveLog=function(e){return f({},e)},(Ot||(Ot={})).filterSensitiveLog=function(e){return f({},e)},(xt||(xt={})).filterSensitiveLog=function(e){return f({},e)},(Ct||(Ct={})).filterSensitiveLog=function(e){return f({},e)},(Tt||(Tt={})).filterSensitiveLog=function(e){return f({},e)},(Pt||(Pt={})).filterSensitiveLog=function(e){return f({},e)},(Nt||(Nt={})).filterSensitiveLog=function(e){return f({},e)},(Rt||(Rt={})).filterSensitiveLog=function(e){return f({},e)},(Lt||(Lt={})).filterSensitiveLog=function(e){return f({},e)},(jt||(jt={})).filterSensitiveLog=function(e){return f({},e)},(Dt||(Dt={})).filterSensitiveLog=function(e){return f({},e)},(Ut||(Ut={})).filterSensitiveLog=function(e){return f({},e)},(Bt||(Bt={})).filterSensitiveLog=function(e){return f({},e)},(Ft||(Ft={})).filterSensitiveLog=function(e){return f({},e)},(zt||(zt={})).filterSensitiveLog=function(e){return f({},e)},(qt||(qt={})).filterSensitiveLog=function(e){return f({},e)},(Kt||(Kt={})).filterSensitiveLog=function(e){return f({},e)},(Ht||(Ht={})).filterSensitiveLog=function(e){return f({},e)},(Vt||(Vt={})).filterSensitiveLog=function(e){return f({},e)},(Gt||(Gt={})).filterSensitiveLog=function(e){return f({},e)},(Wt||(Wt={})).filterSensitiveLog=function(e){return f({},e)},($t||($t={})).filterSensitiveLog=function(e){return f({},e)},(Yt||(Yt={})).filterSensitiveLog=function(e){return f({},e)},(Jt||(Jt={})).filterSensitiveLog=function(e){return f({},e)},(Zt||(Zt={})).filterSensitiveLog=function(e){return f(f({},e),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d})},(Xt||(Xt={})).filterSensitiveLog=function(e){return f(f({},e),e.SSECustomerKey&&{SSECustomerKey:Zr.d})},(Qt||(Qt={})).filterSensitiveLog=function(e){return f({},e)},(en||(en={})).filterSensitiveLog=function(e){return f({},e)},(tn||(tn={})).filterSensitiveLog=function(e){return f({},e)},(nn||(nn={})).filterSensitiveLog=function(e){return f({},e)},(rn||(rn={})).filterSensitiveLog=function(e){return f({},e)},(on||(on={})).filterSensitiveLog=function(e){return f({},e)},(sn||(sn={})).filterSensitiveLog=function(e){return f({},e)},(an||(an={})).filterSensitiveLog=function(e){return f({},e)},(un||(un={})).filterSensitiveLog=function(e){return f({},e)},(cn||(cn={})).filterSensitiveLog=function(e){return f({},e)},(fn||(fn={})).filterSensitiveLog=function(e){return f({},e)},(ln||(ln={})).filterSensitiveLog=function(e){return f({},e)},(dn||(dn={})).filterSensitiveLog=function(e){return f({},e)},(hn||(hn={})).filterSensitiveLog=function(e){return f({},e)},(pn||(pn={})).filterSensitiveLog=function(e){return f({},e)},(vn||(vn={})).filterSensitiveLog=function(e){return f({},e)},(gn||(gn={})).filterSensitiveLog=function(e){return f({},e)},(mn||(mn={})).filterSensitiveLog=function(e){return f({},e)},(bn||(bn={})).filterSensitiveLog=function(e){return f({},e)},(yn||(yn={})).filterSensitiveLog=function(e){return f({},e)},(wn||(wn={})).filterSensitiveLog=function(e){return f({},e)},(_n||(_n={})).filterSensitiveLog=function(e){return f({},e)},(Sn||(Sn={})).filterSensitiveLog=function(e){return f({},e)},(En||(En={})).filterSensitiveLog=function(e){return f(f({},e),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d})},(Mn||(Mn={})).filterSensitiveLog=function(e){return f(f({},e),e.SSECustomerKey&&{SSECustomerKey:Zr.d})},(An||(An={})).filterSensitiveLog=function(e){return f({},e)},(In||(In={})).filterSensitiveLog=function(e){return f({},e)},(kn||(kn={})).filterSensitiveLog=function(e){return f(f({},e),e.InventoryConfigurationList&&{InventoryConfigurationList:e.InventoryConfigurationList.map((function(e){return je.filterSensitiveLog(e)}))})},(On||(On={})).filterSensitiveLog=function(e){return f({},e)},(xn||(xn={})).filterSensitiveLog=function(e){return f({},e)},(Cn||(Cn={})).filterSensitiveLog=function(e){return f({},e)},(Tn||(Tn={})).filterSensitiveLog=function(e){return f({},e)},(Pn||(Pn={})).filterSensitiveLog=function(e){return f({},e)},(Nn||(Nn={})).filterSensitiveLog=function(e){return f({},e)},(Rn||(Rn={})).filterSensitiveLog=function(e){return f({},e)},(Ln||(Ln={})).filterSensitiveLog=function(e){return f({},e)},(jn||(jn={})).filterSensitiveLog=function(e){return f({},e)},(Dn||(Dn={})).filterSensitiveLog=function(e){return f({},e)},(Un||(Un={})).filterSensitiveLog=function(e){return f({},e)},(Bn||(Bn={})).filterSensitiveLog=function(e){return f({},e)},(Fn||(Fn={})).filterSensitiveLog=function(e){return f({},e)},(zn||(zn={})).filterSensitiveLog=function(e){return f({},e)},(qn||(qn={})).filterSensitiveLog=function(e){return f({},e)},(Kn||(Kn={})).filterSensitiveLog=function(e){return f({},e)},(Hn||(Hn={})).filterSensitiveLog=function(e){return f({},e)},(Vn||(Vn={})).filterSensitiveLog=function(e){return f({},e)},(Gn||(Gn={})).filterSensitiveLog=function(e){return f({},e)},(Wn||(Wn={})).filterSensitiveLog=function(e){return f({},e)},($n||($n={})).filterSensitiveLog=function(e){return f({},e)},(Yn||(Yn={})).filterSensitiveLog=function(e){return f({},e)},(Jn||(Jn={})).filterSensitiveLog=function(e){return f({},e)},(Zn||(Zn={})).filterSensitiveLog=function(e){return f({},e)},(Xn||(Xn={})).filterSensitiveLog=function(e){return f({},e)},(Qn||(Qn={})).filterSensitiveLog=function(e){return f({},e)},(er||(er={})).filterSensitiveLog=function(e){return f({},e)},(tr||(tr={})).filterSensitiveLog=function(e){return f(f({},e),e.ServerSideEncryptionConfiguration&&{ServerSideEncryptionConfiguration:Ie.filterSensitiveLog(e.ServerSideEncryptionConfiguration)})},(nr||(nr={})).filterSensitiveLog=function(e){return f(f({},e),e.InventoryConfiguration&&{InventoryConfiguration:je.filterSensitiveLog(e.InventoryConfiguration)})},(rr||(rr={})).filterSensitiveLog=function(e){return f({},e)},(ir||(ir={})).filterSensitiveLog=function(e){return f({},e)},(or||(or={})).filterSensitiveLog=function(e){return f({},e)},(sr||(sr={})).filterSensitiveLog=function(e){return f({},e)},(ar||(ar={})).filterSensitiveLog=function(e){return f({},e)},(ur||(ur={})).filterSensitiveLog=function(e){return f({},e)},(cr||(cr={})).filterSensitiveLog=function(e){return f({},e)},(fr||(fr={})).filterSensitiveLog=function(e){return f({},e)},(lr||(lr={})).filterSensitiveLog=function(e){return f({},e)},(dr||(dr={})).filterSensitiveLog=function(e){return f({},e)},(hr||(hr={})).filterSensitiveLog=function(e){return f({},e)},(pr||(pr={})).filterSensitiveLog=function(e){return f({},e)},(vr||(vr={})).filterSensitiveLog=function(e){return f({},e)},(gr||(gr={})).filterSensitiveLog=function(e){return f({},e)},(mr||(mr={})).filterSensitiveLog=function(e){return f({},e)},(br||(br={})).filterSensitiveLog=function(e){return f({},e)},(yr||(yr={})).filterSensitiveLog=function(e){return f({},e)},(wr||(wr={})).filterSensitiveLog=function(e){return f(f(f({},e),e.SSEKMSEncryptionContext&&{SSEKMSEncryptionContext:Zr.d}),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d})},(_r||(_r={})).filterSensitiveLog=function(e){return f(f(f(f({},e),e.SSECustomerKey&&{SSECustomerKey:Zr.d}),e.SSEKMSEncryptionContext&&{SSEKMSEncryptionContext:Zr.d}),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d})},(Sr||(Sr={})).filterSensitiveLog=function(e){return f({},e)},(Er||(Er={})).filterSensitiveLog=function(e){return f({},e)},(Mr||(Mr={})).filterSensitiveLog=function(e){return f({},e)},(Ar||(Ar={})).filterSensitiveLog=function(e){return f({},e)},(Ir||(Ir={})).filterSensitiveLog=function(e){return f({},e)},(kr||(kr={})).filterSensitiveLog=function(e){return f({},e)},(Or||(Or={})).filterSensitiveLog=function(e){return f({},e)},(xr||(xr={})).filterSensitiveLog=function(e){return f({},e)},(Cr||(Cr={})).filterSensitiveLog=function(e){return f({},e)},(Tr||(Tr={})).filterSensitiveLog=function(e){return f({},e)},(Pr||(Pr={})).filterSensitiveLog=function(e){return f({},e)},(Nr||(Nr={})).filterSensitiveLog=function(e){return f({},e)},(Rr||(Rr={})).filterSensitiveLog=function(e){return f({},e)},(Lr||(Lr={})).filterSensitiveLog=function(e){return f({},e)},(jr||(jr={})).filterSensitiveLog=function(e){return f(f({},e),e.KMSKeyId&&{KMSKeyId:Zr.d})},(Dr||(Dr={})).filterSensitiveLog=function(e){return f({},e)},(Ur||(Ur={})).filterSensitiveLog=function(e){return f(f({},e),e.Encryption&&{Encryption:jr.filterSensitiveLog(e.Encryption)})},(Br||(Br={})).filterSensitiveLog=function(e){return f(f({},e),e.S3&&{S3:Ur.filterSensitiveLog(e.S3)})},function(e){e.IGNORE="IGNORE",e.NONE="NONE",e.USE="USE"}(Fr||(Fr={})),(zr||(zr={})).filterSensitiveLog=function(e){return f({},e)},function(e){e.DOCUMENT="DOCUMENT",e.LINES="LINES"}(qr||(qr={})),(Kr||(Kr={})).filterSensitiveLog=function(e){return f({},e)},(Hr||(Hr={})).filterSensitiveLog=function(e){return f({},e)},(Vr||(Vr={})).filterSensitiveLog=function(e){return f({},e)},function(e){e.ALWAYS="ALWAYS",e.ASNEEDED="ASNEEDED"}(Gr||(Gr={})),(Wr||(Wr={})).filterSensitiveLog=function(e){return f({},e)},($r||($r={})).filterSensitiveLog=function(e){return f({},e)},(Yr||(Yr={})).filterSensitiveLog=function(e){return f({},e)},(Jr||(Jr={})).filterSensitiveLog=function(e){return f({},e)};var Xr=n(2),Qr=n(1);var ei=function(){function e(e,t){void 0===t&&(t=[]),this.name=e,this.children=t,this.attributes={}}return e.prototype.withName=function(e){return this.name=e,this},e.prototype.addAttribute=function(e,t){return this.attributes[e]=t,this},e.prototype.addChildNode=function(e){return this.children.push(e),this},e.prototype.removeAttribute=function(e){return delete this.attributes[e],this},e.prototype.toString=function(){var e,t,n=Boolean(this.children.length),r="<"+this.name,i=this.attributes;try{for(var o=Object(Qr.__values)(Object.keys(i)),s=o.next();!s.done;s=o.next()){var a=s.value,u=i[a];null!=u&&(r+=" "+a+'="'+(""+u).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")+'"')}}catch(t){e={error:t}}finally{try{s&&!s.done&&(t=o.return)&&t.call(o)}finally{if(e)throw e.error}}return r+(n?">"+this.children.map((function(e){return e.toString()})).join("")+"</"+this.name+">":"/>")},e}();var ti=function(){function e(e){this.value=e}return e.prototype.toString=function(){return(""+this.value).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")},e}(),ni=n(253),ri=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c;return d(this,(function(l){switch(l.label){case 0:return r=[f({},e)],c={},[4,Ai(e.body,t)];case 1:switch(n=f.apply(void 0,r.concat([(c.body=l.sent(),c)])),o="UnknownError",o=Ii(e,n.body),o){case"NoSuchUpload":case"com.amazonaws.s3#NoSuchUpload":return[3,2]}return[3,4];case 2:return s=[{}],[4,pi(n,t)];case 3:return i=f.apply(void 0,[f.apply(void 0,s.concat([l.sent()])),{name:o,$metadata:Si(e)}]),[3,5];case 4:a=n.body,o=a.code||a.Code||o,i=f(f({},a),{name:""+o,message:a.message||a.Message||o,$fault:"client",$metadata:Si(e)}),l.label=5;case 5:return u=i.message||i.Message||o,i.message=u,delete i.Message,[2,Promise.reject(Object.assign(new Error(u),i))]}}))}))},ii=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u;return d(this,(function(c){switch(c.label){case 0:return r=[f({},e)],u={},[4,Ai(e.body,t)];case 1:return n=f.apply(void 0,r.concat([(u.body=c.sent(),u)])),o="UnknownError",o=Ii(e,n.body),s=n.body,o=s.code||s.Code||o,i=f(f({},s),{name:""+o,message:s.message||s.Message||o,$fault:"client",$metadata:Si(e)}),a=i.message||i.Message||o,i.message=a,delete i.Message,[2,Promise.reject(Object.assign(new Error(a),i))]}}))}))},oi=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u;return d(this,(function(c){switch(c.label){case 0:return r=[f({},e)],u={},[4,Ai(e.body,t)];case 1:return n=f.apply(void 0,r.concat([(u.body=c.sent(),u)])),o="UnknownError",o=Ii(e,n.body),s=n.body,o=s.code||s.Code||o,i=f(f({},s),{name:""+o,message:s.message||s.Message||o,$fault:"client",$metadata:Si(e)}),a=i.message||i.Message||o,i.message=a,delete i.Message,[2,Promise.reject(Object.assign(new Error(a),i))]}}))}))},si=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u;return d(this,(function(c){switch(c.label){case 0:return r=[f({},e)],u={},[4,Ai(e.body,t)];case 1:return n=f.apply(void 0,r.concat([(u.body=c.sent(),u)])),o="UnknownError",o=Ii(e,n.body),s=n.body,o=s.code||s.Code||o,i=f(f({},s),{name:""+o,message:s.message||s.Message||o,$fault:"client",$metadata:Si(e)}),a=i.message||i.Message||o,i.message=a,delete i.Message,[2,Promise.reject(Object.assign(new Error(a),i))]}}))}))},ai=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c;return d(this,(function(l){switch(l.label){case 0:return r=[f({},e)],c={},[4,Ai(e.body,t)];case 1:switch(n=f.apply(void 0,r.concat([(c.body=l.sent(),c)])),o="UnknownError",o=Ii(e,n.body),o){case"NoSuchKey":case"com.amazonaws.s3#NoSuchKey":return[3,2]}return[3,4];case 2:return s=[{}],[4,hi(n,t)];case 3:return i=f.apply(void 0,[f.apply(void 0,s.concat([l.sent()])),{name:o,$metadata:Si(e)}]),[3,5];case 4:a=n.body,o=a.code||a.Code||o,i=f(f({},a),{name:""+o,message:a.message||a.Message||o,$fault:"client",$metadata:Si(e)}),l.label=5;case 5:return u=i.message||i.Message||o,i.message=u,delete i.Message,[2,Promise.reject(Object.assign(new Error(u),i))]}}))}))},ui=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c;return d(this,(function(l){switch(l.label){case 0:return r=[f({},e)],c={},[4,Ai(e.body,t)];case 1:switch(n=f.apply(void 0,r.concat([(c.body=l.sent(),c)])),o="UnknownError",o=Ii(e,n.body),o){case"NoSuchBucket":case"com.amazonaws.s3#NoSuchBucket":return[3,2]}return[3,4];case 2:return s=[{}],[4,di(n,t)];case 3:return i=f.apply(void 0,[f.apply(void 0,s.concat([l.sent()])),{name:o,$metadata:Si(e)}]),[3,5];case 4:a=n.body,o=a.code||a.Code||o,i=f(f({},a),{name:""+o,message:a.message||a.Message||o,$fault:"client",$metadata:Si(e)}),l.label=5;case 5:return u=i.message||i.Message||o,i.message=u,delete i.Message,[2,Promise.reject(Object.assign(new Error(u),i))]}}))}))},ci=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u;return d(this,(function(c){switch(c.label){case 0:return r=[f({},e)],u={},[4,Ai(e.body,t)];case 1:return n=f.apply(void 0,r.concat([(u.body=c.sent(),u)])),o="UnknownError",o=Ii(e,n.body),s=n.body,o=s.code||s.Code||o,i=f(f({},s),{name:""+o,message:s.message||s.Message||o,$fault:"client",$metadata:Si(e)}),a=i.message||i.Message||o,i.message=a,delete i.Message,[2,Promise.reject(Object.assign(new Error(a),i))]}}))}))},fi=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u;return d(this,(function(c){switch(c.label){case 0:return r=[f({},e)],u={},[4,Ai(e.body,t)];case 1:return n=f.apply(void 0,r.concat([(u.body=c.sent(),u)])),o="UnknownError",o=Ii(e,n.body),s=n.body,o=s.code||s.Code||o,i=f(f({},s),{name:""+o,message:s.message||s.Message||o,$fault:"client",$metadata:Si(e)}),a=i.message||i.Message||o,i.message=a,delete i.Message,[2,Promise.reject(Object.assign(new Error(a),i))]}}))}))},li=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u;return d(this,(function(c){switch(c.label){case 0:return r=[f({},e)],u={},[4,Ai(e.body,t)];case 1:return n=f.apply(void 0,r.concat([(u.body=c.sent(),u)])),o="UnknownError",o=Ii(e,n.body),s=n.body,o=s.code||s.Code||o,i=f(f({},s),{name:""+o,message:s.message||s.Message||o,$fault:"client",$metadata:Si(e)}),a=i.message||i.Message||o,i.message=a,delete i.Message,[2,Promise.reject(Object.assign(new Error(a),i))]}}))}))},di=function(e,t){return l(void 0,void 0,void 0,(function(){var t;return d(this,(function(n){return t={name:"NoSuchBucket",$fault:"client",$metadata:Si(e)},e.body,[2,t]}))}))},hi=function(e,t){return l(void 0,void 0,void 0,(function(){var t;return d(this,(function(n){return t={name:"NoSuchKey",$fault:"client",$metadata:Si(e)},e.body,[2,t]}))}))},pi=function(e,t){return l(void 0,void 0,void 0,(function(){var t;return d(this,(function(n){return t={name:"NoSuchUpload",$fault:"client",$metadata:Si(e)},e.body,[2,t]}))}))},vi=function(e,t){var n=new ei("CompletedMultipartUpload");void 0!==e.Parts&&gi(e.Parts,t).map((function(e){e=e.withName("Part"),n.addChildNode(e)}));return n},gi=function(e,t){return e.map((function(e){return function(e,t){var n=new ei("CompletedPart");if(void 0!==e.ETag){var r=new ei("ETag").addChildNode(new ti(e.ETag)).withName("ETag");n.addChildNode(r)}if(void 0!==e.PartNumber){r=new ei("PartNumber").addChildNode(new ti(String(e.PartNumber))).withName("PartNumber");n.addChildNode(r)}return n}(e).withName("member")}))},mi=function(e,t){return(e||[]).map((function(e){return function(e,t){var n={Prefix:void 0};return void 0!==e.Prefix&&(n.Prefix=e.Prefix),n}(e)}))},bi=function(e,t){var n={ID:void 0,DisplayName:void 0};return void 0!==e.ID&&(n.ID=e.ID),void 0!==e.DisplayName&&(n.DisplayName=e.DisplayName),n},yi=function(e,t){return(e||[]).map((function(e){return function(e,t){var n={Size:void 0,ETag:void 0,Owner:void 0,StorageClass:void 0,Key:void 0,LastModified:void 0};return void 0!==e.Size&&(n.Size=parseInt(e.Size)),void 0!==e.ETag&&(n.ETag=e.ETag),void 0!==e.Owner&&(n.Owner=wi(e.Owner,t)),void 0!==e.StorageClass&&(n.StorageClass=e.StorageClass),void 0!==e.Key&&(n.Key=e.Key),void 0!==e.LastModified&&(n.LastModified=new Date(e.LastModified)),n}(e,t)}))},wi=function(e,t){var n={DisplayName:void 0,ID:void 0};return void 0!==e.DisplayName&&(n.DisplayName=e.DisplayName),void 0!==e.ID&&(n.ID=e.ID),n},_i=function(e,t){return(e||[]).map((function(e){return function(e,t){var n={Size:void 0,LastModified:void 0,PartNumber:void 0,ETag:void 0};return void 0!==e.Size&&(n.Size=parseInt(e.Size)),void 0!==e.LastModified&&(n.LastModified=new Date(e.LastModified)),void 0!==e.PartNumber&&(n.PartNumber=parseInt(e.PartNumber)),void 0!==e.ETag&&(n.ETag=e.ETag),n}(e)}))},Si=function(e){return{httpStatusCode:e.statusCode,httpHeaders:e.headers,requestId:e.headers["x-amzn-requestid"]}},Ei=function(e,t){return void 0===e&&(e=new Uint8Array),e instanceof Uint8Array?Promise.resolve(e):t.streamCollector(e)||Promise.resolve(new Uint8Array)},Mi=function(e){return!(void 0===e||""===e||Object.getOwnPropertyNames(e).includes("length")&&0==e.length||Object.getOwnPropertyNames(e).includes("size")&&0==e.size)},Ai=function(e,t){return function(e,t){return Ei(e,t).then((function(e){return t.utf8Encoder(e)}))}(e,t).then((function(e){if(e.length){var t=Object(ni.parse)(e,{attributeNamePrefix:"",ignoreAttributes:!1,parseNodeValue:!1,tagValueProcessor:function(e,t){return e.replace(/&/g,"&").replace(/'/g,"'").replace(/"/g,'"').replace(/>/g,">").replace(/</g,"<")}}),n=Object.keys(t)[0],r=t[n];return r["#text"]&&(r[n]=r["#text"],delete r["#text"]),Object(Zr.h)(r)}return{}}))},Ii=function(e,t){return void 0!==t.Code?t.Code:404==e.statusCode?"NotFound":""},ki=function(e){return"string"==typeof e&&0===e.indexOf("arn:")&&e.split(":").length>=6},Oi=/^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$/,xi=/(\d+\.){3}\d+/,Ci=/\.\./,Ti=/\./,Pi=/^(.+\.)?s3[.-]([a-z0-9-]+)\./,Ni=/^s3(-external-1)?\.amazonaws\.com$/,Ri=function(e){return ji(e)?e.replace(/fips-|-fips/,""):e},Li=function(e){var t=e.match(Pi);return[t[2],e.replace(new RegExp("^"+t[0]),"")]},ji=function(e){return e.startsWith("fips-")||e.endsWith("-fips")},Di=function(e,t){return e===t||Ri(e)===t||e===Ri(t)},Ui=function(e,t){if(void 0===t&&(t={tlsCompatible:!0}),e.length>=64||!/^[a-z0-9][a-z0-9.-]+[a-z0-9]$/.test(e)||/(\d+\.){3}\d+/.test(e)||/[.-]{2}/.test(e)||(null==t?void 0:t.tlsCompatible)&&Ti.test(e))throw new Error("Invalid DNS label "+e)},Bi=function(e){var t=e.baseHostname;return Pi.test(t)?function(e){return"string"==typeof e.bucketName}(e)?zi(e):Fi(e):{bucketEndpoint:!1,hostname:t}},Fi=function(e){var t,n=Object(Qr.__read)((t=e.baseHostname,Ni.test(t)?[t.replace(".amazonaws.com",""),"amazonaws.com"]:Li(t)),2),r=n[0],i=n[1],o=e.pathStyleEndpoint,s=e.dualstackEndpoint,a=void 0!==s&&s,u=e.accelerateEndpoint,c=void 0!==u&&u,f=e.tlsCompatible,l=void 0===f||f,d=e.useArnRegion,h=e.bucketName,p=e.clientPartition,v=void 0===p?"aws":p,g=e.clientSigningRegion,m=void 0===g?r:g;!function(e){if(e.pathStyleEndpoint)throw new Error("Path-style S3 endpoint is not supported when bucket is an ARN");if(e.accelerateEndpoint)throw new Error("Accelerate endpoint is not supported when bucket is an ARN");if(!e.tlsCompatible)throw new Error("HTTPS is required when bucket is an ARN")}({pathStyleEndpoint:o,accelerateEndpoint:c,tlsCompatible:l});var b=h.service,y=h.partition,w=h.accountId,_=h.region,S=h.resource;!function(e){if("s3"!==e&&"s3-outposts"!==e)throw new Error("Expect 's3' or 's3-outposts' in ARN service component")}(b),function(e,t){if(e!==t.clientPartition)throw new Error('Partition in ARN is incompatible, got "'+e+'" but expected "'+t.clientPartition+'"')}(y,{clientPartition:v}),function(e){if(!/[0-9]{12}/.exec(e))throw new Error("Access point ARN accountID does not match regex '[0-9]{12}'")}(w),function(e,t){if(""===e)throw new Error("ARN region is empty");if(!t.useArnRegion&&!Di(e,t.clientRegion)&&!Di(e,t.clientSigningRegion))throw new Error("Region in ARN is incompatible, got "+e+" but expected "+t.clientRegion);if(t.useArnRegion&&ji(e))throw new Error("Endpoint does not support FIPS region")}(_,{useArnRegion:d,clientRegion:r,clientSigningRegion:m});var E=function(e){var t=e.includes(":")?":":"/",n=Object(Qr.__read)(e.split(t)),r=n[0],i=n.slice(1);if("accesspoint"===r){if(1!==i.length||""===i[0])throw new Error("Access Point ARN should have one resource accesspoint"+t+"{accesspointname}");return{accesspointName:i[0]}}if("outpost"===r){if(!i[0]||"accesspoint"!==i[1]||!i[2]||3!==i.length)throw new Error("Outpost ARN should have resource outpost"+t+"{outpostId}"+t+"accesspoint"+t+"{accesspointName}");var o=Object(Qr.__read)(i,3),s=o[0];o[1];return{outpostId:s,accesspointName:o[2]}}throw new Error("ARN resource should begin with 'accesspoint"+t+"' or 'outpost"+t+"'")}(S),M=E.accesspointName,A=E.outpostId;Ui(M+"-"+w,{tlsCompatible:l});var I=d?_:r,k=d?_:m;return A?(function(e){if("s3-outposts"!==e)throw new Error("Expect 's3-posts' in Outpost ARN service component")}(b),Ui(A,{tlsCompatible:l}),function(e){if(e)throw new Error("Dualstack endpoint is not supported with Outpost")}(a),function(e){if(ji(null!=e?e:""))throw new Error("FIPS region is not supported with Outpost, got "+e)}(I),{bucketEndpoint:!0,hostname:M+"-"+w+"."+A+".s3-outposts."+I+"."+i,signingRegion:k,signingService:"s3-outposts"}):(function(e){if("s3"!==e)throw new Error("Expect 's3' in Accesspoint ARN service component")}(b),{bucketEndpoint:!0,hostname:M+"-"+w+".s3-accesspoint"+(a?".dualstack":"")+"."+I+"."+i,signingRegion:k})},zi=function(e){var t,n=e.accelerateEndpoint,r=void 0!==n&&n,i=e.baseHostname,o=e.bucketName,s=e.dualstackEndpoint,a=void 0!==s&&s,u=e.pathStyleEndpoint,c=void 0!==u&&u,f=e.tlsCompatible,l=void 0===f||f,d=Object(Qr.__read)((t=i,Ni.test(t)?["us-east-1","amazonaws.com"]:Li(t)),2),h=d[0],p=d[1];return c||!function(e){return Oi.test(e)&&!xi.test(e)&&!Ci.test(e)}(o)||l&&Ti.test(o)?{bucketEndpoint:!1,hostname:a?"s3.dualstack."+h+"."+p:i}:(r?i="s3-accelerate"+(a?".dualstack":"")+"."+p:a&&(i="s3.dualstack."+h+"."+p),{bucketEndpoint:!0,hostname:o+"."+i})},qi=function(e){return function(t,n){return function(r){return Object(Qr.__awaiter)(void 0,void 0,void 0,(function(){var i,o,s,a,u,c,f,l,d,h,p,v,g,m,b,y,w;return Object(Qr.__generator)(this,(function(_){switch(_.label){case 0:return i=r.input.Bucket,o=e.bucketEndpoint,s=r.request,Xr.a.isInstance(s)?e.bucketEndpoint?(s.hostname=i,[3,6]):[3,1]:[3,7];case 1:return ki(i)?(a=function(e){var t=e.split(":");if(t.length<6||"arn"!==t[0])throw new Error("Malformed ARN");var n=Object(Qr.__read)(t);return{partition:n[1],service:n[2],region:n[3],accountId:n[4],resource:n.slice(5).join(":")}}(i),c=Ri,[4,e.region()]):[3,5];case 2:return u=c.apply(void 0,[_.sent()]),[4,e.regionInfoProvider(u)];case 3:return f=_.sent()||{},l=f.partition,d=f.signingRegion,h=void 0===d?u:d,[4,e.useArnRegion()];case 4:return p=_.sent(),v=Bi({bucketName:a,baseHostname:s.hostname,accelerateEndpoint:e.useAccelerateEndpoint,dualstackEndpoint:e.useDualstackEndpoint,pathStyleEndpoint:e.forcePathStyle,tlsCompatible:"https:"===s.protocol,useArnRegion:p,clientPartition:l,clientSigningRegion:h}),y=v.hostname,w=v.bucketEndpoint,g=v.signingRegion,m=v.signingService,g&&g!==h&&(n.signing_region=g),m&&"s3"!==m&&(n.signing_service=m),s.hostname=y,o=w,[3,6];case 5:b=Bi({bucketName:i,baseHostname:s.hostname,accelerateEndpoint:e.useAccelerateEndpoint,dualstackEndpoint:e.useDualstackEndpoint,pathStyleEndpoint:e.forcePathStyle,tlsCompatible:"https:"===s.protocol}),y=b.hostname,w=b.bucketEndpoint,s.hostname=y,o=w,_.label=6;case 6:o&&(s.path=s.path.replace(/^(\/)?[^\/]+/,""),""===s.path&&(s.path="/")),_.label=7;case 7:return[2,t(Object(Qr.__assign)(Object(Qr.__assign)({},r),{request:s}))]}}))}))}}},Ki={tags:["BUCKET_ENDPOINT"],name:"bucketEndpointMiddleware",relation:"before",toMiddleware:"hostHeaderMiddleware"},Hi=function(e){return{applyToStack:function(t){t.addRelativeTo(qi(e),Ki)}}};var Vi=n(10);var Gi={name:"ssecMiddleware",step:"initialize",tags:["SSE"]},Wi=function(e){return{applyToStack:function(t){t.add(function(e){var t=this;return function(n){return function(r){return Object(Qr.__awaiter)(t,void 0,void 0,(function(){var t,i,o,s,a,u,c,f,l,d,h,p,v,g,m,b,y;return Object(Qr.__generator)(this,(function(w){switch(w.label){case 0:t=Object(Qr.__assign)({},r.input),i=[{target:"SSECustomerKey",hash:"SSECustomerKeyMD5"},{target:"CopySourceSSECustomerKey",hash:"CopySourceSSECustomerKeyMD5"}],w.label=1;case 1:w.trys.push([1,6,7,8]),o=Object(Qr.__values)(i),s=o.next(),w.label=2;case 2:return s.done?[3,5]:(a=s.value,(u=t[a.target])?(c=ArrayBuffer.isView(u)?new Uint8Array(u.buffer,u.byteOffset,u.byteLength):"string"==typeof u?e.utf8Decoder(u):new Uint8Array(u),f=e.base64Encoder(c),(l=new e.md5).update(c),d=[Object(Qr.__assign)({},t)],(y={})[a.target]=f,h=a.hash,v=(p=e).base64Encoder,[4,l.digest()]):[3,4]);case 3:t=Qr.__assign.apply(void 0,d.concat([(y[h]=v.apply(p,[w.sent()]),y)])),w.label=4;case 4:return s=o.next(),[3,2];case 5:return[3,8];case 6:return g=w.sent(),m={error:g},[3,8];case 7:try{s&&!s.done&&(b=o.return)&&b.call(o)}finally{if(m)throw m.error}return[7];case 8:return[2,n(Object(Qr.__assign)(Object(Qr.__assign)({},r),{input:t}))]}}))}))}}}(e),Gi)}}},$i=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Vi.a)(t,this.serialize,this.deserialize)),this.middlewareStack.use(Wi(t)),this.middlewareStack.use(Hi(t));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"S3Client",commandName:"GetObjectCommand",inputFilterSensitiveLog:Xt.filterSensitiveLog,outputFilterSensitiveLog:Zt.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"S3Client",commandName:"GetObjectCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l;return d(this,(function(d){switch(d.label){case 0:if(n=f(f(f(f(f(f(f(f(f(f({"Content-Type":""},Mi(e.SSECustomerKey)&&{"x-amz-server-side-encryption-customer-key":e.SSECustomerKey}),Mi(e.SSECustomerAlgorithm)&&{"x-amz-server-side-encryption-customer-algorithm":e.SSECustomerAlgorithm}),Mi(e.SSECustomerKeyMD5)&&{"x-amz-server-side-encryption-customer-key-MD5":e.SSECustomerKeyMD5}),Mi(e.RequestPayer)&&{"x-amz-request-payer":e.RequestPayer}),Mi(e.ExpectedBucketOwner)&&{"x-amz-expected-bucket-owner":e.ExpectedBucketOwner}),Mi(e.IfUnmodifiedSince)&&{"If-Unmodified-Since":Object(Zr.e)(e.IfUnmodifiedSince).toString()}),Mi(e.IfModifiedSince)&&{"If-Modified-Since":Object(Zr.e)(e.IfModifiedSince).toString()}),Mi(e.IfNoneMatch)&&{"If-None-Match":e.IfNoneMatch}),Mi(e.IfMatch)&&{"If-Match":e.IfMatch}),Mi(e.Range)&&{Range:e.Range}),r="/{Bucket}/{Key+}",void 0===e.Bucket)throw new Error("No value provided for input HTTP label: Bucket.");if((i=e.Bucket).length<=0)throw new Error("Empty value provided for input HTTP label: Bucket.");if(r=r.replace("{Bucket}",Object(Zr.f)(i)),void 0===e.Key)throw new Error("No value provided for input HTTP label: Key.");if((i=e.Key).length<=0)throw new Error("Empty value provided for input HTTP label: Key.");return r=r.replace("{Key+}",i.split("/").map((function(e){return Object(Zr.f)(e)})).join("/")),o=f(f(f(f(f(f(f(f({"x-id":"GetObject"},void 0!==e.ResponseContentEncoding&&{"response-content-encoding":e.ResponseContentEncoding}),void 0!==e.ResponseCacheControl&&{"response-cache-control":e.ResponseCacheControl}),void 0!==e.ResponseContentLanguage&&{"response-content-language":e.ResponseContentLanguage}),void 0!==e.ResponseContentDisposition&&{"response-content-disposition":e.ResponseContentDisposition}),void 0!==e.PartNumber&&{partNumber:e.PartNumber.toString()}),void 0!==e.VersionId&&{versionId:e.VersionId}),void 0!==e.ResponseExpires&&{"response-expires":(e.ResponseExpires.toISOString().split(".")[0]+"Z").toString()}),void 0!==e.ResponseContentType&&{"response-content-type":e.ResponseContentType}),[4,t.endpoint()];case 1:return s=d.sent(),a=s.hostname,u=s.protocol,c=void 0===u?"https":u,l=s.port,[2,new Xr.a({protocol:c,hostname:a,port:l,method:"GET",headers:n,path:r,query:o,body:void 0})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r;return d(this,(function(i){return 200!==e.statusCode&&e.statusCode>=300?[2,ai(e,t)]:(n={$metadata:Si(e),AcceptRanges:void 0,Body:void 0,CacheControl:void 0,ContentDisposition:void 0,ContentEncoding:void 0,ContentLanguage:void 0,ContentLength:void 0,ContentRange:void 0,ContentType:void 0,DeleteMarker:void 0,ETag:void 0,Expiration:void 0,Expires:void 0,LastModified:void 0,Metadata:void 0,MissingMeta:void 0,ObjectLockLegalHoldStatus:void 0,ObjectLockMode:void 0,ObjectLockRetainUntilDate:void 0,PartsCount:void 0,ReplicationStatus:void 0,RequestCharged:void 0,Restore:void 0,SSECustomerAlgorithm:void 0,SSECustomerKeyMD5:void 0,SSEKMSKeyId:void 0,ServerSideEncryption:void 0,StorageClass:void 0,TagCount:void 0,VersionId:void 0,WebsiteRedirectLocation:void 0},void 0!==e.headers["x-amz-object-lock-mode"]&&(n.ObjectLockMode=e.headers["x-amz-object-lock-mode"]),void 0!==e.headers["content-language"]&&(n.ContentLanguage=e.headers["content-language"]),void 0!==e.headers["content-disposition"]&&(n.ContentDisposition=e.headers["content-disposition"]),void 0!==e.headers["cache-control"]&&(n.CacheControl=e.headers["cache-control"]),void 0!==e.headers["content-type"]&&(n.ContentType=e.headers["content-type"]),void 0!==e.headers["content-range"]&&(n.ContentRange=e.headers["content-range"]),void 0!==e.headers["x-amz-server-side-encryption-aws-kms-key-id"]&&(n.SSEKMSKeyId=e.headers["x-amz-server-side-encryption-aws-kms-key-id"]),void 0!==e.headers["content-length"]&&(n.ContentLength=parseInt(e.headers["content-length"],10)),void 0!==e.headers["x-amz-object-lock-retain-until-date"]&&(n.ObjectLockRetainUntilDate=new Date(e.headers["x-amz-object-lock-retain-until-date"])),void 0!==e.headers["x-amz-object-lock-legal-hold"]&&(n.ObjectLockLegalHoldStatus=e.headers["x-amz-object-lock-legal-hold"]),void 0!==e.headers["x-amz-delete-marker"]&&(n.DeleteMarker="true"===e.headers["x-amz-delete-marker"]),void 0!==e.headers["x-amz-storage-class"]&&(n.StorageClass=e.headers["x-amz-storage-class"]),void 0!==e.headers["content-encoding"]&&(n.ContentEncoding=e.headers["content-encoding"]),void 0!==e.headers["x-amz-restore"]&&(n.Restore=e.headers["x-amz-restore"]),void 0!==e.headers["x-amz-website-redirect-location"]&&(n.WebsiteRedirectLocation=e.headers["x-amz-website-redirect-location"]),void 0!==e.headers["x-amz-server-side-encryption"]&&(n.ServerSideEncryption=e.headers["x-amz-server-side-encryption"]),void 0!==e.headers["x-amz-mp-parts-count"]&&(n.PartsCount=parseInt(e.headers["x-amz-mp-parts-count"],10)),void 0!==e.headers["x-amz-server-side-encryption-customer-algorithm"]&&(n.SSECustomerAlgorithm=e.headers["x-amz-server-side-encryption-customer-algorithm"]),void 0!==e.headers["accept-ranges"]&&(n.AcceptRanges=e.headers["accept-ranges"]),void 0!==e.headers["x-amz-version-id"]&&(n.VersionId=e.headers["x-amz-version-id"]),void 0!==e.headers.expires&&(n.Expires=new Date(e.headers.expires)),void 0!==e.headers["x-amz-expiration"]&&(n.Expiration=e.headers["x-amz-expiration"]),void 0!==e.headers["x-amz-missing-meta"]&&(n.MissingMeta=parseInt(e.headers["x-amz-missing-meta"],10)),void 0!==e.headers["x-amz-replication-status"]&&(n.ReplicationStatus=e.headers["x-amz-replication-status"]),void 0!==e.headers["x-amz-tagging-count"]&&(n.TagCount=parseInt(e.headers["x-amz-tagging-count"],10)),void 0!==e.headers["x-amz-server-side-encryption-customer-key-md5"]&&(n.SSECustomerKeyMD5=e.headers["x-amz-server-side-encryption-customer-key-md5"]),void 0!==e.headers["last-modified"]&&(n.LastModified=new Date(e.headers["last-modified"])),void 0!==e.headers.etag&&(n.ETag=e.headers.etag),void 0!==e.headers["x-amz-request-charged"]&&(n.RequestCharged=e.headers["x-amz-request-charged"]),Object.keys(e.headers).forEach((function(t){void 0===n.Metadata&&(n.Metadata={}),t.startsWith("x-amz-meta-")&&(n.Metadata[t.substring(11)]=e.headers[t])})),r=e.body,n.Body=r,[2,Promise.resolve(n)])}))}))}(e,t)},t}(Zr.b),Yi=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Vi.a)(t,this.serialize,this.deserialize)),this.middlewareStack.use(Hi(t));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"S3Client",commandName:"DeleteObjectCommand",inputFilterSensitiveLog:Z.filterSensitiveLog,outputFilterSensitiveLog:J.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"S3Client",commandName:"DeleteObjectCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l;return d(this,(function(d){switch(d.label){case 0:if(n=f(f(f(f({"Content-Type":""},Mi(e.MFA)&&{"x-amz-mfa":e.MFA}),Mi(e.ExpectedBucketOwner)&&{"x-amz-expected-bucket-owner":e.ExpectedBucketOwner}),Mi(e.BypassGovernanceRetention)&&{"x-amz-bypass-governance-retention":e.BypassGovernanceRetention.toString()}),Mi(e.RequestPayer)&&{"x-amz-request-payer":e.RequestPayer}),r="/{Bucket}/{Key+}",void 0===e.Bucket)throw new Error("No value provided for input HTTP label: Bucket.");if((i=e.Bucket).length<=0)throw new Error("Empty value provided for input HTTP label: Bucket.");if(r=r.replace("{Bucket}",Object(Zr.f)(i)),void 0===e.Key)throw new Error("No value provided for input HTTP label: Key.");if((i=e.Key).length<=0)throw new Error("Empty value provided for input HTTP label: Key.");return r=r.replace("{Key+}",i.split("/").map((function(e){return Object(Zr.f)(e)})).join("/")),o=f({"x-id":"DeleteObject"},void 0!==e.VersionId&&{versionId:e.VersionId}),[4,t.endpoint()];case 1:return s=d.sent(),a=s.hostname,u=s.protocol,c=void 0===u?"https":u,l=s.port,[2,new Xr.a({protocol:c,hostname:a,port:l,method:"DELETE",headers:n,path:r,query:o,body:void 0})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n;return d(this,(function(r){switch(r.label){case 0:return 204!==e.statusCode&&e.statusCode>=300?[2,si(e,t)]:(n={$metadata:Si(e),DeleteMarker:void 0,RequestCharged:void 0,VersionId:void 0},void 0!==e.headers["x-amz-delete-marker"]&&(n.DeleteMarker="true"===e.headers["x-amz-delete-marker"]),void 0!==e.headers["x-amz-request-charged"]&&(n.RequestCharged=e.headers["x-amz-request-charged"]),void 0!==e.headers["x-amz-version-id"]&&(n.VersionId=e.headers["x-amz-version-id"]),[4,Ei(e.body,t)]);case 1:return r.sent(),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(Zr.b),Ji=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Vi.a)(t,this.serialize,this.deserialize)),this.middlewareStack.use(Hi(t));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"S3Client",commandName:"ListObjectsCommand",inputFilterSensitiveLog:Fn.filterSensitiveLog,outputFilterSensitiveLog:Bn.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"S3Client",commandName:"ListObjectsCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l;return d(this,(function(d){switch(d.label){case 0:if(n=f(f({"Content-Type":""},Mi(e.ExpectedBucketOwner)&&{"x-amz-expected-bucket-owner":e.ExpectedBucketOwner}),Mi(e.RequestPayer)&&{"x-amz-request-payer":e.RequestPayer}),r="/{Bucket}",void 0===e.Bucket)throw new Error("No value provided for input HTTP label: Bucket.");if((i=e.Bucket).length<=0)throw new Error("Empty value provided for input HTTP label: Bucket.");return r=r.replace("{Bucket}",Object(Zr.f)(i)),o=f(f(f(f(f({},void 0!==e.MaxKeys&&{"max-keys":e.MaxKeys.toString()}),void 0!==e.Marker&&{marker:e.Marker}),void 0!==e.Prefix&&{prefix:e.Prefix}),void 0!==e.Delimiter&&{delimiter:e.Delimiter}),void 0!==e.EncodingType&&{"encoding-type":e.EncodingType}),[4,t.endpoint()];case 1:return s=d.sent(),a=s.hostname,u=s.protocol,c=void 0===u?"https":u,l=s.port,[2,new Xr.a({protocol:c,hostname:a,port:l,method:"GET",headers:n,path:r,query:o,body:void 0})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r;return d(this,(function(i){switch(i.label){case 0:return 200!==e.statusCode&&e.statusCode>=300?[2,ui(e,t)]:(n={$metadata:Si(e),CommonPrefixes:void 0,Contents:void 0,Delimiter:void 0,EncodingType:void 0,IsTruncated:void 0,Marker:void 0,MaxKeys:void 0,Name:void 0,NextMarker:void 0,Prefix:void 0},[4,Ai(e.body,t)]);case 1:return""===(r=i.sent()).CommonPrefixes&&(n.CommonPrefixes=[]),void 0!==r.CommonPrefixes&&(n.CommonPrefixes=mi(Object(Zr.g)(r.CommonPrefixes),t)),""===r.Contents&&(n.Contents=[]),void 0!==r.Contents&&(n.Contents=yi(Object(Zr.g)(r.Contents),t)),void 0!==r.Delimiter&&(n.Delimiter=r.Delimiter),void 0!==r.EncodingType&&(n.EncodingType=r.EncodingType),void 0!==r.IsTruncated&&(n.IsTruncated="true"==r.IsTruncated),void 0!==r.Marker&&(n.Marker=r.Marker),void 0!==r.MaxKeys&&(n.MaxKeys=parseInt(r.MaxKeys)),void 0!==r.Name&&(n.Name=r.Name),void 0!==r.NextMarker&&(n.NextMarker=r.NextMarker),void 0!==r.Prefix&&(n.Prefix=r.Prefix),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(Zr.b),Zi=n(153),Xi=n(38),Qi=n(110),eo=n(18);function to(e,t,n){return void 0===n&&(n=1048576),new Promise((function(r,i){var o=new FileReader;o.addEventListener("error",i),o.addEventListener("abort",i);var s=e.size,a=0;function u(){a>=s?r():o.readAsArrayBuffer(e.slice(a,Math.min(s,a+n)))}o.addEventListener("load",(function(e){var n=e.target.result;t(new Uint8Array(n)),a+=n.byteLength,u()})),u()}))}var no=n(24),ro=n(15),io=[1732584193,4023233417,2562383102,271733878],oo=function(){function e(){this.state=Uint32Array.from(io),this.buffer=new DataView(new ArrayBuffer(64)),this.bufferLength=0,this.bytesHashed=0,this.finished=!1}return e.prototype.update=function(e){if(!function(e){if("string"==typeof e)return 0===e.length;return 0===e.byteLength}(e)){if(this.finished)throw new Error("Attempted to update an already finished hash.");var t=function(e){if("string"==typeof e)return Object(ro.a)(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength/Uint8Array.BYTES_PER_ELEMENT);return new Uint8Array(e)}(e),n=0,r=t.byteLength;for(this.bytesHashed+=r;r>0;)this.buffer.setUint8(this.bufferLength++,t[n++]),r--,64===this.bufferLength&&(this.hashBuffer(),this.bufferLength=0)}},e.prototype.digest=function(){return Object(Qr.__awaiter)(this,void 0,void 0,(function(){var e,t,n,r,i,o,s;return Object(Qr.__generator)(this,(function(a){if(!this.finished){if(t=(e=this).buffer,n=e.bufferLength,r=e.bytesHashed,i=8*r,t.setUint8(this.bufferLength++,128),n%64>=56){for(s=this.bufferLength;s<64;s++)t.setUint8(s,0);this.hashBuffer(),this.bufferLength=0}for(s=this.bufferLength;s<56;s++)t.setUint8(s,0);t.setUint32(56,i>>>0,!0),t.setUint32(60,Math.floor(i/4294967296),!0),this.hashBuffer(),this.finished=!0}for(o=new DataView(new ArrayBuffer(16)),s=0;s<4;s++)o.setUint32(4*s,this.state[s],!0);return[2,new Uint8Array(o.buffer,o.byteOffset,o.byteLength)]}))}))},e.prototype.hashBuffer=function(){var e=this.buffer,t=this.state,n=t[0],r=t[1],i=t[2],o=t[3];n=ao(n,r,i,o,e.getUint32(0,!0),7,3614090360),o=ao(o,n,r,i,e.getUint32(4,!0),12,3905402710),i=ao(i,o,n,r,e.getUint32(8,!0),17,606105819),r=ao(r,i,o,n,e.getUint32(12,!0),22,3250441966),n=ao(n,r,i,o,e.getUint32(16,!0),7,4118548399),o=ao(o,n,r,i,e.getUint32(20,!0),12,1200080426),i=ao(i,o,n,r,e.getUint32(24,!0),17,2821735955),r=ao(r,i,o,n,e.getUint32(28,!0),22,4249261313),n=ao(n,r,i,o,e.getUint32(32,!0),7,1770035416),o=ao(o,n,r,i,e.getUint32(36,!0),12,2336552879),i=ao(i,o,n,r,e.getUint32(40,!0),17,4294925233),r=ao(r,i,o,n,e.getUint32(44,!0),22,2304563134),n=ao(n,r,i,o,e.getUint32(48,!0),7,1804603682),o=ao(o,n,r,i,e.getUint32(52,!0),12,4254626195),i=ao(i,o,n,r,e.getUint32(56,!0),17,2792965006),n=uo(n,r=ao(r,i,o,n,e.getUint32(60,!0),22,1236535329),i,o,e.getUint32(4,!0),5,4129170786),o=uo(o,n,r,i,e.getUint32(24,!0),9,3225465664),i=uo(i,o,n,r,e.getUint32(44,!0),14,643717713),r=uo(r,i,o,n,e.getUint32(0,!0),20,3921069994),n=uo(n,r,i,o,e.getUint32(20,!0),5,3593408605),o=uo(o,n,r,i,e.getUint32(40,!0),9,38016083),i=uo(i,o,n,r,e.getUint32(60,!0),14,3634488961),r=uo(r,i,o,n,e.getUint32(16,!0),20,3889429448),n=uo(n,r,i,o,e.getUint32(36,!0),5,568446438),o=uo(o,n,r,i,e.getUint32(56,!0),9,3275163606),i=uo(i,o,n,r,e.getUint32(12,!0),14,4107603335),r=uo(r,i,o,n,e.getUint32(32,!0),20,1163531501),n=uo(n,r,i,o,e.getUint32(52,!0),5,2850285829),o=uo(o,n,r,i,e.getUint32(8,!0),9,4243563512),i=uo(i,o,n,r,e.getUint32(28,!0),14,1735328473),n=co(n,r=uo(r,i,o,n,e.getUint32(48,!0),20,2368359562),i,o,e.getUint32(20,!0),4,4294588738),o=co(o,n,r,i,e.getUint32(32,!0),11,2272392833),i=co(i,o,n,r,e.getUint32(44,!0),16,1839030562),r=co(r,i,o,n,e.getUint32(56,!0),23,4259657740),n=co(n,r,i,o,e.getUint32(4,!0),4,2763975236),o=co(o,n,r,i,e.getUint32(16,!0),11,1272893353),i=co(i,o,n,r,e.getUint32(28,!0),16,4139469664),r=co(r,i,o,n,e.getUint32(40,!0),23,3200236656),n=co(n,r,i,o,e.getUint32(52,!0),4,681279174),o=co(o,n,r,i,e.getUint32(0,!0),11,3936430074),i=co(i,o,n,r,e.getUint32(12,!0),16,3572445317),r=co(r,i,o,n,e.getUint32(24,!0),23,76029189),n=co(n,r,i,o,e.getUint32(36,!0),4,3654602809),o=co(o,n,r,i,e.getUint32(48,!0),11,3873151461),i=co(i,o,n,r,e.getUint32(60,!0),16,530742520),n=fo(n,r=co(r,i,o,n,e.getUint32(8,!0),23,3299628645),i,o,e.getUint32(0,!0),6,4096336452),o=fo(o,n,r,i,e.getUint32(28,!0),10,1126891415),i=fo(i,o,n,r,e.getUint32(56,!0),15,2878612391),r=fo(r,i,o,n,e.getUint32(20,!0),21,4237533241),n=fo(n,r,i,o,e.getUint32(48,!0),6,1700485571),o=fo(o,n,r,i,e.getUint32(12,!0),10,2399980690),i=fo(i,o,n,r,e.getUint32(40,!0),15,4293915773),r=fo(r,i,o,n,e.getUint32(4,!0),21,2240044497),n=fo(n,r,i,o,e.getUint32(32,!0),6,1873313359),o=fo(o,n,r,i,e.getUint32(60,!0),10,4264355552),i=fo(i,o,n,r,e.getUint32(24,!0),15,2734768916),r=fo(r,i,o,n,e.getUint32(52,!0),21,1309151649),n=fo(n,r,i,o,e.getUint32(16,!0),6,4149444226),o=fo(o,n,r,i,e.getUint32(44,!0),10,3174756917),i=fo(i,o,n,r,e.getUint32(8,!0),15,718787259),r=fo(r,i,o,n,e.getUint32(36,!0),21,3951481745),t[0]=n+t[0]&4294967295,t[1]=r+t[1]&4294967295,t[2]=i+t[2]&4294967295,t[3]=o+t[3]&4294967295},e}();function so(e,t,n,r,i,o){return((t=(t+e&4294967295)+(r+o&4294967295)&4294967295)<<i|t>>>32-i)+n&4294967295}function ao(e,t,n,r,i,o,s){return so(t&n|~t&r,e,t,i,o,s)}function uo(e,t,n,r,i,o,s){return so(t&r|n&~r,e,t,i,o,s)}function co(e,t,n,r,i,o,s){return so(t^n^r,e,t,i,o,s)}function fo(e,t,n,r,i,o,s){return so(n^(t|~r),e,t,i,o,s)}var lo=n(11),ho=n(39),po=n(17),vo=n(40),go=n(41),mo=new Set(["ap-east-1","ap-northeast-1","ap-northeast-2","ap-south-1","ap-southeast-1","ap-southeast-2","ca-central-1","eu-central-1","eu-north-1","eu-west-1","eu-west-2","eu-west-3","me-south-1","sa-east-1","us-east-1","us-east-2","us-west-1","us-west-2"]),bo=new Set(["cn-north-1","cn-northwest-1"]),yo=new Set(["us-iso-east-1"]),wo=new Set(["us-isob-east-1"]),_o=new Set(["us-gov-east-1","us-gov-west-1"]),So=f(f({},{apiVersion:"2006-03-01",disableHostPrefix:!1,logger:{},regionInfoProvider:function(e,t){var n=void 0;switch(e){case"ap-east-1":n={hostname:"s3.ap-east-1.amazonaws.com",partition:"aws"};break;case"ap-northeast-1":n={hostname:"s3.ap-northeast-1.amazonaws.com",partition:"aws"};break;case"ap-northeast-2":n={hostname:"s3.ap-northeast-2.amazonaws.com",partition:"aws"};break;case"ap-south-1":n={hostname:"s3.ap-south-1.amazonaws.com",partition:"aws"};break;case"ap-southeast-1":n={hostname:"s3.ap-southeast-1.amazonaws.com",partition:"aws"};break;case"ap-southeast-2":n={hostname:"s3.ap-southeast-2.amazonaws.com",partition:"aws"};break;case"ca-central-1":n={hostname:"s3.ca-central-1.amazonaws.com",partition:"aws"};break;case"cn-north-1":n={hostname:"s3.cn-north-1.amazonaws.com.cn",partition:"aws-cn"};break;case"cn-northwest-1":n={hostname:"s3.cn-northwest-1.amazonaws.com.cn",partition:"aws-cn"};break;case"eu-central-1":n={hostname:"s3.eu-central-1.amazonaws.com",partition:"aws"};break;case"eu-north-1":n={hostname:"s3.eu-north-1.amazonaws.com",partition:"aws"};break;case"eu-west-1":n={hostname:"s3.eu-west-1.amazonaws.com",partition:"aws"};break;case"eu-west-2":n={hostname:"s3.eu-west-2.amazonaws.com",partition:"aws"};break;case"eu-west-3":n={hostname:"s3.eu-west-3.amazonaws.com",partition:"aws"};break;case"fips-us-gov-west-1":n={hostname:"s3-fips-us-gov-west-1.amazonaws.com",partition:"aws-us-gov",signingRegion:"us-gov-west-1"};break;case"me-south-1":n={hostname:"s3.me-south-1.amazonaws.com",partition:"aws"};break;case"s3-external-1":n={hostname:"s3-external-1.amazonaws.com",partition:"aws",signingRegion:"us-east-1"};break;case"sa-east-1":n={hostname:"s3.sa-east-1.amazonaws.com",partition:"aws"};break;case"us-east-1":n={hostname:"s3.amazonaws.com",partition:"aws"};break;case"us-east-2":n={hostname:"s3.us-east-2.amazonaws.com",partition:"aws"};break;case"us-gov-east-1":n={hostname:"s3.us-gov-east-1.amazonaws.com",partition:"aws-us-gov"};break;case"us-gov-west-1":n={hostname:"s3.us-gov-west-1.amazonaws.com",partition:"aws-us-gov"};break;case"us-iso-east-1":n={hostname:"s3.us-iso-east-1.c2s.ic.gov",partition:"aws-iso"};break;case"us-isob-east-1":n={hostname:"s3.us-isob-east-1.sc2s.sgov.gov",partition:"aws-iso-b"};break;case"us-west-1":n={hostname:"s3.us-west-1.amazonaws.com",partition:"aws"};break;case"us-west-2":n={hostname:"s3.us-west-2.amazonaws.com",partition:"aws"};break;default:mo.has(e)&&(n={hostname:"s3.{region}.amazonaws.com".replace("{region}",e),partition:"aws"}),bo.has(e)&&(n={hostname:"s3.{region}.amazonaws.com.cn".replace("{region}",e),partition:"aws-cn"}),yo.has(e)&&(n={hostname:"s3.{region}.c2s.ic.gov".replace("{region}",e),partition:"aws-iso"}),wo.has(e)&&(n={hostname:"s3.{region}.sc2s.sgov.gov".replace("{region}",e),partition:"aws-iso-b"}),_o.has(e)&&(n={hostname:"s3.{region}.amazonaws.com".replace("{region}",e),partition:"aws-us-gov"}),void 0===n&&(n={hostname:"s3.{region}.amazonaws.com".replace("{region}",e),partition:"aws"})}return Promise.resolve(n)},signingEscapePath:!1,signingName:"s3",useArnRegion:!1}),{runtime:"browser",base64Decoder:po.a,base64Encoder:po.b,bodyLengthChecker:vo.a,credentialDefaultProvider:Object(no.a)("Credential is missing"),defaultUserAgent:Object(go.a)(Zi.name,Zi.version),eventStreamSerdeProvider:Qi.a,maxAttempts:lo.a,md5:oo,region:Object(no.a)("Region is missing"),requestHandler:new eo.a,sha256:Xi.Sha256,streamCollector:eo.b,streamHasher:function(e,t){return Object(Qr.__awaiter)(this,void 0,void 0,(function(){var n;return Object(Qr.__generator)(this,(function(r){switch(r.label){case 0:return n=new e,[4,to(t,(function(e){n.update(e)}))];case 1:return r.sent(),[2,n.digest()]}}))}))},urlParser:ho.a,utf8Decoder:ro.a,utf8Encoder:ro.b}),Eo=n(22),Mo=n(112),Ao=n(37);var Io={step:"build",tags:["SET_EXPECT_HEADER","EXPECT_HEADER"],name:"addExpectContinueMiddleware"},ko=function(e){return{applyToStack:function(t){t.add(function(e){var t=this;return function(n){return function(r){return Object(Qr.__awaiter)(t,void 0,void 0,(function(){var t;return Object(Qr.__generator)(this,(function(i){return t=r.request,Xr.a.isInstance(t)&&t.body&&"node"===e.runtime&&(t.headers=Object(Qr.__assign)(Object(Qr.__assign)({},t.headers),{Expect:"100-continue"})),[2,n(Object(Qr.__assign)(Object(Qr.__assign)({},r),{request:t}))]}))}))}}}(e),Io)}}},Oo=n(21),xo=n(43);var Co={step:"initialize",tags:["VALIDATE_BUCKET_NAME"],name:"validateBucketNameMiddleware"},To=function(e){return{applyToStack:function(e){e.add(function(){var e=this;return function(t){return function(n){return Object(Qr.__awaiter)(e,void 0,void 0,(function(){var e,r;return Object(Qr.__generator)(this,(function(i){if("string"==typeof(e=n.input.Bucket)&&!ki(e)&&e.indexOf("/")>=0)throw(r=new Error("Bucket name shouldn't contain '/', received '"+e+"'")).name="InvalidBucketName",r;return[2,t(Object(Qr.__assign)({},n))]}))}))}}}(),Co)}}},Po={step:"build",tags:["USE_REGIONAL_ENDPOINT","S3"],name:"useRegionalEndpointMiddleware"},No=function(e){return{applyToStack:function(t){t.add(function(e){return function(t){return function(n){return Object(Qr.__awaiter)(void 0,void 0,void 0,(function(){var r,i;return Object(Qr.__generator)(this,(function(o){switch(o.label){case 0:return r=n.request,!Xr.a.isInstance(r)||e.isCustomEndpoint?[2,t(Object(Qr.__assign)({},n))]:"s3.amazonaws.com"!==r.hostname?[3,1]:(r.hostname="s3.us-east-1.amazonaws.com",[3,3]);case 1:return i="aws-global",[4,e.region()];case 2:i===o.sent()&&(r.hostname="s3.amazonaws.com"),o.label=3;case 3:return[2,t(Object(Qr.__assign)({},n))]}}))}))}}}(e),Po)}}},Ro=n(25),Lo=n(23),jo=function(e){function t(t){var n,r,i,o,s,a,u,c,l,d,h,p=this,v=f(f({},So),t),g=Object(Eo.b)(v),m=Object(Eo.a)(g),b=Object(Ro.b)(m),y=Object(lo.c)(b),w=Object(Lo.b)(y),_=(r=(n=w).bucketEndpoint,i=void 0!==r&&r,o=n.forcePathStyle,s=void 0!==o&&o,a=n.useAccelerateEndpoint,u=void 0!==a&&a,c=n.useDualstackEndpoint,l=void 0!==c&&c,d=n.useArnRegion,h=void 0!==d&&d,Object(Qr.__assign)(Object(Qr.__assign)({},n),{bucketEndpoint:i,forcePathStyle:s,useAccelerateEndpoint:u,useDualstackEndpoint:l,useArnRegion:"function"==typeof h?h:function(){return Promise.resolve(h)}})),S=Object(Oo.b)(_),E=Object(Mo.a)(S);return(p=e.call(this,E)||this).config=E,p.middlewareStack.use(Object(Ro.a)(p.config)),p.middlewareStack.use(Object(lo.b)(p.config)),p.middlewareStack.use(Object(Lo.a)(p.config)),p.middlewareStack.use(Object(Ao.a)(p.config)),p.middlewareStack.use(To(p.config)),p.middlewareStack.use(No(p.config)),p.middlewareStack.use(ko(p.config)),p.middlewareStack.use(Object(Oo.a)(p.config)),p.middlewareStack.use(Object(xo.a)(p.config)),p}return c(t,e),t.prototype.destroy=function(){e.prototype.destroy.call(this)},t}(Zr.a),Do=n(74);function Uo(e){var t=e.port,n=e.query,r=e.protocol,i=e.path,o=e.hostname;r&&":"!==r.substr(-1)&&(r+=":"),t&&(o+=":"+t),i&&"/"!==i.charAt(0)&&(i="/"+i);var s=n?Object(Do.a)(n):"";return s&&"?"!==s[0]&&(s="?"+s),r+"//"+o+i+s}function Bo(e,t){return Object(Qr.__awaiter)(this,void 0,void 0,(function(){var n,r,i=this;return Object(Qr.__generator)(this,(function(o){switch(o.label){case 0:return n=function(e){return function(e){return Object(Qr.__awaiter)(i,void 0,void 0,(function(){return Object(Qr.__generator)(this,(function(t){return[2,{output:{request:e.request},response:void 0}]}))}))}},(r=e.middlewareStack.clone()).add(n,{step:"build",priority:"low"}),[4,t.resolveMiddleware(r,e.config,void 0)(t).then((function(e){return e.output.request}))];case 1:return[2,o.sent()]}}))}))}var Fo=n(111),zo=function(){function e(e){var t=Object(Qr.__assign)({service:e.signingName||e.service||"s3",uriEscapePath:e.uriEscapePath||!1},e);this.signer=new Fo.a(t)}return e.prototype.presign=function(e,t){void 0===t&&(t={});var n=t.unsignableHeaders,r=void 0===n?new Set:n,i=Object(Qr.__rest)(t,["unsignableHeaders"]);return Object(Qr.__awaiter)(this,void 0,void 0,(function(){return Object(Qr.__generator)(this,(function(t){return r.add("content-type"),e.headers["X-Amz-Content-Sha256"]="UNSIGNED-PAYLOAD",[2,this.signer.presign(e,Object(Qr.__assign)({expiresIn:900,unsignableHeaders:r},i))]}))}))},e}(),qo=n(64),Ko=n.n(qo),Ho=new r.a("axios-http-handler"),Vo=function(){function e(e,t){void 0===e&&(e={}),this.httpOptions=e,this.emitter=t}return e.prototype.destroy=function(){},e.prototype.handle=function(e,t){var n=this.httpOptions.requestTimeout,r=this.emitter,i=e.path;if(e.query){var o=Object(Do.a)(e.query);o&&(i+="?"+o)}var s=e.port,a=e.protocol+"//"+e.hostname+(s?":"+s:"")+i,u={};u.url=a,u.method=e.method,u.headers=e.headers,delete u.headers.host,e.body?u.data=e.body:u.headers["Content-Type"]&&(u.data=null),r&&(u.onUploadProgress=function(e){r.emit("sendProgress",e),Ho.debug(e)}),u.responseType="blob";var c=[Ko.a.request(u).then((function(e){return{response:new Xr.b({headers:e.headers,statusCode:e.status,body:e.data})}})).catch((function(e){throw Ho.error(e),e})),Go(n)];return Promise.race(c)},e}();function Go(e){return void 0===e&&(e=0),new Promise((function(t,n){e&&setTimeout((function(){var t=new Error("Request did not complete within "+e+" ms");t.name="TimeoutError",n(t)}),e)}))}var Wo,$o,Yo,Jo,Zo,Xo,Qo,es,ts,ns,rs,is,os,ss,as,us,cs,fs,ls,ds,hs=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Vi.a)(t,this.serialize,this.deserialize)),this.middlewareStack.use(Wi(t)),this.middlewareStack.use(Hi(t));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"S3Client",commandName:"PutObjectCommand",inputFilterSensitiveLog:_r.filterSensitiveLog,outputFilterSensitiveLog:wr.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"S3Client",commandName:"PutObjectCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l,h,p;return d(this,(function(d){switch(d.label){case 0:if(n=f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f({"Content-Type":"application/octet-stream"},Mi(e.GrantFullControl)&&{"x-amz-grant-full-control":e.GrantFullControl}),Mi(e.ContentEncoding)&&{"Content-Encoding":e.ContentEncoding}),Mi(e.RequestPayer)&&{"x-amz-request-payer":e.RequestPayer}),Mi(e.GrantReadACP)&&{"x-amz-grant-read-acp":e.GrantReadACP}),Mi(e.SSECustomerKeyMD5)&&{"x-amz-server-side-encryption-customer-key-MD5":e.SSECustomerKeyMD5}),Mi(e.CacheControl)&&{"Cache-Control":e.CacheControl}),Mi(e.WebsiteRedirectLocation)&&{"x-amz-website-redirect-location":e.WebsiteRedirectLocation}),Mi(e.ObjectLockLegalHoldStatus)&&{"x-amz-object-lock-legal-hold":e.ObjectLockLegalHoldStatus}),Mi(e.GrantWriteACP)&&{"x-amz-grant-write-acp":e.GrantWriteACP}),Mi(e.ContentLength)&&{"Content-Length":e.ContentLength.toString()}),Mi(e.ObjectLockRetainUntilDate)&&{"x-amz-object-lock-retain-until-date":(e.ObjectLockRetainUntilDate.toISOString().split(".")[0]+"Z").toString()}),Mi(e.SSECustomerAlgorithm)&&{"x-amz-server-side-encryption-customer-algorithm":e.SSECustomerAlgorithm}),Mi(e.ContentDisposition)&&{"Content-Disposition":e.ContentDisposition}),Mi(e.SSECustomerKey)&&{"x-amz-server-side-encryption-customer-key":e.SSECustomerKey}),Mi(e.SSEKMSEncryptionContext)&&{"x-amz-server-side-encryption-context":e.SSEKMSEncryptionContext}),Mi(e.Tagging)&&{"x-amz-tagging":e.Tagging}),Mi(e.Expires)&&{Expires:Object(Zr.e)(e.Expires).toString()}),Mi(e.StorageClass)&&{"x-amz-storage-class":e.StorageClass}),Mi(e.ExpectedBucketOwner)&&{"x-amz-expected-bucket-owner":e.ExpectedBucketOwner}),Mi(e.ContentMD5)&&{"Content-MD5":e.ContentMD5}),Mi(e.ServerSideEncryption)&&{"x-amz-server-side-encryption":e.ServerSideEncryption}),Mi(e.ObjectLockMode)&&{"x-amz-object-lock-mode":e.ObjectLockMode}),Mi(e.SSEKMSKeyId)&&{"x-amz-server-side-encryption-aws-kms-key-id":e.SSEKMSKeyId}),Mi(e.ContentLanguage)&&{"Content-Language":e.ContentLanguage}),Mi(e.GrantRead)&&{"x-amz-grant-read":e.GrantRead}),Mi(e.ACL)&&{"x-amz-acl":e.ACL}),Mi(e.ContentType)&&{"Content-Type":e.ContentType}),void 0!==e.Metadata&&Object.keys(e.Metadata).reduce((function(t,n){return t["x-amz-meta-"+n]=e.Metadata[n],t}),{})),r="/{Bucket}/{Key+}",void 0===e.Bucket)throw new Error("No value provided for input HTTP label: Bucket.");if((i=e.Bucket).length<=0)throw new Error("Empty value provided for input HTTP label: Bucket.");if(r=r.replace("{Bucket}",Object(Zr.f)(i)),void 0===e.Key)throw new Error("No value provided for input HTTP label: Key.");if((i=e.Key).length<=0)throw new Error("Empty value provided for input HTTP label: Key.");return r=r.replace("{Key+}",i.split("/").map((function(e){return Object(Zr.f)(e)})).join("/")),o={"x-id":"PutObject"},void 0!==e.Body&&(a=e.Body,s=a),[4,t.endpoint()];case 1:return u=d.sent(),c=u.hostname,l=u.protocol,h=void 0===l?"https":l,p=u.port,[2,new Xr.a({protocol:h,hostname:c,port:p,method:"PUT",headers:n,path:r,query:o,body:s})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n;return d(this,(function(r){switch(r.label){case 0:return 200!==e.statusCode&&e.statusCode>=300?[2,fi(e,t)]:(n={$metadata:Si(e),ETag:void 0,Expiration:void 0,RequestCharged:void 0,SSECustomerAlgorithm:void 0,SSECustomerKeyMD5:void 0,SSEKMSEncryptionContext:void 0,SSEKMSKeyId:void 0,ServerSideEncryption:void 0,VersionId:void 0},void 0!==e.headers["x-amz-server-side-encryption-context"]&&(n.SSEKMSEncryptionContext=e.headers["x-amz-server-side-encryption-context"]),void 0!==e.headers["x-amz-expiration"]&&(n.Expiration=e.headers["x-amz-expiration"]),void 0!==e.headers["x-amz-server-side-encryption-customer-key-md5"]&&(n.SSECustomerKeyMD5=e.headers["x-amz-server-side-encryption-customer-key-md5"]),void 0!==e.headers.etag&&(n.ETag=e.headers.etag),void 0!==e.headers["x-amz-server-side-encryption-customer-algorithm"]&&(n.SSECustomerAlgorithm=e.headers["x-amz-server-side-encryption-customer-algorithm"]),void 0!==e.headers["x-amz-version-id"]&&(n.VersionId=e.headers["x-amz-version-id"]),void 0!==e.headers["x-amz-request-charged"]&&(n.RequestCharged=e.headers["x-amz-request-charged"]),void 0!==e.headers["x-amz-server-side-encryption-aws-kms-key-id"]&&(n.SSEKMSKeyId=e.headers["x-amz-server-side-encryption-aws-kms-key-id"]),void 0!==e.headers["x-amz-server-side-encryption"]&&(n.ServerSideEncryption=e.headers["x-amz-server-side-encryption"]),[4,Ei(e.body,t)]);case 1:return r.sent(),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(Zr.b),ps=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Vi.a)(t,this.serialize,this.deserialize)),this.middlewareStack.use(Wi(t)),this.middlewareStack.use(Hi(t));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"S3Client",commandName:"CreateMultipartUploadCommand",inputFilterSensitiveLog:D.filterSensitiveLog,outputFilterSensitiveLog:j.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"S3Client",commandName:"CreateMultipartUploadCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l;return d(this,(function(d){switch(d.label){case 0:if(n=f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f({"Content-Type":""},Mi(e.GrantFullControl)&&{"x-amz-grant-full-control":e.GrantFullControl}),Mi(e.SSECustomerKeyMD5)&&{"x-amz-server-side-encryption-customer-key-MD5":e.SSECustomerKeyMD5}),Mi(e.SSECustomerAlgorithm)&&{"x-amz-server-side-encryption-customer-algorithm":e.SSECustomerAlgorithm}),Mi(e.SSEKMSKeyId)&&{"x-amz-server-side-encryption-aws-kms-key-id":e.SSEKMSKeyId}),Mi(e.ObjectLockLegalHoldStatus)&&{"x-amz-object-lock-legal-hold":e.ObjectLockLegalHoldStatus}),Mi(e.RequestPayer)&&{"x-amz-request-payer":e.RequestPayer}),Mi(e.GrantRead)&&{"x-amz-grant-read":e.GrantRead}),Mi(e.GrantWriteACP)&&{"x-amz-grant-write-acp":e.GrantWriteACP}),Mi(e.WebsiteRedirectLocation)&&{"x-amz-website-redirect-location":e.WebsiteRedirectLocation}),Mi(e.ContentType)&&{"Content-Type":e.ContentType}),Mi(e.ContentLanguage)&&{"Content-Language":e.ContentLanguage}),Mi(e.CacheControl)&&{"Cache-Control":e.CacheControl}),Mi(e.GrantReadACP)&&{"x-amz-grant-read-acp":e.GrantReadACP}),Mi(e.Tagging)&&{"x-amz-tagging":e.Tagging}),Mi(e.SSEKMSEncryptionContext)&&{"x-amz-server-side-encryption-context":e.SSEKMSEncryptionContext}),Mi(e.ACL)&&{"x-amz-acl":e.ACL}),Mi(e.SSECustomerKey)&&{"x-amz-server-side-encryption-customer-key":e.SSECustomerKey}),Mi(e.ExpectedBucketOwner)&&{"x-amz-expected-bucket-owner":e.ExpectedBucketOwner}),Mi(e.Expires)&&{Expires:Object(Zr.e)(e.Expires).toString()}),Mi(e.ObjectLockRetainUntilDate)&&{"x-amz-object-lock-retain-until-date":(e.ObjectLockRetainUntilDate.toISOString().split(".")[0]+"Z").toString()}),Mi(e.ServerSideEncryption)&&{"x-amz-server-side-encryption":e.ServerSideEncryption}),Mi(e.ContentDisposition)&&{"Content-Disposition":e.ContentDisposition}),Mi(e.ObjectLockMode)&&{"x-amz-object-lock-mode":e.ObjectLockMode}),Mi(e.StorageClass)&&{"x-amz-storage-class":e.StorageClass}),Mi(e.ContentEncoding)&&{"Content-Encoding":e.ContentEncoding}),void 0!==e.Metadata&&Object.keys(e.Metadata).reduce((function(t,n){return t["x-amz-meta-"+n]=e.Metadata[n],t}),{})),r="/{Bucket}/{Key+}",void 0===e.Bucket)throw new Error("No value provided for input HTTP label: Bucket.");if((i=e.Bucket).length<=0)throw new Error("Empty value provided for input HTTP label: Bucket.");if(r=r.replace("{Bucket}",Object(Zr.f)(i)),void 0===e.Key)throw new Error("No value provided for input HTTP label: Key.");if((i=e.Key).length<=0)throw new Error("Empty value provided for input HTTP label: Key.");return r=r.replace("{Key+}",i.split("/").map((function(e){return Object(Zr.f)(e)})).join("/")),o={uploads:""},[4,t.endpoint()];case 1:return s=d.sent(),a=s.hostname,u=s.protocol,c=void 0===u?"https":u,l=s.port,[2,new Xr.a({protocol:c,hostname:a,port:l,method:"POST",headers:n,path:r,query:o,body:void 0})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r;return d(this,(function(i){switch(i.label){case 0:return 200!==e.statusCode&&e.statusCode>=300?[2,oi(e,t)]:(n={$metadata:Si(e),AbortDate:void 0,AbortRuleId:void 0,Bucket:void 0,Key:void 0,RequestCharged:void 0,SSECustomerAlgorithm:void 0,SSECustomerKeyMD5:void 0,SSEKMSEncryptionContext:void 0,SSEKMSKeyId:void 0,ServerSideEncryption:void 0,UploadId:void 0},void 0!==e.headers["x-amz-server-side-encryption-context"]&&(n.SSEKMSEncryptionContext=e.headers["x-amz-server-side-encryption-context"]),void 0!==e.headers["x-amz-server-side-encryption"]&&(n.ServerSideEncryption=e.headers["x-amz-server-side-encryption"]),void 0!==e.headers["x-amz-request-charged"]&&(n.RequestCharged=e.headers["x-amz-request-charged"]),void 0!==e.headers["x-amz-abort-date"]&&(n.AbortDate=new Date(e.headers["x-amz-abort-date"])),void 0!==e.headers["x-amz-server-side-encryption-customer-algorithm"]&&(n.SSECustomerAlgorithm=e.headers["x-amz-server-side-encryption-customer-algorithm"]),void 0!==e.headers["x-amz-server-side-encryption-aws-kms-key-id"]&&(n.SSEKMSKeyId=e.headers["x-amz-server-side-encryption-aws-kms-key-id"]),void 0!==e.headers["x-amz-abort-rule-id"]&&(n.AbortRuleId=e.headers["x-amz-abort-rule-id"]),void 0!==e.headers["x-amz-server-side-encryption-customer-key-md5"]&&(n.SSECustomerKeyMD5=e.headers["x-amz-server-side-encryption-customer-key-md5"]),[4,Ai(e.body,t)]);case 1:return void 0!==(r=i.sent()).Bucket&&(n.Bucket=r.Bucket),void 0!==r.Key&&(n.Key=r.Key),void 0!==r.UploadId&&(n.UploadId=r.UploadId),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(Zr.b);!function(e){e.SELECT="SELECT"}(Wo||(Wo={})),($o||($o={})).filterSensitiveLog=function(e){return f(f({},e),e.OutputLocation&&{OutputLocation:Br.filterSensitiveLog(e.OutputLocation)})},(Yo||(Yo={})).filterSensitiveLog=function(e){return f(f({},e),e.RestoreRequest&&{RestoreRequest:$o.filterSensitiveLog(e.RestoreRequest)})},(Jo||(Jo={})).filterSensitiveLog=function(e){return f({},e)},(Zo||(Zo={})).filterSensitiveLog=function(e){return f({},e)},(Xo||(Xo={})).filterSensitiveLog=function(e){return f({},e)},(Qo||(Qo={})).filterSensitiveLog=function(e){return f({},e)},(es||(es={})).filterSensitiveLog=function(e){return f({},e)},(ts||(ts={})).filterSensitiveLog=function(e){return f({},e)},(ns||(ns={})).filterSensitiveLog=function(e){return f({},e)},function(e){e.visit=function(e,t){return void 0!==e.Cont?t.Cont(e.Cont):void 0!==e.Progress?t.Progress(e.Progress):void 0!==e.Stats?t.Stats(e.Stats):void 0!==e.End?t.End(e.End):void 0!==e.Records?t.Records(e.Records):t._(e.$unknown[0],e.$unknown[1])},e.filterSensitiveLog=function(e){var t;return void 0!==e.Cont?{Cont:Jo.filterSensitiveLog(e.Cont)}:void 0!==e.Progress?{Progress:Qo.filterSensitiveLog(e.Progress)}:void 0!==e.Stats?{Stats:ns.filterSensitiveLog(e.Stats)}:void 0!==e.End?{End:Zo.filterSensitiveLog(e.End)}:void 0!==e.Records?{Records:es.filterSensitiveLog(e.Records)}:void 0!==e.$unknown?((t={})[e.$unknown[0]]="UNKNOWN",t):void 0}}(rs||(rs={})),(is||(is={})).filterSensitiveLog=function(e){return f(f({},e),e.Payload&&{Payload:"STREAMING_CONTENT"})},(os||(os={})).filterSensitiveLog=function(e){return f({},e)},(ss||(ss={})).filterSensitiveLog=function(e){return f({},e)},(as||(as={})).filterSensitiveLog=function(e){return f(f({},e),e.SSECustomerKey&&{SSECustomerKey:Zr.d})},(us||(us={})).filterSensitiveLog=function(e){return f(f({},e),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d})},(cs||(cs={})).filterSensitiveLog=function(e){return f(f({},e),e.SSECustomerKey&&{SSECustomerKey:Zr.d})},(fs||(fs={})).filterSensitiveLog=function(e){return f({},e)},(ls||(ls={})).filterSensitiveLog=function(e){return f(f({},e),e.SSEKMSKeyId&&{SSEKMSKeyId:Zr.d})},(ds||(ds={})).filterSensitiveLog=function(e){return f(f(f({},e),e.SSECustomerKey&&{SSECustomerKey:Zr.d}),e.CopySourceSSECustomerKey&&{CopySourceSSECustomerKey:Zr.d})};var vs=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Vi.a)(t,this.serialize,this.deserialize)),this.middlewareStack.use(Wi(t)),this.middlewareStack.use(Hi(t));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"S3Client",commandName:"UploadPartCommand",inputFilterSensitiveLog:cs.filterSensitiveLog,outputFilterSensitiveLog:us.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"S3Client",commandName:"UploadPartCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l,h,p;return d(this,(function(d){switch(d.label){case 0:if(n=f(f(f(f(f(f(f({"Content-Type":"application/octet-stream"},Mi(e.ExpectedBucketOwner)&&{"x-amz-expected-bucket-owner":e.ExpectedBucketOwner}),Mi(e.RequestPayer)&&{"x-amz-request-payer":e.RequestPayer}),Mi(e.ContentLength)&&{"Content-Length":e.ContentLength.toString()}),Mi(e.SSECustomerKey)&&{"x-amz-server-side-encryption-customer-key":e.SSECustomerKey}),Mi(e.SSECustomerAlgorithm)&&{"x-amz-server-side-encryption-customer-algorithm":e.SSECustomerAlgorithm}),Mi(e.SSECustomerKeyMD5)&&{"x-amz-server-side-encryption-customer-key-MD5":e.SSECustomerKeyMD5}),Mi(e.ContentMD5)&&{"Content-MD5":e.ContentMD5}),r="/{Bucket}/{Key+}",void 0===e.Bucket)throw new Error("No value provided for input HTTP label: Bucket.");if((i=e.Bucket).length<=0)throw new Error("Empty value provided for input HTTP label: Bucket.");if(r=r.replace("{Bucket}",Object(Zr.f)(i)),void 0===e.Key)throw new Error("No value provided for input HTTP label: Key.");if((i=e.Key).length<=0)throw new Error("Empty value provided for input HTTP label: Key.");return r=r.replace("{Key+}",i.split("/").map((function(e){return Object(Zr.f)(e)})).join("/")),o=f(f({"x-id":"UploadPart"},void 0!==e.PartNumber&&{partNumber:e.PartNumber.toString()}),void 0!==e.UploadId&&{uploadId:e.UploadId}),void 0!==e.Body&&(a=e.Body,s=a),[4,t.endpoint()];case 1:return u=d.sent(),c=u.hostname,l=u.protocol,h=void 0===l?"https":l,p=u.port,[2,new Xr.a({protocol:h,hostname:c,port:p,method:"PUT",headers:n,path:r,query:o,body:s})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n;return d(this,(function(r){switch(r.label){case 0:return 200!==e.statusCode&&e.statusCode>=300?[2,li(e,t)]:(n={$metadata:Si(e),ETag:void 0,RequestCharged:void 0,SSECustomerAlgorithm:void 0,SSECustomerKeyMD5:void 0,SSEKMSKeyId:void 0,ServerSideEncryption:void 0},void 0!==e.headers["x-amz-server-side-encryption-customer-key-md5"]&&(n.SSECustomerKeyMD5=e.headers["x-amz-server-side-encryption-customer-key-md5"]),void 0!==e.headers["x-amz-server-side-encryption"]&&(n.ServerSideEncryption=e.headers["x-amz-server-side-encryption"]),void 0!==e.headers["x-amz-server-side-encryption-aws-kms-key-id"]&&(n.SSEKMSKeyId=e.headers["x-amz-server-side-encryption-aws-kms-key-id"]),void 0!==e.headers["x-amz-server-side-encryption-customer-algorithm"]&&(n.SSECustomerAlgorithm=e.headers["x-amz-server-side-encryption-customer-algorithm"]),void 0!==e.headers["x-amz-request-charged"]&&(n.RequestCharged=e.headers["x-amz-request-charged"]),void 0!==e.headers.etag&&(n.ETag=e.headers.etag),[4,Ei(e.body,t)]);case 1:return r.sent(),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(Zr.b),gs=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Vi.a)(t,this.serialize,this.deserialize)),this.middlewareStack.use(Hi(t));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"S3Client",commandName:"CompleteMultipartUploadCommand",inputFilterSensitiveLog:I.filterSensitiveLog,outputFilterSensitiveLog:E.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"S3Client",commandName:"CompleteMultipartUploadCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l,h,p;return d(this,(function(d){switch(d.label){case 0:if(n=f(f({"Content-Type":"application/xml"},Mi(e.ExpectedBucketOwner)&&{"x-amz-expected-bucket-owner":e.ExpectedBucketOwner}),Mi(e.RequestPayer)&&{"x-amz-request-payer":e.RequestPayer}),r="/{Bucket}/{Key+}",void 0===e.Key)throw new Error("No value provided for input HTTP label: Key.");if((i=e.Key).length<=0)throw new Error("Empty value provided for input HTTP label: Key.");if(r=r.replace("{Key+}",i.split("/").map((function(e){return Object(Zr.f)(e)})).join("/")),void 0===e.Bucket)throw new Error("No value provided for input HTTP label: Bucket.");if((i=e.Bucket).length<=0)throw new Error("Empty value provided for input HTTP label: Bucket.");return r=r.replace("{Bucket}",Object(Zr.f)(i)),o=f({},void 0!==e.UploadId&&{uploadId:e.UploadId}),void 0!==e.MultipartUpload&&(a=vi(e.MultipartUpload,t),s='<?xml version="1.0" encoding="UTF-8"?>',a.addAttribute("xmlns","http://s3.amazonaws.com/doc/2006-03-01/"),s+=a.toString()),[4,t.endpoint()];case 1:return u=d.sent(),c=u.hostname,l=u.protocol,h=void 0===l?"https":l,p=u.port,[2,new Xr.a({protocol:h,hostname:c,port:p,method:"POST",headers:n,path:r,query:o,body:s})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r;return d(this,(function(i){switch(i.label){case 0:return 200!==e.statusCode&&e.statusCode>=300?[2,ii(e,t)]:(n={$metadata:Si(e),Bucket:void 0,ETag:void 0,Expiration:void 0,Key:void 0,Location:void 0,RequestCharged:void 0,SSEKMSKeyId:void 0,ServerSideEncryption:void 0,VersionId:void 0},void 0!==e.headers["x-amz-expiration"]&&(n.Expiration=e.headers["x-amz-expiration"]),void 0!==e.headers["x-amz-server-side-encryption"]&&(n.ServerSideEncryption=e.headers["x-amz-server-side-encryption"]),void 0!==e.headers["x-amz-server-side-encryption-aws-kms-key-id"]&&(n.SSEKMSKeyId=e.headers["x-amz-server-side-encryption-aws-kms-key-id"]),void 0!==e.headers["x-amz-version-id"]&&(n.VersionId=e.headers["x-amz-version-id"]),void 0!==e.headers["x-amz-request-charged"]&&(n.RequestCharged=e.headers["x-amz-request-charged"]),[4,Ai(e.body,t)]);case 1:return void 0!==(r=i.sent()).Bucket&&(n.Bucket=r.Bucket),void 0!==r.ETag&&(n.ETag=r.ETag),void 0!==r.Key&&(n.Key=r.Key),void 0!==r.Location&&(n.Location=r.Location),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(Zr.b),ms=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Vi.a)(t,this.serialize,this.deserialize)),this.middlewareStack.use(Hi(t));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"S3Client",commandName:"AbortMultipartUploadCommand",inputFilterSensitiveLog:v.filterSensitiveLog,outputFilterSensitiveLog:p.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"S3Client",commandName:"AbortMultipartUploadCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l;return d(this,(function(d){switch(d.label){case 0:if(n=f(f({"Content-Type":""},Mi(e.RequestPayer)&&{"x-amz-request-payer":e.RequestPayer}),Mi(e.ExpectedBucketOwner)&&{"x-amz-expected-bucket-owner":e.ExpectedBucketOwner}),r="/{Bucket}/{Key+}",void 0===e.Key)throw new Error("No value provided for input HTTP label: Key.");if((i=e.Key).length<=0)throw new Error("Empty value provided for input HTTP label: Key.");if(r=r.replace("{Key+}",i.split("/").map((function(e){return Object(Zr.f)(e)})).join("/")),void 0===e.Bucket)throw new Error("No value provided for input HTTP label: Bucket.");if((i=e.Bucket).length<=0)throw new Error("Empty value provided for input HTTP label: Bucket.");return r=r.replace("{Bucket}",Object(Zr.f)(i)),o=f({"x-id":"AbortMultipartUpload"},void 0!==e.UploadId&&{uploadId:e.UploadId}),[4,t.endpoint()];case 1:return s=d.sent(),a=s.hostname,u=s.protocol,c=void 0===u?"https":u,l=s.port,[2,new Xr.a({protocol:c,hostname:a,port:l,method:"DELETE",headers:n,path:r,query:o,body:void 0})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n;return d(this,(function(r){switch(r.label){case 0:return 204!==e.statusCode&&e.statusCode>=300?[2,ri(e,t)]:(n={$metadata:Si(e),RequestCharged:void 0},void 0!==e.headers["x-amz-request-charged"]&&(n.RequestCharged=e.headers["x-amz-request-charged"]),[4,Ei(e.body,t)]);case 1:return r.sent(),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(Zr.b),bs=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Vi.a)(t,this.serialize,this.deserialize)),this.middlewareStack.use(Hi(t));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"S3Client",commandName:"ListPartsCommand",inputFilterSensitiveLog:Yn.filterSensitiveLog,outputFilterSensitiveLog:$n.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"S3Client",commandName:"ListPartsCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l;return d(this,(function(d){switch(d.label){case 0:if(n=f(f({"Content-Type":""},Mi(e.RequestPayer)&&{"x-amz-request-payer":e.RequestPayer}),Mi(e.ExpectedBucketOwner)&&{"x-amz-expected-bucket-owner":e.ExpectedBucketOwner}),r="/{Bucket}/{Key+}",void 0===e.Bucket)throw new Error("No value provided for input HTTP label: Bucket.");if((i=e.Bucket).length<=0)throw new Error("Empty value provided for input HTTP label: Bucket.");if(r=r.replace("{Bucket}",Object(Zr.f)(i)),void 0===e.Key)throw new Error("No value provided for input HTTP label: Key.");if((i=e.Key).length<=0)throw new Error("Empty value provided for input HTTP label: Key.");return r=r.replace("{Key+}",i.split("/").map((function(e){return Object(Zr.f)(e)})).join("/")),o=f(f(f({"x-id":"ListParts"},void 0!==e.UploadId&&{uploadId:e.UploadId}),void 0!==e.MaxParts&&{"max-parts":e.MaxParts.toString()}),void 0!==e.PartNumberMarker&&{"part-number-marker":e.PartNumberMarker.toString()}),[4,t.endpoint()];case 1:return s=d.sent(),a=s.hostname,u=s.protocol,c=void 0===u?"https":u,l=s.port,[2,new Xr.a({protocol:c,hostname:a,port:l,method:"GET",headers:n,path:r,query:o,body:void 0})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r;return d(this,(function(i){switch(i.label){case 0:return 200!==e.statusCode&&e.statusCode>=300?[2,ci(e,t)]:(n={$metadata:Si(e),AbortDate:void 0,AbortRuleId:void 0,Bucket:void 0,Initiator:void 0,IsTruncated:void 0,Key:void 0,MaxParts:void 0,NextPartNumberMarker:void 0,Owner:void 0,PartNumberMarker:void 0,Parts:void 0,RequestCharged:void 0,StorageClass:void 0,UploadId:void 0},void 0!==e.headers["x-amz-abort-rule-id"]&&(n.AbortRuleId=e.headers["x-amz-abort-rule-id"]),void 0!==e.headers["x-amz-request-charged"]&&(n.RequestCharged=e.headers["x-amz-request-charged"]),void 0!==e.headers["x-amz-abort-date"]&&(n.AbortDate=new Date(e.headers["x-amz-abort-date"])),[4,Ai(e.body,t)]);case 1:return void 0!==(r=i.sent()).Bucket&&(n.Bucket=r.Bucket),void 0!==r.Initiator&&(n.Initiator=bi(r.Initiator,t)),void 0!==r.IsTruncated&&(n.IsTruncated="true"==r.IsTruncated),void 0!==r.Key&&(n.Key=r.Key),void 0!==r.MaxParts&&(n.MaxParts=parseInt(r.MaxParts)),void 0!==r.NextPartNumberMarker&&(n.NextPartNumberMarker=parseInt(r.NextPartNumberMarker)),void 0!==r.Owner&&(n.Owner=wi(r.Owner,t)),void 0!==r.PartNumberMarker&&(n.PartNumberMarker=parseInt(r.PartNumberMarker)),""===r.Part&&(n.Parts=[]),void 0!==r.Part&&(n.Parts=_i(Object(Zr.g)(r.Part),t)),void 0!==r.StorageClass&&(n.StorageClass=r.StorageClass),void 0!==r.UploadId&&(n.UploadId=r.UploadId),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(Zr.b),ys=n(49),ws=n(106),_s=n(16),Ss=function(e){var t,n=Object(_s.parse)(e),r=n.hostname,i=void 0===r?"localhost":r,o=n.pathname,s=void 0===o?"/":o,a=n.port,u=n.protocol,c=void 0===u?"https:":u,f=n.search;return f&&(t=Object(ws.a)(f)),{hostname:i,port:a?parseInt(a):void 0,protocol:c,path:s,query:t}};function Es(e){return(Es="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var Ms=function(){return(Ms=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},As=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},Is=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},ks=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},Os=new r.a("AWSS3ProviderManagedUpload"),xs=function(){function e(e,t,n){this.minPartSize=5242880,this.queueSize=4,this.body=null,this.params=null,this.opts=null,this.multiPartMap=[],this.cancel=!1,this.bytesUploaded=0,this.totalBytesToUpload=0,this.emitter=null,this.params=e,this.opts=t,this.emitter=n}return e.prototype.upload=function(){return As(this,void 0,void 0,(function(){var e,t,n,r,i,o;return Is(this,(function(s){switch(s.label){case 0:return e=this,[4,this.validateAndSanitizeBody(this.params.Body)];case 1:return e.body=s.sent(),this.totalBytesToUpload=this.byteLength(this.body),this.totalBytesToUpload<=this.minPartSize?(this.params.Body=this.body,t=new hs(this.params),[4,this._createNewS3Client(this.opts,this.emitter)]):[3,3];case 2:return[2,s.sent().send(t)];case 3:return[4,this.createMultiPartUpload()];case 4:n=s.sent(),r=Math.ceil(this.totalBytesToUpload/this.minPartSize),i=0,s.label=5;case 5:return i<r?[4,this.checkIfUploadCancelled(n)]:[3,10];case 6:return s.sent(),o=this.createParts(i),[4,this.uploadParts(n,o)];case 7:return s.sent(),[4,this.checkIfUploadCancelled(n)];case 8:s.sent(),s.label=9;case 9:return i+=this.queueSize,[3,5];case 10:return[4,this.finishMultiPartUpload(n)];case 11:return[2,s.sent()]}}))}))},e.prototype.createParts=function(e){for(var t=[],n=e,r=e*this.minPartSize;r<this.totalBytesToUpload&&t.length<this.queueSize;){var i=Math.min(r+this.minPartSize,this.totalBytesToUpload);t.push({bodyPart:this.body.slice(r,i),partNumber:++n,emitter:new ys.EventEmitter,_lastUploadedBytes:0}),r+=this.minPartSize}return t},e.prototype.createMultiPartUpload=function(){return As(this,void 0,void 0,(function(){var e,t;return Is(this,(function(n){switch(n.label){case 0:return e=new ps(this.params),[4,this._createNewS3Client(this.opts)];case 1:return[4,n.sent().send(e)];case 2:return t=n.sent(),Os.debug(t.UploadId),[2,t.UploadId]}}))}))},e.prototype.uploadParts=function(e,t){return As(this,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,d,h,p;return Is(this,(function(v){switch(v.label){case 0:n=[],v.label=1;case 1:v.trys.push([1,6,7,8]),r=ks(t),i=r.next(),v.label=2;case 2:return i.done?[3,5]:(o=i.value,this.setupEventListener(o),s={PartNumber:o.partNumber,Body:o.bodyPart,UploadId:e,Key:this.params.Key,Bucket:this.params.Bucket},a=new vs(s),[4,this._createNewS3Client(this.opts,o.emitter)]);case 3:u=v.sent(),n.push(u.send(a)),v.label=4;case 4:return i=r.next(),[3,2];case 5:return[3,8];case 6:return c=v.sent(),h={error:c},[3,8];case 7:try{i&&!i.done&&(p=r.return)&&p.call(r)}finally{if(h)throw h.error}return[7];case 8:return v.trys.push([8,10,,11]),[4,Promise.all(n)];case 9:for(f=v.sent(),l=0;l<f.length;l++)this.multiPartMap.push({PartNumber:t[l].partNumber,ETag:f[l].ETag});return[3,11];case 10:return d=v.sent(),Os.error("error happened while uploading a part. Cancelling the multipart upload",d),this.cancelUpload(),[2];case 11:return[2]}}))}))},e.prototype.finishMultiPartUpload=function(e){return As(this,void 0,void 0,(function(){var t,n,r,i;return Is(this,(function(o){switch(o.label){case 0:return t={Bucket:this.params.Bucket,Key:this.params.Key,UploadId:e,MultipartUpload:{Parts:this.multiPartMap}},n=new gs(t),[4,this._createNewS3Client(this.opts)];case 1:r=o.sent(),o.label=2;case 2:return o.trys.push([2,4,,5]),[4,r.send(n)];case 3:return[2,o.sent().Key];case 4:return i=o.sent(),Os.error("error happened while finishing the upload. Cancelling the multipart upload",i),this.cancelUpload(),[2];case 5:return[2]}}))}))},e.prototype.checkIfUploadCancelled=function(e){return As(this,void 0,void 0,(function(){var t,n;return Is(this,(function(r){switch(r.label){case 0:if(!this.cancel)return[3,5];t="Upload was cancelled.",r.label=1;case 1:return r.trys.push([1,3,,4]),[4,this.cleanup(e)];case 2:return r.sent(),[3,4];case 3:return n=r.sent(),t+=n.errorMessage,[3,4];case 4:throw new Error(t);case 5:return[2]}}))}))},e.prototype.cancelUpload=function(){this.cancel=!0},e.prototype.cleanup=function(e){return As(this,void 0,void 0,(function(){var t,n,r;return Is(this,(function(i){switch(i.label){case 0:return this.body=null,this.multiPartMap=[],this.bytesUploaded=0,this.totalBytesToUpload=0,t={Bucket:this.params.Bucket,Key:this.params.Key,UploadId:e},[4,this._createNewS3Client(this.opts)];case 1:return[4,(n=i.sent()).send(new ms(t))];case 2:return i.sent(),[4,n.send(new bs(t))];case 3:if((r=i.sent())&&r.Parts&&r.Parts.length>0)throw new Error("Multi Part upload clean up failed");return[2]}}))}))},e.prototype.setupEventListener=function(e){var t=this;e.emitter.on("sendProgress",(function(n){t.progressChanged(e.partNumber,n.loaded-e._lastUploadedBytes),e._lastUploadedBytes=n.loaded}))},e.prototype.progressChanged=function(e,t){this.bytesUploaded+=t,this.emitter.emit("sendProgress",{loaded:this.bytesUploaded,total:this.totalBytesToUpload,part:e,key:this.params.Key})},e.prototype.byteLength=function(e){if(null==e)return 0;if("number"==typeof e.byteLength)return e.byteLength;if("number"==typeof e.length)return e.length;if("number"==typeof e.size)return e.size;if("string"!=typeof e.path)throw new Error("Cannot determine length of "+e)},e.prototype.validateAndSanitizeBody=function(e){return As(this,void 0,void 0,(function(){return Is(this,(function(t){switch(t.label){case 0:return this.isGenericObject(e)?[2,JSON.stringify(e)]:[3,1];case 1:return this.isBlob(e)?a.a.isReactNative?[4,Object(eo.b)(e)]:[3,3]:[3,4];case 2:return[2,t.sent()];case 3:case 4:return[2,e]}}))}))},e.prototype.isBlob=function(e){return"undefined"!=typeof Blob&&e instanceof Blob},e.prototype.isGenericObject=function(e){if(null!==e&&"object"===Es(e))try{return!(this.byteLength(e)>=0)}catch(e){return!0}return!1},e.prototype._createNewS3Client=function(e,t){return As(this,void 0,void 0,(function(){var n,r,i,o,s;return Is(this,(function(u){switch(u.label){case 0:return[4,this._getCredentials()];case 1:return n=u.sent(),r=e.region,i=e.dangerouslyConnectToHttpEndpointForTesting,o={},i&&(o={endpoint:"http://localhost:20005",tls:!1,bucketEndpoint:!1,forcePathStyle:!0}),(s=new jo(Ms(Ms({region:r,credentials:n},o),{requestHandler:new Vo({},t),customUserAgent:Object(a.b)(),urlParser:Ss}))).middlewareStack.remove("contentLengthMiddleware"),[2,s]}}))}))},e.prototype._getCredentials=function(){return s.a.get().then((function(e){if(!e)return!1;var t=s.a.shear(e);return Os.debug("set credentials for storage",t),t})).catch((function(e){return Os.warn("ensure credentials error",e),!1}))},e}();function Cs(e){return(Cs="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var Ts=function(){return(Ts=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},Ps=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},Ns=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},Rs=new r.a("AWSS3Provider"),Ls="undefined"!=typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("amplify_default"):"@@amplify_default",js=function(e,t,n,r,i){if(e){var s={attrs:n};r&&(s.metrics=r),o.a.dispatch("storage",{event:t,data:s,message:i},"Storage",Ls)}},Ds=function(){function e(e){this._config=e||{},Rs.debug("Storage Options",this._config)}return e.prototype.getCategory=function(){return e.CATEGORY},e.prototype.getProviderName=function(){return e.PROVIDER_NAME},e.prototype.configure=function(e){if(Rs.debug("configure Storage",e),!e)return this._config;var t=i.a.parseMobilehubConfig(e);return this._config=Object.assign({},this._config,t.Storage),this._config.bucket||Rs.debug("Do not have bucket yet"),this._config},e.prototype.get=function(e,t){return Ps(this,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,d,h,p,v,g,m,b,y,w,_,S,E;return Ns(this,(function(M){switch(M.label){case 0:return[4,this._ensureCredentials()];case 1:if(!M.sent())return[2,Promise.reject("No credentials")];if(n=Object.assign({},this._config,t),r=n.bucket,i=n.download,o=n.cacheControl,s=n.contentDisposition,a=n.contentEncoding,u=n.contentLanguage,c=n.contentType,f=n.expires,l=n.track,d=this._prefix(n),h=d+e,p=this._createNewS3Client(n),Rs.debug("get "+e+" from "+h),v={Bucket:r,Key:h},o&&(v.ResponseCacheControl=o),s&&(v.ResponseContentDisposition=s),a&&(v.ResponseContentEncoding=a),u&&(v.ResponseContentLanguage=u),c&&(v.ResponseContentType=c),!0!==i)return[3,5];g=new $i(v),M.label=2;case 2:return M.trys.push([2,4,,5]),[4,p.send(g)];case 3:return m=M.sent(),js(l,"download",{method:"get",result:"success"},{fileSize:Number(m.Body.size||m.Body.length)},"Download success for "+e),[2,m];case 4:throw b=M.sent(),js(l,"download",{method:"get",result:"failed"},null,"Download failed with "+b.message),b;case 5:v.Expires=f||900,M.label=6;case 6:return M.trys.push([6,9,,10]),y=new zo(Ts({},p.config)),[4,Bo(p,new $i(v))];case 7:return w=M.sent(),S=Uo,[4,y.presign(w,{expiresIn:v.Expires})];case 8:return _=S.apply(void 0,[M.sent()]),js(l,"getSignedUrl",{method:"get",result:"success"},null,"Signed URL: "+_),[2,_];case 9:throw E=M.sent(),Rs.warn("get signed url error",E),js(l,"getSignedUrl",{method:"get",result:"failed"},null,"Could not get a signed URL for "+e),E;case 10:return[2]}}))}))},e.prototype.put=function(e,t,n){return Ps(this,void 0,void 0,(function(){var r,i,o,s,a,u,c,f,l,d,h,p,v,g,m,b,y,w,_,S,E,M,A,I;return Ns(this,(function(k){switch(k.label){case 0:return[4,this._ensureCredentials()];case 1:if(!k.sent())return[2,Promise.reject("No credentials")];r=Object.assign({},this._config,n),i=r.bucket,o=r.track,s=r.progressCallback,a=r.contentType,u=r.contentDisposition,c=r.cacheControl,f=r.expires,l=r.metadata,d=r.tagging,h=r.acl,p=r.serverSideEncryption,v=r.SSECustomerAlgorithm,g=r.SSECustomerKey,m=r.SSECustomerKeyMD5,b=r.SSEKMSKeyId,y=a||"binary/octet-stream",w=this._prefix(r),_=w+e,Rs.debug("put "+e+" to "+_),S={Bucket:i,Key:_,Body:t,ContentType:y},c&&(S.CacheControl=c),u&&(S.ContentDisposition=u),f&&(S.Expires=f),l&&(S.Metadata=l),d&&(S.Tagging=d),p&&(S.ServerSideEncryption=p,v&&(S.SSECustomerAlgorithm=v),g&&(S.SSECustomerKey=g),m&&(S.SSECustomerKeyMD5=m),b&&(S.SSEKMSKeyId=b)),E=new ys.EventEmitter,M=new xs(S,r,E),h&&(S.ACL=h),k.label=2;case 2:return k.trys.push([2,4,,5]),E.on("sendProgress",(function(e){s&&("function"==typeof s?s(e):Rs.warn("progressCallback should be a function, not a "+Cs(s)))})),[4,M.upload()];case 3:return A=k.sent(),Rs.debug("upload result",A),js(o,"upload",{method:"put",result:"success"},null,"Upload success for "+e),[2,{key:e}];case 4:throw I=k.sent(),Rs.warn("error uploading",I),js(o,"upload",{method:"put",result:"failed"},null,"Error uploading "+e),I;case 5:return[2]}}))}))},e.prototype.remove=function(e,t){return Ps(this,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f;return Ns(this,(function(l){switch(l.label){case 0:return[4,this._ensureCredentials()];case 1:if(!l.sent())return[2,Promise.reject("No credentials")];n=Object.assign({},this._config,t),r=n.bucket,i=n.track,o=this._prefix(n),s=o+e,a=this._createNewS3Client(n),Rs.debug("remove "+e+" from "+s),u=new Yi({Bucket:r,Key:s}),l.label=2;case 2:return l.trys.push([2,4,,5]),[4,a.send(u)];case 3:return c=l.sent(),js(i,"delete",{method:"remove",result:"success"},null,"Deleted "+e+" successfully"),[2,c];case 4:throw f=l.sent(),js(i,"delete",{method:"remove",result:"failed"},null,"Deletion of "+e+" failed with "+f),f;case 5:return[2]}}))}))},e.prototype.list=function(e,t){return Ps(this,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,d;return Ns(this,(function(h){switch(h.label){case 0:return[4,this._ensureCredentials()];case 1:if(!h.sent())return[2,Promise.reject("No credentials")];n=Object.assign({},this._config,t),r=n.bucket,i=n.track,o=n.maxKeys,s=this._prefix(n),a=s+e,u=this._createNewS3Client(n),Rs.debug("list "+e+" from "+a),c=new Ji({Bucket:r,Prefix:a,MaxKeys:o}),h.label=2;case 2:return h.trys.push([2,4,,5]),[4,u.send(c)];case 3:return f=h.sent(),l=[],f&&f.Contents&&(l=f.Contents.map((function(e){return{key:e.Key.substr(s.length),eTag:e.ETag,lastModified:e.LastModified,size:e.Size}}))),js(i,"list",{method:"list",result:"success"},null,l.length+" items returned from list operation"),Rs.debug("list",l),[2,l];case 4:throw d=h.sent(),Rs.warn("list error",d),js(i,"list",{method:"list",result:"failed"},null,"Listing items failed: "+d.message),d;case 5:return[2]}}))}))},e.prototype._ensureCredentials=function(){var e=this;return s.a.get().then((function(t){if(!t)return!1;var n=s.a.shear(t);return Rs.debug("set credentials for storage",n),e._config.credentials=n,!0})).catch((function(e){return Rs.warn("ensure credentials error",e),!1}))},e.prototype._prefix=function(e){var t=e.credentials,n=e.level,r=e.customPrefix||{},i=e.identityId||t.identityId,o=(void 0!==r.private?r.private:"private/")+i+"/",s=(void 0!==r.protected?r.protected:"protected/")+i+"/",a=void 0!==r.public?r.public:"public/";switch(n){case"private":return o;case"protected":return s;default:return a}},e.prototype._createNewS3Client=function(e,t){var n=e.region,r=e.credentials,i={};return e.dangerouslyConnectToHttpEndpointForTesting&&(i={endpoint:"http://localhost:20005",tls:!1,bucketEndpoint:!1,forcePathStyle:!0}),new jo(Ts(Ts({region:n,credentials:r,customUserAgent:Object(a.b)()},i),{requestHandler:new Vo({},t)}))},e.CATEGORY="Storage",e.PROVIDER_NAME="AWSS3",e}(),Us=function(){return(Us=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},Bs=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},Fs=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},zs=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},qs=new r.a("StorageClass"),Ks=function(){function e(){this._config={},this._pluggables=[],qs.debug("Storage Options",this._config),this.get=this.get.bind(this),this.put=this.put.bind(this),this.remove=this.remove.bind(this),this.list=this.list.bind(this)}return e.prototype.getModuleName=function(){return"Storage"},e.prototype.addPluggable=function(e){if(e&&"Storage"===e.getCategory()){this._pluggables.push(e);return e.configure(this._config[e.getProviderName()])}},e.prototype.getPluggable=function(e){var t=this._pluggables.find((function(t){return t.getProviderName()===e}));return void 0===t?(qs.debug("No plugin found with providerName",e),null):t},e.prototype.removePluggable=function(e){this._pluggables=this._pluggables.filter((function(t){return t.getProviderName()!==e}))},e.prototype.configure=function(e){var t=this;if(qs.debug("configure Storage"),!e)return this._config;var n=i.a.parseMobilehubConfig(e),r=Object.keys(n.Storage),o=["bucket","region","level","track","customPrefix","serverSideEncryption","SSECustomerAlgorithm","SSECustomerKey","SSECustomerKeyMD5","SSEKMSKeyId"],s=function(e){return o.some((function(t){return t===e}))};return r&&r.find((function(e){return s(e)}))&&!n.Storage.AWSS3&&(n.Storage.AWSS3={}),Object.entries(n.Storage).map((function(e){var t=zs(e,2),r=t[0],i=t[1];r&&s(r)&&void 0!==i&&(n.Storage.AWSS3[r]=i,delete n.Storage[r])})),Object.keys(n.Storage).forEach((function(e){"string"!=typeof n.Storage[e]&&(t._config[e]=Us(Us({},t._config[e]),n.Storage[e]))})),this._pluggables.forEach((function(e){e.configure(t._config[e.getProviderName()])})),0===this._pluggables.length&&this.addPluggable(new Ds),this._config},e.prototype.get=function(e,t){return Bs(this,void 0,void 0,(function(){var n,r,i;return Fs(this,(function(o){return n=(t||{}).provider,r=void 0===n?"AWSS3":n,void 0===(i=this._pluggables.find((function(e){return e.getProviderName()===r})))&&(qs.debug("No plugin found with providerName",r),Promise.reject("No plugin found in Storage for the provider")),[2,i.get(e,t)]}))}))},e.prototype.put=function(e,t,n){return Bs(this,void 0,void 0,(function(){var r,i,o;return Fs(this,(function(s){return r=(n||{}).provider,i=void 0===r?"AWSS3":r,void 0===(o=this._pluggables.find((function(e){return e.getProviderName()===i})))&&(qs.debug("No plugin found with providerName",i),Promise.reject("No plugin found in Storage for the provider")),[2,o.put(e,t,n)]}))}))},e.prototype.remove=function(e,t){return Bs(this,void 0,void 0,(function(){var n,r,i;return Fs(this,(function(o){return n=(t||{}).provider,r=void 0===n?"AWSS3":n,void 0===(i=this._pluggables.find((function(e){return e.getProviderName()===r})))&&(qs.debug("No plugin found with providerName",r),Promise.reject("No plugin found in Storage for the provider")),[2,i.remove(e,t)]}))}))},e.prototype.list=function(e,t){return Bs(this,void 0,void 0,(function(){var n,r,i;return Fs(this,(function(o){return n=(t||{}).provider,r=void 0===n?"AWSS3":n,void 0===(i=this._pluggables.find((function(e){return e.getProviderName()===r})))&&(qs.debug("No plugin found with providerName",r),Promise.reject("No plugin found in Storage for the provider")),[2,i.list(e,t)]}))}))},e}(),Hs=n(19),Vs=function(){return(Vs=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},Gs=new r.a("Storage"),Ws=null,$s=function(){if(Ws)return Ws;Gs.debug("Create Storage Instance, debug"),(Ws=new Ks).vault=new Ks;var e=Ws.configure;return Ws.configure=function(t){Gs.debug("storage configure called");var n=Vs({},e.call(Ws,t));Object.keys(n).forEach((function(e){"string"!=typeof n[e]&&(n[e]=Vs(Vs({},n[e]),{level:"private"}))})),Gs.debug("storage vault configure called"),Ws.vault.configure(n)},Ws}();Hs.a.register($s)},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=new(n(44).a)("ClientDevice_Browser");function i(){return"undefined"==typeof window?{}:function(){if("undefined"==typeof window)return r.warn("No window object available to get browser client info"),{};var e=window.navigator;if(!e)return r.warn("No navigator object available to get browser client info"),{};var t=e.platform,n=e.product,i=e.vendor,o=e.userAgent,s=e.language,a=function(e){var t=/.+(Opera[\s[A-Z]*|OPR[\sA-Z]*)\/([0-9\.]+).*/i.exec(e);if(t)return{type:t[1],version:t[2]};var n=/.+(Trident|Edge)\/([0-9\.]+).*/i.exec(e);if(n)return{type:n[1],version:n[2]};var r=/.+(Chrome|Firefox|FxiOS)\/([0-9\.]+).*/i.exec(e);if(r)return{type:r[1],version:r[2]};var i=/.+(Safari)\/([0-9\.]+).*/i.exec(e);if(i)return{type:i[1],version:i[2]};var o=/.+(AppleWebKit)\/([0-9\.]+).*/i.exec(e);if(o)return{type:o[1],version:o[2]};var s=/.*([A-Z]+)\/([0-9\.]+).*/i.exec(e);if(s)return{type:s[1],version:s[2]};return{type:"",version:""}}(o),u=(c=/\(([A-Za-z\s].*)\)/.exec((new Date).toString()),c&&c[1]||"");var c;return{platform:t,make:n||i,model:a.type,version:a.version,appVersion:[a.type,a.version].join("/"),language:s,timezone:u}}()}var o=function(){function e(){}return e.clientInfo=function(){return i()},e.dimension=function(){return"undefined"==typeof window?(r.warn("No window object available to get browser client info"),{width:320,height:320}):{width:window.innerWidth,height:window.innerHeight}},e}()},function(e,t,n){"use strict";n.d(t,"a",(function(){return f}));var r=n(44),i=new r.a("I18n"),o=function(){function e(e){this._options=null,this._lang=null,this._dict={},this._options=Object.assign({},e),this._lang=this._options.language,!this._lang&&"undefined"!=typeof window&&window&&window.navigator&&(this._lang=window.navigator.language),i.debug(this._lang)}return e.prototype.setLanguage=function(e){this._lang=e},e.prototype.get=function(e,t){if(void 0===t&&(t=void 0),!this._lang)return void 0!==t?t:e;var n=this._lang,r=this.getByLanguage(e,n);return r||(n.indexOf("-")>0&&(r=this.getByLanguage(e,n.split("-")[0])),r||(void 0!==t?t:e))},e.prototype.getByLanguage=function(e,t,n){if(void 0===n&&(n=null),!t)return n;var r=this._dict[t];return r?r[e]:n},e.prototype.putVocabulariesForLanguage=function(e,t){var n=this._dict[e];n||(n=this._dict[e]={}),Object.assign(n,t)},e.prototype.putVocabularies=function(e){var t=this;Object.keys(e).map((function(n){t.putVocabulariesForLanguage(n,e[n])}))},e}(),s=n(19),a=new r.a("I18n"),u=null,c=null,f=function(){function e(){}return e.configure=function(t){return a.debug("configure I18n"),t?(u=Object.assign({},u,t.I18n||t),e.createInstance(),u):u},e.getModuleName=function(){return"I18n"},e.createInstance=function(){a.debug("create I18n instance"),c||(c=new o(u))},e.setLanguage=function(t){return e.checkConfig(),c.setLanguage(t)},e.get=function(t,n){return e.checkConfig()?c.get(t,n):void 0===n?t:n},e.putVocabulariesForLanguage=function(t,n){return e.checkConfig(),c.putVocabulariesForLanguage(t,n)},e.putVocabularies=function(t){return e.checkConfig(),c.putVocabularies(t)},e.checkConfig=function(){return c||(c=new o(u)),!0},e}();s.a.register(f)},function(e,t,n){"use strict";n.d(t,"a",(function(){return a}));var r=n(44),i=n(33),o=n(19);function s(e){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=function(){function e(){this._logger=new r.a("ServiceWorker")}return Object.defineProperty(e.prototype,"serviceWorker",{get:function(){return this._serviceWorker},enumerable:!0,configurable:!0}),e.prototype.register=function(e,t){var n=this;return void 0===e&&(e="/service-worker.js"),void 0===t&&(t="/"),this._logger.debug("registering "+e),this._logger.debug("registering service worker with scope "+t),new Promise((function(r,i){if(!navigator||!("serviceWorker"in navigator))return i(new Error("Service Worker not available"));navigator.serviceWorker.register(e,{scope:t}).then((function(e){return e.installing?n._serviceWorker=e.installing:e.waiting?n._serviceWorker=e.waiting:e.active&&(n._serviceWorker=e.active),n._registration=e,n._setupListeners(),n._logger.debug("Service Worker Registration Success: "+e),r(e)})).catch((function(e){return n._logger.debug("Service Worker Registration Failed "+e),i(e)}))}))},e.prototype.enablePush=function(e){var t=this;if(!this._registration)throw new Error("Service Worker not registered");return this._publicKey=e,new Promise((function(n,r){if(!Object(i.b)().isBrowser)return r(new Error("Service Worker not available"));t._registration.pushManager.getSubscription().then((function(r){if(!r)return t._logger.debug("User is NOT subscribed to push"),t._registration.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:t._urlB64ToUint8Array(e)}).then((function(e){t._subscription=e,t._logger.debug("User subscribed: "+JSON.stringify(e)),n(e)})).catch((function(e){t._logger.error(e)}));t._subscription=r,t._logger.debug("User is subscribed to push: "+JSON.stringify(r)),n(r)}))}))},e.prototype._urlB64ToUint8Array=function(e){for(var t=(e+"=".repeat((4-e.length%4)%4)).replace(/\-/g,"+").replace(/_/g,"/"),n=window.atob(t),r=new Uint8Array(n.length),i=0;i<n.length;++i)r[i]=n.charCodeAt(i);return r},e.prototype.send=function(e){this._serviceWorker&&this._serviceWorker.postMessage("object"===s(e)?JSON.stringify(e):e)},e.prototype._setupListeners=function(){var e=this;this._serviceWorker.addEventListener("statechange",(function(t){var n=e._serviceWorker.state;e._logger.debug("ServiceWorker statechange: "+n),o.a.Analytics&&"function"==typeof o.a.Analytics.record&&o.a.Analytics.record({name:"ServiceWorker",attributes:{state:n}})})),this._serviceWorker.addEventListener("message",(function(t){e._logger.debug("ServiceWorker message event: "+t)}))},e}()},function(e,t,n){"use strict";n.d(t,"a",(function(){return dr}));var r=n(88),i=n(44),o=n(141),s=n(104),a=n(33),u=n(50),c=n(89),f=function(e,t){return(f=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function l(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}f(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var d=function(){return(d=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function h(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))}function p(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}}Object.create;function v(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s}var g,m,b,y,w,_,S,E,M,A,I,k,O,x,C,T,P,N,R,L,j,D,U,B,F,z,q,K,H,V,G,W,$,Y,J,Z,X,Q,ee,te,ne,re,ie,oe,se,ae,ue,ce,fe,le,de,he,pe,ve,ge,me,be,ye,we,_e,Se,Ee,Me,Ae,Ie,ke,Oe,xe,Ce,Te,Pe,Ne,Re,Le,je,De,Ue,Be,Fe,ze,qe,Ke,He,Ve,Ge,We,$e,Ye,Je,Ze,Xe,Qe,et,tt,nt,rt,it,ot,st,at,ut,ct,ft,lt,dt,ht,pt,vt,gt,mt,bt,yt,wt,_t,St,Et,Mt,At,It,kt,Ot,xt,Ct,Tt,Pt,Nt,Rt,Lt,jt,Dt,Ut;Object.create;(g||(g={})).filterSensitiveLog=function(e){return d({},e)},(m||(m={})).filterSensitiveLog=function(e){return d({},e)},(b||(b={})).filterSensitiveLog=function(e){return d({},e)},(y||(y={})).filterSensitiveLog=function(e){return d({},e)},(w||(w={})).filterSensitiveLog=function(e){return d({},e)},(_||(_={})).filterSensitiveLog=function(e){return d({},e)},(S||(S={})).filterSensitiveLog=function(e){return d({},e)},(E||(E={})).filterSensitiveLog=function(e){return d({},e)},(M||(M={})).filterSensitiveLog=function(e){return d({},e)},(A||(A={})).filterSensitiveLog=function(e){return d({},e)},(I||(I={})).filterSensitiveLog=function(e){return d({},e)},(k||(k={})).filterSensitiveLog=function(e){return d({},e)},(O||(O={})).filterSensitiveLog=function(e){return d({},e)},(x||(x={})).filterSensitiveLog=function(e){return d({},e)},(C||(C={})).filterSensitiveLog=function(e){return d({},e)},(T||(T={})).filterSensitiveLog=function(e){return d({},e)},(P||(P={})).filterSensitiveLog=function(e){return d({},e)},(N||(N={})).filterSensitiveLog=function(e){return d({},e)},(R||(R={})).filterSensitiveLog=function(e){return d({},e)},(L||(L={})).filterSensitiveLog=function(e){return d({},e)},(j||(j={})).filterSensitiveLog=function(e){return d({},e)},(D||(D={})).filterSensitiveLog=function(e){return d({},e)},(U||(U={})).filterSensitiveLog=function(e){return d({},e)},(B||(B={})).filterSensitiveLog=function(e){return d({},e)},(F||(F={})).filterSensitiveLog=function(e){return d({},e)},(z||(z={})).filterSensitiveLog=function(e){return d({},e)},(q||(q={})).filterSensitiveLog=function(e){return d({},e)},(K||(K={})).filterSensitiveLog=function(e){return d({},e)},(H||(H={})).filterSensitiveLog=function(e){return d({},e)},(V||(V={})).filterSensitiveLog=function(e){return d({},e)},(G||(G={})).filterSensitiveLog=function(e){return d({},e)},(W||(W={})).filterSensitiveLog=function(e){return d({},e)},($||($={})).filterSensitiveLog=function(e){return d({},e)},(Y||(Y={})).filterSensitiveLog=function(e){return d({},e)},(J||(J={})).filterSensitiveLog=function(e){return d({},e)},(Z||(Z={})).filterSensitiveLog=function(e){return d({},e)},(X||(X={})).filterSensitiveLog=function(e){return d({},e)},(Q||(Q={})).filterSensitiveLog=function(e){return d({},e)},(ee||(ee={})).filterSensitiveLog=function(e){return d({},e)},(te||(te={})).filterSensitiveLog=function(e){return d({},e)},(ne||(ne={})).filterSensitiveLog=function(e){return d({},e)},(re||(re={})).filterSensitiveLog=function(e){return d({},e)},(ie||(ie={})).filterSensitiveLog=function(e){return d({},e)},(oe||(oe={})).filterSensitiveLog=function(e){return d({},e)},(se||(se={})).filterSensitiveLog=function(e){return d({},e)},(ae||(ae={})).filterSensitiveLog=function(e){return d({},e)},(ue||(ue={})).filterSensitiveLog=function(e){return d({},e)},(ce||(ce={})).filterSensitiveLog=function(e){return d({},e)},(fe||(fe={})).filterSensitiveLog=function(e){return d({},e)},(le||(le={})).filterSensitiveLog=function(e){return d({},e)},(de||(de={})).filterSensitiveLog=function(e){return d({},e)},(he||(he={})).filterSensitiveLog=function(e){return d({},e)},(pe||(pe={})).filterSensitiveLog=function(e){return d({},e)},(ve||(ve={})).filterSensitiveLog=function(e){return d({},e)},(ge||(ge={})).filterSensitiveLog=function(e){return d({},e)},(me||(me={})).filterSensitiveLog=function(e){return d({},e)},(be||(be={})).filterSensitiveLog=function(e){return d({},e)},(ye||(ye={})).filterSensitiveLog=function(e){return d({},e)},(we||(we={})).filterSensitiveLog=function(e){return d({},e)},(_e||(_e={})).filterSensitiveLog=function(e){return d({},e)},(Se||(Se={})).filterSensitiveLog=function(e){return d({},e)},(Ee||(Ee={})).filterSensitiveLog=function(e){return d({},e)},(Me||(Me={})).filterSensitiveLog=function(e){return d({},e)},(Ae||(Ae={})).filterSensitiveLog=function(e){return d({},e)},(Ie||(Ie={})).filterSensitiveLog=function(e){return d({},e)},(ke||(ke={})).filterSensitiveLog=function(e){return d({},e)},(Oe||(Oe={})).filterSensitiveLog=function(e){return d({},e)},(xe||(xe={})).filterSensitiveLog=function(e){return d({},e)},(Ce||(Ce={})).filterSensitiveLog=function(e){return d({},e)},(Te||(Te={})).filterSensitiveLog=function(e){return d({},e)},(Pe||(Pe={})).filterSensitiveLog=function(e){return d({},e)},(Ne||(Ne={})).filterSensitiveLog=function(e){return d({},e)},(Re||(Re={})).filterSensitiveLog=function(e){return d({},e)},(Le||(Le={})).filterSensitiveLog=function(e){return d({},e)},(je||(je={})).filterSensitiveLog=function(e){return d({},e)},(De||(De={})).filterSensitiveLog=function(e){return d({},e)},(Ue||(Ue={})).filterSensitiveLog=function(e){return d({},e)},(Be||(Be={})).filterSensitiveLog=function(e){return d({},e)},(Fe||(Fe={})).filterSensitiveLog=function(e){return d({},e)},(ze||(ze={})).filterSensitiveLog=function(e){return d({},e)},(qe||(qe={})).filterSensitiveLog=function(e){return d({},e)},(Ke||(Ke={})).filterSensitiveLog=function(e){return d({},e)},(He||(He={})).filterSensitiveLog=function(e){return d({},e)},(Ve||(Ve={})).filterSensitiveLog=function(e){return d({},e)},(Ge||(Ge={})).filterSensitiveLog=function(e){return d({},e)},(We||(We={})).filterSensitiveLog=function(e){return d({},e)},($e||($e={})).filterSensitiveLog=function(e){return d({},e)},(Ye||(Ye={})).filterSensitiveLog=function(e){return d({},e)},(Je||(Je={})).filterSensitiveLog=function(e){return d({},e)},(Ze||(Ze={})).filterSensitiveLog=function(e){return d({},e)},(Xe||(Xe={})).filterSensitiveLog=function(e){return d({},e)},(Qe||(Qe={})).filterSensitiveLog=function(e){return d({},e)},(et||(et={})).filterSensitiveLog=function(e){return d({},e)},(tt||(tt={})).filterSensitiveLog=function(e){return d({},e)},(nt||(nt={})).filterSensitiveLog=function(e){return d({},e)},(rt||(rt={})).filterSensitiveLog=function(e){return d({},e)},(it||(it={})).filterSensitiveLog=function(e){return d({},e)},(ot||(ot={})).filterSensitiveLog=function(e){return d({},e)},(st||(st={})).filterSensitiveLog=function(e){return d({},e)},(at||(at={})).filterSensitiveLog=function(e){return d({},e)},(ut||(ut={})).filterSensitiveLog=function(e){return d({},e)},(ct||(ct={})).filterSensitiveLog=function(e){return d({},e)},(ft||(ft={})).filterSensitiveLog=function(e){return d({},e)},(lt||(lt={})).filterSensitiveLog=function(e){return d({},e)},(dt||(dt={})).filterSensitiveLog=function(e){return d({},e)},(ht||(ht={})).filterSensitiveLog=function(e){return d({},e)},(pt||(pt={})).filterSensitiveLog=function(e){return d({},e)},(vt||(vt={})).filterSensitiveLog=function(e){return d({},e)},(gt||(gt={})).filterSensitiveLog=function(e){return d({},e)},(mt||(mt={})).filterSensitiveLog=function(e){return d({},e)},(bt||(bt={})).filterSensitiveLog=function(e){return d({},e)},(yt||(yt={})).filterSensitiveLog=function(e){return d({},e)},(wt||(wt={})).filterSensitiveLog=function(e){return d({},e)},(_t||(_t={})).filterSensitiveLog=function(e){return d({},e)},(St||(St={})).filterSensitiveLog=function(e){return d({},e)},(Et||(Et={})).filterSensitiveLog=function(e){return d({},e)},(Mt||(Mt={})).filterSensitiveLog=function(e){return d({},e)},(At||(At={})).filterSensitiveLog=function(e){return d({},e)},(It||(It={})).filterSensitiveLog=function(e){return d({},e)},(kt||(kt={})).filterSensitiveLog=function(e){return d({},e)},(Ot||(Ot={})).filterSensitiveLog=function(e){return d({},e)},(xt||(xt={})).filterSensitiveLog=function(e){return d({},e)},(Ct||(Ct={})).filterSensitiveLog=function(e){return d({},e)},(Tt||(Tt={})).filterSensitiveLog=function(e){return d({},e)},(Pt||(Pt={})).filterSensitiveLog=function(e){return d({},e)},(Nt||(Nt={})).filterSensitiveLog=function(e){return d({},e)},(Rt||(Rt={})).filterSensitiveLog=function(e){return d({},e)},(Lt||(Lt={})).filterSensitiveLog=function(e){return d({},e)},(jt||(jt={})).filterSensitiveLog=function(e){return d({},e)},(Dt||(Dt={})).filterSensitiveLog=function(e){return d({},e)},(Ut||(Ut={})).filterSensitiveLog=function(e){return d({},e)};var Bt=n(2),Ft=n(0),zt=function(e,t){return h(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,h,v,g,m;return p(this,(function(p){switch(p.label){case 0:return r=[d({},e)],m={},[4,mn(e.body,t)];case 1:switch(n=d.apply(void 0,r.concat([(m.body=p.sent(),m)])),o="UnknownError",o=bn(e,n.body),o){case"BadRequestException":case"com.amazonaws.pinpoint#BadRequestException":return[3,2];case"ForbiddenException":case"com.amazonaws.pinpoint#ForbiddenException":return[3,4];case"InternalServerErrorException":case"com.amazonaws.pinpoint#InternalServerErrorException":return[3,6];case"MethodNotAllowedException":case"com.amazonaws.pinpoint#MethodNotAllowedException":return[3,8];case"NotFoundException":case"com.amazonaws.pinpoint#NotFoundException":return[3,10];case"PayloadTooLargeException":case"com.amazonaws.pinpoint#PayloadTooLargeException":return[3,12];case"TooManyRequestsException":case"com.amazonaws.pinpoint#TooManyRequestsException":return[3,14]}return[3,16];case 2:return s=[{}],[4,Kt(n,t)];case 3:return i=d.apply(void 0,[d.apply(void 0,s.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 4:return a=[{}],[4,Ht(n,t)];case 5:return i=d.apply(void 0,[d.apply(void 0,a.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 6:return u=[{}],[4,Vt(n,t)];case 7:return i=d.apply(void 0,[d.apply(void 0,u.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 8:return c=[{}],[4,Gt(n,t)];case 9:return i=d.apply(void 0,[d.apply(void 0,c.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 10:return f=[{}],[4,Wt(n,t)];case 11:return i=d.apply(void 0,[d.apply(void 0,f.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 12:return l=[{}],[4,$t(n,t)];case 13:return i=d.apply(void 0,[d.apply(void 0,l.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 14:return h=[{}],[4,Yt(n,t)];case 15:return i=d.apply(void 0,[d.apply(void 0,h.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 16:v=n.body,o=v.code||v.Code||o,i=d(d({},v),{name:""+o,message:v.message||v.Message||o,$fault:"client",$metadata:vn(e)}),p.label=17;case 17:return g=i.message||i.Message||o,i.message=g,delete i.Message,[2,Promise.reject(Object.assign(new Error(g),i))]}}))}))},qt=function(e,t){return h(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,h,v,g,m;return p(this,(function(p){switch(p.label){case 0:return r=[d({},e)],m={},[4,mn(e.body,t)];case 1:switch(n=d.apply(void 0,r.concat([(m.body=p.sent(),m)])),o="UnknownError",o=bn(e,n.body),o){case"BadRequestException":case"com.amazonaws.pinpoint#BadRequestException":return[3,2];case"ForbiddenException":case"com.amazonaws.pinpoint#ForbiddenException":return[3,4];case"InternalServerErrorException":case"com.amazonaws.pinpoint#InternalServerErrorException":return[3,6];case"MethodNotAllowedException":case"com.amazonaws.pinpoint#MethodNotAllowedException":return[3,8];case"NotFoundException":case"com.amazonaws.pinpoint#NotFoundException":return[3,10];case"PayloadTooLargeException":case"com.amazonaws.pinpoint#PayloadTooLargeException":return[3,12];case"TooManyRequestsException":case"com.amazonaws.pinpoint#TooManyRequestsException":return[3,14]}return[3,16];case 2:return s=[{}],[4,Kt(n,t)];case 3:return i=d.apply(void 0,[d.apply(void 0,s.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 4:return a=[{}],[4,Ht(n,t)];case 5:return i=d.apply(void 0,[d.apply(void 0,a.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 6:return u=[{}],[4,Vt(n,t)];case 7:return i=d.apply(void 0,[d.apply(void 0,u.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 8:return c=[{}],[4,Gt(n,t)];case 9:return i=d.apply(void 0,[d.apply(void 0,c.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 10:return f=[{}],[4,Wt(n,t)];case 11:return i=d.apply(void 0,[d.apply(void 0,f.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 12:return l=[{}],[4,$t(n,t)];case 13:return i=d.apply(void 0,[d.apply(void 0,l.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 14:return h=[{}],[4,Yt(n,t)];case 15:return i=d.apply(void 0,[d.apply(void 0,h.concat([p.sent()])),{name:o,$metadata:vn(e)}]),[3,17];case 16:v=n.body,o=v.code||v.Code||o,i=d(d({},v),{name:""+o,message:v.message||v.Message||o,$fault:"client",$metadata:vn(e)}),p.label=17;case 17:return g=i.message||i.Message||o,i.message=g,delete i.Message,[2,Promise.reject(Object.assign(new Error(g),i))]}}))}))},Kt=function(e,t){return h(void 0,void 0,void 0,(function(){var t,n;return p(this,(function(r){return t={name:"BadRequestException",$fault:"client",$metadata:vn(e),Message:void 0,RequestID:void 0},void 0!==(n=e.body).Message&&null!==n.Message&&(t.Message=n.Message),void 0!==n.RequestID&&null!==n.RequestID&&(t.RequestID=n.RequestID),[2,t]}))}))},Ht=function(e,t){return h(void 0,void 0,void 0,(function(){var t,n;return p(this,(function(r){return t={name:"ForbiddenException",$fault:"client",$metadata:vn(e),Message:void 0,RequestID:void 0},void 0!==(n=e.body).Message&&null!==n.Message&&(t.Message=n.Message),void 0!==n.RequestID&&null!==n.RequestID&&(t.RequestID=n.RequestID),[2,t]}))}))},Vt=function(e,t){return h(void 0,void 0,void 0,(function(){var t,n;return p(this,(function(r){return t={name:"InternalServerErrorException",$fault:"server",$metadata:vn(e),Message:void 0,RequestID:void 0},void 0!==(n=e.body).Message&&null!==n.Message&&(t.Message=n.Message),void 0!==n.RequestID&&null!==n.RequestID&&(t.RequestID=n.RequestID),[2,t]}))}))},Gt=function(e,t){return h(void 0,void 0,void 0,(function(){var t,n;return p(this,(function(r){return t={name:"MethodNotAllowedException",$fault:"client",$metadata:vn(e),Message:void 0,RequestID:void 0},void 0!==(n=e.body).Message&&null!==n.Message&&(t.Message=n.Message),void 0!==n.RequestID&&null!==n.RequestID&&(t.RequestID=n.RequestID),[2,t]}))}))},Wt=function(e,t){return h(void 0,void 0,void 0,(function(){var t,n;return p(this,(function(r){return t={name:"NotFoundException",$fault:"client",$metadata:vn(e),Message:void 0,RequestID:void 0},void 0!==(n=e.body).Message&&null!==n.Message&&(t.Message=n.Message),void 0!==n.RequestID&&null!==n.RequestID&&(t.RequestID=n.RequestID),[2,t]}))}))},$t=function(e,t){return h(void 0,void 0,void 0,(function(){var t,n;return p(this,(function(r){return t={name:"PayloadTooLargeException",$fault:"client",$metadata:vn(e),Message:void 0,RequestID:void 0},void 0!==(n=e.body).Message&&null!==n.Message&&(t.Message=n.Message),void 0!==n.RequestID&&null!==n.RequestID&&(t.RequestID=n.RequestID),[2,t]}))}))},Yt=function(e,t){return h(void 0,void 0,void 0,(function(){var t,n;return p(this,(function(r){return t={name:"TooManyRequestsException",$fault:"client",$metadata:vn(e),Message:void 0,RequestID:void 0},void 0!==(n=e.body).Message&&null!==n.Message&&(t.Message=n.Message),void 0!==n.RequestID&&null!==n.RequestID&&(t.RequestID=n.RequestID),[2,t]}))}))},Jt=function(e,t){return d(d(d(d(d(d(d(d({},void 0!==e.AppVersion&&{AppVersion:e.AppVersion}),void 0!==e.Locale&&{Locale:e.Locale}),void 0!==e.Make&&{Make:e.Make}),void 0!==e.Model&&{Model:e.Model}),void 0!==e.ModelVersion&&{ModelVersion:e.ModelVersion}),void 0!==e.Platform&&{Platform:e.Platform}),void 0!==e.PlatformVersion&&{PlatformVersion:e.PlatformVersion}),void 0!==e.Timezone&&{Timezone:e.Timezone})},Zt=function(e,t){return d(d(d(d(d(d({},void 0!==e.City&&{City:e.City}),void 0!==e.Country&&{Country:e.Country}),void 0!==e.Latitude&&{Latitude:e.Latitude}),void 0!==e.Longitude&&{Longitude:e.Longitude}),void 0!==e.PostalCode&&{PostalCode:e.PostalCode}),void 0!==e.Region&&{Region:e.Region})},Xt=function(e,t){return d(d(d(d(d(d(d(d(d(d(d({},void 0!==e.Address&&{Address:e.Address}),void 0!==e.Attributes&&{Attributes:an(e.Attributes,t)}),void 0!==e.ChannelType&&{ChannelType:e.ChannelType}),void 0!==e.Demographic&&{Demographic:Jt(e.Demographic,t)}),void 0!==e.EffectiveDate&&{EffectiveDate:e.EffectiveDate}),void 0!==e.EndpointStatus&&{EndpointStatus:e.EndpointStatus}),void 0!==e.Location&&{Location:Zt(e.Location,t)}),void 0!==e.Metrics&&{Metrics:nn(e.Metrics,t)}),void 0!==e.OptOut&&{OptOut:e.OptOut}),void 0!==e.RequestId&&{RequestId:e.RequestId}),void 0!==e.User&&{User:Qt(e.User,t)})},Qt=function(e,t){return d(d({},void 0!==e.UserAttributes&&{UserAttributes:an(e.UserAttributes,t)}),void 0!==e.UserId&&{UserId:e.UserId})},en=function(e,t){return d({},void 0!==e.BatchItem&&{BatchItem:sn(e.BatchItem,t)})},tn=function(e,t){return e.map((function(e){return e}))},nn=function(e,t){return Object.entries(e).reduce((function(e,t){var n,r=v(t,2),i=r[0],o=r[1];return d(d({},e),((n={})[i]=o,n))}),{})},rn=function(e,t){return Object.entries(e).reduce((function(e,t){var n,r=v(t,2),i=r[0],o=r[1];return d(d({},e),((n={})[i]=o,n))}),{})},on=function(e,t){return Object.entries(e).reduce((function(e,n){var r,i=v(n,2),o=i[0],s=i[1];return d(d({},e),((r={})[o]=function(e,t){return d(d(d(d(d(d(d(d(d(d({},void 0!==e.AppPackageName&&{AppPackageName:e.AppPackageName}),void 0!==e.AppTitle&&{AppTitle:e.AppTitle}),void 0!==e.AppVersionCode&&{AppVersionCode:e.AppVersionCode}),void 0!==e.Attributes&&{Attributes:rn(e.Attributes,t)}),void 0!==e.ClientSdkVersion&&{ClientSdkVersion:e.ClientSdkVersion}),void 0!==e.EventType&&{EventType:e.EventType}),void 0!==e.Metrics&&{Metrics:nn(e.Metrics,t)}),void 0!==e.SdkName&&{SdkName:e.SdkName}),void 0!==e.Session&&{Session:cn(e.Session,t)}),void 0!==e.Timestamp&&{Timestamp:e.Timestamp})}(s,t),r))}),{})},sn=function(e,t){return Object.entries(e).reduce((function(e,n){var r,i=v(n,2),o=i[0],s=i[1];return d(d({},e),((r={})[o]=function(e,t){return d(d({},void 0!==e.Endpoint&&{Endpoint:un(e.Endpoint,t)}),void 0!==e.Events&&{Events:on(e.Events,t)})}(s,t),r))}),{})},an=function(e,t){return Object.entries(e).reduce((function(e,n){var r,i=v(n,2),o=i[0],s=i[1];return d(d({},e),((r={})[o]=tn(s,t),r))}),{})},un=function(e,t){return d(d(d(d(d(d(d(d(d(d(d({},void 0!==e.Address&&{Address:e.Address}),void 0!==e.Attributes&&{Attributes:an(e.Attributes,t)}),void 0!==e.ChannelType&&{ChannelType:e.ChannelType}),void 0!==e.Demographic&&{Demographic:Jt(e.Demographic,t)}),void 0!==e.EffectiveDate&&{EffectiveDate:e.EffectiveDate}),void 0!==e.EndpointStatus&&{EndpointStatus:e.EndpointStatus}),void 0!==e.Location&&{Location:Zt(e.Location,t)}),void 0!==e.Metrics&&{Metrics:nn(e.Metrics,t)}),void 0!==e.OptOut&&{OptOut:e.OptOut}),void 0!==e.RequestId&&{RequestId:e.RequestId}),void 0!==e.User&&{User:Qt(e.User,t)})},cn=function(e,t){return d(d(d(d({},void 0!==e.Duration&&{Duration:e.Duration}),void 0!==e.Id&&{Id:e.Id}),void 0!==e.StartTimestamp&&{StartTimestamp:e.StartTimestamp}),void 0!==e.StopTimestamp&&{StopTimestamp:e.StopTimestamp})},fn=function(e,t){return{Message:void 0!==e.Message&&null!==e.Message?e.Message:void 0,StatusCode:void 0!==e.StatusCode&&null!==e.StatusCode?e.StatusCode:void 0}},ln=function(e,t){return{Results:void 0!==e.Results&&null!==e.Results?hn(e.Results,t):void 0}},dn=function(e,t){return Object.entries(e).reduce((function(e,t){var n,r=v(t,2),i=r[0],o=r[1];return d(d({},e),((n={})[i]=function(e,t){return{Message:void 0!==e.Message&&null!==e.Message?e.Message:void 0,StatusCode:void 0!==e.StatusCode&&null!==e.StatusCode?e.StatusCode:void 0}}(o),n))}),{})},hn=function(e,t){return Object.entries(e).reduce((function(e,n){var r,i=v(n,2),o=i[0],s=i[1];return d(d({},e),((r={})[o]=function(e,t){return{EndpointItemResponse:void 0!==e.EndpointItemResponse&&null!==e.EndpointItemResponse?fn(e.EndpointItemResponse):void 0,EventsItemResponse:void 0!==e.EventsItemResponse&&null!==e.EventsItemResponse?dn(e.EventsItemResponse,t):void 0}}(s,t),r))}),{})},pn=function(e,t){return{Message:void 0!==e.Message&&null!==e.Message?e.Message:void 0,RequestID:void 0!==e.RequestID&&null!==e.RequestID?e.RequestID:void 0}},vn=function(e){return{httpStatusCode:e.statusCode,httpHeaders:e.headers,requestId:e.headers["x-amzn-requestid"]}},gn=function(e,t){return void 0===e&&(e=new Uint8Array),e instanceof Uint8Array?Promise.resolve(e):t.streamCollector(e)||Promise.resolve(new Uint8Array)},mn=function(e,t){return function(e,t){return gn(e,t).then((function(e){return t.utf8Encoder(e)}))}(e,t).then((function(e){return e.length?JSON.parse(e):{}}))},bn=function(e,t){var n,r,i=function(e){var t=e;return t.indexOf(":")>=0&&(t=t.split(":")[0]),t.indexOf("#")>=0&&(t=t.split("#")[1]),t},o=(n=e.headers,r="x-amzn-errortype",Object.keys(n).find((function(e){return e.toLowerCase()===r.toLowerCase()})));return void 0!==o?i(e.headers[o]):void 0!==t.code?i(t.code):void 0!==t.__type?i(t.__type):""},yn=n(10),wn=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return l(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(yn.a)(t,this.serialize,this.deserialize));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"PinpointClient",commandName:"PutEventsCommand",inputFilterSensitiveLog:Ie.filterSensitiveLog,outputFilterSensitiveLog:ke.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"PinpointClient",commandName:"PutEventsCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return h(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f;return p(this,(function(l){switch(l.label){case 0:if(n={"Content-Type":"application/json"},r="/v1/apps/{ApplicationId}/events",void 0===e.ApplicationId)throw new Error("No value provided for input HTTP label: ApplicationId.");if((i=e.ApplicationId).length<=0)throw new Error("Empty value provided for input HTTP label: ApplicationId.");return r=r.replace("{ApplicationId}",Object(Ft.f)(i)),void 0!==e.EventsRequest&&(o=en(e.EventsRequest,t)),void 0===o&&(o={}),o=JSON.stringify(o),[4,t.endpoint()];case 1:return s=l.sent(),a=s.hostname,u=s.protocol,c=void 0===u?"https":u,f=s.port,[2,new Bt.a({protocol:c,hostname:a,port:f,method:"POST",headers:n,path:r,body:o})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return h(void 0,void 0,void 0,(function(){var n,r;return p(this,(function(i){switch(i.label){case 0:return 202!==e.statusCode&&e.statusCode>=300?[2,zt(e,t)]:(n={$metadata:vn(e),EventsResponse:void 0},[4,mn(e.body,t)]);case 1:return r=i.sent(),n.EventsResponse=ln(r,t),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(Ft.b),_n=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return l(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(yn.a)(t,this.serialize,this.deserialize));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"PinpointClient",commandName:"UpdateEndpointCommand",inputFilterSensitiveLog:ct.filterSensitiveLog,outputFilterSensitiveLog:ft.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"PinpointClient",commandName:"UpdateEndpointCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return h(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f;return p(this,(function(l){switch(l.label){case 0:if(n={"Content-Type":"application/json"},r="/v1/apps/{ApplicationId}/endpoints/{EndpointId}",void 0===e.ApplicationId)throw new Error("No value provided for input HTTP label: ApplicationId.");if((i=e.ApplicationId).length<=0)throw new Error("Empty value provided for input HTTP label: ApplicationId.");if(r=r.replace("{ApplicationId}",Object(Ft.f)(i)),void 0===e.EndpointId)throw new Error("No value provided for input HTTP label: EndpointId.");if((i=e.EndpointId).length<=0)throw new Error("Empty value provided for input HTTP label: EndpointId.");return r=r.replace("{EndpointId}",Object(Ft.f)(i)),void 0!==e.EndpointRequest&&(o=Xt(e.EndpointRequest,t)),void 0===o&&(o={}),o=JSON.stringify(o),[4,t.endpoint()];case 1:return s=l.sent(),a=s.hostname,u=s.protocol,c=void 0===u?"https":u,f=s.port,[2,new Bt.a({protocol:c,hostname:a,port:f,method:"PUT",headers:n,path:r,body:o})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return h(void 0,void 0,void 0,(function(){var n,r;return p(this,(function(i){switch(i.label){case 0:return 202!==e.statusCode&&e.statusCode>=300?[2,qt(e,t)]:(n={$metadata:vn(e),MessageBody:void 0},[4,mn(e.body,t)]);case 1:return r=i.sent(),n.MessageBody=pn(r,t),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(Ft.b),Sn=n(149),En=n(38),Mn=n(18),An=n(24),In=n(11),kn=n(39),On=n(17),xn=n(40),Cn=n(41),Tn=n(15),Pn=new Set(["ap-east-1","ap-northeast-1","ap-northeast-2","ap-south-1","ap-southeast-1","ap-southeast-2","ca-central-1","eu-central-1","eu-north-1","eu-west-1","eu-west-2","eu-west-3","me-south-1","sa-east-1","us-east-1","us-east-2","us-west-1","us-west-2"]),Nn=new Set(["cn-north-1","cn-northwest-1"]),Rn=new Set(["us-iso-east-1"]),Ln=new Set(["us-isob-east-1"]),jn=new Set(["us-gov-east-1","us-gov-west-1"]),Dn=d(d({},{apiVersion:"2016-12-01",disableHostPrefix:!1,logger:{},regionInfoProvider:function(e,t){var n=void 0;switch(e){case"ap-south-1":n={hostname:"pinpoint.ap-south-1.amazonaws.com",partition:"aws",signingService:"mobiletargeting"};break;case"ap-southeast-2":n={hostname:"pinpoint.ap-southeast-2.amazonaws.com",partition:"aws",signingService:"mobiletargeting"};break;case"eu-central-1":n={hostname:"pinpoint.eu-central-1.amazonaws.com",partition:"aws",signingService:"mobiletargeting"};break;case"eu-west-1":n={hostname:"pinpoint.eu-west-1.amazonaws.com",partition:"aws",signingService:"mobiletargeting"};break;case"us-east-1":n={hostname:"pinpoint.us-east-1.amazonaws.com",partition:"aws",signingService:"mobiletargeting"};break;case"us-west-2":n={hostname:"pinpoint.us-west-2.amazonaws.com",partition:"aws",signingService:"mobiletargeting"};break;default:Pn.has(e)&&(n={hostname:"pinpoint.{region}.amazonaws.com".replace("{region}",e),partition:"aws",signingService:"mobiletargeting"}),Nn.has(e)&&(n={hostname:"pinpoint.{region}.amazonaws.com.cn".replace("{region}",e),partition:"aws-cn"}),Rn.has(e)&&(n={hostname:"pinpoint.{region}.c2s.ic.gov".replace("{region}",e),partition:"aws-iso"}),Ln.has(e)&&(n={hostname:"pinpoint.{region}.sc2s.sgov.gov".replace("{region}",e),partition:"aws-iso-b"}),jn.has(e)&&(n={hostname:"pinpoint.{region}.amazonaws.com".replace("{region}",e),partition:"aws-us-gov"}),void 0===n&&(n={hostname:"pinpoint.{region}.amazonaws.com".replace("{region}",e),partition:"aws",signingService:"mobiletargeting"})}return Promise.resolve(n)},signingName:"mobiletargeting"}),{runtime:"browser",base64Decoder:On.a,base64Encoder:On.b,bodyLengthChecker:xn.a,credentialDefaultProvider:Object(An.a)("Credential is missing"),defaultUserAgent:Object(Cn.a)(Sn.name,Sn.version),maxAttempts:In.a,region:Object(An.a)("Region is missing"),requestHandler:new Mn.a,sha256:En.Sha256,streamCollector:Mn.b,urlParser:kn.a,utf8Decoder:Tn.a,utf8Encoder:Tn.b}),Un=n(22),Bn=n(37),Fn=n(21),zn=n(43),qn=n(25),Kn=n(23),Hn=function(e){function t(t){var n=this,r=d(d({},Dn),t),i=Object(Un.b)(r),o=Object(Un.a)(i),s=Object(qn.b)(o),a=Object(In.c)(s),u=Object(Kn.b)(a),c=Object(Fn.b)(u);return(n=e.call(this,c)||this).config=c,n.middlewareStack.use(Object(qn.a)(n.config)),n.middlewareStack.use(Object(In.b)(n.config)),n.middlewareStack.use(Object(Kn.a)(n.config)),n.middlewareStack.use(Object(Bn.a)(n.config)),n.middlewareStack.use(Object(Fn.a)(n.config)),n.middlewareStack.use(Object(zn.a)(n.config)),n}return l(t,e),t.prototype.destroy=function(){e.prototype.destroy.call(this)},t}(Ft.a),Vn=n(26),Gn=n(27),Wn=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},$n=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},Yn=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},Jn=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(Yn(arguments[t]));return e},Zn=new i.a("EventsBuffer"),Xn=[429,500],Qn=[202],er=function(){function e(e,t){this._pause=!1,this._flush=!1,Zn.debug("Instantiating buffer with config:",t),this._buffer=[],this._client=e,this._config=t,this._sendBatch=this._sendBatch.bind(this),this._startLoop()}return e.prototype.push=function(e){var t;if(this._buffer>this._config.bufferSize)return Zn.debug("Exceeded analytics events buffer size"),e.handlers.reject(new Error("Exceeded the size of analytics events buffer"));var n=((t={})[e.params.event.eventId]=e,t);this._buffer.push(n)},e.prototype.pause=function(){this._pause=!0},e.prototype.resume=function(){this._pause=!1},e.prototype.updateClient=function(e){this._client=e},e.prototype.flush=function(){this._flush=!0},e.prototype._startLoop=function(){this._interval&&clearInterval(this._interval);var e=this._config.flushInterval;this._interval=setInterval(this._sendBatch,e)},e.prototype._sendBatch=function(){var e=this._buffer.length;if(this._flush&&!e&&clearInterval(this._interval),!this._pause&&e){var t=this._config.flushSize,n=Math.min(t,e),r=this._buffer.splice(0,n);this._putEvents(r)}},e.prototype._putEvents=function(e){return Wn(this,void 0,void 0,(function(){var t,n,r,i,o;return $n(this,(function(s){switch(s.label){case 0:t=this._bufferToMap(e),n=this._generateBatchEventParams(t),s.label=1;case 1:return s.trys.push([1,3,,4]),r=new wn(n),[4,this._client.send(r)];case 2:return i=s.sent(),this._processPutEventsSuccessResponse(i,t),[3,4];case 3:return o=s.sent(),[2,this._handlePutEventsFailure(o,t)];case 4:return[2]}}))}))},e.prototype._generateBatchEventParams=function(e){var t={ApplicationId:"",EventsRequest:{BatchItem:{}}};return Object.values(e).forEach((function(e){var n=e.params,r=n.event,i=n.timestamp,o=n.config,s=r.name,a=r.attributes,u=r.metrics,c=r.eventId,f=r.session,l=o.appId,d=o.endpointId,h=t.EventsRequest.BatchItem;t.ApplicationId=t.ApplicationId||l,h[d]||(h[d]={Endpoint:{},Events:{}}),h[d].Events[c]={EventType:s,Timestamp:new Date(i).toISOString(),Attributes:a,Metrics:u,Session:f}})),t},e.prototype._handlePutEventsFailure=function(e,t){Zn.debug("_putEvents Failed: ",e);var n=e.$metadata&&e.$metadata.httpStatusCode;if(Xn.includes(n)){var r=Object.values(t);this._retry(r)}else;},e.prototype._processPutEventsSuccessResponse=function(e,t){var n=e.EventsResponse.Results,r=[];Object.entries(n).forEach((function(e){var n=Yn(e,2),i=n[0],o=n[1].EventsItemResponse;Object.entries(o).forEach((function(e){var n,o,s=Yn(e,2),a=s[0],u=s[1],c=u.StatusCode,f=u.Message,l=t[a],d={EventsResponse:{Results:(n={},n[i]={EventsItemResponse:(o={},o[a]={StatusCode:c,Message:f},o)},n)}};if(Qn.includes(c))l.handlers.resolve(d);else{if(!Xn.includes(c)){var h=l.params.event.name;return Zn.error("event "+a+" : "+h+" failed with error: "+f),l.handlers.reject(d)}r.push(l)}}))})),r.length&&this._retry(r)},e.prototype._retry=function(e){var t,n=[];e.forEach((function(e){var t,r=e.params,i=r.event,o=i.eventId,s=i.name;if(r.resendLimit-- >0)return Zn.debug("resending event "+o+" : "+s+" with "+r.resendLimit+" retry attempts remaining"),void n.push((t={},t[o]=e,t));Zn.debug("no retry attempts remaining for event "+o+" : "+s)})),(t=this._buffer).unshift.apply(t,Jn(n))},e.prototype._bufferToMap=function(e){return e.reduce((function(e,t){var n=Yn(Object.entries(t),1),r=Yn(n[0],2),i=r[0],o=r[1];return e[i]=o,e}),{})},e}();function tr(e){return(tr="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var nr=function(){return(nr=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},rr=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},ir=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},or=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n},sr="undefined"!=typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("amplify_default"):"@@amplify_default",ar=function(e,t){r.a.dispatch("analytics",{event:e,data:t},"Analytics",sr)},ur=new i.a("AWSPinpointProvider"),cr=[429,500],fr=[202],lr="undefined"!=typeof navigator&&navigator&&"function"==typeof navigator.sendBeacon,dr=function(){function e(e){this._endpointGenerating=!0,this._endpointUpdateInProgress=!1,this._buffer=null,this._endpointBuffer=[],this._config=e||{},this._config.bufferSize=this._config.bufferSize||1e3,this._config.flushSize=this._config.flushSize||100,this._config.flushInterval=this._config.flushInterval||5e3,this._config.resendLimit=this._config.resendLimit||5,this._clientInfo=o.a.clientInfo()}return e.prototype.getCategory=function(){return e.category},e.prototype.getProviderName=function(){return e.providerName},e.prototype.configure=function(e){var t=this;ur.debug("configure Analytics",e);var n=e||{};if(this._config=Object.assign({},this._config,n),this._endpointGenerating=!!e.autoSessionRecord,this._config.appId&&!this._config.disabled)if(this._config.endpointId)ar("pinpointProvider_configured",null);else{var r=this.getProviderName()+"_"+this._config.appId;this._getEndpointId(r).then((function(e){ur.debug("setting endpoint id from the cache",e),t._config.endpointId=e,ar("pinpointProvider_configured",null)})).catch((function(e){ur.debug("Failed to generate endpointId",e)}))}else this._flushBuffer();return this._config},e.prototype.record=function(e,t){return rr(this,void 0,void 0,(function(){var n,r;return ir(this,(function(i){switch(i.label){case 0:return ur.debug("_public record",e),[4,this._getCredentials()];case 1:return(n=i.sent())&&this._config.appId&&this._config.region?(this._initClients(n),r=(new Date).getTime(),this._generateSession(e),e.event.eventId=Object(Gn.v1)(),Object.assign(e,{timestamp:r,config:this._config}),e.event.immediate?[2,this._send(e,t)]:(this._putToBuffer(e,t),[2])):(ur.debug("cannot send events without credentials, applicationId or region"),[2,t.reject(new Error("No credentials, applicationId or region"))])}}))}))},e.prototype._sendEndpointUpdate=function(e){return rr(this,void 0,void 0,(function(){var t;return ir(this,(function(n){switch(n.label){case 0:return this._endpointUpdateInProgress?(this._endpointBuffer.push(e),[2]):(this._endpointUpdateInProgress=!0,[4,this._updateEndpoint(e)]);case 1:return n.sent(),t=this._endpointBuffer.shift(),this._endpointUpdateInProgress=!1,t&&this._sendEndpointUpdate(t),[2]}}))}))},e.prototype._putToBuffer=function(e,t){"_update_endpoint"!==e.event.name?this._buffer&&this._buffer.push({params:e,handlers:t}):this._sendEndpointUpdate({params:e,handlers:t})},e.prototype._generateSession=function(e){this._sessionId=this._sessionId||Object(Gn.v1)();var t=e.event;switch(t.name){case"_session.start":this._sessionStartTimestamp=(new Date).getTime(),this._sessionId=Object(Gn.v1)(),t.session={Id:this._sessionId,StartTimestamp:new Date(this._sessionStartTimestamp).toISOString()};break;case"_session.stop":var n=(new Date).getTime();this._sessionStartTimestamp=this._sessionStartTimestamp||(new Date).getTime(),this._sessionId=this._sessionId||Object(Gn.v1)(),t.session={Id:this._sessionId,Duration:n-this._sessionStartTimestamp,StartTimestamp:new Date(this._sessionStartTimestamp).toISOString(),StopTimestamp:new Date(n).toISOString()},this._sessionId=void 0,this._sessionStartTimestamp=void 0;break;default:this._sessionStartTimestamp=this._sessionStartTimestamp||(new Date).getTime(),this._sessionId=this._sessionId||Object(Gn.v1)(),t.session={Id:this._sessionId,StartTimestamp:new Date(this._sessionStartTimestamp).toISOString()}}},e.prototype._send=function(e,t){return rr(this,void 0,void 0,(function(){return ir(this,(function(n){switch(e.event.name){case"_update_endpoint":return[2,this._updateEndpoint({params:e,handlers:t})];case"_session.stop":return[2,this._pinpointSendStopSession(e,t)];default:return[2,this._pinpointPutEvents(e,t)]}return[2]}))}))},e.prototype._generateBatchItemContext=function(e){var t,n=e.event,r=e.timestamp,i=e.config,o=n.name,s=n.attributes,a=n.metrics,u=n.eventId,c=n.session,f=i.appId,l=i.endpointId,d={ApplicationId:f,EventsRequest:{BatchItem:{}}},h={Endpoint:{}};return h.Events=((t={})[u]={EventType:o,Timestamp:new Date(r).toISOString(),Attributes:s,Metrics:a,Session:c},t),d.EventsRequest.BatchItem[l]=h,d},e.prototype._pinpointPutEvents=function(e,t){return rr(this,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,d;return ir(this,(function(h){switch(h.label){case 0:n=e.event.eventId,r=e.config.endpointId,i=this._generateBatchItemContext(e),o=new wn(i),h.label=1;case 1:return h.trys.push([1,3,,4]),[4,this.pinpointClient.send(o)];case 2:return s=h.sent(),a=r,u=n,c=s.EventsResponse.Results[a].EventsItemResponse[u],f=c.StatusCode,l=c.Message,fr.includes(f)?(ur.debug("record event success. ",s),[2,t.resolve(s)]):cr.includes(f)?(this._retry(e,t),[3,4]):(ur.error("Event "+n+" is not accepted, the error is "+l),[2,t.reject(s)]);case 3:return d=h.sent(),this._eventError(d),[2,t.reject(d)];case 4:return[2]}}))}))},e.prototype._pinpointSendStopSession=function(e,t){if(lr){var n=this._generateBatchItemContext(e),r=this._config.region,i=n.ApplicationId,o=n.EventsRequest,a={secret_key:this._config.credentials.secretAccessKey,access_key:this._config.credentials.accessKeyId,session_token:this._config.credentials.sessionToken},u="https://pinpoint."+r+".amazonaws.com/v1/apps/"+i+"/events/legacy",c=JSON.stringify(o),f={url:u,body:c,method:"POST"},l={region:r,service:"mobiletargeting"},d=s.a.signUrl(f,a,l,null);return navigator.sendBeacon(d,c)?t.resolve("sendBeacon success"):t.reject("sendBeacon failure")}this._pinpointPutEvents(e,t)},e.prototype._retry=function(e,t){var n=e.config.resendLimit;e.resendLimit="number"==typeof e.resendLimit?e.resendLimit:n,e.resendLimit-- >0?(ur.debug("resending event "+e.eventName+" with "+e.resendLimit+" retry times left"),this._pinpointPutEvents(e,t)):ur.debug("retry times used up for event "+e.eventName)},e.prototype._updateEndpoint=function(e){return rr(this,void 0,void 0,(function(){var t,n,r,i,o,s,u,c,f,l,d,h;return ir(this,(function(p){switch(p.label){case 0:t=e.params,n=e.handlers,r=t.config,i=t.event,o=r.appId,s=r.endpointId,u=this._endpointRequest(r,a.a.transferKeyToLowerCase(i,[],["attributes","userAttributes","Attributes","UserAttributes"])),c={ApplicationId:o,EndpointId:s,EndpointRequest:u},p.label=1;case 1:return p.trys.push([1,3,,4]),f=new _n(c),[4,this.pinpointClient.send(f)];case 2:return l=p.sent(),ur.debug("updateEndpoint success",l),this._endpointGenerating=!1,this._resumeBuffer(),n.resolve(l),[2];case 3:return d=p.sent(),h={err:d,update_params:c,endpointObject:e},[2,this._handleEndpointUpdateFailure(h)];case 4:return[2]}}))}))},e.prototype._handleEndpointUpdateFailure=function(e){return rr(this,void 0,void 0,(function(){var t,n,r;return ir(this,(function(i){switch(t=e.err,n=e.endpointObject,r=t.$metadata&&t.$metadata.httpStatusCode,ur.debug("updateEndpoint error",t),r){case 403:return[2,this._handleEndpointUpdateForbidden(e)];default:if(cr.includes(r))return!0,[2,this._retryEndpointUpdate(n,!0)];ur.error("updateEndpoint failed",t),n.handlers.reject(t)}return[2]}))}))},e.prototype._handleEndpointUpdateForbidden=function(e){var t=e.err,n=e.endpointObject,r=t.code,i=t.retryable;if("ExpiredTokenException"!==r&&!i)return n.handlers.reject(t);this._retryEndpointUpdate(n)},e.prototype._retryEndpointUpdate=function(e,t){void 0===t&&(t=!1),ur.debug("_retryEndpointUpdate",e);var n=e.params,r=n.config.resendLimit;if(n.resendLimit="number"==typeof n.resendLimit?n.resendLimit:r,n.resendLimit-- >0)return ur.debug("resending endpoint update "+n.event.eventId+" with "+n.resendLimit+" retry attempts remaining"),void(this._endpointBuffer.length?this._endpointBuffer.unshift(e):this._updateEndpoint(e));ur.warn("resending endpoint update "+n.event.eventId+" failed after "+n.config.resendLimit+" attempts"),this._endpointGenerating&&ur.error("Initial endpoint update failed. ")},e.prototype._initClients=function(e){return rr(this,void 0,void 0,(function(){var t,n;return ir(this,(function(r){return ur.debug("init clients"),this.pinpointClient&&this._config.credentials&&this._config.credentials.sessionToken===e.sessionToken&&this._config.credentials.identityId===e.identityId?(ur.debug("no change for aws credentials, directly return from init"),[2]):(t=this._config.credentials?this._config.credentials.identityId:null,this._config.credentials=e,n=this._config.region,ur.debug("init clients with credentials",e),this.pinpointClient=new Hn({region:n,credentials:e,customUserAgent:Object(u.b)()}),this.pinpointClient.middlewareStack.addRelativeTo((function(e){return function(t){return delete t.request.headers["amz-sdk-invocation-id"],delete t.request.headers["amz-sdk-request"],e(t)}}),{step:"finalizeRequest",relation:"after",toMiddleware:"retryMiddleware"}),this._bufferExists()&&t===e.identityId?this._updateBufferClient():this._initBuffer(),this._customizePinpointClientReq(),[2])}))}))},e.prototype._bufferExists=function(){return this._buffer&&this._buffer instanceof er},e.prototype._initBuffer=function(){this._bufferExists()&&this._flushBuffer(),this._buffer=new er(this.pinpointClient,this._config),this._endpointGenerating&&this._buffer.pause()},e.prototype._updateBufferClient=function(){this._bufferExists()&&this._buffer.updateClient(this.pinpointClient)},e.prototype._flushBuffer=function(){this._bufferExists()&&(this._buffer.flush(),this._buffer=null)},e.prototype._resumeBuffer=function(){this._bufferExists()&&this._buffer.resume()},e.prototype._customizePinpointClientReq=function(){},e.prototype._getEndpointId=function(e){return rr(this,void 0,void 0,(function(){var t;return ir(this,(function(n){switch(n.label){case 0:return[4,Vn.a.getItem(e)];case 1:return t=n.sent(),ur.debug("endpointId from cache",t,"type",tr(t)),t||(t=Object(Gn.v1)(),Vn.a.setItem(e,t)),[2,t]}}))}))},e.prototype._endpointRequest=function(e,t){var n=e.credentials,r=this._clientInfo||{},i=e.clientContext||{},o=e.endpoint||{},s={appVersion:r.appVersion,make:r.make,model:r.model,modelVersion:r.version,platform:r.platform},u=(i.clientId,i.appTitle,i.appVersionName,i.appVersionCode,i.appPackageName,or(i,["clientId","appTitle","appVersionName","appVersionCode","appPackageName"])),c=t.address?"android"===r.platform?"GCM":"APNS":void 0,f=nr(nr(nr({channelType:c,requestId:Object(Gn.v1)(),effectiveDate:(new Date).toISOString()},o),t),{attributes:nr(nr({},o.attributes),t.attributes),demographic:nr(nr(nr(nr({},s),u),o.demographic),t.demographic),location:nr(nr({},o.location),t.location),metrics:nr(nr({},o.metrics),t.metrics),user:{userId:t.userId||o.userId||n.identityId,userAttributes:nr(nr({},o.userAttributes),t.userAttributes)}}),l=(f.userId,f.userAttributes,f.name,f.session,f.eventId,f.immediate,or(f,["userId","userAttributes","name","session","eventId","immediate"]));return a.a.transferKeyToUpperCase(l,[],["metrics","userAttributes","attributes"])},e.prototype._eventError=function(e){ur.error("record event failed.",e),ur.warn('Please ensure you have updated your Pinpoint IAM Policy with the Action: "mobiletargeting:PutEvents" in order to record events')},e.prototype._getCredentials=function(){return rr(this,void 0,void 0,(function(){var e,t;return ir(this,(function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,c.a.get()];case 1:return(e=n.sent())?(ur.debug("set credentials for analytics",e),[2,c.a.shear(e)]):[2,null];case 2:return t=n.sent(),ur.debug("ensure credentials error",t),[2,null];case 3:return[2]}}))}))},e.category="Analytics",e.providerName="AWSPinpoint",e}()},function(e,t,n){"use strict";n.d(t,"a",(function(){return Ht}));var r=n(44),i=n(50),o=n(89),s=function(e,t){return(s=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}s(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var u=function(){return(u=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function c(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))}function f(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}}Object.create;var l,d,h,p,v,g,m,b,y,w,_,S,E,M,A,I,k,O,x,C,T,P,N,R,L,j,D,U,B,F,z,q,K,H,V,G,W,$,Y,J,Z,X,Q,ee,te,ne,re,ie,oe,se,ae,ue,ce,fe,le,de,he,pe,ve,ge,me,be,ye,we,_e,Se,Ee,Me,Ae,Ie,ke,Oe,xe,Ce,Te,Pe,Ne,Re,Le,je,De,Ue;Object.create;(l||(l={})).filterSensitiveLog=function(e){return u({},e)},(d||(d={})).filterSensitiveLog=function(e){return u({},e)},(h||(h={})).filterSensitiveLog=function(e){return u({},e)},(p||(p={})).filterSensitiveLog=function(e){return u({},e)},(v||(v={})).filterSensitiveLog=function(e){return u({},e)},(g||(g={})).filterSensitiveLog=function(e){return u({},e)},(m||(m={})).filterSensitiveLog=function(e){return u({},e)},function(e){e.ACTIVE="ACTIVE",e.CREATING="CREATING",e.DELETING="DELETING"}(b||(b={})),(y||(y={})).filterSensitiveLog=function(e){return u({},e)},(w||(w={})).filterSensitiveLog=function(e){return u({},e)},(_||(_={})).filterSensitiveLog=function(e){return u({},e)},(S||(S={})).filterSensitiveLog=function(e){return u({},e)},(E||(E={})).filterSensitiveLog=function(e){return u({},e)},(M||(M={})).filterSensitiveLog=function(e){return u({},e)},(A||(A={})).filterSensitiveLog=function(e){return u({},e)},(I||(I={})).filterSensitiveLog=function(e){return u({},e)},(k||(k={})).filterSensitiveLog=function(e){return u({},e)},function(e){e.KMS="KMS",e.NONE="NONE"}(O||(O={})),function(e){e.ALL="ALL",e.INCOMING_BYTES="IncomingBytes",e.INCOMING_RECORDS="IncomingRecords",e.ITERATOR_AGE_MILLISECONDS="IteratorAgeMilliseconds",e.OUTGOING_BYTES="OutgoingBytes",e.OUTGOING_RECORDS="OutgoingRecords",e.READ_PROVISIONED_THROUGHPUT_EXCEEDED="ReadProvisionedThroughputExceeded",e.WRITE_PROVISIONED_THROUGHPUT_EXCEEDED="WriteProvisionedThroughputExceeded"}(x||(x={})),(C||(C={})).filterSensitiveLog=function(e){return u({},e)},(T||(T={})).filterSensitiveLog=function(e){return u({},e)},(P||(P={})).filterSensitiveLog=function(e){return u({},e)},function(e){e.ACTIVE="ACTIVE",e.CREATING="CREATING",e.DELETING="DELETING",e.UPDATING="UPDATING"}(N||(N={})),(R||(R={})).filterSensitiveLog=function(e){return u({},e)},(L||(L={})).filterSensitiveLog=function(e){return u({},e)},(j||(j={})).filterSensitiveLog=function(e){return u({},e)},(D||(D={})).filterSensitiveLog=function(e){return u({},e)},(U||(U={})).filterSensitiveLog=function(e){return u({},e)},(B||(B={})).filterSensitiveLog=function(e){return u({},e)},(F||(F={})).filterSensitiveLog=function(e){return u({},e)},(z||(z={})).filterSensitiveLog=function(e){return u({},e)},(q||(q={})).filterSensitiveLog=function(e){return u({},e)},(K||(K={})).filterSensitiveLog=function(e){return u({},e)},(H||(H={})).filterSensitiveLog=function(e){return u({},e)},(V||(V={})).filterSensitiveLog=function(e){return u({},e)},(G||(G={})).filterSensitiveLog=function(e){return u({},e)},(W||(W={})).filterSensitiveLog=function(e){return u({},e)},($||($={})).filterSensitiveLog=function(e){return u({},e)},(Y||(Y={})).filterSensitiveLog=function(e){return u({},e)},(J||(J={})).filterSensitiveLog=function(e){return u({},e)},(Z||(Z={})).filterSensitiveLog=function(e){return u({},e)},(X||(X={})).filterSensitiveLog=function(e){return u({},e)},(Q||(Q={})).filterSensitiveLog=function(e){return u({},e)},(ee||(ee={})).filterSensitiveLog=function(e){return u({},e)},(te||(te={})).filterSensitiveLog=function(e){return u({},e)},function(e){e.AFTER_SEQUENCE_NUMBER="AFTER_SEQUENCE_NUMBER",e.AT_SEQUENCE_NUMBER="AT_SEQUENCE_NUMBER",e.AT_TIMESTAMP="AT_TIMESTAMP",e.LATEST="LATEST",e.TRIM_HORIZON="TRIM_HORIZON"}(ne||(ne={})),(re||(re={})).filterSensitiveLog=function(e){return u({},e)},(ie||(ie={})).filterSensitiveLog=function(e){return u({},e)},(oe||(oe={})).filterSensitiveLog=function(e){return u({},e)},(se||(se={})).filterSensitiveLog=function(e){return u({},e)},function(e){e.AFTER_SHARD_ID="AFTER_SHARD_ID",e.AT_LATEST="AT_LATEST",e.AT_TIMESTAMP="AT_TIMESTAMP",e.AT_TRIM_HORIZON="AT_TRIM_HORIZON",e.FROM_TIMESTAMP="FROM_TIMESTAMP",e.FROM_TRIM_HORIZON="FROM_TRIM_HORIZON"}(ae||(ae={})),(ue||(ue={})).filterSensitiveLog=function(e){return u({},e)},(ce||(ce={})).filterSensitiveLog=function(e){return u({},e)},(fe||(fe={})).filterSensitiveLog=function(e){return u({},e)},(le||(le={})).filterSensitiveLog=function(e){return u({},e)},(de||(de={})).filterSensitiveLog=function(e){return u({},e)},(he||(he={})).filterSensitiveLog=function(e){return u({},e)},(pe||(pe={})).filterSensitiveLog=function(e){return u({},e)},(ve||(ve={})).filterSensitiveLog=function(e){return u({},e)},(ge||(ge={})).filterSensitiveLog=function(e){return u({},e)},(me||(me={})).filterSensitiveLog=function(e){return u({},e)},(be||(be={})).filterSensitiveLog=function(e){return u({},e)},(ye||(ye={})).filterSensitiveLog=function(e){return u({},e)},(we||(we={})).filterSensitiveLog=function(e){return u({},e)},(_e||(_e={})).filterSensitiveLog=function(e){return u({},e)},(Se||(Se={})).filterSensitiveLog=function(e){return u({},e)},(Ee||(Ee={})).filterSensitiveLog=function(e){return u({},e)},(Me||(Me={})).filterSensitiveLog=function(e){return u({},e)},(Ae||(Ae={})).filterSensitiveLog=function(e){return u({},e)},(Ie||(Ie={})).filterSensitiveLog=function(e){return u({},e)},(ke||(ke={})).filterSensitiveLog=function(e){return u({},e)},(Oe||(Oe={})).filterSensitiveLog=function(e){return u({},e)},(xe||(xe={})).filterSensitiveLog=function(e){return u({},e)},(Ce||(Ce={})).filterSensitiveLog=function(e){return u({},e)},(Te||(Te={})).filterSensitiveLog=function(e){return u({},e)},(Pe||(Pe={})).filterSensitiveLog=function(e){return u({},e)},(Ne||(Ne={})).filterSensitiveLog=function(e){return u({},e)},function(e){e.visit=function(e,t){return void 0!==e.KMSThrottlingException?t.KMSThrottlingException(e.KMSThrottlingException):void 0!==e.InternalFailureException?t.InternalFailureException(e.InternalFailureException):void 0!==e.ResourceInUseException?t.ResourceInUseException(e.ResourceInUseException):void 0!==e.KMSOptInRequired?t.KMSOptInRequired(e.KMSOptInRequired):void 0!==e.KMSDisabledException?t.KMSDisabledException(e.KMSDisabledException):void 0!==e.KMSAccessDeniedException?t.KMSAccessDeniedException(e.KMSAccessDeniedException):void 0!==e.KMSInvalidStateException?t.KMSInvalidStateException(e.KMSInvalidStateException):void 0!==e.KMSNotFoundException?t.KMSNotFoundException(e.KMSNotFoundException):void 0!==e.ResourceNotFoundException?t.ResourceNotFoundException(e.ResourceNotFoundException):void 0!==e.SubscribeToShardEvent?t.SubscribeToShardEvent(e.SubscribeToShardEvent):t._(e.$unknown[0],e.$unknown[1])},e.filterSensitiveLog=function(e){var t;return void 0!==e.KMSThrottlingException?{KMSThrottlingException:ee.filterSensitiveLog(e.KMSThrottlingException)}:void 0!==e.InternalFailureException?{InternalFailureException:se.filterSensitiveLog(e.InternalFailureException)}:void 0!==e.ResourceInUseException?{ResourceInUseException:p.filterSensitiveLog(e.ResourceInUseException)}:void 0!==e.KMSOptInRequired?{KMSOptInRequired:Q.filterSensitiveLog(e.KMSOptInRequired)}:void 0!==e.KMSDisabledException?{KMSDisabledException:J.filterSensitiveLog(e.KMSDisabledException)}:void 0!==e.KMSAccessDeniedException?{KMSAccessDeniedException:Y.filterSensitiveLog(e.KMSAccessDeniedException)}:void 0!==e.KMSInvalidStateException?{KMSInvalidStateException:Z.filterSensitiveLog(e.KMSInvalidStateException)}:void 0!==e.KMSNotFoundException?{KMSNotFoundException:X.filterSensitiveLog(e.KMSNotFoundException)}:void 0!==e.ResourceNotFoundException?{ResourceNotFoundException:v.filterSensitiveLog(e.ResourceNotFoundException)}:void 0!==e.SubscribeToShardEvent?{SubscribeToShardEvent:Ne.filterSensitiveLog(e.SubscribeToShardEvent)}:void 0!==e.$unknown?((t={})[e.$unknown[0]]="UNKNOWN",t):void 0}}(Re||(Re={})),(Le||(Le={})).filterSensitiveLog=function(e){return u(u({},e),e.EventStream&&{EventStream:"STREAMING_CONTENT"})},function(e){e.UNIFORM_SCALING="UNIFORM_SCALING"}(je||(je={})),(De||(De={})).filterSensitiveLog=function(e){return u({},e)},(Ue||(Ue={})).filterSensitiveLog=function(e){return u({},e)};var Be=n(2),Fe=function(e,t){return c(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,c,l,d,h,p,v,g,m,b,y,w;return f(this,(function(f){switch(f.label){case 0:return r=[u({},e)],w={},[4,dt(e.body,t)];case 1:switch(n=u.apply(void 0,r.concat([(w.body=f.sent(),w)])),o="UnknownError",s=n.body.__type.split("#"),o=void 0===s[1]?s[0]:s[1],o){case"InvalidArgumentException":case"com.amazonaws.kinesis#InvalidArgumentException":return[3,2];case"KMSAccessDeniedException":case"com.amazonaws.kinesis#KMSAccessDeniedException":return[3,4];case"KMSDisabledException":case"com.amazonaws.kinesis#KMSDisabledException":return[3,6];case"KMSInvalidStateException":case"com.amazonaws.kinesis#KMSInvalidStateException":return[3,8];case"KMSNotFoundException":case"com.amazonaws.kinesis#KMSNotFoundException":return[3,10];case"KMSOptInRequired":case"com.amazonaws.kinesis#KMSOptInRequired":return[3,12];case"KMSThrottlingException":case"com.amazonaws.kinesis#KMSThrottlingException":return[3,14];case"ProvisionedThroughputExceededException":case"com.amazonaws.kinesis#ProvisionedThroughputExceededException":return[3,16];case"ResourceNotFoundException":case"com.amazonaws.kinesis#ResourceNotFoundException":return[3,18]}return[3,20];case 2:return a=[{}],[4,ze(n,t)];case 3:return i=u.apply(void 0,[u.apply(void 0,a.concat([f.sent()])),{name:o,$metadata:ct(e)}]),[3,21];case 4:return c=[{}],[4,qe(n,t)];case 5:return i=u.apply(void 0,[u.apply(void 0,c.concat([f.sent()])),{name:o,$metadata:ct(e)}]),[3,21];case 6:return l=[{}],[4,Ke(n,t)];case 7:return i=u.apply(void 0,[u.apply(void 0,l.concat([f.sent()])),{name:o,$metadata:ct(e)}]),[3,21];case 8:return d=[{}],[4,He(n,t)];case 9:return i=u.apply(void 0,[u.apply(void 0,d.concat([f.sent()])),{name:o,$metadata:ct(e)}]),[3,21];case 10:return h=[{}],[4,Ve(n,t)];case 11:return i=u.apply(void 0,[u.apply(void 0,h.concat([f.sent()])),{name:o,$metadata:ct(e)}]),[3,21];case 12:return p=[{}],[4,Ge(n,t)];case 13:return i=u.apply(void 0,[u.apply(void 0,p.concat([f.sent()])),{name:o,$metadata:ct(e)}]),[3,21];case 14:return v=[{}],[4,We(n,t)];case 15:return i=u.apply(void 0,[u.apply(void 0,v.concat([f.sent()])),{name:o,$metadata:ct(e)}]),[3,21];case 16:return g=[{}],[4,$e(n,t)];case 17:return i=u.apply(void 0,[u.apply(void 0,g.concat([f.sent()])),{name:o,$metadata:ct(e)}]),[3,21];case 18:return m=[{}],[4,Ye(n,t)];case 19:return i=u.apply(void 0,[u.apply(void 0,m.concat([f.sent()])),{name:o,$metadata:ct(e)}]),[3,21];case 20:b=n.body,o=b.code||b.Code||o,i=u(u({},b),{name:""+o,message:b.message||b.Message||o,$fault:"client",$metadata:ct(e)}),f.label=21;case 21:return y=i.message||i.Message||o,i.message=y,delete i.Message,[2,Promise.reject(Object.assign(new Error(y),i))]}}))}))},ze=function(e,t){return c(void 0,void 0,void 0,(function(){var n,r;return f(this,(function(i){return n=e.body,r=Xe(n,t),[2,u({name:"InvalidArgumentException",$fault:"client",$metadata:ct(e)},r)]}))}))},qe=function(e,t){return c(void 0,void 0,void 0,(function(){var n,r;return f(this,(function(i){return n=e.body,r=Qe(n,t),[2,u({name:"KMSAccessDeniedException",$fault:"client",$metadata:ct(e)},r)]}))}))},Ke=function(e,t){return c(void 0,void 0,void 0,(function(){var n,r;return f(this,(function(i){return n=e.body,r=et(n,t),[2,u({name:"KMSDisabledException",$fault:"client",$metadata:ct(e)},r)]}))}))},He=function(e,t){return c(void 0,void 0,void 0,(function(){var n,r;return f(this,(function(i){return n=e.body,r=tt(n,t),[2,u({name:"KMSInvalidStateException",$fault:"client",$metadata:ct(e)},r)]}))}))},Ve=function(e,t){return c(void 0,void 0,void 0,(function(){var n,r;return f(this,(function(i){return n=e.body,r=nt(n,t),[2,u({name:"KMSNotFoundException",$fault:"client",$metadata:ct(e)},r)]}))}))},Ge=function(e,t){return c(void 0,void 0,void 0,(function(){var n,r;return f(this,(function(i){return n=e.body,r=rt(n,t),[2,u({name:"KMSOptInRequired",$fault:"client",$metadata:ct(e)},r)]}))}))},We=function(e,t){return c(void 0,void 0,void 0,(function(){var n,r;return f(this,(function(i){return n=e.body,r=it(n,t),[2,u({name:"KMSThrottlingException",$fault:"client",$metadata:ct(e)},r)]}))}))},$e=function(e,t){return c(void 0,void 0,void 0,(function(){var n,r;return f(this,(function(i){return n=e.body,r=ot(n,t),[2,u({name:"ProvisionedThroughputExceededException",$fault:"client",$metadata:ct(e)},r)]}))}))},Ye=function(e,t){return c(void 0,void 0,void 0,(function(){var n,r;return f(this,(function(i){return n=e.body,r=ut(n,t),[2,u({name:"ResourceNotFoundException",$fault:"client",$metadata:ct(e)},r)]}))}))},Je=function(e,t){return u(u({},void 0!==e.Records&&{Records:Ze(e.Records,t)}),void 0!==e.StreamName&&{StreamName:e.StreamName})},Ze=function(e,t){return e.map((function(e){return function(e,t){return u(u(u({},void 0!==e.Data&&{Data:t.base64Encoder(e.Data)}),void 0!==e.ExplicitHashKey&&{ExplicitHashKey:e.ExplicitHashKey}),void 0!==e.PartitionKey&&{PartitionKey:e.PartitionKey})}(e,t)}))},Xe=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},Qe=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},et=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},tt=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},nt=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},rt=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},it=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},ot=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},st=function(e,t){return{EncryptionType:void 0!==e.EncryptionType&&null!==e.EncryptionType?e.EncryptionType:void 0,FailedRecordCount:void 0!==e.FailedRecordCount&&null!==e.FailedRecordCount?e.FailedRecordCount:void 0,Records:void 0!==e.Records&&null!==e.Records?at(e.Records,t):void 0}},at=function(e,t){return(e||[]).map((function(e){return function(e,t){return{ErrorCode:void 0!==e.ErrorCode&&null!==e.ErrorCode?e.ErrorCode:void 0,ErrorMessage:void 0!==e.ErrorMessage&&null!==e.ErrorMessage?e.ErrorMessage:void 0,SequenceNumber:void 0!==e.SequenceNumber&&null!==e.SequenceNumber?e.SequenceNumber:void 0,ShardId:void 0!==e.ShardId&&null!==e.ShardId?e.ShardId:void 0}}(e)}))},ut=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},ct=function(e){return{httpStatusCode:e.statusCode,httpHeaders:e.headers,requestId:e.headers["x-amzn-requestid"]}},ft=function(e,t){return void 0===e&&(e=new Uint8Array),e instanceof Uint8Array?Promise.resolve(e):t.streamCollector(e)||Promise.resolve(new Uint8Array)},lt=function(e,t,n,r,i){return c(void 0,void 0,void 0,(function(){var o,s,a,u,c,l;return f(this,(function(f){switch(f.label){case 0:return[4,e.endpoint()];case 1:return o=f.sent(),s=o.hostname,a=o.protocol,u=void 0===a?"https":a,c=o.port,l={protocol:u,hostname:s,port:c,method:"POST",path:n,headers:t},void 0!==r&&(l.hostname=r),void 0!==i&&(l.body=i),[2,new Be.a(l)]}}))}))},dt=function(e,t){return function(e,t){return ft(e,t).then((function(e){return t.utf8Encoder(e)}))}(e,t).then((function(e){return e.length?JSON.parse(e):{}}))},ht=n(10),pt=n(0),vt=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return a(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(ht.a)(t,this.serialize,this.deserialize));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"KinesisClient",commandName:"PutRecordsCommand",inputFilterSensitiveLog:Se.filterSensitiveLog,outputFilterSensitiveLog:Me.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"KinesisClient",commandName:"PutRecordsCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return c(void 0,void 0,void 0,(function(){var n,r;return f(this,(function(i){return n={"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":"Kinesis_20131202.PutRecords"},r=JSON.stringify(Je(e,t)),[2,lt(t,n,"/",void 0,r)]}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return c(void 0,void 0,void 0,(function(){var n,r,i;return f(this,(function(o){switch(o.label){case 0:return e.statusCode>=300?[2,Fe(e,t)]:[4,dt(e.body,t)];case 1:return n=o.sent(),{},r=st(n,t),i=u({$metadata:ct(e)},r),[2,Promise.resolve(i)]}}))}))}(e,t)},t}(pt.b),gt=n(150),mt=n(38),bt=n(110),yt=n(18),wt=n(24),_t=n(11),St=n(39),Et=n(17),Mt=n(40),At=n(41),It=n(15),kt=new Set(["ap-east-1","ap-northeast-1","ap-northeast-2","ap-south-1","ap-southeast-1","ap-southeast-2","ca-central-1","eu-central-1","eu-north-1","eu-west-1","eu-west-2","eu-west-3","me-south-1","sa-east-1","us-east-1","us-east-2","us-west-1","us-west-2"]),Ot=new Set(["cn-north-1","cn-northwest-1"]),xt=new Set(["us-iso-east-1"]),Ct=new Set(["us-isob-east-1"]),Tt=new Set(["us-gov-east-1","us-gov-west-1"]),Pt=u(u({},{apiVersion:"2013-12-02",disableHostPrefix:!1,logger:{},regionInfoProvider:function(e,t){var n=void 0;switch(e){case"ap-east-1":n={hostname:"kinesis.ap-east-1.amazonaws.com",partition:"aws"};break;case"ap-northeast-1":n={hostname:"kinesis.ap-northeast-1.amazonaws.com",partition:"aws"};break;case"ap-northeast-2":n={hostname:"kinesis.ap-northeast-2.amazonaws.com",partition:"aws"};break;case"ap-south-1":n={hostname:"kinesis.ap-south-1.amazonaws.com",partition:"aws"};break;case"ap-southeast-1":n={hostname:"kinesis.ap-southeast-1.amazonaws.com",partition:"aws"};break;case"ap-southeast-2":n={hostname:"kinesis.ap-southeast-2.amazonaws.com",partition:"aws"};break;case"ca-central-1":n={hostname:"kinesis.ca-central-1.amazonaws.com",partition:"aws"};break;case"cn-north-1":n={hostname:"kinesis.cn-north-1.amazonaws.com.cn",partition:"aws-cn"};break;case"cn-northwest-1":n={hostname:"kinesis.cn-northwest-1.amazonaws.com.cn",partition:"aws-cn"};break;case"eu-central-1":n={hostname:"kinesis.eu-central-1.amazonaws.com",partition:"aws"};break;case"eu-north-1":n={hostname:"kinesis.eu-north-1.amazonaws.com",partition:"aws"};break;case"eu-west-1":n={hostname:"kinesis.eu-west-1.amazonaws.com",partition:"aws"};break;case"eu-west-2":n={hostname:"kinesis.eu-west-2.amazonaws.com",partition:"aws"};break;case"eu-west-3":n={hostname:"kinesis.eu-west-3.amazonaws.com",partition:"aws"};break;case"me-south-1":n={hostname:"kinesis.me-south-1.amazonaws.com",partition:"aws"};break;case"sa-east-1":n={hostname:"kinesis.sa-east-1.amazonaws.com",partition:"aws"};break;case"us-east-1":n={hostname:"kinesis.us-east-1.amazonaws.com",partition:"aws"};break;case"us-east-2":n={hostname:"kinesis.us-east-2.amazonaws.com",partition:"aws"};break;case"us-gov-east-1":n={hostname:"kinesis.us-gov-east-1.amazonaws.com",partition:"aws-us-gov"};break;case"us-gov-west-1":n={hostname:"kinesis.us-gov-west-1.amazonaws.com",partition:"aws-us-gov"};break;case"us-iso-east-1":n={hostname:"kinesis.us-iso-east-1.c2s.ic.gov",partition:"aws-iso"};break;case"us-isob-east-1":n={hostname:"kinesis.us-isob-east-1.sc2s.sgov.gov",partition:"aws-iso-b"};break;case"us-west-1":n={hostname:"kinesis.us-west-1.amazonaws.com",partition:"aws"};break;case"us-west-2":n={hostname:"kinesis.us-west-2.amazonaws.com",partition:"aws"};break;default:kt.has(e)&&(n={hostname:"kinesis.{region}.amazonaws.com".replace("{region}",e),partition:"aws"}),Ot.has(e)&&(n={hostname:"kinesis.{region}.amazonaws.com.cn".replace("{region}",e),partition:"aws-cn"}),xt.has(e)&&(n={hostname:"kinesis.{region}.c2s.ic.gov".replace("{region}",e),partition:"aws-iso"}),Ct.has(e)&&(n={hostname:"kinesis.{region}.sc2s.sgov.gov".replace("{region}",e),partition:"aws-iso-b"}),Tt.has(e)&&(n={hostname:"kinesis.{region}.amazonaws.com".replace("{region}",e),partition:"aws-us-gov"}),void 0===n&&(n={hostname:"kinesis.{region}.amazonaws.com".replace("{region}",e),partition:"aws"})}return Promise.resolve(n)},signingName:"kinesis"}),{runtime:"browser",base64Decoder:Et.a,base64Encoder:Et.b,bodyLengthChecker:Mt.a,credentialDefaultProvider:Object(wt.a)("Credential is missing"),defaultUserAgent:Object(At.a)(gt.name,gt.version),eventStreamSerdeProvider:bt.a,maxAttempts:_t.a,region:Object(wt.a)("Region is missing"),requestHandler:new yt.a,sha256:mt.Sha256,streamCollector:yt.b,urlParser:St.a,utf8Decoder:It.a,utf8Encoder:It.b}),Nt=n(22),Rt=n(112),Lt=n(37),jt=n(21),Dt=n(43),Ut=n(25),Bt=n(23),Ft=function(e){function t(t){var n=this,r=u(u({},Pt),t),i=Object(Nt.b)(r),o=Object(Nt.a)(i),s=Object(Ut.b)(o),a=Object(_t.c)(s),c=Object(Bt.b)(a),f=Object(jt.b)(c),l=Object(Rt.a)(f);return(n=e.call(this,l)||this).config=l,n.middlewareStack.use(Object(Ut.a)(n.config)),n.middlewareStack.use(Object(_t.b)(n.config)),n.middlewareStack.use(Object(Bt.a)(n.config)),n.middlewareStack.use(Object(Lt.a)(n.config)),n.middlewareStack.use(Object(jt.a)(n.config)),n.middlewareStack.use(Object(Dt.a)(n.config)),n}return a(t,e),t.prototype.destroy=function(){e.prototype.destroy.call(this)},t}(pt.a),zt=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},qt=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},Kt=new r.a("AWSKinesisProvider"),Ht=function(){function e(e){this._buffer=[],this._config=e||{},this._config.bufferSize=this._config.bufferSize||1e3,this._config.flushSize=this._config.flushSize||100,this._config.flushInterval=this._config.flushInterval||5e3,this._config.resendLimit=this._config.resendLimit||5,this._setupTimer()}return e.prototype._setupTimer=function(){var e=this;this._timer&&clearInterval(this._timer);var t=this._config,n=t.flushSize,r=t.flushInterval;this._timer=setInterval((function(){for(var t=e._buffer.length<n?e._buffer.length:n,r=[],i=0;i<t;i+=1){var o=e._buffer.shift();r.push(o)}e._sendFromBuffer(r)}),r)},e.prototype.getCategory=function(){return"Analytics"},e.prototype.getProviderName=function(){return"AWSKinesis"},e.prototype.configure=function(e){Kt.debug("configure Analytics",e);var t=e||{};return this._config=Object.assign({},this._config,t),this._setupTimer(),this._config},e.prototype.record=function(e){return zt(this,void 0,void 0,(function(){var t;return qt(this,(function(n){switch(n.label){case 0:return[4,this._getCredentials()];case 1:return(t=n.sent())?(Object.assign(e,{config:this._config,credentials:t}),[2,this._putToBuffer(e)]):[2,Promise.resolve(!1)]}}))}))},e.prototype.updateEndpoint=function(){return Kt.debug("updateEndpoint is not implemented in Kinesis provider"),Promise.resolve(!0)},e.prototype._putToBuffer=function(e){return this._buffer.length<1e3?(this._buffer.push(e),Promise.resolve(!0)):(Kt.debug("exceed analytics events buffer size"),Promise.reject(!1))},e.prototype._sendFromBuffer=function(e){for(var t=this,n=[],r=null,i=[],o=0;o<e.length;o+=1){var s=e[o].credentials;0===o?(i.push(e[o]),r=s):s.sessionToken===r.sessionToken&&s.identityId===r.identityId?(Kt.debug("no change for cred, put event in the same group"),i.push(e[o])):(n.push(i),(i=[]).push(e[o]),r=s)}n.push(i),n.map((function(e){t._sendEvents(e)}))},e.prototype._sendEvents=function(e){var t=this;if(0!==e.length){var n=e[0],r=n.config,i=n.credentials;if(!this._init(r,i))return!1;var o={};e.map((function(e){var t=e.event,n=t.streamName;void 0===o[n]&&(o[n]=[]);var r=t.data&&"string"!=typeof t.data?JSON.stringify(t.data):t.data,s={Data:Object(It.a)(r),PartitionKey:t.partitionKey||"partition-"+i.identityId};o[n].push(s)})),Object.keys(o).map((function(e){return zt(t,void 0,void 0,(function(){var t,n;return qt(this,(function(r){switch(r.label){case 0:Kt.debug("putting records to kinesis with records",o[e]),r.label=1;case 1:return r.trys.push([1,3,,4]),t=new vt({Records:o[e],StreamName:e}),[4,this._kinesis.send(t)];case 2:return r.sent(),Kt.debug("Upload records to stream",e),[3,4];case 3:return n=r.sent(),Kt.debug("Failed to upload records to Kinesis",n),[3,4];case 4:return[2]}}))}))}))}},e.prototype._init=function(e,t){if(Kt.debug("init clients"),this._kinesis&&this._config.credentials&&this._config.credentials.sessionToken===t.sessionToken&&this._config.credentials.identityId===t.identityId)return Kt.debug("no change for analytics config, directly return from init"),!0;this._config.credentials=t;var n=e.region,r=e.endpoint;return this._initKinesis(n,r,t)},e.prototype._initKinesis=function(e,t,n){return Kt.debug("initialize kinesis with credentials",n),this._kinesis=new Ft({region:e,credentials:n,customUserAgent:Object(i.b)(),endpoint:t}),!0},e.prototype._getCredentials=function(){var e=this;return o.a.get().then((function(t){return t?(Kt.debug("set credentials for analytics",e._config.credentials),o.a.shear(t)):null})).catch((function(e){return Kt.debug("ensure credentials error",e),null}))},e}()},function(e,t,n){"use strict";n.d(t,"a",(function(){return c}));var r=n(76);function i(e,t){void 0===t&&(t={});var n=function(e){if(e&&"j"===e[0]&&":"===e[1])return e.substr(2);return e}(e);if(function(e,t){return void 0===t&&(t=!e||"{"!==e[0]&&"["!==e[0]&&'"'!==e[0]),!t}(n,t.doNotParse))try{return JSON.parse(n)}catch(e){}return e}var o=function(){return(o=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},s=function(){function e(e,t){var n=this;this.changeListeners=[],this.HAS_DOCUMENT_COOKIE=!1,this.cookies=function(e,t){return"string"==typeof e?r.parse(e,t):"object"==typeof e&&null!==e?e:{}}(e,t),new Promise((function(){n.HAS_DOCUMENT_COOKIE="object"==typeof document&&"string"==typeof document.cookie})).catch((function(){}))}return e.prototype._updateBrowserValues=function(e){this.HAS_DOCUMENT_COOKIE&&(this.cookies=r.parse(document.cookie,e))},e.prototype._emitChange=function(e){for(var t=0;t<this.changeListeners.length;++t)this.changeListeners[t](e)},e.prototype.get=function(e,t,n){return void 0===t&&(t={}),this._updateBrowserValues(n),i(this.cookies[e],t)},e.prototype.getAll=function(e,t){void 0===e&&(e={}),this._updateBrowserValues(t);var n={};for(var r in this.cookies)n[r]=i(this.cookies[r],e);return n},e.prototype.set=function(e,t,n){var i;"object"==typeof t&&(t=JSON.stringify(t)),this.cookies=o(o({},this.cookies),((i={})[e]=t,i)),this.HAS_DOCUMENT_COOKIE&&(document.cookie=r.serialize(e,t,n)),this._emitChange({name:e,value:t,options:n})},e.prototype.remove=function(e,t){var n=t=o(o({},t),{expires:new Date(1970,1,1,0,0,1),maxAge:0});this.cookies=o({},this.cookies),delete this.cookies[e],this.HAS_DOCUMENT_COOKIE&&(document.cookie=r.serialize(e,"",n)),this._emitChange({name:e,value:void 0,options:t})},e.prototype.addChangeListener=function(e){this.changeListeners.push(e)},e.prototype.removeChangeListener=function(e){var t=this.changeListeners.indexOf(e);t>=0&&this.changeListeners.splice(t,1)},e}(),a=n(33),u=Object(a.b)().isBrowser,c=function(){function e(e){void 0===e&&(e={}),this.cookies=new s,this.store=u?window.localStorage:Object.create(null),this.cookies=e.req?new s(e.req.headers.cookie):new s,Object.assign(this.store,this.cookies.getAll())}return Object.defineProperty(e.prototype,"length",{get:function(){return Object.entries(this.store).length},enumerable:!0,configurable:!0}),e.prototype.clear=function(){var e=this;Array.from(new Array(this.length)).map((function(t,n){return e.key(n)})).forEach((function(t){return e.removeItem(t)}))},e.prototype.getItem=function(e){return this.getLocalItem(e)},e.prototype.getLocalItem=function(e){return Object.prototype.hasOwnProperty.call(this.store,e)?this.store[e]:null},e.prototype.getUniversalItem=function(e){return this.cookies.get(e)},e.prototype.key=function(e){return Object.keys(this.store)[e]},e.prototype.removeItem=function(e){this.removeLocalItem(e),this.removeUniversalItem(e)},e.prototype.removeLocalItem=function(e){delete this.store[e]},e.prototype.removeUniversalItem=function(e){this.cookies.remove(e,{path:"/"})},e.prototype.setItem=function(e,t){switch(this.setLocalItem(e,t),e.split(".").pop()){case"LastAuthUser":case"accessToken":case"idToken":this.setUniversalItem(e,t)}},e.prototype.setLocalItem=function(e,t){this.store[e]=t},e.prototype.setUniversalItem=function(e,t){this.cookies.set(e,t,{path:"/",sameSite:!0,secure:"localhost"!==window.location.hostname})},e}()},function(e){e.exports=JSON.parse('{"name":"@aws-sdk/client-cognito-identity","description":"AWS SDK for JavaScript Cognito Identity Client for Node.js, Browser and React Native","version":"1.0.0-rc.4","scripts":{"clean":"npm run remove-definitions && npm run remove-dist","build-documentation":"npm run clean && typedoc ./","prepublishOnly":"yarn build","pretest":"yarn build:cjs","remove-definitions":"rimraf ./types","remove-dist":"rimraf ./dist","remove-documentation":"rimraf ./docs","test:unit":"mocha **/cjs/**/*.spec.js","test:e2e":"mocha **/cjs/**/*.ispec.js && karma start karma.conf.js","test":"yarn test:unit","build:cjs":"tsc -p tsconfig.json","build:es":"tsc -p tsconfig.es.json","build":"yarn build:cjs && yarn build:es"},"main":"./dist/cjs/index.js","types":"./types/index.d.ts","module":"./dist/es/index.js","browser":{"./runtimeConfig":"./runtimeConfig.browser"},"react-native":{"./runtimeConfig":"./runtimeConfig.native"},"sideEffects":false,"dependencies":{"@aws-crypto/sha256-browser":"^1.0.0","@aws-crypto/sha256-js":"^1.0.0","@aws-sdk/config-resolver":"1.0.0-rc.3","@aws-sdk/credential-provider-node":"1.0.0-rc.3","@aws-sdk/fetch-http-handler":"1.0.0-rc.3","@aws-sdk/hash-node":"1.0.0-rc.3","@aws-sdk/invalid-dependency":"1.0.0-rc.3","@aws-sdk/middleware-content-length":"1.0.0-rc.3","@aws-sdk/middleware-host-header":"1.0.0-rc.3","@aws-sdk/middleware-logger":"1.0.0-rc.4","@aws-sdk/middleware-retry":"1.0.0-rc.4","@aws-sdk/middleware-serde":"1.0.0-rc.3","@aws-sdk/middleware-signing":"1.0.0-rc.3","@aws-sdk/middleware-stack":"1.0.0-rc.4","@aws-sdk/middleware-user-agent":"1.0.0-rc.3","@aws-sdk/node-config-provider":"1.0.0-rc.3","@aws-sdk/node-http-handler":"1.0.0-rc.3","@aws-sdk/protocol-http":"1.0.0-rc.3","@aws-sdk/smithy-client":"1.0.0-rc.4","@aws-sdk/types":"1.0.0-rc.3","@aws-sdk/url-parser-browser":"1.0.0-rc.3","@aws-sdk/url-parser-node":"1.0.0-rc.3","@aws-sdk/util-base64-browser":"1.0.0-rc.3","@aws-sdk/util-base64-node":"1.0.0-rc.3","@aws-sdk/util-body-length-browser":"1.0.0-rc.3","@aws-sdk/util-body-length-node":"1.0.0-rc.3","@aws-sdk/util-user-agent-browser":"1.0.0-rc.3","@aws-sdk/util-user-agent-node":"1.0.0-rc.3","@aws-sdk/util-utf8-browser":"1.0.0-rc.3","@aws-sdk/util-utf8-node":"1.0.0-rc.3","tslib":"^2.0.0"},"devDependencies":{"@aws-sdk/client-documentation-generator":"1.0.0-rc.3","@aws-sdk/client-iam":"1.0.0-rc.4","@types/chai":"^4.2.11","@types/mocha":"^7.0.2","@types/node":"^12.7.5","jest":"^26.1.0","rimraf":"^3.0.0","typedoc":"^0.17.8","typescript":"~4.0.2"},"engines":{"node":">=10.0.0"},"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","homepage":"https://github.com/aws/aws-sdk-js-v3/tree/master/clients/client-cognito-identity","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-cognito-identity"}}')},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(1).__exportStar(n(385),t)},function(e){e.exports=JSON.parse('{"name":"@aws-sdk/client-pinpoint","description":"AWS SDK for JavaScript Pinpoint Client for Node.js, Browser and React Native","version":"1.0.0-rc.4","scripts":{"clean":"npm run remove-definitions && npm run remove-dist","build-documentation":"npm run clean && typedoc ./","prepublishOnly":"yarn build","pretest":"yarn build:cjs","remove-definitions":"rimraf ./types","remove-dist":"rimraf ./dist","remove-documentation":"rimraf ./docs","test":"exit 0","build:cjs":"tsc -p tsconfig.json","build:es":"tsc -p tsconfig.es.json","build":"yarn build:cjs && yarn build:es"},"main":"./dist/cjs/index.js","types":"./types/index.d.ts","module":"./dist/es/index.js","browser":{"./runtimeConfig":"./runtimeConfig.browser"},"react-native":{"./runtimeConfig":"./runtimeConfig.native"},"sideEffects":false,"dependencies":{"@aws-crypto/sha256-browser":"^1.0.0","@aws-crypto/sha256-js":"^1.0.0","@aws-sdk/config-resolver":"1.0.0-rc.3","@aws-sdk/credential-provider-node":"1.0.0-rc.3","@aws-sdk/fetch-http-handler":"1.0.0-rc.3","@aws-sdk/hash-node":"1.0.0-rc.3","@aws-sdk/invalid-dependency":"1.0.0-rc.3","@aws-sdk/middleware-content-length":"1.0.0-rc.3","@aws-sdk/middleware-host-header":"1.0.0-rc.3","@aws-sdk/middleware-logger":"1.0.0-rc.4","@aws-sdk/middleware-retry":"1.0.0-rc.4","@aws-sdk/middleware-serde":"1.0.0-rc.3","@aws-sdk/middleware-signing":"1.0.0-rc.3","@aws-sdk/middleware-stack":"1.0.0-rc.4","@aws-sdk/middleware-user-agent":"1.0.0-rc.3","@aws-sdk/node-config-provider":"1.0.0-rc.3","@aws-sdk/node-http-handler":"1.0.0-rc.3","@aws-sdk/protocol-http":"1.0.0-rc.3","@aws-sdk/smithy-client":"1.0.0-rc.4","@aws-sdk/types":"1.0.0-rc.3","@aws-sdk/url-parser-browser":"1.0.0-rc.3","@aws-sdk/url-parser-node":"1.0.0-rc.3","@aws-sdk/util-base64-browser":"1.0.0-rc.3","@aws-sdk/util-base64-node":"1.0.0-rc.3","@aws-sdk/util-body-length-browser":"1.0.0-rc.3","@aws-sdk/util-body-length-node":"1.0.0-rc.3","@aws-sdk/util-user-agent-browser":"1.0.0-rc.3","@aws-sdk/util-user-agent-node":"1.0.0-rc.3","@aws-sdk/util-utf8-browser":"1.0.0-rc.3","@aws-sdk/util-utf8-node":"1.0.0-rc.3","tslib":"^2.0.0"},"devDependencies":{"@aws-sdk/client-documentation-generator":"1.0.0-rc.3","@types/node":"^12.7.5","jest":"^26.1.0","rimraf":"^3.0.0","typedoc":"^0.17.8","typescript":"~4.0.2"},"engines":{"node":">=10.0.0"},"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","homepage":"https://github.com/aws/aws-sdk-js-v3/tree/master/clients/client-pinpoint","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-pinpoint"}}')},function(e){e.exports=JSON.parse('{"name":"@aws-sdk/client-kinesis","description":"AWS SDK for JavaScript Kinesis Client for Node.js, Browser and React Native","version":"1.0.0-rc.4","scripts":{"clean":"npm run remove-definitions && npm run remove-dist","build-documentation":"npm run clean && typedoc ./","prepublishOnly":"yarn build","pretest":"yarn build:cjs","remove-definitions":"rimraf ./types","remove-dist":"rimraf ./dist","remove-documentation":"rimraf ./docs","test":"exit 0","build:cjs":"tsc -p tsconfig.json","build:es":"tsc -p tsconfig.es.json","build":"yarn build:cjs && yarn build:es"},"main":"./dist/cjs/index.js","types":"./types/index.d.ts","module":"./dist/es/index.js","browser":{"./runtimeConfig":"./runtimeConfig.browser"},"react-native":{"./runtimeConfig":"./runtimeConfig.native"},"sideEffects":false,"dependencies":{"@aws-crypto/sha256-browser":"^1.0.0","@aws-crypto/sha256-js":"^1.0.0","@aws-sdk/config-resolver":"1.0.0-rc.3","@aws-sdk/credential-provider-node":"1.0.0-rc.3","@aws-sdk/eventstream-serde-browser":"1.0.0-rc.3","@aws-sdk/eventstream-serde-config-resolver":"1.0.0-rc.3","@aws-sdk/eventstream-serde-node":"1.0.0-rc.3","@aws-sdk/fetch-http-handler":"1.0.0-rc.3","@aws-sdk/hash-node":"1.0.0-rc.3","@aws-sdk/invalid-dependency":"1.0.0-rc.3","@aws-sdk/middleware-content-length":"1.0.0-rc.3","@aws-sdk/middleware-host-header":"1.0.0-rc.3","@aws-sdk/middleware-logger":"1.0.0-rc.4","@aws-sdk/middleware-retry":"1.0.0-rc.4","@aws-sdk/middleware-serde":"1.0.0-rc.3","@aws-sdk/middleware-signing":"1.0.0-rc.3","@aws-sdk/middleware-stack":"1.0.0-rc.4","@aws-sdk/middleware-user-agent":"1.0.0-rc.3","@aws-sdk/node-config-provider":"1.0.0-rc.3","@aws-sdk/node-http-handler":"1.0.0-rc.3","@aws-sdk/protocol-http":"1.0.0-rc.3","@aws-sdk/smithy-client":"1.0.0-rc.4","@aws-sdk/types":"1.0.0-rc.3","@aws-sdk/url-parser-browser":"1.0.0-rc.3","@aws-sdk/url-parser-node":"1.0.0-rc.3","@aws-sdk/util-base64-browser":"1.0.0-rc.3","@aws-sdk/util-base64-node":"1.0.0-rc.3","@aws-sdk/util-body-length-browser":"1.0.0-rc.3","@aws-sdk/util-body-length-node":"1.0.0-rc.3","@aws-sdk/util-user-agent-browser":"1.0.0-rc.3","@aws-sdk/util-user-agent-node":"1.0.0-rc.3","@aws-sdk/util-utf8-browser":"1.0.0-rc.3","@aws-sdk/util-utf8-node":"1.0.0-rc.3","tslib":"^2.0.0"},"devDependencies":{"@aws-sdk/client-documentation-generator":"1.0.0-rc.3","@types/node":"^12.7.5","jest":"^26.1.0","rimraf":"^3.0.0","typedoc":"^0.17.8","typescript":"~4.0.2"},"engines":{"node":">=10.0.0"},"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","homepage":"https://github.com/aws/aws-sdk-js-v3/tree/master/clients/client-kinesis","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-kinesis"}}')},function(e){e.exports=JSON.parse('{"name":"@aws-sdk/client-firehose","description":"AWS SDK for JavaScript Firehose Client for Node.js, Browser and React Native","version":"1.0.0-rc.4","scripts":{"clean":"npm run remove-definitions && npm run remove-dist","build-documentation":"npm run clean && typedoc ./","prepublishOnly":"yarn build","pretest":"yarn build:cjs","remove-definitions":"rimraf ./types","remove-dist":"rimraf ./dist","remove-documentation":"rimraf ./docs","test":"exit 0","build:cjs":"tsc -p tsconfig.json","build:es":"tsc -p tsconfig.es.json","build":"yarn build:cjs && yarn build:es"},"main":"./dist/cjs/index.js","types":"./types/index.d.ts","module":"./dist/es/index.js","browser":{"./runtimeConfig":"./runtimeConfig.browser"},"react-native":{"./runtimeConfig":"./runtimeConfig.native"},"sideEffects":false,"dependencies":{"@aws-crypto/sha256-browser":"^1.0.0","@aws-crypto/sha256-js":"^1.0.0","@aws-sdk/config-resolver":"1.0.0-rc.3","@aws-sdk/credential-provider-node":"1.0.0-rc.3","@aws-sdk/fetch-http-handler":"1.0.0-rc.3","@aws-sdk/hash-node":"1.0.0-rc.3","@aws-sdk/invalid-dependency":"1.0.0-rc.3","@aws-sdk/middleware-content-length":"1.0.0-rc.3","@aws-sdk/middleware-host-header":"1.0.0-rc.3","@aws-sdk/middleware-logger":"1.0.0-rc.4","@aws-sdk/middleware-retry":"1.0.0-rc.4","@aws-sdk/middleware-serde":"1.0.0-rc.3","@aws-sdk/middleware-signing":"1.0.0-rc.3","@aws-sdk/middleware-stack":"1.0.0-rc.4","@aws-sdk/middleware-user-agent":"1.0.0-rc.3","@aws-sdk/node-config-provider":"1.0.0-rc.3","@aws-sdk/node-http-handler":"1.0.0-rc.3","@aws-sdk/protocol-http":"1.0.0-rc.3","@aws-sdk/smithy-client":"1.0.0-rc.4","@aws-sdk/types":"1.0.0-rc.3","@aws-sdk/url-parser-browser":"1.0.0-rc.3","@aws-sdk/url-parser-node":"1.0.0-rc.3","@aws-sdk/util-base64-browser":"1.0.0-rc.3","@aws-sdk/util-base64-node":"1.0.0-rc.3","@aws-sdk/util-body-length-browser":"1.0.0-rc.3","@aws-sdk/util-body-length-node":"1.0.0-rc.3","@aws-sdk/util-user-agent-browser":"1.0.0-rc.3","@aws-sdk/util-user-agent-node":"1.0.0-rc.3","@aws-sdk/util-utf8-browser":"1.0.0-rc.3","@aws-sdk/util-utf8-node":"1.0.0-rc.3","tslib":"^2.0.0"},"devDependencies":{"@aws-sdk/client-documentation-generator":"1.0.0-rc.3","@types/node":"^12.7.5","jest":"^26.1.0","rimraf":"^3.0.0","typedoc":"^0.17.8","typescript":"~4.0.2"},"engines":{"node":">=10.0.0"},"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","homepage":"https://github.com/aws/aws-sdk-js-v3/tree/master/clients/client-firehose","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-firehose"}}')},function(e){e.exports=JSON.parse('{"name":"@aws-sdk/client-personalize-events","description":"AWS SDK for JavaScript Personalize Events Client for Node.js, Browser and React Native","version":"1.0.0-rc.4","scripts":{"clean":"npm run remove-definitions && npm run remove-dist","build-documentation":"npm run clean && typedoc ./","prepublishOnly":"yarn build","pretest":"yarn build:cjs","remove-definitions":"rimraf ./types","remove-dist":"rimraf ./dist","remove-documentation":"rimraf ./docs","test":"exit 0","build:cjs":"tsc -p tsconfig.json","build:es":"tsc -p tsconfig.es.json","build":"yarn build:cjs && yarn build:es"},"main":"./dist/cjs/index.js","types":"./types/index.d.ts","module":"./dist/es/index.js","browser":{"./runtimeConfig":"./runtimeConfig.browser"},"react-native":{"./runtimeConfig":"./runtimeConfig.native"},"sideEffects":false,"dependencies":{"@aws-crypto/sha256-browser":"^1.0.0","@aws-crypto/sha256-js":"^1.0.0","@aws-sdk/config-resolver":"1.0.0-rc.3","@aws-sdk/credential-provider-node":"1.0.0-rc.3","@aws-sdk/fetch-http-handler":"1.0.0-rc.3","@aws-sdk/hash-node":"1.0.0-rc.3","@aws-sdk/invalid-dependency":"1.0.0-rc.3","@aws-sdk/middleware-content-length":"1.0.0-rc.3","@aws-sdk/middleware-host-header":"1.0.0-rc.3","@aws-sdk/middleware-logger":"1.0.0-rc.4","@aws-sdk/middleware-retry":"1.0.0-rc.4","@aws-sdk/middleware-serde":"1.0.0-rc.3","@aws-sdk/middleware-signing":"1.0.0-rc.3","@aws-sdk/middleware-stack":"1.0.0-rc.4","@aws-sdk/middleware-user-agent":"1.0.0-rc.3","@aws-sdk/node-config-provider":"1.0.0-rc.3","@aws-sdk/node-http-handler":"1.0.0-rc.3","@aws-sdk/protocol-http":"1.0.0-rc.3","@aws-sdk/smithy-client":"1.0.0-rc.4","@aws-sdk/types":"1.0.0-rc.3","@aws-sdk/url-parser-browser":"1.0.0-rc.3","@aws-sdk/url-parser-node":"1.0.0-rc.3","@aws-sdk/util-base64-browser":"1.0.0-rc.3","@aws-sdk/util-base64-node":"1.0.0-rc.3","@aws-sdk/util-body-length-browser":"1.0.0-rc.3","@aws-sdk/util-body-length-node":"1.0.0-rc.3","@aws-sdk/util-user-agent-browser":"1.0.0-rc.3","@aws-sdk/util-user-agent-node":"1.0.0-rc.3","@aws-sdk/util-utf8-browser":"1.0.0-rc.3","@aws-sdk/util-utf8-node":"1.0.0-rc.3","tslib":"^2.0.0"},"devDependencies":{"@aws-sdk/client-documentation-generator":"1.0.0-rc.3","@types/node":"^12.7.5","jest":"^26.1.0","rimraf":"^3.0.0","typedoc":"^0.17.8","typescript":"~4.0.2"},"engines":{"node":">=10.0.0"},"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","homepage":"https://github.com/aws/aws-sdk-js-v3/tree/master/clients/client-personalize-events","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-personalize-events"}}')},function(e){e.exports=JSON.parse('{"name":"@aws-sdk/client-s3","description":"AWS SDK for JavaScript S3 Client for Node.js, Browser and React Native","version":"1.0.0-rc.4","scripts":{"clean":"npm run remove-definitions && npm run remove-dist","build-documentation":"npm run clean && typedoc ./","prepublishOnly":"yarn build","pretest":"yarn build:cjs","remove-definitions":"rimraf ./types","remove-dist":"rimraf ./dist","remove-documentation":"rimraf ./docs","test:unit":"mocha **/cjs/**/*.spec.js","test:e2e":"mocha **/cjs/**/*.ispec.js && karma start karma.conf.js","test":"yarn test:unit","build:cjs":"tsc -p tsconfig.json","build:es":"tsc -p tsconfig.es.json","build":"yarn build:cjs && yarn build:es"},"main":"./dist/cjs/index.js","types":"./types/index.d.ts","module":"./dist/es/index.js","browser":{"./runtimeConfig":"./runtimeConfig.browser"},"react-native":{"./runtimeConfig":"./runtimeConfig.native"},"sideEffects":false,"dependencies":{"@aws-crypto/sha256-browser":"^1.0.0","@aws-crypto/sha256-js":"^1.0.0","@aws-sdk/config-resolver":"1.0.0-rc.3","@aws-sdk/credential-provider-node":"1.0.0-rc.3","@aws-sdk/eventstream-serde-browser":"1.0.0-rc.3","@aws-sdk/eventstream-serde-config-resolver":"1.0.0-rc.3","@aws-sdk/eventstream-serde-node":"1.0.0-rc.3","@aws-sdk/fetch-http-handler":"1.0.0-rc.3","@aws-sdk/hash-blob-browser":"1.0.0-rc.3","@aws-sdk/hash-node":"1.0.0-rc.3","@aws-sdk/hash-stream-node":"1.0.0-rc.3","@aws-sdk/invalid-dependency":"1.0.0-rc.3","@aws-sdk/md5-js":"1.0.0-rc.3","@aws-sdk/middleware-apply-body-checksum":"1.0.0-rc.3","@aws-sdk/middleware-bucket-endpoint":"1.0.0-rc.4","@aws-sdk/middleware-content-length":"1.0.0-rc.3","@aws-sdk/middleware-expect-continue":"1.0.0-rc.3","@aws-sdk/middleware-host-header":"1.0.0-rc.3","@aws-sdk/middleware-location-constraint":"1.0.0-rc.3","@aws-sdk/middleware-logger":"1.0.0-rc.4","@aws-sdk/middleware-retry":"1.0.0-rc.4","@aws-sdk/middleware-sdk-s3":"1.0.0-rc.3","@aws-sdk/middleware-serde":"1.0.0-rc.3","@aws-sdk/middleware-signing":"1.0.0-rc.3","@aws-sdk/middleware-ssec":"1.0.0-rc.3","@aws-sdk/middleware-stack":"1.0.0-rc.4","@aws-sdk/middleware-user-agent":"1.0.0-rc.3","@aws-sdk/node-config-provider":"1.0.0-rc.3","@aws-sdk/node-http-handler":"1.0.0-rc.3","@aws-sdk/protocol-http":"1.0.0-rc.3","@aws-sdk/smithy-client":"1.0.0-rc.4","@aws-sdk/types":"1.0.0-rc.3","@aws-sdk/url-parser-browser":"1.0.0-rc.3","@aws-sdk/url-parser-node":"1.0.0-rc.3","@aws-sdk/util-base64-browser":"1.0.0-rc.3","@aws-sdk/util-base64-node":"1.0.0-rc.3","@aws-sdk/util-body-length-browser":"1.0.0-rc.3","@aws-sdk/util-body-length-node":"1.0.0-rc.3","@aws-sdk/util-user-agent-browser":"1.0.0-rc.3","@aws-sdk/util-user-agent-node":"1.0.0-rc.3","@aws-sdk/util-utf8-browser":"1.0.0-rc.3","@aws-sdk/util-utf8-node":"1.0.0-rc.3","@aws-sdk/xml-builder":"1.0.0-rc.3","fast-xml-parser":"^3.16.0","tslib":"^2.0.0"},"devDependencies":{"@aws-sdk/client-documentation-generator":"1.0.0-rc.3","@types/chai":"^4.2.11","@types/mocha":"^7.0.2","@types/node":"^12.7.5","jest":"^26.1.0","rimraf":"^3.0.0","typedoc":"^0.17.8","typescript":"~4.0.2"},"engines":{"node":">=10.0.0"},"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","homepage":"https://github.com/aws/aws-sdk-js-v3/tree/master/clients/client-s3","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-s3"}}')},function(e,t,n){"use strict";(function(e){n.d(t,"a",(function(){return r})),n.d(t,"b",(function(){return S}));var r,i,o=n(58),s=n(52),a=n(42),u=n(26),c=n(44),f=n(88),l=n(34),d=n(14),h=n(13),p=n(9),v=n(3),g=function(){return(g=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},m=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},b=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},y=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},w=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(y(arguments[t]));return e},_=new c.a("DataStore");!function(e){e.CONNECTED="CONNECTED"}(r||(r={})),function(e){e[e.none=0]="none",e[e.unauth=1]="unauth",e[e.auth=2]="auth"}(i||(i={}));var S=function(){function t(e,t,n){void 0===n&&(n={}),this.schema=e,this.syncPredicates=t,this.amplifyConfig=n,this.typeQuery=new WeakMap,this.buffer=[]}return t.prototype.buildSubscription=function(e,t,n,r,i,o){var s=this.amplifyConfig.aws_appsync_authenticationType,a=this.getAuthorizationInfo(t,r,s,i,o)||{},u=a.authMode,c=a.isOwner,f=a.ownerField,l=a.ownerValue,d=y(Object(h.c)(e,t,n,c,f),3);return{authMode:u,opType:d[0],opName:d[1],query:d[2],isOwner:c,ownerField:f,ownerValue:l}},t.prototype.getAuthorizationInfo=function(e,t,n,r,s){void 0===r&&(r={}),void 0===s&&(s={});var a=Object(h.e)(e);if(n===o.a.AWS_IAM&&a.find((function(e){return"private"===e.authStrategy&&"iam"===e.provider}))&&t===i.unauth)return null;var u,c=a.filter((function(e){return"groups"===e.authStrategy&&["userPools","oidc"].includes(e.provider)}));return n!==o.a.AMAZON_COGNITO_USER_POOLS&&n!==o.a.OPENID_CONNECT||!c.find((function(e){var t=Object(h.f)(r,e),n=Object(h.f)(s,e);return w(t,n).find((function(t){return e.groups.find((function(e){return e===t}))}))}))?((n===o.a.AMAZON_COGNITO_USER_POOLS?a.filter((function(e){return"owner"===e.authStrategy&&"userPools"===e.provider})):[]).forEach((function(e){var t=r[e.identityClaim];t&&(u={authMode:o.a.AMAZON_COGNITO_USER_POOLS,isOwner:!e.areSubscriptionsPublic,ownerField:e.ownerField,ownerValue:t})})),u||((n===o.a.OPENID_CONNECT?a.filter((function(e){return"owner"===e.authStrategy&&"oidc"===e.provider})):[]).forEach((function(e){var t=s[e.identityClaim];t&&(u={authMode:o.a.OPENID_CONNECT,isOwner:!e.areSubscriptionsPublic,ownerField:e.ownerField,ownerValue:t})})),u||{authMode:n,isOwner:!1})):{authMode:n,isOwner:!1}},t.prototype.hubQueryCompletionListener=function(e,t){t.payload.event===l.a.SUBSCRIPTION_ACK&&e()},t.prototype.start=function(){var t=this;return[new d.a((function(n){var o,c,l=[],d=[],v=i.none;return m(t,void 0,void 0,(function(){var t,w,S,E,M,A,I,k,O,x,C=this;return b(this,(function(T){switch(T.label){case 0:return T.trys.push([0,2,,3]),[4,a.a.currentCredentials()];case 1:return t=T.sent(),v=t.authenticated?i.auth:i.unauth,[3,3];case 2:return T.sent(),[3,3];case 3:return T.trys.push([3,5,,6]),[4,a.a.currentSession()];case 4:return w=T.sent(),o=w.getIdToken().decodePayload(),[3,6];case 5:return T.sent(),[3,6];case 6:if(T.trys.push([6,11,,12]),S=this.amplifyConfig,E=S.aws_cognito_region,M=S.Auth,!E||M&&!M.region)throw"Auth is not configured";return A=void 0,[4,u.a.getItem("federatedInfo")];case 7:return(I=T.sent())?(A=I.token,[3,10]):[3,8];case 8:return[4,a.a.currentAuthenticatedUser()];case 9:(k=T.sent())&&(A=k.token),T.label=10;case 10:return A&&(O=A.split(".")[1],c=JSON.parse(e.from(O,"base64").toString("utf8"))),[3,12];case 11:return x=T.sent(),_.debug("error getting OIDC JWT",x),[3,12];case 12:return Object.values(this.schema.namespaces).forEach((function(e){Object.values(e.models).filter((function(e){return e.syncable})).forEach((function(t){return m(C,void 0,void 0,(function(){var r=this;return b(this,(function(i){return[h.a.CREATE,h.a.UPDATE,h.a.DELETE].map((function(n){return r.buildSubscription(e,t,n,v,o,c)})).forEach((function(e){var i=e.opType,o=e.opName,a=e.query,u=e.isOwner,c=e.ownerField,h=e.ownerValue,v=e.authMode;return m(r,void 0,void 0,(function(){var e,r,w,S=this;return b(this,(function(E){if(e={},u){if(!h)return n.error("Owner field required, sign in is needed in order to perform this operation"),[2];e[c]=h}return r=s.a.graphql(g({query:a,variables:e},{authMode:v})),d.push(r.map((function(e){return e.value})).subscribe({next:function(e){var n=e.data,r=e.errors;if(Array.isArray(r)&&r.length>0){var s=r.map((function(e){return e.message}));return _.warn("Skipping incoming subscription. Messages: "+s.join("\n")),void S.drainBuffer()}var a=p.a.getPredicates(S.syncPredicates.get(t),!1),u=n[o];S.passesPredicateValidation(u,a)&&S.pushToBuffer(i,t,u),S.drainBuffer()},error:function(e){var t=e.error,r=y((void 0===t?{errors:[]}:t).errors,1)[0],i=(void 0===r?{}:r).message,o=void 0===i?"":i;_.warn("subscriptionError",o),"function"==typeof w&&w(),o.includes('"errorType":"Unauthorized"')||n.error(o)}})),l.push(m(S,void 0,void 0,(function(){var e,t=this;return b(this,(function(n){switch(n.label){case 0:return[4,new Promise((function(n){w=n,e=t.hubQueryCompletionListener.bind(t,n),f.a.listen("api",e)}))];case 1:return n.sent(),f.a.remove("api",e),[2]}}))}))),[2]}))}))})),[2]}))}))}))})),Promise.all(l).then((function(){return n.next(r.CONNECTED)})),[2]}}))})),function(){d.forEach((function(e){return e.unsubscribe()}))}})),new d.a((function(e){return t.dataObserver=e,t.drainBuffer(),function(){t.dataObserver=null}}))]},t.prototype.passesPredicateValidation=function(e,t){if(!t)return!0;var n=t.predicates,r=t.type;return Object(v.y)(e,r,n)},t.prototype.pushToBuffer=function(e,t,n){this.buffer.push([e,t,n])},t.prototype.drainBuffer=function(){var e=this;this.dataObserver&&(this.buffer.forEach((function(t){return e.dataObserver.next(t)})),this.buffer=[])},t}()}).call(this,n(6).Buffer)},function(e){e.exports=JSON.parse('{"name":"@aws-sdk/client-lex-runtime-service","description":"AWS SDK for JavaScript Lex Runtime Service Client for Node.js, Browser and React Native","version":"1.0.0-rc.4","scripts":{"clean":"npm run remove-definitions && npm run remove-dist","build-documentation":"npm run clean && typedoc ./","prepublishOnly":"yarn build","pretest":"yarn build:cjs","remove-definitions":"rimraf ./types","remove-dist":"rimraf ./dist","remove-documentation":"rimraf ./docs","test:unit":"mocha **/cjs/**/*.spec.js","test":"yarn test:unit","build:cjs":"tsc -p tsconfig.json","build:es":"tsc -p tsconfig.es.json","build":"yarn build:cjs && yarn build:es"},"main":"./dist/cjs/index.js","types":"./types/index.d.ts","module":"./dist/es/index.js","browser":{"./runtimeConfig":"./runtimeConfig.browser"},"react-native":{"./runtimeConfig":"./runtimeConfig.native"},"sideEffects":false,"dependencies":{"@aws-crypto/sha256-browser":"^1.0.0","@aws-crypto/sha256-js":"^1.0.0","@aws-sdk/config-resolver":"1.0.0-rc.3","@aws-sdk/credential-provider-node":"1.0.0-rc.3","@aws-sdk/fetch-http-handler":"1.0.0-rc.3","@aws-sdk/hash-node":"1.0.0-rc.3","@aws-sdk/invalid-dependency":"1.0.0-rc.3","@aws-sdk/middleware-content-length":"1.0.0-rc.3","@aws-sdk/middleware-host-header":"1.0.0-rc.3","@aws-sdk/middleware-logger":"1.0.0-rc.4","@aws-sdk/middleware-retry":"1.0.0-rc.4","@aws-sdk/middleware-serde":"1.0.0-rc.3","@aws-sdk/middleware-signing":"1.0.0-rc.3","@aws-sdk/middleware-stack":"1.0.0-rc.4","@aws-sdk/middleware-user-agent":"1.0.0-rc.3","@aws-sdk/node-config-provider":"1.0.0-rc.3","@aws-sdk/node-http-handler":"1.0.0-rc.3","@aws-sdk/protocol-http":"1.0.0-rc.3","@aws-sdk/smithy-client":"1.0.0-rc.4","@aws-sdk/types":"1.0.0-rc.3","@aws-sdk/url-parser-browser":"1.0.0-rc.3","@aws-sdk/url-parser-node":"1.0.0-rc.3","@aws-sdk/util-base64-browser":"1.0.0-rc.3","@aws-sdk/util-base64-node":"1.0.0-rc.3","@aws-sdk/util-body-length-browser":"1.0.0-rc.3","@aws-sdk/util-body-length-node":"1.0.0-rc.3","@aws-sdk/util-user-agent-browser":"1.0.0-rc.3","@aws-sdk/util-user-agent-node":"1.0.0-rc.3","@aws-sdk/util-utf8-browser":"1.0.0-rc.3","@aws-sdk/util-utf8-node":"1.0.0-rc.3","tslib":"^2.0.0"},"devDependencies":{"@aws-sdk/client-documentation-generator":"1.0.0-rc.3","@types/chai":"^4.2.11","@types/mocha":"^7.0.2","@types/node":"^12.7.5","jest":"^26.1.0","rimraf":"^3.0.0","typedoc":"^0.17.8","typescript":"~4.0.2"},"engines":{"node":">=10.0.0"},"author":{"name":"AWS SDK for JavaScript Team","url":"https://aws.amazon.com/javascript/"},"license":"Apache-2.0","homepage":"https://github.com/aws/aws-sdk-js-v3/tree/master/clients/client-lex-runtime-service","repository":{"type":"git","url":"https://github.com/aws/aws-sdk-js-v3.git","directory":"clients/client-lex-runtime-service"}}')},,function(e,t,n){"use strict";n.r(t);var r=n(19),i=n(143);n.d(t,"Amplify",(function(){return r.a}));var o=n(63),s=n(26),a=n(491);n.d(t,"Analytics",(function(){return a.a}));var u=n(144);n.d(t,"AWSPinpointProvider",(function(){return u.a}));var c=n(145);n.d(t,"AWSKinesisProvider",(function(){return c.a}));var f=n(492);n.d(t,"AWSKinesisFirehoseProvider",(function(){return f.a}));var l=n(490);n.d(t,"AmazonPersonalizeProvider",(function(){return l.a})),n.d(t,"Auth",(function(){return o.a}));var d=n(140);n.d(t,"Storage",(function(){return d.a})),n.d(t,"StorageClass",(function(){return d.b}));var h=n(62);n.d(t,"API",(function(){return h.a})),n.d(t,"APIClass",(function(){return h.b}));var p=n(248);n.d(t,"graphqlOperation",(function(){return p.b}));var v=n(258);n.d(t,"DataStore",(function(){return v.a}));var g=n(9);n.d(t,"Predicates",(function(){return g.b}));var m=n(4);n.d(t,"SortDirection",(function(){return m.e})),n.d(t,"syncExpression",(function(){return m.n}));var b=n(105);n.d(t,"PubSub",(function(){return b.a})),n.d(t,"Cache",(function(){return s.a}));var y=n(489);n.d(t,"Interactions",(function(){return y.a}));var w=n(246);for(var _ in w)["default","Analytics","AWSPinpointProvider","AWSKinesisProvider","AWSKinesisFirehoseProvider","AmazonPersonalizeProvider","Auth","Storage","StorageClass","API","APIClass","graphqlOperation","DataStore","Predicates","SortDirection","syncExpression","PubSub","Cache","Interactions","XR","Predictions","Logger","Hub","JS","ClientDevice","Signer","I18n","ServiceWorker","withSSRContext","Amplify"].indexOf(_)<0&&function(e){n.d(t,e,(function(){return w[e]}))}(_);var S=n(493);n.d(t,"XR",(function(){return S.a}));var E=n(488);n.d(t,"Predictions",(function(){return E.a}));var M=n(44);n.d(t,"Logger",(function(){return M.a}));var A=n(88);n.d(t,"Hub",(function(){return A.a}));var I=n(33);n.d(t,"JS",(function(){return I.a}));var k=n(141);n.d(t,"ClientDevice",(function(){return k.a}));var O=n(104);n.d(t,"Signer",(function(){return O.a}));var x=n(142);n.d(t,"I18n",(function(){return x.a})),n.d(t,"ServiceWorker",(function(){return i.a}));var C=n(247);n.d(t,"withSSRContext",(function(){return C.a})),r.a.Auth=o.a,r.a.Cache=s.a,r.a.ServiceWorker=i.a,t.default=r.a},,,function(e,t){var n={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==n.call(e)}},function(e,t,n){var r;e.exports=(r=n(32),function(){if("function"==typeof ArrayBuffer){var e=r.lib.WordArray,t=e.init;(e.init=function(e){if(e instanceof ArrayBuffer&&(e=new Uint8Array(e)),(e instanceof Int8Array||"undefined"!=typeof Uint8ClampedArray&&e instanceof Uint8ClampedArray||e instanceof Int16Array||e instanceof Uint16Array||e instanceof Int32Array||e instanceof Uint32Array||e instanceof Float32Array||e instanceof Float64Array)&&(e=new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),e instanceof Uint8Array){for(var n=e.byteLength,r=[],i=0;i<n;i++)r[i>>>2]|=e[i]<<24-i%4*8;t.call(this,r,n)}else t.apply(this,arguments)}).prototype=e}}(),r.lib.WordArray)},function(e,t,n){"use strict";var r=n(8).Buffer,i=n(273).Transform;function o(e){i.call(this),this._block=r.allocUnsafe(e),this._blockSize=e,this._blockOffset=0,this._length=[0,0,0,0],this._finalized=!1}n(7)(o,i),o.prototype._transform=function(e,t,n){var r=null;try{this.update(e,t)}catch(e){r=e}n(r)},o.prototype._flush=function(e){var t=null;try{this.push(this.digest())}catch(e){t=e}e(t)},o.prototype.update=function(e,t){if(function(e,t){if(!r.isBuffer(e)&&"string"!=typeof e)throw new TypeError(t+" must be a string or a buffer")}(e,"Data"),this._finalized)throw new Error("Digest already called");r.isBuffer(e)||(e=r.from(e,t));for(var n=this._block,i=0;this._blockOffset+e.length-i>=this._blockSize;){for(var o=this._blockOffset;o<this._blockSize;)n[o++]=e[i++];this._update(),this._blockOffset=0}for(;i<e.length;)n[this._blockOffset++]=e[i++];for(var s=0,a=8*e.length;a>0;++s)this._length[s]+=a,(a=this._length[s]/4294967296|0)>0&&(this._length[s]-=4294967296*a);return this},o.prototype._update=function(){throw new Error("_update is not implemented")},o.prototype.digest=function(e){if(this._finalized)throw new Error("Digest already called");this._finalized=!0;var t=this._digest();void 0!==e&&(t=t.toString(e)),this._block.fill(0),this._blockOffset=0;for(var n=0;n<4;++n)this._length[n]=0;return t},o.prototype._digest=function(){throw new Error("_digest is not implemented")},e.exports=o},function(e,t,n){"use strict";(function(t,r){var i;e.exports=A,A.ReadableState=M;n(49).EventEmitter;var o=function(e,t){return e.listeners(t).length},s=n(164),a=n(6).Buffer,u=t.Uint8Array||function(){};var c,f=n(274);c=f&&f.debuglog?f.debuglog("stream"):function(){};var l,d,h,p=n(275),v=n(165),g=n(166).getHighWaterMark,m=n(67).codes,b=m.ERR_INVALID_ARG_TYPE,y=m.ERR_STREAM_PUSH_AFTER_EOF,w=m.ERR_METHOD_NOT_IMPLEMENTED,_=m.ERR_STREAM_UNSHIFT_AFTER_END_EVENT;n(7)(A,s);var S=v.errorOrDestroy,E=["error","close","destroy","pause","resume"];function M(e,t,r){i=i||n(68),e=e||{},"boolean"!=typeof r&&(r=t instanceof i),this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.readableObjectMode),this.highWaterMark=g(this,e,"readableHighWaterMark",r),this.buffer=new p,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.paused=!0,this.emitClose=!1!==e.emitClose,this.autoDestroy=!!e.autoDestroy,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(l||(l=n(59).StringDecoder),this.decoder=new l(e.encoding),this.encoding=e.encoding)}function A(e){if(i=i||n(68),!(this instanceof A))return new A(e);var t=this instanceof i;this._readableState=new M(e,this,t),this.readable=!0,e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy)),s.call(this)}function I(e,t,n,r,i){c("readableAddChunk",t);var o,s=e._readableState;if(null===t)s.reading=!1,function(e,t){if(c("onEofChunk"),t.ended)return;if(t.decoder){var n=t.decoder.end();n&&n.length&&(t.buffer.push(n),t.length+=t.objectMode?1:n.length)}t.ended=!0,t.sync?x(e):(t.needReadable=!1,t.emittedReadable||(t.emittedReadable=!0,C(e)))}(e,s);else if(i||(o=function(e,t){var n;r=t,a.isBuffer(r)||r instanceof u||"string"==typeof t||void 0===t||e.objectMode||(n=new b("chunk",["string","Buffer","Uint8Array"],t));var r;return n}(s,t)),o)S(e,o);else if(s.objectMode||t&&t.length>0)if("string"==typeof t||s.objectMode||Object.getPrototypeOf(t)===a.prototype||(t=function(e){return a.from(e)}(t)),r)s.endEmitted?S(e,new _):k(e,s,t,!0);else if(s.ended)S(e,new y);else{if(s.destroyed)return!1;s.reading=!1,s.decoder&&!n?(t=s.decoder.write(t),s.objectMode||0!==t.length?k(e,s,t,!1):T(e,s)):k(e,s,t,!1)}else r||(s.reading=!1,T(e,s));return!s.ended&&(s.length<s.highWaterMark||0===s.length)}function k(e,t,n,r){t.flowing&&0===t.length&&!t.sync?(t.awaitDrain=0,e.emit("data",n)):(t.length+=t.objectMode?1:n.length,r?t.buffer.unshift(n):t.buffer.push(n),t.needReadable&&x(e)),T(e,t)}Object.defineProperty(A.prototype,"destroyed",{enumerable:!1,get:function(){return void 0!==this._readableState&&this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}}),A.prototype.destroy=v.destroy,A.prototype._undestroy=v.undestroy,A.prototype._destroy=function(e,t){t(e)},A.prototype.push=function(e,t){var n,r=this._readableState;return r.objectMode?n=!0:"string"==typeof e&&((t=t||r.defaultEncoding)!==r.encoding&&(e=a.from(e,t),t=""),n=!0),I(this,e,t,!1,n)},A.prototype.unshift=function(e){return I(this,e,null,!0,!1)},A.prototype.isPaused=function(){return!1===this._readableState.flowing},A.prototype.setEncoding=function(e){l||(l=n(59).StringDecoder);var t=new l(e);this._readableState.decoder=t,this._readableState.encoding=this._readableState.decoder.encoding;for(var r=this._readableState.buffer.head,i="";null!==r;)i+=t.write(r.data),r=r.next;return this._readableState.buffer.clear(),""!==i&&this._readableState.buffer.push(i),this._readableState.length=i.length,this};function O(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!=e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=function(e){return e>=1073741824?e=1073741824:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function x(e){var t=e._readableState;c("emitReadable",t.needReadable,t.emittedReadable),t.needReadable=!1,t.emittedReadable||(c("emitReadable",t.flowing),t.emittedReadable=!0,r.nextTick(C,e))}function C(e){var t=e._readableState;c("emitReadable_",t.destroyed,t.length,t.ended),t.destroyed||!t.length&&!t.ended||(e.emit("readable"),t.emittedReadable=!1),t.needReadable=!t.flowing&&!t.ended&&t.length<=t.highWaterMark,j(e)}function T(e,t){t.readingMore||(t.readingMore=!0,r.nextTick(P,e,t))}function P(e,t){for(;!t.reading&&!t.ended&&(t.length<t.highWaterMark||t.flowing&&0===t.length);){var n=t.length;if(c("maybeReadMore read 0"),e.read(0),n===t.length)break}t.readingMore=!1}function N(e){var t=e._readableState;t.readableListening=e.listenerCount("readable")>0,t.resumeScheduled&&!t.paused?t.flowing=!0:e.listenerCount("data")>0&&e.resume()}function R(e){c("readable nexttick read 0"),e.read(0)}function L(e,t){c("resume",t.reading),t.reading||e.read(0),t.resumeScheduled=!1,e.emit("resume"),j(e),t.flowing&&!t.reading&&e.read(0)}function j(e){var t=e._readableState;for(c("flow",t.flowing);t.flowing&&null!==e.read(););}function D(e,t){return 0===t.length?null:(t.objectMode?n=t.buffer.shift():!e||e>=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.first():t.buffer.concat(t.length),t.buffer.clear()):n=t.buffer.consume(e,t.decoder),n);var n}function U(e){var t=e._readableState;c("endReadable",t.endEmitted),t.endEmitted||(t.ended=!0,r.nextTick(B,t,e))}function B(e,t){if(c("endReadableNT",e.endEmitted,e.length),!e.endEmitted&&0===e.length&&(e.endEmitted=!0,t.readable=!1,t.emit("end"),e.autoDestroy)){var n=t._writableState;(!n||n.autoDestroy&&n.finished)&&t.destroy()}}function F(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1}A.prototype.read=function(e){c("read",e),e=parseInt(e,10);var t=this._readableState,n=e;if(0!==e&&(t.emittedReadable=!1),0===e&&t.needReadable&&((0!==t.highWaterMark?t.length>=t.highWaterMark:t.length>0)||t.ended))return c("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?U(this):x(this),null;if(0===(e=O(e,t))&&t.ended)return 0===t.length&&U(this),null;var r,i=t.needReadable;return c("need readable",i),(0===t.length||t.length-e<t.highWaterMark)&&c("length less than watermark",i=!0),t.ended||t.reading?c("reading or ended",i=!1):i&&(c("do read"),t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=O(n,t))),null===(r=e>0?D(e,t):null)?(t.needReadable=t.length<=t.highWaterMark,e=0):(t.length-=e,t.awaitDrain=0),0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&U(this)),null!==r&&this.emit("data",r),r},A.prototype._read=function(e){S(this,new w("_read()"))},A.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,c("pipe count=%d opts=%j",i.pipesCount,t);var s=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?u:g;function a(t,r){c("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,c("cleanup"),e.removeListener("close",p),e.removeListener("finish",v),e.removeListener("drain",f),e.removeListener("error",h),e.removeListener("unpipe",a),n.removeListener("end",u),n.removeListener("end",g),n.removeListener("data",d),l=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function u(){c("onend"),e.end()}i.endEmitted?r.nextTick(s):n.once("end",s),e.on("unpipe",a);var f=function(e){return function(){var t=e._readableState;c("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&o(e,"data")&&(t.flowing=!0,j(e))}}(n);e.on("drain",f);var l=!1;function d(t){c("ondata");var r=e.write(t);c("dest.write",r),!1===r&&((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==F(i.pipes,e))&&!l&&(c("false write response, pause",i.awaitDrain),i.awaitDrain++),n.pause())}function h(t){c("onerror",t),g(),e.removeListener("error",h),0===o(e,"error")&&S(e,t)}function p(){e.removeListener("finish",v),g()}function v(){c("onfinish"),e.removeListener("close",p),g()}function g(){c("unpipe"),n.unpipe(e)}return n.on("data",d),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?Array.isArray(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",h),e.once("close",p),e.once("finish",v),e.emit("pipe",n),i.flowing||(c("pipe resume"),n.resume()),e},A.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes||(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n)),this;if(!e){var r=t.pipes,i=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var o=0;o<i;o++)r[o].emit("unpipe",this,{hasUnpiped:!1});return this}var s=F(t.pipes,e);return-1===s||(t.pipes.splice(s,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this,n)),this},A.prototype.on=function(e,t){var n=s.prototype.on.call(this,e,t),i=this._readableState;return"data"===e?(i.readableListening=this.listenerCount("readable")>0,!1!==i.flowing&&this.resume()):"readable"===e&&(i.endEmitted||i.readableListening||(i.readableListening=i.needReadable=!0,i.flowing=!1,i.emittedReadable=!1,c("on readable",i.length,i.reading),i.length?x(this):i.reading||r.nextTick(R,this))),n},A.prototype.addListener=A.prototype.on,A.prototype.removeListener=function(e,t){var n=s.prototype.removeListener.call(this,e,t);return"readable"===e&&r.nextTick(N,this),n},A.prototype.removeAllListeners=function(e){var t=s.prototype.removeAllListeners.apply(this,arguments);return"readable"!==e&&void 0!==e||r.nextTick(N,this),t},A.prototype.resume=function(){var e=this._readableState;return e.flowing||(c("resume"),e.flowing=!e.readableListening,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,r.nextTick(L,e,t))}(this,e)),e.paused=!1,this},A.prototype.pause=function(){return c("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(c("pause"),this._readableState.flowing=!1,this.emit("pause")),this._readableState.paused=!0,this},A.prototype.wrap=function(e){var t=this,n=this._readableState,r=!1;for(var i in e.on("end",(function(){if(c("wrapped end"),n.decoder&&!n.ended){var e=n.decoder.end();e&&e.length&&t.push(e)}t.push(null)})),e.on("data",(function(i){(c("wrapped data"),n.decoder&&(i=n.decoder.write(i)),n.objectMode&&null==i)||(n.objectMode||i&&i.length)&&(t.push(i)||(r=!0,e.pause()))})),e)void 0===this[i]&&"function"==typeof e[i]&&(this[i]=function(t){return function(){return e[t].apply(e,arguments)}}(i));for(var o=0;o<E.length;o++)e.on(E[o],this.emit.bind(this,E[o]));return this._read=function(t){c("wrapped _read",t),r&&(r=!1,e.resume())},this},"function"==typeof Symbol&&(A.prototype[Symbol.asyncIterator]=function(){return void 0===d&&(d=n(277)),d(this)}),Object.defineProperty(A.prototype,"readableHighWaterMark",{enumerable:!1,get:function(){return this._readableState.highWaterMark}}),Object.defineProperty(A.prototype,"readableBuffer",{enumerable:!1,get:function(){return this._readableState&&this._readableState.buffer}}),Object.defineProperty(A.prototype,"readableFlowing",{enumerable:!1,get:function(){return this._readableState.flowing},set:function(e){this._readableState&&(this._readableState.flowing=e)}}),A._fromList=D,Object.defineProperty(A.prototype,"readableLength",{enumerable:!1,get:function(){return this._readableState.length}}),"function"==typeof Symbol&&(A.from=function(e,t){return void 0===h&&(h=n(278)),h(A,e,t)})}).call(this,n(31),n(20))},function(e,t,n){e.exports=n(49).EventEmitter},function(e,t,n){"use strict";(function(t){function n(e,t){i(e,t),r(e)}function r(e){e._writableState&&!e._writableState.emitClose||e._readableState&&!e._readableState.emitClose||e.emit("close")}function i(e,t){e.emit("error",t)}e.exports={destroy:function(e,o){var s=this,a=this._readableState&&this._readableState.destroyed,u=this._writableState&&this._writableState.destroyed;return a||u?(o?o(e):e&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,t.nextTick(i,this,e)):t.nextTick(i,this,e)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,(function(e){!o&&e?s._writableState?s._writableState.errorEmitted?t.nextTick(r,s):(s._writableState.errorEmitted=!0,t.nextTick(n,s,e)):t.nextTick(n,s,e):o?(t.nextTick(r,s),o(e)):t.nextTick(r,s)})),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)},errorOrDestroy:function(e,t){var n=e._readableState,r=e._writableState;n&&n.autoDestroy||r&&r.autoDestroy?e.destroy(t):e.emit("error",t)}}}).call(this,n(20))},function(e,t,n){"use strict";var r=n(67).codes.ERR_INVALID_OPT_VALUE;e.exports={getHighWaterMark:function(e,t,n,i){var o=function(e,t,n){return null!=e.highWaterMark?e.highWaterMark:t?e[n]:null}(t,i,n);if(null!=o){if(!isFinite(o)||Math.floor(o)!==o||o<0)throw new r(i?n:"highWaterMark",o);return Math.floor(o)}return e.objectMode?16:16384}}},function(e,t,n){"use strict";(function(t,r){function i(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var i=r.callback;t.pendingcb--,i(n),r=r.next}t.corkedRequestsFree.next=e}(t,e)}}var o;e.exports=A,A.WritableState=M;var s={deprecate:n(114)},a=n(164),u=n(6).Buffer,c=t.Uint8Array||function(){};var f,l=n(165),d=n(166).getHighWaterMark,h=n(67).codes,p=h.ERR_INVALID_ARG_TYPE,v=h.ERR_METHOD_NOT_IMPLEMENTED,g=h.ERR_MULTIPLE_CALLBACK,m=h.ERR_STREAM_CANNOT_PIPE,b=h.ERR_STREAM_DESTROYED,y=h.ERR_STREAM_NULL_VALUES,w=h.ERR_STREAM_WRITE_AFTER_END,_=h.ERR_UNKNOWN_ENCODING,S=l.errorOrDestroy;function E(){}function M(e,t,s){o=o||n(68),e=e||{},"boolean"!=typeof s&&(s=t instanceof o),this.objectMode=!!e.objectMode,s&&(this.objectMode=this.objectMode||!!e.writableObjectMode),this.highWaterMark=d(this,e,"writableHighWaterMark",s),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var a=!1===e.decodeStrings;this.decodeStrings=!a,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,i=n.sync,o=n.writecb;if("function"!=typeof o)throw new g;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,i,o){--t.pendingcb,n?(r.nextTick(o,i),r.nextTick(T,e,t),e._writableState.errorEmitted=!0,S(e,i)):(o(i),e._writableState.errorEmitted=!0,S(e,i),T(e,t))}(e,n,i,t,o);else{var s=x(n)||e.destroyed;s||n.corked||n.bufferProcessing||!n.bufferedRequest||O(e,n),i?r.nextTick(k,e,n,s,o):k(e,n,s,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=!1!==e.emitClose,this.autoDestroy=!!e.autoDestroy,this.bufferedRequestCount=0,this.corkedRequestsFree=new i(this)}function A(e){var t=this instanceof(o=o||n(68));if(!t&&!f.call(A,this))return new A(e);this._writableState=new M(e,this,t),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),a.call(this)}function I(e,t,n,r,i,o,s){t.writelen=r,t.writecb=s,t.writing=!0,t.sync=!0,t.destroyed?t.onwrite(new b("write")):n?e._writev(i,t.onwrite):e._write(i,o,t.onwrite),t.sync=!1}function k(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),T(e,t)}function O(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),s=t.corkedRequestsFree;s.entry=n;for(var a=0,u=!0;n;)o[a]=n,n.isBuf||(u=!1),n=n.next,a+=1;o.allBuffers=u,I(e,t,!0,t.length,o,"",s.finish),t.pendingcb++,t.lastBufferedRequest=null,s.next?(t.corkedRequestsFree=s.next,s.next=null):t.corkedRequestsFree=new i(t),t.bufferedRequestCount=0}else{for(;n;){var c=n.chunk,f=n.encoding,l=n.callback;if(I(e,t,!1,t.objectMode?1:c.length,c,f,l),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function x(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function C(e,t){e._final((function(n){t.pendingcb--,n&&S(e,n),t.prefinished=!0,e.emit("prefinish"),T(e,t)}))}function T(e,t){var n=x(t);if(n&&(function(e,t){t.prefinished||t.finalCalled||("function"!=typeof e._final||t.destroyed?(t.prefinished=!0,e.emit("prefinish")):(t.pendingcb++,t.finalCalled=!0,r.nextTick(C,e,t)))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"),t.autoDestroy))){var i=e._readableState;(!i||i.autoDestroy&&i.endEmitted)&&e.destroy()}return n}n(7)(A,a),M.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(M.prototype,"buffer",{get:s.deprecate((function(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(f=Function.prototype[Symbol.hasInstance],Object.defineProperty(A,Symbol.hasInstance,{value:function(e){return!!f.call(this,e)||this===A&&(e&&e._writableState instanceof M)}})):f=function(e){return e instanceof this},A.prototype.pipe=function(){S(this,new m)},A.prototype.write=function(e,t,n){var i,o=this._writableState,s=!1,a=!o.objectMode&&(i=e,u.isBuffer(i)||i instanceof c);return a&&!u.isBuffer(e)&&(e=function(e){return u.from(e)}(e)),"function"==typeof t&&(n=t,t=null),a?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=E),o.ending?function(e,t){var n=new w;S(e,n),r.nextTick(t,n)}(this,n):(a||function(e,t,n,i){var o;return null===n?o=new y:"string"==typeof n||t.objectMode||(o=new p("chunk",["string","Buffer"],n)),!o||(S(e,o),r.nextTick(i,o),!1)}(this,o,e,n))&&(o.pendingcb++,s=function(e,t,n,r,i,o){if(!n){var s=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=u.from(t,n));return t}(t,r,i);r!==s&&(n=!0,i="buffer",r=s)}var a=t.objectMode?1:r.length;t.length+=a;var c=t.length<t.highWaterMark;c||(t.needDrain=!0);if(t.writing||t.corked){var f=t.lastBufferedRequest;t.lastBufferedRequest={chunk:r,encoding:i,isBuf:n,callback:o,next:null},f?f.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else I(e,t,!1,a,r,i,o);return c}(this,o,a,e,t,n)),s},A.prototype.cork=function(){this._writableState.corked++},A.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.bufferProcessing||!e.bufferedRequest||O(this,e))},A.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new _(e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(A.prototype,"writableBuffer",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}}),Object.defineProperty(A.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),A.prototype._write=function(e,t,n){n(new v("_write()"))},A.prototype._writev=null,A.prototype.end=function(e,t,n){var i=this._writableState;return"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),i.corked&&(i.corked=1,this.uncork()),i.ending||function(e,t,n){t.ending=!0,T(e,t),n&&(t.finished?r.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,i,n),this},Object.defineProperty(A.prototype,"writableLength",{enumerable:!1,get:function(){return this._writableState.length}}),Object.defineProperty(A.prototype,"destroyed",{enumerable:!1,get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),A.prototype.destroy=l.destroy,A.prototype._undestroy=l.undestroy,A.prototype._destroy=function(e,t){t(e)}}).call(this,n(31),n(20))},function(e,t,n){"use strict";e.exports=f;var r=n(67).codes,i=r.ERR_METHOD_NOT_IMPLEMENTED,o=r.ERR_MULTIPLE_CALLBACK,s=r.ERR_TRANSFORM_ALREADY_TRANSFORMING,a=r.ERR_TRANSFORM_WITH_LENGTH_0,u=n(68);function c(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(null===r)return this.emit("error",new o);n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var i=this._readableState;i.reading=!1,(i.needReadable||i.length<i.highWaterMark)&&this._read(i.highWaterMark)}function f(e){if(!(this instanceof f))return new f(e);u.call(this,e),this._transformState={afterTransform:c.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.on("prefinish",l)}function l(){var e=this;"function"!=typeof this._flush||this._readableState.destroyed?d(this,null,null):this._flush((function(t,n){d(e,t,n)}))}function d(e,t,n){if(t)return e.emit("error",t);if(null!=n&&e.push(n),e._writableState.length)throw new a;if(e._transformState.transforming)throw new s;return e.push(null)}n(7)(f,u),f.prototype.push=function(e,t){return this._transformState.needTransform=!1,u.prototype.push.call(this,e,t)},f.prototype._transform=function(e,t,n){n(new i("_transform()"))},f.prototype._write=function(e,t,n){var r=this._transformState;if(r.writecb=n,r.writechunk=e,r.writeencoding=t,!r.transforming){var i=this._readableState;(r.needTransform||i.needReadable||i.length<i.highWaterMark)&&this._read(i.highWaterMark)}},f.prototype._read=function(e){var t=this._transformState;null===t.writechunk||t.transforming?t.needTransform=!0:(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform))},f.prototype._destroy=function(e,t){u.prototype._destroy.call(this,e,(function(e){t(e)}))}},function(e,t,n){var r=n(7),i=n(69),o=n(8).Buffer,s=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],a=new Array(64);function u(){this.init(),this._w=a,i.call(this,64,56)}function c(e,t,n){return n^e&(t^n)}function f(e,t,n){return e&t|n&(e|t)}function l(e){return(e>>>2|e<<30)^(e>>>13|e<<19)^(e>>>22|e<<10)}function d(e){return(e>>>6|e<<26)^(e>>>11|e<<21)^(e>>>25|e<<7)}function h(e){return(e>>>7|e<<25)^(e>>>18|e<<14)^e>>>3}r(u,i),u.prototype.init=function(){return this._a=1779033703,this._b=3144134277,this._c=1013904242,this._d=2773480762,this._e=1359893119,this._f=2600822924,this._g=528734635,this._h=1541459225,this},u.prototype._update=function(e){for(var t,n=this._w,r=0|this._a,i=0|this._b,o=0|this._c,a=0|this._d,u=0|this._e,p=0|this._f,v=0|this._g,g=0|this._h,m=0;m<16;++m)n[m]=e.readInt32BE(4*m);for(;m<64;++m)n[m]=0|(((t=n[m-2])>>>17|t<<15)^(t>>>19|t<<13)^t>>>10)+n[m-7]+h(n[m-15])+n[m-16];for(var b=0;b<64;++b){var y=g+d(u)+c(u,p,v)+s[b]+n[b]|0,w=l(r)+f(r,i,o)|0;g=v,v=p,p=u,u=a+y|0,a=o,o=i,i=r,r=y+w|0}this._a=r+this._a|0,this._b=i+this._b|0,this._c=o+this._c|0,this._d=a+this._d|0,this._e=u+this._e|0,this._f=p+this._f|0,this._g=v+this._g|0,this._h=g+this._h|0},u.prototype._hash=function(){var e=o.allocUnsafe(32);return e.writeInt32BE(this._a,0),e.writeInt32BE(this._b,4),e.writeInt32BE(this._c,8),e.writeInt32BE(this._d,12),e.writeInt32BE(this._e,16),e.writeInt32BE(this._f,20),e.writeInt32BE(this._g,24),e.writeInt32BE(this._h,28),e},e.exports=u},function(e,t,n){var r=n(7),i=n(69),o=n(8).Buffer,s=[1116352408,3609767458,1899447441,602891725,3049323471,3964484399,3921009573,2173295548,961987163,4081628472,1508970993,3053834265,2453635748,2937671579,2870763221,3664609560,3624381080,2734883394,310598401,1164996542,607225278,1323610764,1426881987,3590304994,1925078388,4068182383,2162078206,991336113,2614888103,633803317,3248222580,3479774868,3835390401,2666613458,4022224774,944711139,264347078,2341262773,604807628,2007800933,770255983,1495990901,1249150122,1856431235,1555081692,3175218132,1996064986,2198950837,2554220882,3999719339,2821834349,766784016,2952996808,2566594879,3210313671,3203337956,3336571891,1034457026,3584528711,2466948901,113926993,3758326383,338241895,168717936,666307205,1188179964,773529912,1546045734,1294757372,1522805485,1396182291,2643833823,1695183700,2343527390,1986661051,1014477480,2177026350,1206759142,2456956037,344077627,2730485921,1290863460,2820302411,3158454273,3259730800,3505952657,3345764771,106217008,3516065817,3606008344,3600352804,1432725776,4094571909,1467031594,275423344,851169720,430227734,3100823752,506948616,1363258195,659060556,3750685593,883997877,3785050280,958139571,3318307427,1322822218,3812723403,1537002063,2003034995,1747873779,3602036899,1955562222,1575990012,2024104815,1125592928,2227730452,2716904306,2361852424,442776044,2428436474,593698344,2756734187,3733110249,3204031479,2999351573,3329325298,3815920427,3391569614,3928383900,3515267271,566280711,3940187606,3454069534,4118630271,4000239992,116418474,1914138554,174292421,2731055270,289380356,3203993006,460393269,320620315,685471733,587496836,852142971,1086792851,1017036298,365543100,1126000580,2618297676,1288033470,3409855158,1501505948,4234509866,1607167915,987167468,1816402316,1246189591],a=new Array(160);function u(){this.init(),this._w=a,i.call(this,128,112)}function c(e,t,n){return n^e&(t^n)}function f(e,t,n){return e&t|n&(e|t)}function l(e,t){return(e>>>28|t<<4)^(t>>>2|e<<30)^(t>>>7|e<<25)}function d(e,t){return(e>>>14|t<<18)^(e>>>18|t<<14)^(t>>>9|e<<23)}function h(e,t){return(e>>>1|t<<31)^(e>>>8|t<<24)^e>>>7}function p(e,t){return(e>>>1|t<<31)^(e>>>8|t<<24)^(e>>>7|t<<25)}function v(e,t){return(e>>>19|t<<13)^(t>>>29|e<<3)^e>>>6}function g(e,t){return(e>>>19|t<<13)^(t>>>29|e<<3)^(e>>>6|t<<26)}function m(e,t){return e>>>0<t>>>0?1:0}r(u,i),u.prototype.init=function(){return this._ah=1779033703,this._bh=3144134277,this._ch=1013904242,this._dh=2773480762,this._eh=1359893119,this._fh=2600822924,this._gh=528734635,this._hh=1541459225,this._al=4089235720,this._bl=2227873595,this._cl=4271175723,this._dl=1595750129,this._el=2917565137,this._fl=725511199,this._gl=4215389547,this._hl=327033209,this},u.prototype._update=function(e){for(var t=this._w,n=0|this._ah,r=0|this._bh,i=0|this._ch,o=0|this._dh,a=0|this._eh,u=0|this._fh,b=0|this._gh,y=0|this._hh,w=0|this._al,_=0|this._bl,S=0|this._cl,E=0|this._dl,M=0|this._el,A=0|this._fl,I=0|this._gl,k=0|this._hl,O=0;O<32;O+=2)t[O]=e.readInt32BE(4*O),t[O+1]=e.readInt32BE(4*O+4);for(;O<160;O+=2){var x=t[O-30],C=t[O-30+1],T=h(x,C),P=p(C,x),N=v(x=t[O-4],C=t[O-4+1]),R=g(C,x),L=t[O-14],j=t[O-14+1],D=t[O-32],U=t[O-32+1],B=P+j|0,F=T+L+m(B,P)|0;F=(F=F+N+m(B=B+R|0,R)|0)+D+m(B=B+U|0,U)|0,t[O]=F,t[O+1]=B}for(var z=0;z<160;z+=2){F=t[z],B=t[z+1];var q=f(n,r,i),K=f(w,_,S),H=l(n,w),V=l(w,n),G=d(a,M),W=d(M,a),$=s[z],Y=s[z+1],J=c(a,u,b),Z=c(M,A,I),X=k+W|0,Q=y+G+m(X,k)|0;Q=(Q=(Q=Q+J+m(X=X+Z|0,Z)|0)+$+m(X=X+Y|0,Y)|0)+F+m(X=X+B|0,B)|0;var ee=V+K|0,te=H+q+m(ee,V)|0;y=b,k=I,b=u,I=A,u=a,A=M,a=o+Q+m(M=E+X|0,E)|0,o=i,E=S,i=r,S=_,r=n,_=w,n=Q+te+m(w=X+ee|0,X)|0}this._al=this._al+w|0,this._bl=this._bl+_|0,this._cl=this._cl+S|0,this._dl=this._dl+E|0,this._el=this._el+M|0,this._fl=this._fl+A|0,this._gl=this._gl+I|0,this._hl=this._hl+k|0,this._ah=this._ah+n+m(this._al,w)|0,this._bh=this._bh+r+m(this._bl,_)|0,this._ch=this._ch+i+m(this._cl,S)|0,this._dh=this._dh+o+m(this._dl,E)|0,this._eh=this._eh+a+m(this._el,M)|0,this._fh=this._fh+u+m(this._fl,A)|0,this._gh=this._gh+b+m(this._gl,I)|0,this._hh=this._hh+y+m(this._hl,k)|0},u.prototype._hash=function(){var e=o.allocUnsafe(64);function t(t,n,r){e.writeInt32BE(t,r),e.writeInt32BE(n,r+4)}return t(this._ah,this._al,0),t(this._bh,this._bl,8),t(this._ch,this._cl,16),t(this._dh,this._dl,24),t(this._eh,this._el,32),t(this._fh,this._fl,40),t(this._gh,this._gl,48),t(this._hh,this._hl,56),e},e.exports=u},function(e,t,n){"use strict";(function(t,r){var i=n(92);e.exports=y;var o,s=n(160);y.ReadableState=b;n(49).EventEmitter;var a=function(e,t){return e.listeners(t).length},u=n(172),c=n(119).Buffer,f=t.Uint8Array||function(){};var l=Object.create(n(80));l.inherits=n(7);var d=n(286),h=void 0;h=d&&d.debuglog?d.debuglog("stream"):function(){};var p,v=n(287),g=n(173);l.inherits(y,u);var m=["error","close","destroy","pause","resume"];function b(e,t){e=e||{};var r=t instanceof(o=o||n(60));this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.readableObjectMode);var i=e.highWaterMark,s=e.readableHighWaterMark,a=this.objectMode?16:16384;this.highWaterMark=i||0===i?i:r&&(s||0===s)?s:a,this.highWaterMark=Math.floor(this.highWaterMark),this.buffer=new v,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(p||(p=n(59).StringDecoder),this.decoder=new p(e.encoding),this.encoding=e.encoding)}function y(e){if(o=o||n(60),!(this instanceof y))return new y(e);this._readableState=new b(e,this),this.readable=!0,e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy)),u.call(this)}function w(e,t,n,r,i){var o,s=e._readableState;null===t?(s.reading=!1,function(e,t){if(t.ended)return;if(t.decoder){var n=t.decoder.end();n&&n.length&&(t.buffer.push(n),t.length+=t.objectMode?1:n.length)}t.ended=!0,E(e)}(e,s)):(i||(o=function(e,t){var n;r=t,c.isBuffer(r)||r instanceof f||"string"==typeof t||void 0===t||e.objectMode||(n=new TypeError("Invalid non-string/buffer chunk"));var r;return n}(s,t)),o?e.emit("error",o):s.objectMode||t&&t.length>0?("string"==typeof t||s.objectMode||Object.getPrototypeOf(t)===c.prototype||(t=function(e){return c.from(e)}(t)),r?s.endEmitted?e.emit("error",new Error("stream.unshift() after end event")):_(e,s,t,!0):s.ended?e.emit("error",new Error("stream.push() after EOF")):(s.reading=!1,s.decoder&&!n?(t=s.decoder.write(t),s.objectMode||0!==t.length?_(e,s,t,!1):A(e,s)):_(e,s,t,!1))):r||(s.reading=!1));return function(e){return!e.ended&&(e.needReadable||e.length<e.highWaterMark||0===e.length)}(s)}function _(e,t,n,r){t.flowing&&0===t.length&&!t.sync?(e.emit("data",n),e.read(0)):(t.length+=t.objectMode?1:n.length,r?t.buffer.unshift(n):t.buffer.push(n),t.needReadable&&E(e)),A(e,t)}Object.defineProperty(y.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}}),y.prototype.destroy=g.destroy,y.prototype._undestroy=g.undestroy,y.prototype._destroy=function(e,t){this.push(null),t(e)},y.prototype.push=function(e,t){var n,r=this._readableState;return r.objectMode?n=!0:"string"==typeof e&&((t=t||r.defaultEncoding)!==r.encoding&&(e=c.from(e,t),t=""),n=!0),w(this,e,t,!1,n)},y.prototype.unshift=function(e){return w(this,e,null,!0,!1)},y.prototype.isPaused=function(){return!1===this._readableState.flowing},y.prototype.setEncoding=function(e){return p||(p=n(59).StringDecoder),this._readableState.decoder=new p(e),this._readableState.encoding=e,this};function S(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!=e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=function(e){return e>=8388608?e=8388608:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function E(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(h("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?i.nextTick(M,e):M(e))}function M(e){h("emit readable"),e.emit("readable"),x(e)}function A(e,t){t.readingMore||(t.readingMore=!0,i.nextTick(I,e,t))}function I(e,t){for(var n=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length<t.highWaterMark&&(h("maybeReadMore read 0"),e.read(0),n!==t.length);)n=t.length;t.readingMore=!1}function k(e){h("readable nexttick read 0"),e.read(0)}function O(e,t){t.reading||(h("resume read 0"),e.read(0)),t.resumeScheduled=!1,t.awaitDrain=0,e.emit("resume"),x(e),t.flowing&&!t.reading&&e.read(0)}function x(e){var t=e._readableState;for(h("flow",t.flowing);t.flowing&&null!==e.read(););}function C(e,t){return 0===t.length?null:(t.objectMode?n=t.buffer.shift():!e||e>=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):n=function(e,t,n){var r;e<t.head.data.length?(r=t.head.data.slice(0,e),t.head.data=t.head.data.slice(e)):r=e===t.head.data.length?t.shift():n?function(e,t){var n=t.head,r=1,i=n.data;e-=i.length;for(;n=n.next;){var o=n.data,s=e>o.length?o.length:e;if(s===o.length?i+=o:i+=o.slice(0,e),0===(e-=s)){s===o.length?(++r,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n,n.data=o.slice(s));break}++r}return t.length-=r,i}(e,t):function(e,t){var n=c.allocUnsafe(e),r=t.head,i=1;r.data.copy(n),e-=r.data.length;for(;r=r.next;){var o=r.data,s=e>o.length?o.length:e;if(o.copy(n,n.length-e,0,s),0===(e-=s)){s===o.length?(++i,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r,r.data=o.slice(s));break}++i}return t.length-=i,n}(e,t);return r}(e,t.buffer,t.decoder),n);var n}function T(e){var t=e._readableState;if(t.length>0)throw new Error('"endReadable()" called on non-empty stream');t.endEmitted||(t.ended=!0,i.nextTick(P,t,e))}function P(e,t){e.endEmitted||0!==e.length||(e.endEmitted=!0,t.readable=!1,t.emit("end"))}function N(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1}y.prototype.read=function(e){h("read",e),e=parseInt(e,10);var t=this._readableState,n=e;if(0!==e&&(t.emittedReadable=!1),0===e&&t.needReadable&&(t.length>=t.highWaterMark||t.ended))return h("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?T(this):E(this),null;if(0===(e=S(e,t))&&t.ended)return 0===t.length&&T(this),null;var r,i=t.needReadable;return h("need readable",i),(0===t.length||t.length-e<t.highWaterMark)&&h("length less than watermark",i=!0),t.ended||t.reading?h("reading or ended",i=!1):i&&(h("do read"),t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=S(n,t))),null===(r=e>0?C(e,t):null)?(t.needReadable=!0,e=0):t.length-=e,0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&T(this)),null!==r&&this.emit("data",r),r},y.prototype._read=function(e){this.emit("error",new Error("_read() is not implemented"))},y.prototype.pipe=function(e,t){var n=this,o=this._readableState;switch(o.pipesCount){case 0:o.pipes=e;break;case 1:o.pipes=[o.pipes,e];break;default:o.pipes.push(e)}o.pipesCount+=1,h("pipe count=%d opts=%j",o.pipesCount,t);var u=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?f:y;function c(t,r){h("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,h("cleanup"),e.removeListener("close",m),e.removeListener("finish",b),e.removeListener("drain",l),e.removeListener("error",g),e.removeListener("unpipe",c),n.removeListener("end",f),n.removeListener("end",y),n.removeListener("data",v),d=!0,!o.awaitDrain||e._writableState&&!e._writableState.needDrain||l())}function f(){h("onend"),e.end()}o.endEmitted?i.nextTick(u):n.once("end",u),e.on("unpipe",c);var l=function(e){return function(){var t=e._readableState;h("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&a(e,"data")&&(t.flowing=!0,x(e))}}(n);e.on("drain",l);var d=!1;var p=!1;function v(t){h("ondata"),p=!1,!1!==e.write(t)||p||((1===o.pipesCount&&o.pipes===e||o.pipesCount>1&&-1!==N(o.pipes,e))&&!d&&(h("false write response, pause",n._readableState.awaitDrain),n._readableState.awaitDrain++,p=!0),n.pause())}function g(t){h("onerror",t),y(),e.removeListener("error",g),0===a(e,"error")&&e.emit("error",t)}function m(){e.removeListener("finish",b),y()}function b(){h("onfinish"),e.removeListener("close",m),y()}function y(){h("unpipe"),n.unpipe(e)}return n.on("data",v),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?s(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",g),e.once("close",m),e.once("finish",b),e.emit("pipe",n),o.flowing||(h("pipe resume"),n.resume()),e},y.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes||(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n)),this;if(!e){var r=t.pipes,i=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var o=0;o<i;o++)r[o].emit("unpipe",this,n);return this}var s=N(t.pipes,e);return-1===s||(t.pipes.splice(s,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this,n)),this},y.prototype.on=function(e,t){var n=u.prototype.on.call(this,e,t);if("data"===e)!1!==this._readableState.flowing&&this.resume();else if("readable"===e){var r=this._readableState;r.endEmitted||r.readableListening||(r.readableListening=r.needReadable=!0,r.emittedReadable=!1,r.reading?r.length&&E(this):i.nextTick(k,this))}return n},y.prototype.addListener=y.prototype.on,y.prototype.resume=function(){var e=this._readableState;return e.flowing||(h("resume"),e.flowing=!0,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,i.nextTick(O,e,t))}(this,e)),this},y.prototype.pause=function(){return h("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(h("pause"),this._readableState.flowing=!1,this.emit("pause")),this},y.prototype.wrap=function(e){var t=this,n=this._readableState,r=!1;for(var i in e.on("end",(function(){if(h("wrapped end"),n.decoder&&!n.ended){var e=n.decoder.end();e&&e.length&&t.push(e)}t.push(null)})),e.on("data",(function(i){(h("wrapped data"),n.decoder&&(i=n.decoder.write(i)),n.objectMode&&null==i)||(n.objectMode||i&&i.length)&&(t.push(i)||(r=!0,e.pause()))})),e)void 0===this[i]&&"function"==typeof e[i]&&(this[i]=function(t){return function(){return e[t].apply(e,arguments)}}(i));for(var o=0;o<m.length;o++)e.on(m[o],this.emit.bind(this,m[o]));return this._read=function(t){h("wrapped _read",t),r&&(r=!1,e.resume())},this},Object.defineProperty(y.prototype,"readableHighWaterMark",{enumerable:!1,get:function(){return this._readableState.highWaterMark}}),y._fromList=C}).call(this,n(31),n(20))},function(e,t,n){e.exports=n(49).EventEmitter},function(e,t,n){"use strict";var r=n(92);function i(e,t){e.emit("error",t)}e.exports={destroy:function(e,t){var n=this,o=this._readableState&&this._readableState.destroyed,s=this._writableState&&this._writableState.destroyed;return o||s?(t?t(e):!e||this._writableState&&this._writableState.errorEmitted||r.nextTick(i,this,e),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,(function(e){!t&&e?(r.nextTick(i,n,e),n._writableState&&(n._writableState.errorEmitted=!0)):t&&t(e)})),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},function(e,t,n){"use strict";e.exports=s;var r=n(60),i=Object.create(n(80));function o(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(!r)return this.emit("error",new Error("write callback called multiple times"));n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var i=this._readableState;i.reading=!1,(i.needReadable||i.length<i.highWaterMark)&&this._read(i.highWaterMark)}function s(e){if(!(this instanceof s))return new s(e);r.call(this,e),this._transformState={afterTransform:o.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.on("prefinish",a)}function a(){var e=this;"function"==typeof this._flush?this._flush((function(t,n){u(e,t,n)})):u(this,null,null)}function u(e,t,n){if(t)return e.emit("error",t);if(null!=n&&e.push(n),e._writableState.length)throw new Error("Calling transform done when ws.length != 0");if(e._transformState.transforming)throw new Error("Calling transform done when still transforming");return e.push(null)}i.inherits=n(7),i.inherits(s,r),s.prototype.push=function(e,t){return this._transformState.needTransform=!1,r.prototype.push.call(this,e,t)},s.prototype._transform=function(e,t,n){throw new Error("_transform() is not implemented")},s.prototype._write=function(e,t,n){var r=this._transformState;if(r.writecb=n,r.writechunk=e,r.writeencoding=t,!r.transforming){var i=this._readableState;(r.needTransform||i.needReadable||i.length<i.highWaterMark)&&this._read(i.highWaterMark)}},s.prototype._read=function(e){var t=this._transformState;null!==t.writechunk&&t.writecb&&!t.transforming?(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform)):t.needTransform=!0},s.prototype._destroy=function(e,t){var n=this;r.prototype._destroy.call(this,e,(function(e){t(e),n.emit("close")}))}},function(e,t,n){"use strict";var r=n(7),i=n(296),o=n(56),s=n(8).Buffer,a=n(176),u=n(116),c=n(117),f=s.alloc(128);function l(e,t){o.call(this,"digest"),"string"==typeof t&&(t=s.from(t));var n="sha512"===e||"sha384"===e?128:64;(this._alg=e,this._key=t,t.length>n)?t=("rmd160"===e?new u:c(e)).update(t).digest():t.length<n&&(t=s.concat([t,f],n));for(var r=this._ipad=s.allocUnsafe(n),i=this._opad=s.allocUnsafe(n),a=0;a<n;a++)r[a]=54^t[a],i[a]=92^t[a];this._hash="rmd160"===e?new u:c(e),this._hash.update(r)}r(l,o),l.prototype._update=function(e){this._hash.update(e)},l.prototype._final=function(){var e=this._hash.digest();return("rmd160"===this._alg?new u:c(this._alg)).update(this._opad).update(e).digest()},e.exports=function(e,t){return"rmd160"===(e=e.toLowerCase())||"ripemd160"===e?new l("rmd160",t):"md5"===e?new i(a,t):new l(e,t)}},function(e,t,n){var r=n(113);e.exports=function(e){return(new r).update(e).digest()}},function(e){e.exports=JSON.parse('{"sha224WithRSAEncryption":{"sign":"rsa","hash":"sha224","id":"302d300d06096086480165030402040500041c"},"RSA-SHA224":{"sign":"ecdsa/rsa","hash":"sha224","id":"302d300d06096086480165030402040500041c"},"sha256WithRSAEncryption":{"sign":"rsa","hash":"sha256","id":"3031300d060960864801650304020105000420"},"RSA-SHA256":{"sign":"ecdsa/rsa","hash":"sha256","id":"3031300d060960864801650304020105000420"},"sha384WithRSAEncryption":{"sign":"rsa","hash":"sha384","id":"3041300d060960864801650304020205000430"},"RSA-SHA384":{"sign":"ecdsa/rsa","hash":"sha384","id":"3041300d060960864801650304020205000430"},"sha512WithRSAEncryption":{"sign":"rsa","hash":"sha512","id":"3051300d060960864801650304020305000440"},"RSA-SHA512":{"sign":"ecdsa/rsa","hash":"sha512","id":"3051300d060960864801650304020305000440"},"RSA-SHA1":{"sign":"rsa","hash":"sha1","id":"3021300906052b0e03021a05000414"},"ecdsa-with-SHA1":{"sign":"ecdsa","hash":"sha1","id":""},"sha256":{"sign":"ecdsa","hash":"sha256","id":""},"sha224":{"sign":"ecdsa","hash":"sha224","id":""},"sha384":{"sign":"ecdsa","hash":"sha384","id":""},"sha512":{"sign":"ecdsa","hash":"sha512","id":""},"DSA-SHA":{"sign":"dsa","hash":"sha1","id":""},"DSA-SHA1":{"sign":"dsa","hash":"sha1","id":""},"DSA":{"sign":"dsa","hash":"sha1","id":""},"DSA-WITH-SHA224":{"sign":"dsa","hash":"sha224","id":""},"DSA-SHA224":{"sign":"dsa","hash":"sha224","id":""},"DSA-WITH-SHA256":{"sign":"dsa","hash":"sha256","id":""},"DSA-SHA256":{"sign":"dsa","hash":"sha256","id":""},"DSA-WITH-SHA384":{"sign":"dsa","hash":"sha384","id":""},"DSA-SHA384":{"sign":"dsa","hash":"sha384","id":""},"DSA-WITH-SHA512":{"sign":"dsa","hash":"sha512","id":""},"DSA-SHA512":{"sign":"dsa","hash":"sha512","id":""},"DSA-RIPEMD160":{"sign":"dsa","hash":"rmd160","id":""},"ripemd160WithRSA":{"sign":"rsa","hash":"rmd160","id":"3021300906052b2403020105000414"},"RSA-RIPEMD160":{"sign":"rsa","hash":"rmd160","id":"3021300906052b2403020105000414"},"md5WithRSAEncryption":{"sign":"rsa","hash":"md5","id":"3020300c06082a864886f70d020505000410"},"RSA-MD5":{"sign":"rsa","hash":"md5","id":"3020300c06082a864886f70d020505000410"}}')},function(e,t,n){t.pbkdf2=n(298),t.pbkdf2Sync=n(181)},function(e,t){var n=Math.pow(2,30)-1;e.exports=function(e,t){if("number"!=typeof e)throw new TypeError("Iterations not a number");if(e<0)throw new TypeError("Bad iterations");if("number"!=typeof t)throw new TypeError("Key length not a number");if(t<0||t>n||t!=t)throw new TypeError("Bad key length")}},function(e,t,n){(function(t){var n;if(t.browser)n="utf-8";else if(t.version){n=parseInt(t.version.split(".")[0].slice(1),10)>=6?"utf-8":"binary"}else n="utf-8";e.exports=n}).call(this,n(20))},function(e,t,n){var r=n(176),i=n(116),o=n(117),s=n(8).Buffer,a=n(179),u=n(180),c=n(182),f=s.alloc(128),l={md5:16,sha1:20,sha224:28,sha256:32,sha384:48,sha512:64,rmd160:20,ripemd160:20};function d(e,t,n){var a=function(e){function t(t){return o(e).update(t).digest()}return"rmd160"===e||"ripemd160"===e?function(e){return(new i).update(e).digest()}:"md5"===e?r:t}(e),u="sha512"===e||"sha384"===e?128:64;t.length>u?t=a(t):t.length<u&&(t=s.concat([t,f],u));for(var c=s.allocUnsafe(u+l[e]),d=s.allocUnsafe(u+l[e]),h=0;h<u;h++)c[h]=54^t[h],d[h]=92^t[h];var p=s.allocUnsafe(u+n+4);c.copy(p,0,0,u),this.ipad1=p,this.ipad2=c,this.opad=d,this.alg=e,this.blocksize=u,this.hash=a,this.size=l[e]}d.prototype.run=function(e,t){return e.copy(t,this.blocksize),this.hash(t).copy(this.opad,this.blocksize),this.hash(this.opad)},e.exports=function(e,t,n,r,i){a(n,r);var o=new d(i=i||"sha1",e=c(e,u,"Password"),(t=c(t,u,"Salt")).length),f=s.allocUnsafe(r),h=s.allocUnsafe(t.length+4);t.copy(h,0,0,t.length);for(var p=0,v=l[i],g=Math.ceil(r/v),m=1;m<=g;m++){h.writeUInt32BE(m,t.length);for(var b=o.run(h,o.ipad1),y=b,w=1;w<n;w++){y=o.run(y,o.ipad2);for(var _=0;_<v;_++)b[_]^=y[_]}b.copy(f,p),p+=v}return f}},function(e,t,n){var r=n(8).Buffer;e.exports=function(e,t,n){if(r.isBuffer(e))return e;if("string"==typeof e)return r.from(e,t);if(ArrayBuffer.isView(e))return r.from(e.buffer);throw new TypeError(n+" must be a string, a Buffer, a typed array or a DataView")}},function(e,t,n){"use strict";t.readUInt32BE=function(e,t){return(e[0+t]<<24|e[1+t]<<16|e[2+t]<<8|e[3+t])>>>0},t.writeUInt32BE=function(e,t,n){e[0+n]=t>>>24,e[1+n]=t>>>16&255,e[2+n]=t>>>8&255,e[3+n]=255&t},t.ip=function(e,t,n,r){for(var i=0,o=0,s=6;s>=0;s-=2){for(var a=0;a<=24;a+=8)i<<=1,i|=t>>>a+s&1;for(a=0;a<=24;a+=8)i<<=1,i|=e>>>a+s&1}for(s=6;s>=0;s-=2){for(a=1;a<=25;a+=8)o<<=1,o|=t>>>a+s&1;for(a=1;a<=25;a+=8)o<<=1,o|=e>>>a+s&1}n[r+0]=i>>>0,n[r+1]=o>>>0},t.rip=function(e,t,n,r){for(var i=0,o=0,s=0;s<4;s++)for(var a=24;a>=0;a-=8)i<<=1,i|=t>>>a+s&1,i<<=1,i|=e>>>a+s&1;for(s=4;s<8;s++)for(a=24;a>=0;a-=8)o<<=1,o|=t>>>a+s&1,o<<=1,o|=e>>>a+s&1;n[r+0]=i>>>0,n[r+1]=o>>>0},t.pc1=function(e,t,n,r){for(var i=0,o=0,s=7;s>=5;s--){for(var a=0;a<=24;a+=8)i<<=1,i|=t>>a+s&1;for(a=0;a<=24;a+=8)i<<=1,i|=e>>a+s&1}for(a=0;a<=24;a+=8)i<<=1,i|=t>>a+s&1;for(s=1;s<=3;s++){for(a=0;a<=24;a+=8)o<<=1,o|=t>>a+s&1;for(a=0;a<=24;a+=8)o<<=1,o|=e>>a+s&1}for(a=0;a<=24;a+=8)o<<=1,o|=e>>a+s&1;n[r+0]=i>>>0,n[r+1]=o>>>0},t.r28shl=function(e,t){return e<<t&268435455|e>>>28-t};var r=[14,11,17,4,27,23,25,0,13,22,7,18,5,9,16,24,2,20,12,21,1,8,15,26,15,4,25,19,9,1,26,16,5,11,23,8,12,7,17,0,22,3,10,14,6,20,27,24];t.pc2=function(e,t,n,i){for(var o=0,s=0,a=r.length>>>1,u=0;u<a;u++)o<<=1,o|=e>>>r[u]&1;for(u=a;u<r.length;u++)s<<=1,s|=t>>>r[u]&1;n[i+0]=o>>>0,n[i+1]=s>>>0},t.expand=function(e,t,n){var r=0,i=0;r=(1&e)<<5|e>>>27;for(var o=23;o>=15;o-=4)r<<=6,r|=e>>>o&63;for(o=11;o>=3;o-=4)i|=e>>>o&63,i<<=6;i|=(31&e)<<1|e>>>31,t[n+0]=r>>>0,t[n+1]=i>>>0};var i=[14,0,4,15,13,7,1,4,2,14,15,2,11,13,8,1,3,10,10,6,6,12,12,11,5,9,9,5,0,3,7,8,4,15,1,12,14,8,8,2,13,4,6,9,2,1,11,7,15,5,12,11,9,3,7,14,3,10,10,0,5,6,0,13,15,3,1,13,8,4,14,7,6,15,11,2,3,8,4,14,9,12,7,0,2,1,13,10,12,6,0,9,5,11,10,5,0,13,14,8,7,10,11,1,10,3,4,15,13,4,1,2,5,11,8,6,12,7,6,12,9,0,3,5,2,14,15,9,10,13,0,7,9,0,14,9,6,3,3,4,15,6,5,10,1,2,13,8,12,5,7,14,11,12,4,11,2,15,8,1,13,1,6,10,4,13,9,0,8,6,15,9,3,8,0,7,11,4,1,15,2,14,12,3,5,11,10,5,14,2,7,12,7,13,13,8,14,11,3,5,0,6,6,15,9,0,10,3,1,4,2,7,8,2,5,12,11,1,12,10,4,14,15,9,10,3,6,15,9,0,0,6,12,10,11,1,7,13,13,8,15,9,1,4,3,5,14,11,5,12,2,7,8,2,4,14,2,14,12,11,4,2,1,12,7,4,10,7,11,13,6,1,8,5,5,0,3,15,15,10,13,3,0,9,14,8,9,6,4,11,2,8,1,12,11,7,10,1,13,14,7,2,8,13,15,6,9,15,12,0,5,9,6,10,3,4,0,5,14,3,12,10,1,15,10,4,15,2,9,7,2,12,6,9,8,5,0,6,13,1,3,13,4,14,14,0,7,11,5,3,11,8,9,4,14,3,15,2,5,12,2,9,8,5,12,15,3,10,7,11,0,14,4,1,10,7,1,6,13,0,11,8,6,13,4,13,11,0,2,11,14,7,15,4,0,9,8,1,13,10,3,14,12,3,9,5,7,12,5,2,10,15,6,8,1,6,1,6,4,11,11,13,13,8,12,1,3,4,7,10,14,7,10,9,15,5,6,0,8,15,0,14,5,2,9,3,2,12,13,1,2,15,8,13,4,8,6,10,15,3,11,7,1,4,10,12,9,5,3,6,14,11,5,0,0,14,12,9,7,2,7,2,11,1,4,14,1,7,9,4,12,10,14,8,2,13,0,15,6,12,10,9,13,0,15,3,3,5,5,6,8,11];t.substitute=function(e,t){for(var n=0,r=0;r<4;r++){n<<=4,n|=i[64*r+(e>>>18-6*r&63)]}for(r=0;r<4;r++){n<<=4,n|=i[256+64*r+(t>>>18-6*r&63)]}return n>>>0};var o=[16,25,12,11,3,20,4,15,31,17,9,6,27,14,1,22,30,24,8,18,0,5,29,23,13,19,2,26,10,21,28,7];t.permute=function(e){for(var t=0,n=0;n<o.length;n++)t<<=1,t|=e>>>o[n]&1;return t>>>0},t.padSplit=function(e,t,n){for(var r=e.toString(2);r.length<t;)r="0"+r;for(var i=[],o=0;o<t;o+=n)i.push(r.slice(o,o+n));return i.join(" ")}},function(e,t,n){"use strict";var r=n(46),i=n(7),o=n(183),s=n(121);function a(){this.tmp=new Array(2),this.keys=null}function u(e){s.call(this,e);var t=new a;this._desState=t,this.deriveKeys(t,e.key)}i(u,s),e.exports=u,u.create=function(e){return new u(e)};var c=[1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1];u.prototype.deriveKeys=function(e,t){e.keys=new Array(32),r.equal(t.length,this.blockSize,"Invalid key length");var n=o.readUInt32BE(t,0),i=o.readUInt32BE(t,4);o.pc1(n,i,e.tmp,0),n=e.tmp[0],i=e.tmp[1];for(var s=0;s<e.keys.length;s+=2){var a=c[s>>>1];n=o.r28shl(n,a),i=o.r28shl(i,a),o.pc2(n,i,e.keys,s)}},u.prototype._update=function(e,t,n,r){var i=this._desState,s=o.readUInt32BE(e,t),a=o.readUInt32BE(e,t+4);o.ip(s,a,i.tmp,0),s=i.tmp[0],a=i.tmp[1],"encrypt"===this.type?this._encrypt(i,s,a,i.tmp,0):this._decrypt(i,s,a,i.tmp,0),s=i.tmp[0],a=i.tmp[1],o.writeUInt32BE(n,s,r),o.writeUInt32BE(n,a,r+4)},u.prototype._pad=function(e,t){for(var n=e.length-t,r=t;r<e.length;r++)e[r]=n;return!0},u.prototype._unpad=function(e){for(var t=e[e.length-1],n=e.length-t;n<e.length;n++)r.equal(e[n],t);return e.slice(0,e.length-t)},u.prototype._encrypt=function(e,t,n,r,i){for(var s=t,a=n,u=0;u<e.keys.length;u+=2){var c=e.keys[u],f=e.keys[u+1];o.expand(a,e.tmp,0),c^=e.tmp[0],f^=e.tmp[1];var l=o.substitute(c,f),d=a;a=(s^o.permute(l))>>>0,s=d}o.rip(a,s,r,i)},u.prototype._decrypt=function(e,t,n,r,i){for(var s=n,a=t,u=e.keys.length-2;u>=0;u-=2){var c=e.keys[u],f=e.keys[u+1];o.expand(s,e.tmp,0),c^=e.tmp[0],f^=e.tmp[1];var l=o.substitute(c,f),d=s;s=(a^o.permute(l))>>>0,a=d}o.rip(s,a,r,i)}},function(e,t,n){var r=n(81),i=n(8).Buffer,o=n(186);function s(e){var t=e._cipher.encryptBlockRaw(e._prev);return o(e._prev),t}t.encrypt=function(e,t){var n=Math.ceil(t.length/16),o=e._cache.length;e._cache=i.concat([e._cache,i.allocUnsafe(16*n)]);for(var a=0;a<n;a++){var u=s(e),c=o+16*a;e._cache.writeUInt32BE(u[0],c+0),e._cache.writeUInt32BE(u[1],c+4),e._cache.writeUInt32BE(u[2],c+8),e._cache.writeUInt32BE(u[3],c+12)}var f=e._cache.slice(0,t.length);return e._cache=e._cache.slice(t.length),r(t,f)}},function(e,t){e.exports=function(e){for(var t,n=e.length;n--;){if(255!==(t=e.readUInt8(n))){t++,e.writeUInt8(t,n);break}e.writeUInt8(0,n)}}},function(e){e.exports=JSON.parse('{"aes-128-ecb":{"cipher":"AES","key":128,"iv":0,"mode":"ECB","type":"block"},"aes-192-ecb":{"cipher":"AES","key":192,"iv":0,"mode":"ECB","type":"block"},"aes-256-ecb":{"cipher":"AES","key":256,"iv":0,"mode":"ECB","type":"block"},"aes-128-cbc":{"cipher":"AES","key":128,"iv":16,"mode":"CBC","type":"block"},"aes-192-cbc":{"cipher":"AES","key":192,"iv":16,"mode":"CBC","type":"block"},"aes-256-cbc":{"cipher":"AES","key":256,"iv":16,"mode":"CBC","type":"block"},"aes128":{"cipher":"AES","key":128,"iv":16,"mode":"CBC","type":"block"},"aes192":{"cipher":"AES","key":192,"iv":16,"mode":"CBC","type":"block"},"aes256":{"cipher":"AES","key":256,"iv":16,"mode":"CBC","type":"block"},"aes-128-cfb":{"cipher":"AES","key":128,"iv":16,"mode":"CFB","type":"stream"},"aes-192-cfb":{"cipher":"AES","key":192,"iv":16,"mode":"CFB","type":"stream"},"aes-256-cfb":{"cipher":"AES","key":256,"iv":16,"mode":"CFB","type":"stream"},"aes-128-cfb8":{"cipher":"AES","key":128,"iv":16,"mode":"CFB8","type":"stream"},"aes-192-cfb8":{"cipher":"AES","key":192,"iv":16,"mode":"CFB8","type":"stream"},"aes-256-cfb8":{"cipher":"AES","key":256,"iv":16,"mode":"CFB8","type":"stream"},"aes-128-cfb1":{"cipher":"AES","key":128,"iv":16,"mode":"CFB1","type":"stream"},"aes-192-cfb1":{"cipher":"AES","key":192,"iv":16,"mode":"CFB1","type":"stream"},"aes-256-cfb1":{"cipher":"AES","key":256,"iv":16,"mode":"CFB1","type":"stream"},"aes-128-ofb":{"cipher":"AES","key":128,"iv":16,"mode":"OFB","type":"stream"},"aes-192-ofb":{"cipher":"AES","key":192,"iv":16,"mode":"OFB","type":"stream"},"aes-256-ofb":{"cipher":"AES","key":256,"iv":16,"mode":"OFB","type":"stream"},"aes-128-ctr":{"cipher":"AES","key":128,"iv":16,"mode":"CTR","type":"stream"},"aes-192-ctr":{"cipher":"AES","key":192,"iv":16,"mode":"CTR","type":"stream"},"aes-256-ctr":{"cipher":"AES","key":256,"iv":16,"mode":"CTR","type":"stream"},"aes-128-gcm":{"cipher":"AES","key":128,"iv":12,"mode":"GCM","type":"auth"},"aes-192-gcm":{"cipher":"AES","key":192,"iv":12,"mode":"GCM","type":"auth"},"aes-256-gcm":{"cipher":"AES","key":256,"iv":12,"mode":"GCM","type":"auth"}}')},function(e,t,n){var r=n(93),i=n(8).Buffer,o=n(56),s=n(7),a=n(311),u=n(81),c=n(186);function f(e,t,n,s){o.call(this);var u=i.alloc(4,0);this._cipher=new r.AES(t);var f=this._cipher.encryptBlock(u);this._ghash=new a(f),n=function(e,t,n){if(12===t.length)return e._finID=i.concat([t,i.from([0,0,0,1])]),i.concat([t,i.from([0,0,0,2])]);var r=new a(n),o=t.length,s=o%16;r.update(t),s&&(s=16-s,r.update(i.alloc(s,0))),r.update(i.alloc(8,0));var u=8*o,f=i.alloc(8);f.writeUIntBE(u,0,8),r.update(f),e._finID=r.state;var l=i.from(e._finID);return c(l),l}(this,n,f),this._prev=i.from(n),this._cache=i.allocUnsafe(0),this._secCache=i.allocUnsafe(0),this._decrypt=s,this._alen=0,this._len=0,this._mode=e,this._authTag=null,this._called=!1}s(f,o),f.prototype._update=function(e){if(!this._called&&this._alen){var t=16-this._alen%16;t<16&&(t=i.alloc(t,0),this._ghash.update(t))}this._called=!0;var n=this._mode.encrypt(this,e);return this._decrypt?this._ghash.update(e):this._ghash.update(n),this._len+=e.length,n},f.prototype._final=function(){if(this._decrypt&&!this._authTag)throw new Error("Unsupported state or unable to authenticate data");var e=u(this._ghash.final(8*this._alen,8*this._len),this._cipher.encryptBlock(this._finID));if(this._decrypt&&function(e,t){var n=0;e.length!==t.length&&n++;for(var r=Math.min(e.length,t.length),i=0;i<r;++i)n+=e[i]^t[i];return n}(e,this._authTag))throw new Error("Unsupported state or unable to authenticate data");this._authTag=e,this._cipher.scrub()},f.prototype.getAuthTag=function(){if(this._decrypt||!i.isBuffer(this._authTag))throw new Error("Attempting to get auth tag in unsupported state");return this._authTag},f.prototype.setAuthTag=function(e){if(!this._decrypt)throw new Error("Attempting to set auth tag in unsupported state");this._authTag=e},f.prototype.setAAD=function(e){if(this._called)throw new Error("Attempting to set AAD in unsupported state");this._ghash.update(e),this._alen+=e.length},e.exports=f},function(e,t,n){var r=n(93),i=n(8).Buffer,o=n(56);function s(e,t,n,s){o.call(this),this._cipher=new r.AES(t),this._prev=i.from(n),this._cache=i.allocUnsafe(0),this._secCache=i.allocUnsafe(0),this._decrypt=s,this._mode=e}n(7)(s,o),s.prototype._update=function(e){return this._mode.encrypt(this,e,this._decrypt)},s.prototype._final=function(){this._cipher.scrub()},e.exports=s},function(e,t,n){var r=n(66);e.exports=b,b.simpleSieve=g,b.fermatTest=m;var i=n(29),o=new i(24),s=new(n(191)),a=new i(1),u=new i(2),c=new i(5),f=(new i(16),new i(8),new i(10)),l=new i(3),d=(new i(7),new i(11)),h=new i(4),p=(new i(12),null);function v(){if(null!==p)return p;var e=[];e[0]=2;for(var t=1,n=3;n<1048576;n+=2){for(var r=Math.ceil(Math.sqrt(n)),i=0;i<t&&e[i]<=r&&n%e[i]!=0;i++);t!==i&&e[i]<=r||(e[t++]=n)}return p=e,e}function g(e){for(var t=v(),n=0;n<t.length;n++)if(0===e.modn(t[n]))return 0===e.cmpn(t[n]);return!0}function m(e){var t=i.mont(e);return 0===u.toRed(t).redPow(e.subn(1)).fromRed().cmpn(1)}function b(e,t){if(e<16)return new i(2===t||5===t?[140,123]:[140,39]);var n,p;for(t=new i(t);;){for(n=new i(r(Math.ceil(e/8)));n.bitLength()>e;)n.ishrn(1);if(n.isEven()&&n.iadd(a),n.testn(1)||n.iadd(u),t.cmp(u)){if(!t.cmp(c))for(;n.mod(f).cmp(l);)n.iadd(h)}else for(;n.mod(o).cmp(d);)n.iadd(h);if(g(p=n.shrn(1))&&g(n)&&m(p)&&m(n)&&s.test(p)&&s.test(n))return n}}},function(e,t,n){var r=n(29),i=n(124);function o(e){this.rand=e||new i.Rand}e.exports=o,o.create=function(e){return new o(e)},o.prototype._randbelow=function(e){var t=e.bitLength(),n=Math.ceil(t/8);do{var i=new r(this.rand.generate(n))}while(i.cmp(e)>=0);return i},o.prototype._randrange=function(e,t){var n=t.sub(e);return e.add(this._randbelow(n))},o.prototype.test=function(e,t,n){var i=e.bitLength(),o=r.mont(e),s=new r(1).toRed(o);t||(t=Math.max(1,i/48|0));for(var a=e.subn(1),u=0;!a.testn(u);u++);for(var c=e.shrn(u),f=a.toRed(o);t>0;t--){var l=this._randrange(new r(2),a);n&&n(l);var d=l.toRed(o).redPow(c);if(0!==d.cmp(s)&&0!==d.cmp(f)){for(var h=1;h<u;h++){if(0===(d=d.redSqr()).cmp(s))return!1;if(0===d.cmp(f))break}if(h===u)return!1}}return!0},o.prototype.getDivisor=function(e,t){var n=e.bitLength(),i=r.mont(e),o=new r(1).toRed(i);t||(t=Math.max(1,n/48|0));for(var s=e.subn(1),a=0;!s.testn(a);a++);for(var u=e.shrn(a),c=s.toRed(i);t>0;t--){var f=this._randrange(new r(2),s),l=e.gcd(f);if(0!==l.cmpn(1))return l;var d=f.toRed(i).redPow(u);if(0!==d.cmp(o)&&0!==d.cmp(c)){for(var h=1;h<a;h++){if(0===(d=d.redSqr()).cmp(o))return d.fromRed().subn(1).gcd(e);if(0===d.cmp(c))break}if(h===a)return(d=d.redSqr()).fromRed().subn(1).gcd(e)}}return!1}},function(e,t,n){"use strict";(function(t,r){var i;e.exports=A,A.ReadableState=M;n(49).EventEmitter;var o=function(e,t){return e.listeners(t).length},s=n(193),a=n(6).Buffer,u=t.Uint8Array||function(){};var c,f=n(321);c=f&&f.debuglog?f.debuglog("stream"):function(){};var l,d,h,p=n(322),v=n(194),g=n(195).getHighWaterMark,m=n(70).codes,b=m.ERR_INVALID_ARG_TYPE,y=m.ERR_STREAM_PUSH_AFTER_EOF,w=m.ERR_METHOD_NOT_IMPLEMENTED,_=m.ERR_STREAM_UNSHIFT_AFTER_END_EVENT;n(7)(A,s);var S=v.errorOrDestroy,E=["error","close","destroy","pause","resume"];function M(e,t,r){i=i||n(71),e=e||{},"boolean"!=typeof r&&(r=t instanceof i),this.objectMode=!!e.objectMode,r&&(this.objectMode=this.objectMode||!!e.readableObjectMode),this.highWaterMark=g(this,e,"readableHighWaterMark",r),this.buffer=new p,this.length=0,this.pipes=null,this.pipesCount=0,this.flowing=null,this.ended=!1,this.endEmitted=!1,this.reading=!1,this.sync=!0,this.needReadable=!1,this.emittedReadable=!1,this.readableListening=!1,this.resumeScheduled=!1,this.paused=!0,this.emitClose=!1!==e.emitClose,this.autoDestroy=!!e.autoDestroy,this.destroyed=!1,this.defaultEncoding=e.defaultEncoding||"utf8",this.awaitDrain=0,this.readingMore=!1,this.decoder=null,this.encoding=null,e.encoding&&(l||(l=n(59).StringDecoder),this.decoder=new l(e.encoding),this.encoding=e.encoding)}function A(e){if(i=i||n(71),!(this instanceof A))return new A(e);var t=this instanceof i;this._readableState=new M(e,this,t),this.readable=!0,e&&("function"==typeof e.read&&(this._read=e.read),"function"==typeof e.destroy&&(this._destroy=e.destroy)),s.call(this)}function I(e,t,n,r,i){c("readableAddChunk",t);var o,s=e._readableState;if(null===t)s.reading=!1,function(e,t){if(c("onEofChunk"),t.ended)return;if(t.decoder){var n=t.decoder.end();n&&n.length&&(t.buffer.push(n),t.length+=t.objectMode?1:n.length)}t.ended=!0,t.sync?x(e):(t.needReadable=!1,t.emittedReadable||(t.emittedReadable=!0,C(e)))}(e,s);else if(i||(o=function(e,t){var n;r=t,a.isBuffer(r)||r instanceof u||"string"==typeof t||void 0===t||e.objectMode||(n=new b("chunk",["string","Buffer","Uint8Array"],t));var r;return n}(s,t)),o)S(e,o);else if(s.objectMode||t&&t.length>0)if("string"==typeof t||s.objectMode||Object.getPrototypeOf(t)===a.prototype||(t=function(e){return a.from(e)}(t)),r)s.endEmitted?S(e,new _):k(e,s,t,!0);else if(s.ended)S(e,new y);else{if(s.destroyed)return!1;s.reading=!1,s.decoder&&!n?(t=s.decoder.write(t),s.objectMode||0!==t.length?k(e,s,t,!1):T(e,s)):k(e,s,t,!1)}else r||(s.reading=!1,T(e,s));return!s.ended&&(s.length<s.highWaterMark||0===s.length)}function k(e,t,n,r){t.flowing&&0===t.length&&!t.sync?(t.awaitDrain=0,e.emit("data",n)):(t.length+=t.objectMode?1:n.length,r?t.buffer.unshift(n):t.buffer.push(n),t.needReadable&&x(e)),T(e,t)}Object.defineProperty(A.prototype,"destroyed",{enumerable:!1,get:function(){return void 0!==this._readableState&&this._readableState.destroyed},set:function(e){this._readableState&&(this._readableState.destroyed=e)}}),A.prototype.destroy=v.destroy,A.prototype._undestroy=v.undestroy,A.prototype._destroy=function(e,t){t(e)},A.prototype.push=function(e,t){var n,r=this._readableState;return r.objectMode?n=!0:"string"==typeof e&&((t=t||r.defaultEncoding)!==r.encoding&&(e=a.from(e,t),t=""),n=!0),I(this,e,t,!1,n)},A.prototype.unshift=function(e){return I(this,e,null,!0,!1)},A.prototype.isPaused=function(){return!1===this._readableState.flowing},A.prototype.setEncoding=function(e){l||(l=n(59).StringDecoder);var t=new l(e);this._readableState.decoder=t,this._readableState.encoding=this._readableState.decoder.encoding;for(var r=this._readableState.buffer.head,i="";null!==r;)i+=t.write(r.data),r=r.next;return this._readableState.buffer.clear(),""!==i&&this._readableState.buffer.push(i),this._readableState.length=i.length,this};function O(e,t){return e<=0||0===t.length&&t.ended?0:t.objectMode?1:e!=e?t.flowing&&t.length?t.buffer.head.data.length:t.length:(e>t.highWaterMark&&(t.highWaterMark=function(e){return e>=1073741824?e=1073741824:(e--,e|=e>>>1,e|=e>>>2,e|=e>>>4,e|=e>>>8,e|=e>>>16,e++),e}(e)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0))}function x(e){var t=e._readableState;c("emitReadable",t.needReadable,t.emittedReadable),t.needReadable=!1,t.emittedReadable||(c("emitReadable",t.flowing),t.emittedReadable=!0,r.nextTick(C,e))}function C(e){var t=e._readableState;c("emitReadable_",t.destroyed,t.length,t.ended),t.destroyed||!t.length&&!t.ended||(e.emit("readable"),t.emittedReadable=!1),t.needReadable=!t.flowing&&!t.ended&&t.length<=t.highWaterMark,j(e)}function T(e,t){t.readingMore||(t.readingMore=!0,r.nextTick(P,e,t))}function P(e,t){for(;!t.reading&&!t.ended&&(t.length<t.highWaterMark||t.flowing&&0===t.length);){var n=t.length;if(c("maybeReadMore read 0"),e.read(0),n===t.length)break}t.readingMore=!1}function N(e){var t=e._readableState;t.readableListening=e.listenerCount("readable")>0,t.resumeScheduled&&!t.paused?t.flowing=!0:e.listenerCount("data")>0&&e.resume()}function R(e){c("readable nexttick read 0"),e.read(0)}function L(e,t){c("resume",t.reading),t.reading||e.read(0),t.resumeScheduled=!1,e.emit("resume"),j(e),t.flowing&&!t.reading&&e.read(0)}function j(e){var t=e._readableState;for(c("flow",t.flowing);t.flowing&&null!==e.read(););}function D(e,t){return 0===t.length?null:(t.objectMode?n=t.buffer.shift():!e||e>=t.length?(n=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.first():t.buffer.concat(t.length),t.buffer.clear()):n=t.buffer.consume(e,t.decoder),n);var n}function U(e){var t=e._readableState;c("endReadable",t.endEmitted),t.endEmitted||(t.ended=!0,r.nextTick(B,t,e))}function B(e,t){if(c("endReadableNT",e.endEmitted,e.length),!e.endEmitted&&0===e.length&&(e.endEmitted=!0,t.readable=!1,t.emit("end"),e.autoDestroy)){var n=t._writableState;(!n||n.autoDestroy&&n.finished)&&t.destroy()}}function F(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1}A.prototype.read=function(e){c("read",e),e=parseInt(e,10);var t=this._readableState,n=e;if(0!==e&&(t.emittedReadable=!1),0===e&&t.needReadable&&((0!==t.highWaterMark?t.length>=t.highWaterMark:t.length>0)||t.ended))return c("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?U(this):x(this),null;if(0===(e=O(e,t))&&t.ended)return 0===t.length&&U(this),null;var r,i=t.needReadable;return c("need readable",i),(0===t.length||t.length-e<t.highWaterMark)&&c("length less than watermark",i=!0),t.ended||t.reading?c("reading or ended",i=!1):i&&(c("do read"),t.reading=!0,t.sync=!0,0===t.length&&(t.needReadable=!0),this._read(t.highWaterMark),t.sync=!1,t.reading||(e=O(n,t))),null===(r=e>0?D(e,t):null)?(t.needReadable=t.length<=t.highWaterMark,e=0):(t.length-=e,t.awaitDrain=0),0===t.length&&(t.ended||(t.needReadable=!0),n!==e&&t.ended&&U(this)),null!==r&&this.emit("data",r),r},A.prototype._read=function(e){S(this,new w("_read()"))},A.prototype.pipe=function(e,t){var n=this,i=this._readableState;switch(i.pipesCount){case 0:i.pipes=e;break;case 1:i.pipes=[i.pipes,e];break;default:i.pipes.push(e)}i.pipesCount+=1,c("pipe count=%d opts=%j",i.pipesCount,t);var s=(!t||!1!==t.end)&&e!==r.stdout&&e!==r.stderr?u:g;function a(t,r){c("onunpipe"),t===n&&r&&!1===r.hasUnpiped&&(r.hasUnpiped=!0,c("cleanup"),e.removeListener("close",p),e.removeListener("finish",v),e.removeListener("drain",f),e.removeListener("error",h),e.removeListener("unpipe",a),n.removeListener("end",u),n.removeListener("end",g),n.removeListener("data",d),l=!0,!i.awaitDrain||e._writableState&&!e._writableState.needDrain||f())}function u(){c("onend"),e.end()}i.endEmitted?r.nextTick(s):n.once("end",s),e.on("unpipe",a);var f=function(e){return function(){var t=e._readableState;c("pipeOnDrain",t.awaitDrain),t.awaitDrain&&t.awaitDrain--,0===t.awaitDrain&&o(e,"data")&&(t.flowing=!0,j(e))}}(n);e.on("drain",f);var l=!1;function d(t){c("ondata");var r=e.write(t);c("dest.write",r),!1===r&&((1===i.pipesCount&&i.pipes===e||i.pipesCount>1&&-1!==F(i.pipes,e))&&!l&&(c("false write response, pause",i.awaitDrain),i.awaitDrain++),n.pause())}function h(t){c("onerror",t),g(),e.removeListener("error",h),0===o(e,"error")&&S(e,t)}function p(){e.removeListener("finish",v),g()}function v(){c("onfinish"),e.removeListener("close",p),g()}function g(){c("unpipe"),n.unpipe(e)}return n.on("data",d),function(e,t,n){if("function"==typeof e.prependListener)return e.prependListener(t,n);e._events&&e._events[t]?Array.isArray(e._events[t])?e._events[t].unshift(n):e._events[t]=[n,e._events[t]]:e.on(t,n)}(e,"error",h),e.once("close",p),e.once("finish",v),e.emit("pipe",n),i.flowing||(c("pipe resume"),n.resume()),e},A.prototype.unpipe=function(e){var t=this._readableState,n={hasUnpiped:!1};if(0===t.pipesCount)return this;if(1===t.pipesCount)return e&&e!==t.pipes||(e||(e=t.pipes),t.pipes=null,t.pipesCount=0,t.flowing=!1,e&&e.emit("unpipe",this,n)),this;if(!e){var r=t.pipes,i=t.pipesCount;t.pipes=null,t.pipesCount=0,t.flowing=!1;for(var o=0;o<i;o++)r[o].emit("unpipe",this,{hasUnpiped:!1});return this}var s=F(t.pipes,e);return-1===s||(t.pipes.splice(s,1),t.pipesCount-=1,1===t.pipesCount&&(t.pipes=t.pipes[0]),e.emit("unpipe",this,n)),this},A.prototype.on=function(e,t){var n=s.prototype.on.call(this,e,t),i=this._readableState;return"data"===e?(i.readableListening=this.listenerCount("readable")>0,!1!==i.flowing&&this.resume()):"readable"===e&&(i.endEmitted||i.readableListening||(i.readableListening=i.needReadable=!0,i.flowing=!1,i.emittedReadable=!1,c("on readable",i.length,i.reading),i.length?x(this):i.reading||r.nextTick(R,this))),n},A.prototype.addListener=A.prototype.on,A.prototype.removeListener=function(e,t){var n=s.prototype.removeListener.call(this,e,t);return"readable"===e&&r.nextTick(N,this),n},A.prototype.removeAllListeners=function(e){var t=s.prototype.removeAllListeners.apply(this,arguments);return"readable"!==e&&void 0!==e||r.nextTick(N,this),t},A.prototype.resume=function(){var e=this._readableState;return e.flowing||(c("resume"),e.flowing=!e.readableListening,function(e,t){t.resumeScheduled||(t.resumeScheduled=!0,r.nextTick(L,e,t))}(this,e)),e.paused=!1,this},A.prototype.pause=function(){return c("call pause flowing=%j",this._readableState.flowing),!1!==this._readableState.flowing&&(c("pause"),this._readableState.flowing=!1,this.emit("pause")),this._readableState.paused=!0,this},A.prototype.wrap=function(e){var t=this,n=this._readableState,r=!1;for(var i in e.on("end",(function(){if(c("wrapped end"),n.decoder&&!n.ended){var e=n.decoder.end();e&&e.length&&t.push(e)}t.push(null)})),e.on("data",(function(i){(c("wrapped data"),n.decoder&&(i=n.decoder.write(i)),n.objectMode&&null==i)||(n.objectMode||i&&i.length)&&(t.push(i)||(r=!0,e.pause()))})),e)void 0===this[i]&&"function"==typeof e[i]&&(this[i]=function(t){return function(){return e[t].apply(e,arguments)}}(i));for(var o=0;o<E.length;o++)e.on(E[o],this.emit.bind(this,E[o]));return this._read=function(t){c("wrapped _read",t),r&&(r=!1,e.resume())},this},"function"==typeof Symbol&&(A.prototype[Symbol.asyncIterator]=function(){return void 0===d&&(d=n(324)),d(this)}),Object.defineProperty(A.prototype,"readableHighWaterMark",{enumerable:!1,get:function(){return this._readableState.highWaterMark}}),Object.defineProperty(A.prototype,"readableBuffer",{enumerable:!1,get:function(){return this._readableState&&this._readableState.buffer}}),Object.defineProperty(A.prototype,"readableFlowing",{enumerable:!1,get:function(){return this._readableState.flowing},set:function(e){this._readableState&&(this._readableState.flowing=e)}}),A._fromList=D,Object.defineProperty(A.prototype,"readableLength",{enumerable:!1,get:function(){return this._readableState.length}}),"function"==typeof Symbol&&(A.from=function(e,t){return void 0===h&&(h=n(325)),h(A,e,t)})}).call(this,n(31),n(20))},function(e,t,n){e.exports=n(49).EventEmitter},function(e,t,n){"use strict";(function(t){function n(e,t){i(e,t),r(e)}function r(e){e._writableState&&!e._writableState.emitClose||e._readableState&&!e._readableState.emitClose||e.emit("close")}function i(e,t){e.emit("error",t)}e.exports={destroy:function(e,o){var s=this,a=this._readableState&&this._readableState.destroyed,u=this._writableState&&this._writableState.destroyed;return a||u?(o?o(e):e&&(this._writableState?this._writableState.errorEmitted||(this._writableState.errorEmitted=!0,t.nextTick(i,this,e)):t.nextTick(i,this,e)),this):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,(function(e){!o&&e?s._writableState?s._writableState.errorEmitted?t.nextTick(r,s):(s._writableState.errorEmitted=!0,t.nextTick(n,s,e)):t.nextTick(n,s,e):o?(t.nextTick(r,s),o(e)):t.nextTick(r,s)})),this)},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finalCalled=!1,this._writableState.prefinished=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)},errorOrDestroy:function(e,t){var n=e._readableState,r=e._writableState;n&&n.autoDestroy||r&&r.autoDestroy?e.destroy(t):e.emit("error",t)}}}).call(this,n(20))},function(e,t,n){"use strict";var r=n(70).codes.ERR_INVALID_OPT_VALUE;e.exports={getHighWaterMark:function(e,t,n,i){var o=function(e,t,n){return null!=e.highWaterMark?e.highWaterMark:t?e[n]:null}(t,i,n);if(null!=o){if(!isFinite(o)||Math.floor(o)!==o||o<0)throw new r(i?n:"highWaterMark",o);return Math.floor(o)}return e.objectMode?16:16384}}},function(e,t,n){"use strict";(function(t,r){function i(e){var t=this;this.next=null,this.entry=null,this.finish=function(){!function(e,t,n){var r=e.entry;e.entry=null;for(;r;){var i=r.callback;t.pendingcb--,i(n),r=r.next}t.corkedRequestsFree.next=e}(t,e)}}var o;e.exports=A,A.WritableState=M;var s={deprecate:n(114)},a=n(193),u=n(6).Buffer,c=t.Uint8Array||function(){};var f,l=n(194),d=n(195).getHighWaterMark,h=n(70).codes,p=h.ERR_INVALID_ARG_TYPE,v=h.ERR_METHOD_NOT_IMPLEMENTED,g=h.ERR_MULTIPLE_CALLBACK,m=h.ERR_STREAM_CANNOT_PIPE,b=h.ERR_STREAM_DESTROYED,y=h.ERR_STREAM_NULL_VALUES,w=h.ERR_STREAM_WRITE_AFTER_END,_=h.ERR_UNKNOWN_ENCODING,S=l.errorOrDestroy;function E(){}function M(e,t,s){o=o||n(71),e=e||{},"boolean"!=typeof s&&(s=t instanceof o),this.objectMode=!!e.objectMode,s&&(this.objectMode=this.objectMode||!!e.writableObjectMode),this.highWaterMark=d(this,e,"writableHighWaterMark",s),this.finalCalled=!1,this.needDrain=!1,this.ending=!1,this.ended=!1,this.finished=!1,this.destroyed=!1;var a=!1===e.decodeStrings;this.decodeStrings=!a,this.defaultEncoding=e.defaultEncoding||"utf8",this.length=0,this.writing=!1,this.corked=0,this.sync=!0,this.bufferProcessing=!1,this.onwrite=function(e){!function(e,t){var n=e._writableState,i=n.sync,o=n.writecb;if("function"!=typeof o)throw new g;if(function(e){e.writing=!1,e.writecb=null,e.length-=e.writelen,e.writelen=0}(n),t)!function(e,t,n,i,o){--t.pendingcb,n?(r.nextTick(o,i),r.nextTick(T,e,t),e._writableState.errorEmitted=!0,S(e,i)):(o(i),e._writableState.errorEmitted=!0,S(e,i),T(e,t))}(e,n,i,t,o);else{var s=x(n)||e.destroyed;s||n.corked||n.bufferProcessing||!n.bufferedRequest||O(e,n),i?r.nextTick(k,e,n,s,o):k(e,n,s,o)}}(t,e)},this.writecb=null,this.writelen=0,this.bufferedRequest=null,this.lastBufferedRequest=null,this.pendingcb=0,this.prefinished=!1,this.errorEmitted=!1,this.emitClose=!1!==e.emitClose,this.autoDestroy=!!e.autoDestroy,this.bufferedRequestCount=0,this.corkedRequestsFree=new i(this)}function A(e){var t=this instanceof(o=o||n(71));if(!t&&!f.call(A,this))return new A(e);this._writableState=new M(e,this,t),this.writable=!0,e&&("function"==typeof e.write&&(this._write=e.write),"function"==typeof e.writev&&(this._writev=e.writev),"function"==typeof e.destroy&&(this._destroy=e.destroy),"function"==typeof e.final&&(this._final=e.final)),a.call(this)}function I(e,t,n,r,i,o,s){t.writelen=r,t.writecb=s,t.writing=!0,t.sync=!0,t.destroyed?t.onwrite(new b("write")):n?e._writev(i,t.onwrite):e._write(i,o,t.onwrite),t.sync=!1}function k(e,t,n,r){n||function(e,t){0===t.length&&t.needDrain&&(t.needDrain=!1,e.emit("drain"))}(e,t),t.pendingcb--,r(),T(e,t)}function O(e,t){t.bufferProcessing=!0;var n=t.bufferedRequest;if(e._writev&&n&&n.next){var r=t.bufferedRequestCount,o=new Array(r),s=t.corkedRequestsFree;s.entry=n;for(var a=0,u=!0;n;)o[a]=n,n.isBuf||(u=!1),n=n.next,a+=1;o.allBuffers=u,I(e,t,!0,t.length,o,"",s.finish),t.pendingcb++,t.lastBufferedRequest=null,s.next?(t.corkedRequestsFree=s.next,s.next=null):t.corkedRequestsFree=new i(t),t.bufferedRequestCount=0}else{for(;n;){var c=n.chunk,f=n.encoding,l=n.callback;if(I(e,t,!1,t.objectMode?1:c.length,c,f,l),n=n.next,t.bufferedRequestCount--,t.writing)break}null===n&&(t.lastBufferedRequest=null)}t.bufferedRequest=n,t.bufferProcessing=!1}function x(e){return e.ending&&0===e.length&&null===e.bufferedRequest&&!e.finished&&!e.writing}function C(e,t){e._final((function(n){t.pendingcb--,n&&S(e,n),t.prefinished=!0,e.emit("prefinish"),T(e,t)}))}function T(e,t){var n=x(t);if(n&&(function(e,t){t.prefinished||t.finalCalled||("function"!=typeof e._final||t.destroyed?(t.prefinished=!0,e.emit("prefinish")):(t.pendingcb++,t.finalCalled=!0,r.nextTick(C,e,t)))}(e,t),0===t.pendingcb&&(t.finished=!0,e.emit("finish"),t.autoDestroy))){var i=e._readableState;(!i||i.autoDestroy&&i.endEmitted)&&e.destroy()}return n}n(7)(A,a),M.prototype.getBuffer=function(){for(var e=this.bufferedRequest,t=[];e;)t.push(e),e=e.next;return t},function(){try{Object.defineProperty(M.prototype,"buffer",{get:s.deprecate((function(){return this.getBuffer()}),"_writableState.buffer is deprecated. Use _writableState.getBuffer instead.","DEP0003")})}catch(e){}}(),"function"==typeof Symbol&&Symbol.hasInstance&&"function"==typeof Function.prototype[Symbol.hasInstance]?(f=Function.prototype[Symbol.hasInstance],Object.defineProperty(A,Symbol.hasInstance,{value:function(e){return!!f.call(this,e)||this===A&&(e&&e._writableState instanceof M)}})):f=function(e){return e instanceof this},A.prototype.pipe=function(){S(this,new m)},A.prototype.write=function(e,t,n){var i,o=this._writableState,s=!1,a=!o.objectMode&&(i=e,u.isBuffer(i)||i instanceof c);return a&&!u.isBuffer(e)&&(e=function(e){return u.from(e)}(e)),"function"==typeof t&&(n=t,t=null),a?t="buffer":t||(t=o.defaultEncoding),"function"!=typeof n&&(n=E),o.ending?function(e,t){var n=new w;S(e,n),r.nextTick(t,n)}(this,n):(a||function(e,t,n,i){var o;return null===n?o=new y:"string"==typeof n||t.objectMode||(o=new p("chunk",["string","Buffer"],n)),!o||(S(e,o),r.nextTick(i,o),!1)}(this,o,e,n))&&(o.pendingcb++,s=function(e,t,n,r,i,o){if(!n){var s=function(e,t,n){e.objectMode||!1===e.decodeStrings||"string"!=typeof t||(t=u.from(t,n));return t}(t,r,i);r!==s&&(n=!0,i="buffer",r=s)}var a=t.objectMode?1:r.length;t.length+=a;var c=t.length<t.highWaterMark;c||(t.needDrain=!0);if(t.writing||t.corked){var f=t.lastBufferedRequest;t.lastBufferedRequest={chunk:r,encoding:i,isBuf:n,callback:o,next:null},f?f.next=t.lastBufferedRequest:t.bufferedRequest=t.lastBufferedRequest,t.bufferedRequestCount+=1}else I(e,t,!1,a,r,i,o);return c}(this,o,a,e,t,n)),s},A.prototype.cork=function(){this._writableState.corked++},A.prototype.uncork=function(){var e=this._writableState;e.corked&&(e.corked--,e.writing||e.corked||e.bufferProcessing||!e.bufferedRequest||O(this,e))},A.prototype.setDefaultEncoding=function(e){if("string"==typeof e&&(e=e.toLowerCase()),!(["hex","utf8","utf-8","ascii","binary","base64","ucs2","ucs-2","utf16le","utf-16le","raw"].indexOf((e+"").toLowerCase())>-1))throw new _(e);return this._writableState.defaultEncoding=e,this},Object.defineProperty(A.prototype,"writableBuffer",{enumerable:!1,get:function(){return this._writableState&&this._writableState.getBuffer()}}),Object.defineProperty(A.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),A.prototype._write=function(e,t,n){n(new v("_write()"))},A.prototype._writev=null,A.prototype.end=function(e,t,n){var i=this._writableState;return"function"==typeof e?(n=e,e=null,t=null):"function"==typeof t&&(n=t,t=null),null!=e&&this.write(e,t),i.corked&&(i.corked=1,this.uncork()),i.ending||function(e,t,n){t.ending=!0,T(e,t),n&&(t.finished?r.nextTick(n):e.once("finish",n));t.ended=!0,e.writable=!1}(this,i,n),this},Object.defineProperty(A.prototype,"writableLength",{enumerable:!1,get:function(){return this._writableState.length}}),Object.defineProperty(A.prototype,"destroyed",{enumerable:!1,get:function(){return void 0!==this._writableState&&this._writableState.destroyed},set:function(e){this._writableState&&(this._writableState.destroyed=e)}}),A.prototype.destroy=l.destroy,A.prototype._undestroy=l.undestroy,A.prototype._destroy=function(e,t){t(e)}}).call(this,n(31),n(20))},function(e,t,n){"use strict";e.exports=f;var r=n(70).codes,i=r.ERR_METHOD_NOT_IMPLEMENTED,o=r.ERR_MULTIPLE_CALLBACK,s=r.ERR_TRANSFORM_ALREADY_TRANSFORMING,a=r.ERR_TRANSFORM_WITH_LENGTH_0,u=n(71);function c(e,t){var n=this._transformState;n.transforming=!1;var r=n.writecb;if(null===r)return this.emit("error",new o);n.writechunk=null,n.writecb=null,null!=t&&this.push(t),r(e);var i=this._readableState;i.reading=!1,(i.needReadable||i.length<i.highWaterMark)&&this._read(i.highWaterMark)}function f(e){if(!(this instanceof f))return new f(e);u.call(this,e),this._transformState={afterTransform:c.bind(this),needTransform:!1,transforming:!1,writecb:null,writechunk:null,writeencoding:null},this._readableState.needReadable=!0,this._readableState.sync=!1,e&&("function"==typeof e.transform&&(this._transform=e.transform),"function"==typeof e.flush&&(this._flush=e.flush)),this.on("prefinish",l)}function l(){var e=this;"function"!=typeof this._flush||this._readableState.destroyed?d(this,null,null):this._flush((function(t,n){d(e,t,n)}))}function d(e,t,n){if(t)return e.emit("error",t);if(null!=n&&e.push(n),e._writableState.length)throw new a;if(e._transformState.transforming)throw new s;return e.push(null)}n(7)(f,u),f.prototype.push=function(e,t){return this._transformState.needTransform=!1,u.prototype.push.call(this,e,t)},f.prototype._transform=function(e,t,n){n(new i("_transform()"))},f.prototype._write=function(e,t,n){var r=this._transformState;if(r.writecb=n,r.writechunk=e,r.writeencoding=t,!r.transforming){var i=this._readableState;(r.needTransform||i.needReadable||i.length<i.highWaterMark)&&this._read(i.highWaterMark)}},f.prototype._read=function(e){var t=this._transformState;null===t.writechunk||t.transforming?t.needTransform=!0:(t.transforming=!0,this._transform(t.writechunk,t.writeencoding,t.afterTransform))},f.prototype._destroy=function(e,t){u.prototype._destroy.call(this,e,(function(e){t(e)}))}},function(e,t,n){"use strict";var r=t;function i(e){return 1===e.length?"0"+e:e}function o(e){for(var t="",n=0;n<e.length;n++)t+=i(e[n].toString(16));return t}r.toArray=function(e,t){if(Array.isArray(e))return e.slice();if(!e)return[];var n=[];if("string"!=typeof e){for(var r=0;r<e.length;r++)n[r]=0|e[r];return n}if("hex"===t){(e=e.replace(/[^a-z0-9]+/gi,"")).length%2!=0&&(e="0"+e);for(r=0;r<e.length;r+=2)n.push(parseInt(e[r]+e[r+1],16))}else for(r=0;r<e.length;r++){var i=e.charCodeAt(r),o=i>>8,s=255&i;o?n.push(o,s):n.push(s)}return n},r.zero2=i,r.toHex=o,r.encode=function(e,t){return"hex"===t?o(e):e}},function(e,t,n){"use strict";var r=t;r.base=n(95),r.short=n(332),r.mont=n(333),r.edwards=n(334)},function(e,t,n){"use strict";var r=n(51).rotr32;function i(e,t,n){return e&t^~e&n}function o(e,t,n){return e&t^e&n^t&n}function s(e,t,n){return e^t^n}t.ft_1=function(e,t,n,r){return 0===e?i(t,n,r):1===e||3===e?s(t,n,r):2===e?o(t,n,r):void 0},t.ch32=i,t.maj32=o,t.p32=s,t.s0_256=function(e){return r(e,2)^r(e,13)^r(e,22)},t.s1_256=function(e){return r(e,6)^r(e,11)^r(e,25)},t.g0_256=function(e){return r(e,7)^r(e,18)^e>>>3},t.g1_256=function(e){return r(e,17)^r(e,19)^e>>>10}},function(e,t,n){"use strict";var r=n(51),i=n(82),o=n(200),s=n(46),a=r.sum32,u=r.sum32_4,c=r.sum32_5,f=o.ch32,l=o.maj32,d=o.s0_256,h=o.s1_256,p=o.g0_256,v=o.g1_256,g=i.BlockHash,m=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298];function b(){if(!(this instanceof b))return new b;g.call(this),this.h=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],this.k=m,this.W=new Array(64)}r.inherits(b,g),e.exports=b,b.blockSize=512,b.outSize=256,b.hmacStrength=192,b.padLength=64,b.prototype._update=function(e,t){for(var n=this.W,r=0;r<16;r++)n[r]=e[t+r];for(;r<n.length;r++)n[r]=u(v(n[r-2]),n[r-7],p(n[r-15]),n[r-16]);var i=this.h[0],o=this.h[1],g=this.h[2],m=this.h[3],b=this.h[4],y=this.h[5],w=this.h[6],_=this.h[7];for(s(this.k.length===n.length),r=0;r<n.length;r++){var S=c(_,h(b),f(b,y,w),this.k[r],n[r]),E=a(d(i),l(i,o,g));_=w,w=y,y=b,b=a(m,S),m=g,g=o,o=i,i=a(S,E)}this.h[0]=a(this.h[0],i),this.h[1]=a(this.h[1],o),this.h[2]=a(this.h[2],g),this.h[3]=a(this.h[3],m),this.h[4]=a(this.h[4],b),this.h[5]=a(this.h[5],y),this.h[6]=a(this.h[6],w),this.h[7]=a(this.h[7],_)},b.prototype._digest=function(e){return"hex"===e?r.toHex32(this.h,"big"):r.split32(this.h,"big")}},function(e,t,n){"use strict";var r=n(51),i=n(82),o=n(46),s=r.rotr64_hi,a=r.rotr64_lo,u=r.shr64_hi,c=r.shr64_lo,f=r.sum64,l=r.sum64_hi,d=r.sum64_lo,h=r.sum64_4_hi,p=r.sum64_4_lo,v=r.sum64_5_hi,g=r.sum64_5_lo,m=i.BlockHash,b=[1116352408,3609767458,1899447441,602891725,3049323471,3964484399,3921009573,2173295548,961987163,4081628472,1508970993,3053834265,2453635748,2937671579,2870763221,3664609560,3624381080,2734883394,310598401,1164996542,607225278,1323610764,1426881987,3590304994,1925078388,4068182383,2162078206,991336113,2614888103,633803317,3248222580,3479774868,3835390401,2666613458,4022224774,944711139,264347078,2341262773,604807628,2007800933,770255983,1495990901,1249150122,1856431235,1555081692,3175218132,1996064986,2198950837,2554220882,3999719339,2821834349,766784016,2952996808,2566594879,3210313671,3203337956,3336571891,1034457026,3584528711,2466948901,113926993,3758326383,338241895,168717936,666307205,1188179964,773529912,1546045734,1294757372,1522805485,1396182291,2643833823,1695183700,2343527390,1986661051,1014477480,2177026350,1206759142,2456956037,344077627,2730485921,1290863460,2820302411,3158454273,3259730800,3505952657,3345764771,106217008,3516065817,3606008344,3600352804,1432725776,4094571909,1467031594,275423344,851169720,430227734,3100823752,506948616,1363258195,659060556,3750685593,883997877,3785050280,958139571,3318307427,1322822218,3812723403,1537002063,2003034995,1747873779,3602036899,1955562222,1575990012,2024104815,1125592928,2227730452,2716904306,2361852424,442776044,2428436474,593698344,2756734187,3733110249,3204031479,2999351573,3329325298,3815920427,3391569614,3928383900,3515267271,566280711,3940187606,3454069534,4118630271,4000239992,116418474,1914138554,174292421,2731055270,289380356,3203993006,460393269,320620315,685471733,587496836,852142971,1086792851,1017036298,365543100,1126000580,2618297676,1288033470,3409855158,1501505948,4234509866,1607167915,987167468,1816402316,1246189591];function y(){if(!(this instanceof y))return new y;m.call(this),this.h=[1779033703,4089235720,3144134277,2227873595,1013904242,4271175723,2773480762,1595750129,1359893119,2917565137,2600822924,725511199,528734635,4215389547,1541459225,327033209],this.k=b,this.W=new Array(160)}function w(e,t,n,r,i){var o=e&n^~e&i;return o<0&&(o+=4294967296),o}function _(e,t,n,r,i,o){var s=t&r^~t&o;return s<0&&(s+=4294967296),s}function S(e,t,n,r,i){var o=e&n^e&i^n&i;return o<0&&(o+=4294967296),o}function E(e,t,n,r,i,o){var s=t&r^t&o^r&o;return s<0&&(s+=4294967296),s}function M(e,t){var n=s(e,t,28)^s(t,e,2)^s(t,e,7);return n<0&&(n+=4294967296),n}function A(e,t){var n=a(e,t,28)^a(t,e,2)^a(t,e,7);return n<0&&(n+=4294967296),n}function I(e,t){var n=s(e,t,14)^s(e,t,18)^s(t,e,9);return n<0&&(n+=4294967296),n}function k(e,t){var n=a(e,t,14)^a(e,t,18)^a(t,e,9);return n<0&&(n+=4294967296),n}function O(e,t){var n=s(e,t,1)^s(e,t,8)^u(e,t,7);return n<0&&(n+=4294967296),n}function x(e,t){var n=a(e,t,1)^a(e,t,8)^c(e,t,7);return n<0&&(n+=4294967296),n}function C(e,t){var n=s(e,t,19)^s(t,e,29)^u(e,t,6);return n<0&&(n+=4294967296),n}function T(e,t){var n=a(e,t,19)^a(t,e,29)^c(e,t,6);return n<0&&(n+=4294967296),n}r.inherits(y,m),e.exports=y,y.blockSize=1024,y.outSize=512,y.hmacStrength=192,y.padLength=128,y.prototype._prepareBlock=function(e,t){for(var n=this.W,r=0;r<32;r++)n[r]=e[t+r];for(;r<n.length;r+=2){var i=C(n[r-4],n[r-3]),o=T(n[r-4],n[r-3]),s=n[r-14],a=n[r-13],u=O(n[r-30],n[r-29]),c=x(n[r-30],n[r-29]),f=n[r-32],l=n[r-31];n[r]=h(i,o,s,a,u,c,f,l),n[r+1]=p(i,o,s,a,u,c,f,l)}},y.prototype._update=function(e,t){this._prepareBlock(e,t);var n=this.W,r=this.h[0],i=this.h[1],s=this.h[2],a=this.h[3],u=this.h[4],c=this.h[5],h=this.h[6],p=this.h[7],m=this.h[8],b=this.h[9],y=this.h[10],O=this.h[11],x=this.h[12],C=this.h[13],T=this.h[14],P=this.h[15];o(this.k.length===n.length);for(var N=0;N<n.length;N+=2){var R=T,L=P,j=I(m,b),D=k(m,b),U=w(m,b,y,O,x),B=_(m,b,y,O,x,C),F=this.k[N],z=this.k[N+1],q=n[N],K=n[N+1],H=v(R,L,j,D,U,B,F,z,q,K),V=g(R,L,j,D,U,B,F,z,q,K);R=M(r,i),L=A(r,i),j=S(r,i,s,a,u),D=E(r,i,s,a,u,c);var G=l(R,L,j,D),W=d(R,L,j,D);T=x,P=C,x=y,C=O,y=m,O=b,m=l(h,p,H,V),b=d(p,p,H,V),h=u,p=c,u=s,c=a,s=r,a=i,r=l(H,V,G,W),i=d(H,V,G,W)}f(this.h,0,r,i),f(this.h,2,s,a),f(this.h,4,u,c),f(this.h,6,h,p),f(this.h,8,m,b),f(this.h,10,y,O),f(this.h,12,x,C),f(this.h,14,T,P)},y.prototype._digest=function(e){return"hex"===e?r.toHex32(this.h,"big"):r.split32(this.h,"big")}},function(e,t,n){(function(e){!function(e,t){"use strict";function r(e,t){if(!e)throw new Error(t||"Assertion failed")}function i(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}function o(e,t,n){if(o.isBN(e))return e;this.negative=0,this.words=null,this.length=0,this.red=null,null!==e&&("le"!==t&&"be"!==t||(n=t,t=10),this._init(e||0,t||10,n||"be"))}var s;"object"==typeof e?e.exports=o:t.BN=o,o.BN=o,o.wordSize=26;try{s=n(349).Buffer}catch(e){}function a(e,t,n){for(var i=0,o=Math.min(e.length,n),s=0,a=t;a<o;a++){var u,c=e.charCodeAt(a)-48;i<<=4,i|=u=c>=49&&c<=54?c-49+10:c>=17&&c<=22?c-17+10:c,s|=u}return r(!(240&s),"Invalid character in "+e),i}function u(e,t,n,i){for(var o=0,s=0,a=Math.min(e.length,n),u=t;u<a;u++){var c=e.charCodeAt(u)-48;o*=i,s=c>=49?c-49+10:c>=17?c-17+10:c,r(c>=0&&s<i,"Invalid character"),o+=s}return o}function c(e,t){e.words=t.words,e.length=t.length,e.negative=t.negative,e.red=t.red}if(o.isBN=function(e){return e instanceof o||null!==e&&"object"==typeof e&&e.constructor.wordSize===o.wordSize&&Array.isArray(e.words)},o.max=function(e,t){return e.cmp(t)>0?e:t},o.min=function(e,t){return e.cmp(t)<0?e:t},o.prototype._init=function(e,t,n){if("number"==typeof e)return this._initNumber(e,t,n);if("object"==typeof e)return this._initArray(e,t,n);"hex"===t&&(t=16),r(t===(0|t)&&t>=2&&t<=36);var i=0;"-"===(e=e.toString().replace(/\s+/g,""))[0]&&i++,16===t?this._parseHex(e,i):this._parseBase(e,t,i),"-"===e[0]&&(this.negative=1),this._strip(),"le"===n&&this._initArray(this.toArray(),t,n)},o.prototype._initNumber=function(e,t,n){e<0&&(this.negative=1,e=-e),e<67108864?(this.words=[67108863&e],this.length=1):e<4503599627370496?(this.words=[67108863&e,e/67108864&67108863],this.length=2):(r(e<9007199254740992),this.words=[67108863&e,e/67108864&67108863,1],this.length=3),"le"===n&&this._initArray(this.toArray(),t,n)},o.prototype._initArray=function(e,t,n){if(r("number"==typeof e.length),e.length<=0)return this.words=[0],this.length=1,this;this.length=Math.ceil(e.length/3),this.words=new Array(this.length);for(var i=0;i<this.length;i++)this.words[i]=0;var o,s,a=0;if("be"===n)for(i=e.length-1,o=0;i>=0;i-=3)s=e[i]|e[i-1]<<8|e[i-2]<<16,this.words[o]|=s<<a&67108863,this.words[o+1]=s>>>26-a&67108863,(a+=24)>=26&&(a-=26,o++);else if("le"===n)for(i=0,o=0;i<e.length;i+=3)s=e[i]|e[i+1]<<8|e[i+2]<<16,this.words[o]|=s<<a&67108863,this.words[o+1]=s>>>26-a&67108863,(a+=24)>=26&&(a-=26,o++);return this._strip()},o.prototype._parseHex=function(e,t){this.length=Math.ceil((e.length-t)/6),this.words=new Array(this.length);for(var n=0;n<this.length;n++)this.words[n]=0;var r,i,o=0;for(n=e.length-6,r=0;n>=t;n-=6)i=a(e,n,n+6),this.words[r]|=i<<o&67108863,this.words[r+1]|=i>>>26-o&4194303,(o+=24)>=26&&(o-=26,r++);n+6!==t&&(i=a(e,t,n+6),this.words[r]|=i<<o&67108863,this.words[r+1]|=i>>>26-o&4194303),this._strip()},o.prototype._parseBase=function(e,t,n){this.words=[0],this.length=1;for(var r=0,i=1;i<=67108863;i*=t)r++;r--,i=i/t|0;for(var o=e.length-n,s=o%r,a=Math.min(o,o-s)+n,c=0,f=n;f<a;f+=r)c=u(e,f,f+r,t),this.imuln(i),this.words[0]+c<67108864?this.words[0]+=c:this._iaddn(c);if(0!==s){var l=1;for(c=u(e,f,e.length,t),f=0;f<s;f++)l*=t;this.imuln(l),this.words[0]+c<67108864?this.words[0]+=c:this._iaddn(c)}},o.prototype.copy=function(e){e.words=new Array(this.length);for(var t=0;t<this.length;t++)e.words[t]=this.words[t];e.length=this.length,e.negative=this.negative,e.red=this.red},o.prototype._move=function(e){c(e,this)},o.prototype.clone=function(){var e=new o(null);return this.copy(e),e},o.prototype._expand=function(e){for(;this.length<e;)this.words[this.length++]=0;return this},o.prototype._strip=function(){for(;this.length>1&&0===this.words[this.length-1];)this.length--;return this._normSign()},o.prototype._normSign=function(){return 1===this.length&&0===this.words[0]&&(this.negative=0),this},"undefined"!=typeof Symbol&&"function"==typeof Symbol.for)try{o.prototype[Symbol.for("nodejs.util.inspect.custom")]=f}catch(e){o.prototype.inspect=f}else o.prototype.inspect=f;function f(){return(this.red?"<BN-R: ":"<BN: ")+this.toString(16)+">"}var l=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],d=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],h=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];o.prototype.toString=function(e,t){var n;if(t=0|t||1,16===(e=e||10)||"hex"===e){n="";for(var i=0,o=0,s=0;s<this.length;s++){var a=this.words[s],u=(16777215&(a<<i|o)).toString(16);n=0!==(o=a>>>24-i&16777215)||s!==this.length-1?l[6-u.length]+u+n:u+n,(i+=2)>=26&&(i-=26,s--)}for(0!==o&&(n=o.toString(16)+n);n.length%t!=0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}if(e===(0|e)&&e>=2&&e<=36){var c=d[e],f=h[e];n="";var p=this.clone();for(p.negative=0;!p.isZero();){var v=p.modrn(f).toString(e);n=(p=p.idivn(f)).isZero()?v+n:l[c-v.length]+v+n}for(this.isZero()&&(n="0"+n);n.length%t!=0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}r(!1,"Base should be between 2 and 36")},o.prototype.toNumber=function(){var e=this.words[0];return 2===this.length?e+=67108864*this.words[1]:3===this.length&&1===this.words[2]?e+=4503599627370496+67108864*this.words[1]:this.length>2&&r(!1,"Number can only safely store up to 53 bits"),0!==this.negative?-e:e},o.prototype.toJSON=function(){return this.toString(16,2)},s&&(o.prototype.toBuffer=function(e,t){return this.toArrayLike(s,e,t)}),o.prototype.toArray=function(e,t){return this.toArrayLike(Array,e,t)};function p(e,t,n){n.negative=t.negative^e.negative;var r=e.length+t.length|0;n.length=r,r=r-1|0;var i=0|e.words[0],o=0|t.words[0],s=i*o,a=67108863&s,u=s/67108864|0;n.words[0]=a;for(var c=1;c<r;c++){for(var f=u>>>26,l=67108863&u,d=Math.min(c,t.length-1),h=Math.max(0,c-e.length+1);h<=d;h++){var p=c-h|0;f+=(s=(i=0|e.words[p])*(o=0|t.words[h])+l)/67108864|0,l=67108863&s}n.words[c]=0|l,u=0|f}return 0!==u?n.words[c]=0|u:n.length--,n._strip()}o.prototype.toArrayLike=function(e,t,n){this._strip();var i=this.byteLength(),o=n||Math.max(1,i);r(i<=o,"byte array longer than desired length"),r(o>0,"Requested array length <= 0");var s=function(e,t){return e.allocUnsafe?e.allocUnsafe(t):new e(t)}(e,o);return this["_toArrayLike"+("le"===t?"LE":"BE")](s,i),s},o.prototype._toArrayLikeLE=function(e,t){for(var n=0,r=0,i=0,o=0;i<this.length;i++){var s=this.words[i]<<o|r;e[n++]=255&s,n<e.length&&(e[n++]=s>>8&255),n<e.length&&(e[n++]=s>>16&255),6===o?(n<e.length&&(e[n++]=s>>24&255),r=0,o=0):(r=s>>>24,o+=2)}if(n<e.length)for(e[n++]=r;n<e.length;)e[n++]=0},o.prototype._toArrayLikeBE=function(e,t){for(var n=e.length-1,r=0,i=0,o=0;i<this.length;i++){var s=this.words[i]<<o|r;e[n--]=255&s,n>=0&&(e[n--]=s>>8&255),n>=0&&(e[n--]=s>>16&255),6===o?(n>=0&&(e[n--]=s>>24&255),r=0,o=0):(r=s>>>24,o+=2)}if(n>=0)for(e[n--]=r;n>=0;)e[n--]=0},Math.clz32?o.prototype._countBits=function(e){return 32-Math.clz32(e)}:o.prototype._countBits=function(e){var t=e,n=0;return t>=4096&&(n+=13,t>>>=13),t>=64&&(n+=7,t>>>=7),t>=8&&(n+=4,t>>>=4),t>=2&&(n+=2,t>>>=2),n+t},o.prototype._zeroBits=function(e){if(0===e)return 26;var t=e,n=0;return 0==(8191&t)&&(n+=13,t>>>=13),0==(127&t)&&(n+=7,t>>>=7),0==(15&t)&&(n+=4,t>>>=4),0==(3&t)&&(n+=2,t>>>=2),0==(1&t)&&n++,n},o.prototype.bitLength=function(){var e=this.words[this.length-1],t=this._countBits(e);return 26*(this.length-1)+t},o.prototype.zeroBits=function(){if(this.isZero())return 0;for(var e=0,t=0;t<this.length;t++){var n=this._zeroBits(this.words[t]);if(e+=n,26!==n)break}return e},o.prototype.byteLength=function(){return Math.ceil(this.bitLength()/8)},o.prototype.toTwos=function(e){return 0!==this.negative?this.abs().inotn(e).iaddn(1):this.clone()},o.prototype.fromTwos=function(e){return this.testn(e-1)?this.notn(e).iaddn(1).ineg():this.clone()},o.prototype.isNeg=function(){return 0!==this.negative},o.prototype.neg=function(){return this.clone().ineg()},o.prototype.ineg=function(){return this.isZero()||(this.negative^=1),this},o.prototype.iuor=function(e){for(;this.length<e.length;)this.words[this.length++]=0;for(var t=0;t<e.length;t++)this.words[t]=this.words[t]|e.words[t];return this._strip()},o.prototype.ior=function(e){return r(0==(this.negative|e.negative)),this.iuor(e)},o.prototype.or=function(e){return this.length>e.length?this.clone().ior(e):e.clone().ior(this)},o.prototype.uor=function(e){return this.length>e.length?this.clone().iuor(e):e.clone().iuor(this)},o.prototype.iuand=function(e){var t;t=this.length>e.length?e:this;for(var n=0;n<t.length;n++)this.words[n]=this.words[n]&e.words[n];return this.length=t.length,this._strip()},o.prototype.iand=function(e){return r(0==(this.negative|e.negative)),this.iuand(e)},o.prototype.and=function(e){return this.length>e.length?this.clone().iand(e):e.clone().iand(this)},o.prototype.uand=function(e){return this.length>e.length?this.clone().iuand(e):e.clone().iuand(this)},o.prototype.iuxor=function(e){var t,n;this.length>e.length?(t=this,n=e):(t=e,n=this);for(var r=0;r<n.length;r++)this.words[r]=t.words[r]^n.words[r];if(this!==t)for(;r<t.length;r++)this.words[r]=t.words[r];return this.length=t.length,this._strip()},o.prototype.ixor=function(e){return r(0==(this.negative|e.negative)),this.iuxor(e)},o.prototype.xor=function(e){return this.length>e.length?this.clone().ixor(e):e.clone().ixor(this)},o.prototype.uxor=function(e){return this.length>e.length?this.clone().iuxor(e):e.clone().iuxor(this)},o.prototype.inotn=function(e){r("number"==typeof e&&e>=0);var t=0|Math.ceil(e/26),n=e%26;this._expand(t),n>0&&t--;for(var i=0;i<t;i++)this.words[i]=67108863&~this.words[i];return n>0&&(this.words[i]=~this.words[i]&67108863>>26-n),this._strip()},o.prototype.notn=function(e){return this.clone().inotn(e)},o.prototype.setn=function(e,t){r("number"==typeof e&&e>=0);var n=e/26|0,i=e%26;return this._expand(n+1),this.words[n]=t?this.words[n]|1<<i:this.words[n]&~(1<<i),this._strip()},o.prototype.iadd=function(e){var t,n,r;if(0!==this.negative&&0===e.negative)return this.negative=0,t=this.isub(e),this.negative^=1,this._normSign();if(0===this.negative&&0!==e.negative)return e.negative=0,t=this.isub(e),e.negative=1,t._normSign();this.length>e.length?(n=this,r=e):(n=e,r=this);for(var i=0,o=0;o<r.length;o++)t=(0|n.words[o])+(0|r.words[o])+i,this.words[o]=67108863&t,i=t>>>26;for(;0!==i&&o<n.length;o++)t=(0|n.words[o])+i,this.words[o]=67108863&t,i=t>>>26;if(this.length=n.length,0!==i)this.words[this.length]=i,this.length++;else if(n!==this)for(;o<n.length;o++)this.words[o]=n.words[o];return this},o.prototype.add=function(e){var t;return 0!==e.negative&&0===this.negative?(e.negative=0,t=this.sub(e),e.negative^=1,t):0===e.negative&&0!==this.negative?(this.negative=0,t=e.sub(this),this.negative=1,t):this.length>e.length?this.clone().iadd(e):e.clone().iadd(this)},o.prototype.isub=function(e){if(0!==e.negative){e.negative=0;var t=this.iadd(e);return e.negative=1,t._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(e),this.negative=1,this._normSign();var n,r,i=this.cmp(e);if(0===i)return this.negative=0,this.length=1,this.words[0]=0,this;i>0?(n=this,r=e):(n=e,r=this);for(var o=0,s=0;s<r.length;s++)o=(t=(0|n.words[s])-(0|r.words[s])+o)>>26,this.words[s]=67108863&t;for(;0!==o&&s<n.length;s++)o=(t=(0|n.words[s])+o)>>26,this.words[s]=67108863&t;if(0===o&&s<n.length&&n!==this)for(;s<n.length;s++)this.words[s]=n.words[s];return this.length=Math.max(this.length,s),n!==this&&(this.negative=1),this._strip()},o.prototype.sub=function(e){return this.clone().isub(e)};var v=function(e,t,n){var r,i,o,s=e.words,a=t.words,u=n.words,c=0,f=0|s[0],l=8191&f,d=f>>>13,h=0|s[1],p=8191&h,v=h>>>13,g=0|s[2],m=8191&g,b=g>>>13,y=0|s[3],w=8191&y,_=y>>>13,S=0|s[4],E=8191&S,M=S>>>13,A=0|s[5],I=8191&A,k=A>>>13,O=0|s[6],x=8191&O,C=O>>>13,T=0|s[7],P=8191&T,N=T>>>13,R=0|s[8],L=8191&R,j=R>>>13,D=0|s[9],U=8191&D,B=D>>>13,F=0|a[0],z=8191&F,q=F>>>13,K=0|a[1],H=8191&K,V=K>>>13,G=0|a[2],W=8191&G,$=G>>>13,Y=0|a[3],J=8191&Y,Z=Y>>>13,X=0|a[4],Q=8191&X,ee=X>>>13,te=0|a[5],ne=8191&te,re=te>>>13,ie=0|a[6],oe=8191&ie,se=ie>>>13,ae=0|a[7],ue=8191&ae,ce=ae>>>13,fe=0|a[8],le=8191&fe,de=fe>>>13,he=0|a[9],pe=8191&he,ve=he>>>13;n.negative=e.negative^t.negative,n.length=19;var ge=(c+(r=Math.imul(l,z))|0)+((8191&(i=(i=Math.imul(l,q))+Math.imul(d,z)|0))<<13)|0;c=((o=Math.imul(d,q))+(i>>>13)|0)+(ge>>>26)|0,ge&=67108863,r=Math.imul(p,z),i=(i=Math.imul(p,q))+Math.imul(v,z)|0,o=Math.imul(v,q);var me=(c+(r=r+Math.imul(l,H)|0)|0)+((8191&(i=(i=i+Math.imul(l,V)|0)+Math.imul(d,H)|0))<<13)|0;c=((o=o+Math.imul(d,V)|0)+(i>>>13)|0)+(me>>>26)|0,me&=67108863,r=Math.imul(m,z),i=(i=Math.imul(m,q))+Math.imul(b,z)|0,o=Math.imul(b,q),r=r+Math.imul(p,H)|0,i=(i=i+Math.imul(p,V)|0)+Math.imul(v,H)|0,o=o+Math.imul(v,V)|0;var be=(c+(r=r+Math.imul(l,W)|0)|0)+((8191&(i=(i=i+Math.imul(l,$)|0)+Math.imul(d,W)|0))<<13)|0;c=((o=o+Math.imul(d,$)|0)+(i>>>13)|0)+(be>>>26)|0,be&=67108863,r=Math.imul(w,z),i=(i=Math.imul(w,q))+Math.imul(_,z)|0,o=Math.imul(_,q),r=r+Math.imul(m,H)|0,i=(i=i+Math.imul(m,V)|0)+Math.imul(b,H)|0,o=o+Math.imul(b,V)|0,r=r+Math.imul(p,W)|0,i=(i=i+Math.imul(p,$)|0)+Math.imul(v,W)|0,o=o+Math.imul(v,$)|0;var ye=(c+(r=r+Math.imul(l,J)|0)|0)+((8191&(i=(i=i+Math.imul(l,Z)|0)+Math.imul(d,J)|0))<<13)|0;c=((o=o+Math.imul(d,Z)|0)+(i>>>13)|0)+(ye>>>26)|0,ye&=67108863,r=Math.imul(E,z),i=(i=Math.imul(E,q))+Math.imul(M,z)|0,o=Math.imul(M,q),r=r+Math.imul(w,H)|0,i=(i=i+Math.imul(w,V)|0)+Math.imul(_,H)|0,o=o+Math.imul(_,V)|0,r=r+Math.imul(m,W)|0,i=(i=i+Math.imul(m,$)|0)+Math.imul(b,W)|0,o=o+Math.imul(b,$)|0,r=r+Math.imul(p,J)|0,i=(i=i+Math.imul(p,Z)|0)+Math.imul(v,J)|0,o=o+Math.imul(v,Z)|0;var we=(c+(r=r+Math.imul(l,Q)|0)|0)+((8191&(i=(i=i+Math.imul(l,ee)|0)+Math.imul(d,Q)|0))<<13)|0;c=((o=o+Math.imul(d,ee)|0)+(i>>>13)|0)+(we>>>26)|0,we&=67108863,r=Math.imul(I,z),i=(i=Math.imul(I,q))+Math.imul(k,z)|0,o=Math.imul(k,q),r=r+Math.imul(E,H)|0,i=(i=i+Math.imul(E,V)|0)+Math.imul(M,H)|0,o=o+Math.imul(M,V)|0,r=r+Math.imul(w,W)|0,i=(i=i+Math.imul(w,$)|0)+Math.imul(_,W)|0,o=o+Math.imul(_,$)|0,r=r+Math.imul(m,J)|0,i=(i=i+Math.imul(m,Z)|0)+Math.imul(b,J)|0,o=o+Math.imul(b,Z)|0,r=r+Math.imul(p,Q)|0,i=(i=i+Math.imul(p,ee)|0)+Math.imul(v,Q)|0,o=o+Math.imul(v,ee)|0;var _e=(c+(r=r+Math.imul(l,ne)|0)|0)+((8191&(i=(i=i+Math.imul(l,re)|0)+Math.imul(d,ne)|0))<<13)|0;c=((o=o+Math.imul(d,re)|0)+(i>>>13)|0)+(_e>>>26)|0,_e&=67108863,r=Math.imul(x,z),i=(i=Math.imul(x,q))+Math.imul(C,z)|0,o=Math.imul(C,q),r=r+Math.imul(I,H)|0,i=(i=i+Math.imul(I,V)|0)+Math.imul(k,H)|0,o=o+Math.imul(k,V)|0,r=r+Math.imul(E,W)|0,i=(i=i+Math.imul(E,$)|0)+Math.imul(M,W)|0,o=o+Math.imul(M,$)|0,r=r+Math.imul(w,J)|0,i=(i=i+Math.imul(w,Z)|0)+Math.imul(_,J)|0,o=o+Math.imul(_,Z)|0,r=r+Math.imul(m,Q)|0,i=(i=i+Math.imul(m,ee)|0)+Math.imul(b,Q)|0,o=o+Math.imul(b,ee)|0,r=r+Math.imul(p,ne)|0,i=(i=i+Math.imul(p,re)|0)+Math.imul(v,ne)|0,o=o+Math.imul(v,re)|0;var Se=(c+(r=r+Math.imul(l,oe)|0)|0)+((8191&(i=(i=i+Math.imul(l,se)|0)+Math.imul(d,oe)|0))<<13)|0;c=((o=o+Math.imul(d,se)|0)+(i>>>13)|0)+(Se>>>26)|0,Se&=67108863,r=Math.imul(P,z),i=(i=Math.imul(P,q))+Math.imul(N,z)|0,o=Math.imul(N,q),r=r+Math.imul(x,H)|0,i=(i=i+Math.imul(x,V)|0)+Math.imul(C,H)|0,o=o+Math.imul(C,V)|0,r=r+Math.imul(I,W)|0,i=(i=i+Math.imul(I,$)|0)+Math.imul(k,W)|0,o=o+Math.imul(k,$)|0,r=r+Math.imul(E,J)|0,i=(i=i+Math.imul(E,Z)|0)+Math.imul(M,J)|0,o=o+Math.imul(M,Z)|0,r=r+Math.imul(w,Q)|0,i=(i=i+Math.imul(w,ee)|0)+Math.imul(_,Q)|0,o=o+Math.imul(_,ee)|0,r=r+Math.imul(m,ne)|0,i=(i=i+Math.imul(m,re)|0)+Math.imul(b,ne)|0,o=o+Math.imul(b,re)|0,r=r+Math.imul(p,oe)|0,i=(i=i+Math.imul(p,se)|0)+Math.imul(v,oe)|0,o=o+Math.imul(v,se)|0;var Ee=(c+(r=r+Math.imul(l,ue)|0)|0)+((8191&(i=(i=i+Math.imul(l,ce)|0)+Math.imul(d,ue)|0))<<13)|0;c=((o=o+Math.imul(d,ce)|0)+(i>>>13)|0)+(Ee>>>26)|0,Ee&=67108863,r=Math.imul(L,z),i=(i=Math.imul(L,q))+Math.imul(j,z)|0,o=Math.imul(j,q),r=r+Math.imul(P,H)|0,i=(i=i+Math.imul(P,V)|0)+Math.imul(N,H)|0,o=o+Math.imul(N,V)|0,r=r+Math.imul(x,W)|0,i=(i=i+Math.imul(x,$)|0)+Math.imul(C,W)|0,o=o+Math.imul(C,$)|0,r=r+Math.imul(I,J)|0,i=(i=i+Math.imul(I,Z)|0)+Math.imul(k,J)|0,o=o+Math.imul(k,Z)|0,r=r+Math.imul(E,Q)|0,i=(i=i+Math.imul(E,ee)|0)+Math.imul(M,Q)|0,o=o+Math.imul(M,ee)|0,r=r+Math.imul(w,ne)|0,i=(i=i+Math.imul(w,re)|0)+Math.imul(_,ne)|0,o=o+Math.imul(_,re)|0,r=r+Math.imul(m,oe)|0,i=(i=i+Math.imul(m,se)|0)+Math.imul(b,oe)|0,o=o+Math.imul(b,se)|0,r=r+Math.imul(p,ue)|0,i=(i=i+Math.imul(p,ce)|0)+Math.imul(v,ue)|0,o=o+Math.imul(v,ce)|0;var Me=(c+(r=r+Math.imul(l,le)|0)|0)+((8191&(i=(i=i+Math.imul(l,de)|0)+Math.imul(d,le)|0))<<13)|0;c=((o=o+Math.imul(d,de)|0)+(i>>>13)|0)+(Me>>>26)|0,Me&=67108863,r=Math.imul(U,z),i=(i=Math.imul(U,q))+Math.imul(B,z)|0,o=Math.imul(B,q),r=r+Math.imul(L,H)|0,i=(i=i+Math.imul(L,V)|0)+Math.imul(j,H)|0,o=o+Math.imul(j,V)|0,r=r+Math.imul(P,W)|0,i=(i=i+Math.imul(P,$)|0)+Math.imul(N,W)|0,o=o+Math.imul(N,$)|0,r=r+Math.imul(x,J)|0,i=(i=i+Math.imul(x,Z)|0)+Math.imul(C,J)|0,o=o+Math.imul(C,Z)|0,r=r+Math.imul(I,Q)|0,i=(i=i+Math.imul(I,ee)|0)+Math.imul(k,Q)|0,o=o+Math.imul(k,ee)|0,r=r+Math.imul(E,ne)|0,i=(i=i+Math.imul(E,re)|0)+Math.imul(M,ne)|0,o=o+Math.imul(M,re)|0,r=r+Math.imul(w,oe)|0,i=(i=i+Math.imul(w,se)|0)+Math.imul(_,oe)|0,o=o+Math.imul(_,se)|0,r=r+Math.imul(m,ue)|0,i=(i=i+Math.imul(m,ce)|0)+Math.imul(b,ue)|0,o=o+Math.imul(b,ce)|0,r=r+Math.imul(p,le)|0,i=(i=i+Math.imul(p,de)|0)+Math.imul(v,le)|0,o=o+Math.imul(v,de)|0;var Ae=(c+(r=r+Math.imul(l,pe)|0)|0)+((8191&(i=(i=i+Math.imul(l,ve)|0)+Math.imul(d,pe)|0))<<13)|0;c=((o=o+Math.imul(d,ve)|0)+(i>>>13)|0)+(Ae>>>26)|0,Ae&=67108863,r=Math.imul(U,H),i=(i=Math.imul(U,V))+Math.imul(B,H)|0,o=Math.imul(B,V),r=r+Math.imul(L,W)|0,i=(i=i+Math.imul(L,$)|0)+Math.imul(j,W)|0,o=o+Math.imul(j,$)|0,r=r+Math.imul(P,J)|0,i=(i=i+Math.imul(P,Z)|0)+Math.imul(N,J)|0,o=o+Math.imul(N,Z)|0,r=r+Math.imul(x,Q)|0,i=(i=i+Math.imul(x,ee)|0)+Math.imul(C,Q)|0,o=o+Math.imul(C,ee)|0,r=r+Math.imul(I,ne)|0,i=(i=i+Math.imul(I,re)|0)+Math.imul(k,ne)|0,o=o+Math.imul(k,re)|0,r=r+Math.imul(E,oe)|0,i=(i=i+Math.imul(E,se)|0)+Math.imul(M,oe)|0,o=o+Math.imul(M,se)|0,r=r+Math.imul(w,ue)|0,i=(i=i+Math.imul(w,ce)|0)+Math.imul(_,ue)|0,o=o+Math.imul(_,ce)|0,r=r+Math.imul(m,le)|0,i=(i=i+Math.imul(m,de)|0)+Math.imul(b,le)|0,o=o+Math.imul(b,de)|0;var Ie=(c+(r=r+Math.imul(p,pe)|0)|0)+((8191&(i=(i=i+Math.imul(p,ve)|0)+Math.imul(v,pe)|0))<<13)|0;c=((o=o+Math.imul(v,ve)|0)+(i>>>13)|0)+(Ie>>>26)|0,Ie&=67108863,r=Math.imul(U,W),i=(i=Math.imul(U,$))+Math.imul(B,W)|0,o=Math.imul(B,$),r=r+Math.imul(L,J)|0,i=(i=i+Math.imul(L,Z)|0)+Math.imul(j,J)|0,o=o+Math.imul(j,Z)|0,r=r+Math.imul(P,Q)|0,i=(i=i+Math.imul(P,ee)|0)+Math.imul(N,Q)|0,o=o+Math.imul(N,ee)|0,r=r+Math.imul(x,ne)|0,i=(i=i+Math.imul(x,re)|0)+Math.imul(C,ne)|0,o=o+Math.imul(C,re)|0,r=r+Math.imul(I,oe)|0,i=(i=i+Math.imul(I,se)|0)+Math.imul(k,oe)|0,o=o+Math.imul(k,se)|0,r=r+Math.imul(E,ue)|0,i=(i=i+Math.imul(E,ce)|0)+Math.imul(M,ue)|0,o=o+Math.imul(M,ce)|0,r=r+Math.imul(w,le)|0,i=(i=i+Math.imul(w,de)|0)+Math.imul(_,le)|0,o=o+Math.imul(_,de)|0;var ke=(c+(r=r+Math.imul(m,pe)|0)|0)+((8191&(i=(i=i+Math.imul(m,ve)|0)+Math.imul(b,pe)|0))<<13)|0;c=((o=o+Math.imul(b,ve)|0)+(i>>>13)|0)+(ke>>>26)|0,ke&=67108863,r=Math.imul(U,J),i=(i=Math.imul(U,Z))+Math.imul(B,J)|0,o=Math.imul(B,Z),r=r+Math.imul(L,Q)|0,i=(i=i+Math.imul(L,ee)|0)+Math.imul(j,Q)|0,o=o+Math.imul(j,ee)|0,r=r+Math.imul(P,ne)|0,i=(i=i+Math.imul(P,re)|0)+Math.imul(N,ne)|0,o=o+Math.imul(N,re)|0,r=r+Math.imul(x,oe)|0,i=(i=i+Math.imul(x,se)|0)+Math.imul(C,oe)|0,o=o+Math.imul(C,se)|0,r=r+Math.imul(I,ue)|0,i=(i=i+Math.imul(I,ce)|0)+Math.imul(k,ue)|0,o=o+Math.imul(k,ce)|0,r=r+Math.imul(E,le)|0,i=(i=i+Math.imul(E,de)|0)+Math.imul(M,le)|0,o=o+Math.imul(M,de)|0;var Oe=(c+(r=r+Math.imul(w,pe)|0)|0)+((8191&(i=(i=i+Math.imul(w,ve)|0)+Math.imul(_,pe)|0))<<13)|0;c=((o=o+Math.imul(_,ve)|0)+(i>>>13)|0)+(Oe>>>26)|0,Oe&=67108863,r=Math.imul(U,Q),i=(i=Math.imul(U,ee))+Math.imul(B,Q)|0,o=Math.imul(B,ee),r=r+Math.imul(L,ne)|0,i=(i=i+Math.imul(L,re)|0)+Math.imul(j,ne)|0,o=o+Math.imul(j,re)|0,r=r+Math.imul(P,oe)|0,i=(i=i+Math.imul(P,se)|0)+Math.imul(N,oe)|0,o=o+Math.imul(N,se)|0,r=r+Math.imul(x,ue)|0,i=(i=i+Math.imul(x,ce)|0)+Math.imul(C,ue)|0,o=o+Math.imul(C,ce)|0,r=r+Math.imul(I,le)|0,i=(i=i+Math.imul(I,de)|0)+Math.imul(k,le)|0,o=o+Math.imul(k,de)|0;var xe=(c+(r=r+Math.imul(E,pe)|0)|0)+((8191&(i=(i=i+Math.imul(E,ve)|0)+Math.imul(M,pe)|0))<<13)|0;c=((o=o+Math.imul(M,ve)|0)+(i>>>13)|0)+(xe>>>26)|0,xe&=67108863,r=Math.imul(U,ne),i=(i=Math.imul(U,re))+Math.imul(B,ne)|0,o=Math.imul(B,re),r=r+Math.imul(L,oe)|0,i=(i=i+Math.imul(L,se)|0)+Math.imul(j,oe)|0,o=o+Math.imul(j,se)|0,r=r+Math.imul(P,ue)|0,i=(i=i+Math.imul(P,ce)|0)+Math.imul(N,ue)|0,o=o+Math.imul(N,ce)|0,r=r+Math.imul(x,le)|0,i=(i=i+Math.imul(x,de)|0)+Math.imul(C,le)|0,o=o+Math.imul(C,de)|0;var Ce=(c+(r=r+Math.imul(I,pe)|0)|0)+((8191&(i=(i=i+Math.imul(I,ve)|0)+Math.imul(k,pe)|0))<<13)|0;c=((o=o+Math.imul(k,ve)|0)+(i>>>13)|0)+(Ce>>>26)|0,Ce&=67108863,r=Math.imul(U,oe),i=(i=Math.imul(U,se))+Math.imul(B,oe)|0,o=Math.imul(B,se),r=r+Math.imul(L,ue)|0,i=(i=i+Math.imul(L,ce)|0)+Math.imul(j,ue)|0,o=o+Math.imul(j,ce)|0,r=r+Math.imul(P,le)|0,i=(i=i+Math.imul(P,de)|0)+Math.imul(N,le)|0,o=o+Math.imul(N,de)|0;var Te=(c+(r=r+Math.imul(x,pe)|0)|0)+((8191&(i=(i=i+Math.imul(x,ve)|0)+Math.imul(C,pe)|0))<<13)|0;c=((o=o+Math.imul(C,ve)|0)+(i>>>13)|0)+(Te>>>26)|0,Te&=67108863,r=Math.imul(U,ue),i=(i=Math.imul(U,ce))+Math.imul(B,ue)|0,o=Math.imul(B,ce),r=r+Math.imul(L,le)|0,i=(i=i+Math.imul(L,de)|0)+Math.imul(j,le)|0,o=o+Math.imul(j,de)|0;var Pe=(c+(r=r+Math.imul(P,pe)|0)|0)+((8191&(i=(i=i+Math.imul(P,ve)|0)+Math.imul(N,pe)|0))<<13)|0;c=((o=o+Math.imul(N,ve)|0)+(i>>>13)|0)+(Pe>>>26)|0,Pe&=67108863,r=Math.imul(U,le),i=(i=Math.imul(U,de))+Math.imul(B,le)|0,o=Math.imul(B,de);var Ne=(c+(r=r+Math.imul(L,pe)|0)|0)+((8191&(i=(i=i+Math.imul(L,ve)|0)+Math.imul(j,pe)|0))<<13)|0;c=((o=o+Math.imul(j,ve)|0)+(i>>>13)|0)+(Ne>>>26)|0,Ne&=67108863;var Re=(c+(r=Math.imul(U,pe))|0)+((8191&(i=(i=Math.imul(U,ve))+Math.imul(B,pe)|0))<<13)|0;return c=((o=Math.imul(B,ve))+(i>>>13)|0)+(Re>>>26)|0,Re&=67108863,u[0]=ge,u[1]=me,u[2]=be,u[3]=ye,u[4]=we,u[5]=_e,u[6]=Se,u[7]=Ee,u[8]=Me,u[9]=Ae,u[10]=Ie,u[11]=ke,u[12]=Oe,u[13]=xe,u[14]=Ce,u[15]=Te,u[16]=Pe,u[17]=Ne,u[18]=Re,0!==c&&(u[19]=c,n.length++),n};function g(e,t,n){n.negative=t.negative^e.negative,n.length=e.length+t.length;for(var r=0,i=0,o=0;o<n.length-1;o++){var s=i;i=0;for(var a=67108863&r,u=Math.min(o,t.length-1),c=Math.max(0,o-e.length+1);c<=u;c++){var f=o-c,l=(0|e.words[f])*(0|t.words[c]),d=67108863&l;a=67108863&(d=d+a|0),i+=(s=(s=s+(l/67108864|0)|0)+(d>>>26)|0)>>>26,s&=67108863}n.words[o]=a,r=s,s=i}return 0!==r?n.words[o]=r:n.length--,n._strip()}function m(e,t,n){return g(e,t,n)}function b(e,t){this.x=e,this.y=t}Math.imul||(v=p),o.prototype.mulTo=function(e,t){var n=this.length+e.length;return 10===this.length&&10===e.length?v(this,e,t):n<63?p(this,e,t):n<1024?g(this,e,t):m(this,e,t)},b.prototype.makeRBT=function(e){for(var t=new Array(e),n=o.prototype._countBits(e)-1,r=0;r<e;r++)t[r]=this.revBin(r,n,e);return t},b.prototype.revBin=function(e,t,n){if(0===e||e===n-1)return e;for(var r=0,i=0;i<t;i++)r|=(1&e)<<t-i-1,e>>=1;return r},b.prototype.permute=function(e,t,n,r,i,o){for(var s=0;s<o;s++)r[s]=t[e[s]],i[s]=n[e[s]]},b.prototype.transform=function(e,t,n,r,i,o){this.permute(o,e,t,n,r,i);for(var s=1;s<i;s<<=1)for(var a=s<<1,u=Math.cos(2*Math.PI/a),c=Math.sin(2*Math.PI/a),f=0;f<i;f+=a)for(var l=u,d=c,h=0;h<s;h++){var p=n[f+h],v=r[f+h],g=n[f+h+s],m=r[f+h+s],b=l*g-d*m;m=l*m+d*g,g=b,n[f+h]=p+g,r[f+h]=v+m,n[f+h+s]=p-g,r[f+h+s]=v-m,h!==a&&(b=u*l-c*d,d=u*d+c*l,l=b)}},b.prototype.guessLen13b=function(e,t){var n=1|Math.max(t,e),r=1&n,i=0;for(n=n/2|0;n;n>>>=1)i++;return 1<<i+1+r},b.prototype.conjugate=function(e,t,n){if(!(n<=1))for(var r=0;r<n/2;r++){var i=e[r];e[r]=e[n-r-1],e[n-r-1]=i,i=t[r],t[r]=-t[n-r-1],t[n-r-1]=-i}},b.prototype.normalize13b=function(e,t){for(var n=0,r=0;r<t/2;r++){var i=8192*Math.round(e[2*r+1]/t)+Math.round(e[2*r]/t)+n;e[r]=67108863&i,n=i<67108864?0:i/67108864|0}return e},b.prototype.convert13b=function(e,t,n,i){for(var o=0,s=0;s<t;s++)o+=0|e[s],n[2*s]=8191&o,o>>>=13,n[2*s+1]=8191&o,o>>>=13;for(s=2*t;s<i;++s)n[s]=0;r(0===o),r(0==(-8192&o))},b.prototype.stub=function(e){for(var t=new Array(e),n=0;n<e;n++)t[n]=0;return t},b.prototype.mulp=function(e,t,n){var r=2*this.guessLen13b(e.length,t.length),i=this.makeRBT(r),o=this.stub(r),s=new Array(r),a=new Array(r),u=new Array(r),c=new Array(r),f=new Array(r),l=new Array(r),d=n.words;d.length=r,this.convert13b(e.words,e.length,s,r),this.convert13b(t.words,t.length,c,r),this.transform(s,o,a,u,r,i),this.transform(c,o,f,l,r,i);for(var h=0;h<r;h++){var p=a[h]*f[h]-u[h]*l[h];u[h]=a[h]*l[h]+u[h]*f[h],a[h]=p}return this.conjugate(a,u,r),this.transform(a,u,d,o,r,i),this.conjugate(d,o,r),this.normalize13b(d,r),n.negative=e.negative^t.negative,n.length=e.length+t.length,n._strip()},o.prototype.mul=function(e){var t=new o(null);return t.words=new Array(this.length+e.length),this.mulTo(e,t)},o.prototype.mulf=function(e){var t=new o(null);return t.words=new Array(this.length+e.length),m(this,e,t)},o.prototype.imul=function(e){return this.clone().mulTo(e,this)},o.prototype.imuln=function(e){var t=e<0;t&&(e=-e),r("number"==typeof e),r(e<67108864);for(var n=0,i=0;i<this.length;i++){var o=(0|this.words[i])*e,s=(67108863&o)+(67108863&n);n>>=26,n+=o/67108864|0,n+=s>>>26,this.words[i]=67108863&s}return 0!==n&&(this.words[i]=n,this.length++),t?this.ineg():this},o.prototype.muln=function(e){return this.clone().imuln(e)},o.prototype.sqr=function(){return this.mul(this)},o.prototype.isqr=function(){return this.imul(this.clone())},o.prototype.pow=function(e){var t=function(e){for(var t=new Array(e.bitLength()),n=0;n<t.length;n++){var r=n/26|0,i=n%26;t[n]=e.words[r]>>>i&1}return t}(e);if(0===t.length)return new o(1);for(var n=this,r=0;r<t.length&&0===t[r];r++,n=n.sqr());if(++r<t.length)for(var i=n.sqr();r<t.length;r++,i=i.sqr())0!==t[r]&&(n=n.mul(i));return n},o.prototype.iushln=function(e){r("number"==typeof e&&e>=0);var t,n=e%26,i=(e-n)/26,o=67108863>>>26-n<<26-n;if(0!==n){var s=0;for(t=0;t<this.length;t++){var a=this.words[t]&o,u=(0|this.words[t])-a<<n;this.words[t]=u|s,s=a>>>26-n}s&&(this.words[t]=s,this.length++)}if(0!==i){for(t=this.length-1;t>=0;t--)this.words[t+i]=this.words[t];for(t=0;t<i;t++)this.words[t]=0;this.length+=i}return this._strip()},o.prototype.ishln=function(e){return r(0===this.negative),this.iushln(e)},o.prototype.iushrn=function(e,t,n){var i;r("number"==typeof e&&e>=0),i=t?(t-t%26)/26:0;var o=e%26,s=Math.min((e-o)/26,this.length),a=67108863^67108863>>>o<<o,u=n;if(i-=s,i=Math.max(0,i),u){for(var c=0;c<s;c++)u.words[c]=this.words[c];u.length=s}if(0===s);else if(this.length>s)for(this.length-=s,c=0;c<this.length;c++)this.words[c]=this.words[c+s];else this.words[0]=0,this.length=1;var f=0;for(c=this.length-1;c>=0&&(0!==f||c>=i);c--){var l=0|this.words[c];this.words[c]=f<<26-o|l>>>o,f=l&a}return u&&0!==f&&(u.words[u.length++]=f),0===this.length&&(this.words[0]=0,this.length=1),this._strip()},o.prototype.ishrn=function(e,t,n){return r(0===this.negative),this.iushrn(e,t,n)},o.prototype.shln=function(e){return this.clone().ishln(e)},o.prototype.ushln=function(e){return this.clone().iushln(e)},o.prototype.shrn=function(e){return this.clone().ishrn(e)},o.prototype.ushrn=function(e){return this.clone().iushrn(e)},o.prototype.testn=function(e){r("number"==typeof e&&e>=0);var t=e%26,n=(e-t)/26,i=1<<t;return!(this.length<=n)&&!!(this.words[n]&i)},o.prototype.imaskn=function(e){r("number"==typeof e&&e>=0);var t=e%26,n=(e-t)/26;if(r(0===this.negative,"imaskn works only with positive numbers"),this.length<=n)return this;if(0!==t&&n++,this.length=Math.min(n,this.length),0!==t){var i=67108863^67108863>>>t<<t;this.words[this.length-1]&=i}return this._strip()},o.prototype.maskn=function(e){return this.clone().imaskn(e)},o.prototype.iaddn=function(e){return r("number"==typeof e),r(e<67108864),e<0?this.isubn(-e):0!==this.negative?1===this.length&&(0|this.words[0])<=e?(this.words[0]=e-(0|this.words[0]),this.negative=0,this):(this.negative=0,this.isubn(e),this.negative=1,this):this._iaddn(e)},o.prototype._iaddn=function(e){this.words[0]+=e;for(var t=0;t<this.length&&this.words[t]>=67108864;t++)this.words[t]-=67108864,t===this.length-1?this.words[t+1]=1:this.words[t+1]++;return this.length=Math.max(this.length,t+1),this},o.prototype.isubn=function(e){if(r("number"==typeof e),r(e<67108864),e<0)return this.iaddn(-e);if(0!==this.negative)return this.negative=0,this.iaddn(e),this.negative=1,this;if(this.words[0]-=e,1===this.length&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var t=0;t<this.length&&this.words[t]<0;t++)this.words[t]+=67108864,this.words[t+1]-=1;return this._strip()},o.prototype.addn=function(e){return this.clone().iaddn(e)},o.prototype.subn=function(e){return this.clone().isubn(e)},o.prototype.iabs=function(){return this.negative=0,this},o.prototype.abs=function(){return this.clone().iabs()},o.prototype._ishlnsubmul=function(e,t,n){var i,o,s=e.length+n;this._expand(s);var a=0;for(i=0;i<e.length;i++){o=(0|this.words[i+n])+a;var u=(0|e.words[i])*t;a=((o-=67108863&u)>>26)-(u/67108864|0),this.words[i+n]=67108863&o}for(;i<this.length-n;i++)a=(o=(0|this.words[i+n])+a)>>26,this.words[i+n]=67108863&o;if(0===a)return this._strip();for(r(-1===a),a=0,i=0;i<this.length;i++)a=(o=-(0|this.words[i])+a)>>26,this.words[i]=67108863&o;return this.negative=1,this._strip()},o.prototype._wordDiv=function(e,t){var n=(this.length,e.length),r=this.clone(),i=e,s=0|i.words[i.length-1];0!==(n=26-this._countBits(s))&&(i=i.ushln(n),r.iushln(n),s=0|i.words[i.length-1]);var a,u=r.length-i.length;if("mod"!==t){(a=new o(null)).length=u+1,a.words=new Array(a.length);for(var c=0;c<a.length;c++)a.words[c]=0}var f=r.clone()._ishlnsubmul(i,1,u);0===f.negative&&(r=f,a&&(a.words[u]=1));for(var l=u-1;l>=0;l--){var d=67108864*(0|r.words[i.length+l])+(0|r.words[i.length+l-1]);for(d=Math.min(d/s|0,67108863),r._ishlnsubmul(i,d,l);0!==r.negative;)d--,r.negative=0,r._ishlnsubmul(i,1,l),r.isZero()||(r.negative^=1);a&&(a.words[l]=d)}return a&&a._strip(),r._strip(),"div"!==t&&0!==n&&r.iushrn(n),{div:a||null,mod:r}},o.prototype.divmod=function(e,t,n){return r(!e.isZero()),this.isZero()?{div:new o(0),mod:new o(0)}:0!==this.negative&&0===e.negative?(a=this.neg().divmod(e,t),"mod"!==t&&(i=a.div.neg()),"div"!==t&&(s=a.mod.neg(),n&&0!==s.negative&&s.iadd(e)),{div:i,mod:s}):0===this.negative&&0!==e.negative?(a=this.divmod(e.neg(),t),"mod"!==t&&(i=a.div.neg()),{div:i,mod:a.mod}):0!=(this.negative&e.negative)?(a=this.neg().divmod(e.neg(),t),"div"!==t&&(s=a.mod.neg(),n&&0!==s.negative&&s.isub(e)),{div:a.div,mod:s}):e.length>this.length||this.cmp(e)<0?{div:new o(0),mod:this}:1===e.length?"div"===t?{div:this.divn(e.words[0]),mod:null}:"mod"===t?{div:null,mod:new o(this.modrn(e.words[0]))}:{div:this.divn(e.words[0]),mod:new o(this.modrn(e.words[0]))}:this._wordDiv(e,t);var i,s,a},o.prototype.div=function(e){return this.divmod(e,"div",!1).div},o.prototype.mod=function(e){return this.divmod(e,"mod",!1).mod},o.prototype.umod=function(e){return this.divmod(e,"mod",!0).mod},o.prototype.divRound=function(e){var t=this.divmod(e);if(t.mod.isZero())return t.div;var n=0!==t.div.negative?t.mod.isub(e):t.mod,r=e.ushrn(1),i=e.andln(1),o=n.cmp(r);return o<0||1===i&&0===o?t.div:0!==t.div.negative?t.div.isubn(1):t.div.iaddn(1)},o.prototype.modrn=function(e){var t=e<0;t&&(e=-e),r(e<=67108863);for(var n=(1<<26)%e,i=0,o=this.length-1;o>=0;o--)i=(n*i+(0|this.words[o]))%e;return t?-i:i},o.prototype.modn=function(e){return this.modrn(e)},o.prototype.idivn=function(e){var t=e<0;t&&(e=-e),r(e<=67108863);for(var n=0,i=this.length-1;i>=0;i--){var o=(0|this.words[i])+67108864*n;this.words[i]=o/e|0,n=o%e}return this._strip(),t?this.ineg():this},o.prototype.divn=function(e){return this.clone().idivn(e)},o.prototype.egcd=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i=new o(1),s=new o(0),a=new o(0),u=new o(1),c=0;t.isEven()&&n.isEven();)t.iushrn(1),n.iushrn(1),++c;for(var f=n.clone(),l=t.clone();!t.isZero();){for(var d=0,h=1;0==(t.words[0]&h)&&d<26;++d,h<<=1);if(d>0)for(t.iushrn(d);d-- >0;)(i.isOdd()||s.isOdd())&&(i.iadd(f),s.isub(l)),i.iushrn(1),s.iushrn(1);for(var p=0,v=1;0==(n.words[0]&v)&&p<26;++p,v<<=1);if(p>0)for(n.iushrn(p);p-- >0;)(a.isOdd()||u.isOdd())&&(a.iadd(f),u.isub(l)),a.iushrn(1),u.iushrn(1);t.cmp(n)>=0?(t.isub(n),i.isub(a),s.isub(u)):(n.isub(t),a.isub(i),u.isub(s))}return{a:a,b:u,gcd:n.iushln(c)}},o.prototype._invmp=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i,s=new o(1),a=new o(0),u=n.clone();t.cmpn(1)>0&&n.cmpn(1)>0;){for(var c=0,f=1;0==(t.words[0]&f)&&c<26;++c,f<<=1);if(c>0)for(t.iushrn(c);c-- >0;)s.isOdd()&&s.iadd(u),s.iushrn(1);for(var l=0,d=1;0==(n.words[0]&d)&&l<26;++l,d<<=1);if(l>0)for(n.iushrn(l);l-- >0;)a.isOdd()&&a.iadd(u),a.iushrn(1);t.cmp(n)>=0?(t.isub(n),s.isub(a)):(n.isub(t),a.isub(s))}return(i=0===t.cmpn(1)?s:a).cmpn(0)<0&&i.iadd(e),i},o.prototype.gcd=function(e){if(this.isZero())return e.abs();if(e.isZero())return this.abs();var t=this.clone(),n=e.clone();t.negative=0,n.negative=0;for(var r=0;t.isEven()&&n.isEven();r++)t.iushrn(1),n.iushrn(1);for(;;){for(;t.isEven();)t.iushrn(1);for(;n.isEven();)n.iushrn(1);var i=t.cmp(n);if(i<0){var o=t;t=n,n=o}else if(0===i||0===n.cmpn(1))break;t.isub(n)}return n.iushln(r)},o.prototype.invm=function(e){return this.egcd(e).a.umod(e)},o.prototype.isEven=function(){return 0==(1&this.words[0])},o.prototype.isOdd=function(){return 1==(1&this.words[0])},o.prototype.andln=function(e){return this.words[0]&e},o.prototype.bincn=function(e){r("number"==typeof e);var t=e%26,n=(e-t)/26,i=1<<t;if(this.length<=n)return this._expand(n+1),this.words[n]|=i,this;for(var o=i,s=n;0!==o&&s<this.length;s++){var a=0|this.words[s];o=(a+=o)>>>26,a&=67108863,this.words[s]=a}return 0!==o&&(this.words[s]=o,this.length++),this},o.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},o.prototype.cmpn=function(e){var t,n=e<0;if(0!==this.negative&&!n)return-1;if(0===this.negative&&n)return 1;if(this._strip(),this.length>1)t=1;else{n&&(e=-e),r(e<=67108863,"Number is too big");var i=0|this.words[0];t=i===e?0:i<e?-1:1}return 0!==this.negative?0|-t:t},o.prototype.cmp=function(e){if(0!==this.negative&&0===e.negative)return-1;if(0===this.negative&&0!==e.negative)return 1;var t=this.ucmp(e);return 0!==this.negative?0|-t:t},o.prototype.ucmp=function(e){if(this.length>e.length)return 1;if(this.length<e.length)return-1;for(var t=0,n=this.length-1;n>=0;n--){var r=0|this.words[n],i=0|e.words[n];if(r!==i){r<i?t=-1:r>i&&(t=1);break}}return t},o.prototype.gtn=function(e){return 1===this.cmpn(e)},o.prototype.gt=function(e){return 1===this.cmp(e)},o.prototype.gten=function(e){return this.cmpn(e)>=0},o.prototype.gte=function(e){return this.cmp(e)>=0},o.prototype.ltn=function(e){return-1===this.cmpn(e)},o.prototype.lt=function(e){return-1===this.cmp(e)},o.prototype.lten=function(e){return this.cmpn(e)<=0},o.prototype.lte=function(e){return this.cmp(e)<=0},o.prototype.eqn=function(e){return 0===this.cmpn(e)},o.prototype.eq=function(e){return 0===this.cmp(e)},o.red=function(e){return new A(e)},o.prototype.toRed=function(e){return r(!this.red,"Already a number in reduction context"),r(0===this.negative,"red works only with positives"),e.convertTo(this)._forceRed(e)},o.prototype.fromRed=function(){return r(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},o.prototype._forceRed=function(e){return this.red=e,this},o.prototype.forceRed=function(e){return r(!this.red,"Already a number in reduction context"),this._forceRed(e)},o.prototype.redAdd=function(e){return r(this.red,"redAdd works only with red numbers"),this.red.add(this,e)},o.prototype.redIAdd=function(e){return r(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,e)},o.prototype.redSub=function(e){return r(this.red,"redSub works only with red numbers"),this.red.sub(this,e)},o.prototype.redISub=function(e){return r(this.red,"redISub works only with red numbers"),this.red.isub(this,e)},o.prototype.redShl=function(e){return r(this.red,"redShl works only with red numbers"),this.red.shl(this,e)},o.prototype.redMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.mul(this,e)},o.prototype.redIMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.imul(this,e)},o.prototype.redSqr=function(){return r(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},o.prototype.redISqr=function(){return r(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},o.prototype.redSqrt=function(){return r(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},o.prototype.redInvm=function(){return r(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},o.prototype.redNeg=function(){return r(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},o.prototype.redPow=function(e){return r(this.red&&!e.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,e)};var y={k256:null,p224:null,p192:null,p25519:null};function w(e,t){this.name=e,this.p=new o(t,16),this.n=this.p.bitLength(),this.k=new o(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function _(){w.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function S(){w.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function E(){w.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function M(){w.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function A(e){if("string"==typeof e){var t=o._prime(e);this.m=t.p,this.prime=t}else r(e.gtn(1),"modulus must be greater than 1"),this.m=e,this.prime=null}function I(e){A.call(this,e),this.shift=this.m.bitLength(),this.shift%26!=0&&(this.shift+=26-this.shift%26),this.r=new o(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}w.prototype._tmp=function(){var e=new o(null);return e.words=new Array(Math.ceil(this.n/13)),e},w.prototype.ireduce=function(e){var t,n=e;do{this.split(n,this.tmp),t=(n=(n=this.imulK(n)).iadd(this.tmp)).bitLength()}while(t>this.n);var r=t<this.n?-1:n.ucmp(this.p);return 0===r?(n.words[0]=0,n.length=1):r>0?n.isub(this.p):void 0!==n.strip?n.strip():n._strip(),n},w.prototype.split=function(e,t){e.iushrn(this.n,0,t)},w.prototype.imulK=function(e){return e.imul(this.k)},i(_,w),_.prototype.split=function(e,t){for(var n=Math.min(e.length,9),r=0;r<n;r++)t.words[r]=e.words[r];if(t.length=n,e.length<=9)return e.words[0]=0,void(e.length=1);var i=e.words[9];for(t.words[t.length++]=4194303&i,r=10;r<e.length;r++){var o=0|e.words[r];e.words[r-10]=(4194303&o)<<4|i>>>22,i=o}i>>>=22,e.words[r-10]=i,0===i&&e.length>10?e.length-=10:e.length-=9},_.prototype.imulK=function(e){e.words[e.length]=0,e.words[e.length+1]=0,e.length+=2;for(var t=0,n=0;n<e.length;n++){var r=0|e.words[n];t+=977*r,e.words[n]=67108863&t,t=64*r+(t/67108864|0)}return 0===e.words[e.length-1]&&(e.length--,0===e.words[e.length-1]&&e.length--),e},i(S,w),i(E,w),i(M,w),M.prototype.imulK=function(e){for(var t=0,n=0;n<e.length;n++){var r=19*(0|e.words[n])+t,i=67108863&r;r>>>=26,e.words[n]=i,t=r}return 0!==t&&(e.words[e.length++]=t),e},o._prime=function(e){if(y[e])return y[e];var t;if("k256"===e)t=new _;else if("p224"===e)t=new S;else if("p192"===e)t=new E;else{if("p25519"!==e)throw new Error("Unknown prime "+e);t=new M}return y[e]=t,t},A.prototype._verify1=function(e){r(0===e.negative,"red works only with positives"),r(e.red,"red works only with red numbers")},A.prototype._verify2=function(e,t){r(0==(e.negative|t.negative),"red works only with positives"),r(e.red&&e.red===t.red,"red works only with red numbers")},A.prototype.imod=function(e){return this.prime?this.prime.ireduce(e)._forceRed(this):(c(e,e.umod(this.m)._forceRed(this)),e)},A.prototype.neg=function(e){return e.isZero()?e.clone():this.m.sub(e)._forceRed(this)},A.prototype.add=function(e,t){this._verify2(e,t);var n=e.add(t);return n.cmp(this.m)>=0&&n.isub(this.m),n._forceRed(this)},A.prototype.iadd=function(e,t){this._verify2(e,t);var n=e.iadd(t);return n.cmp(this.m)>=0&&n.isub(this.m),n},A.prototype.sub=function(e,t){this._verify2(e,t);var n=e.sub(t);return n.cmpn(0)<0&&n.iadd(this.m),n._forceRed(this)},A.prototype.isub=function(e,t){this._verify2(e,t);var n=e.isub(t);return n.cmpn(0)<0&&n.iadd(this.m),n},A.prototype.shl=function(e,t){return this._verify1(e),this.imod(e.ushln(t))},A.prototype.imul=function(e,t){return this._verify2(e,t),this.imod(e.imul(t))},A.prototype.mul=function(e,t){return this._verify2(e,t),this.imod(e.mul(t))},A.prototype.isqr=function(e){return this.imul(e,e.clone())},A.prototype.sqr=function(e){return this.mul(e,e)},A.prototype.sqrt=function(e){if(e.isZero())return e.clone();var t=this.m.andln(3);if(r(t%2==1),3===t){var n=this.m.add(new o(1)).iushrn(2);return this.pow(e,n)}for(var i=this.m.subn(1),s=0;!i.isZero()&&0===i.andln(1);)s++,i.iushrn(1);r(!i.isZero());var a=new o(1).toRed(this),u=a.redNeg(),c=this.m.subn(1).iushrn(1),f=this.m.bitLength();for(f=new o(2*f*f).toRed(this);0!==this.pow(f,c).cmp(u);)f.redIAdd(u);for(var l=this.pow(f,i),d=this.pow(e,i.addn(1).iushrn(1)),h=this.pow(e,i),p=s;0!==h.cmp(a);){for(var v=h,g=0;0!==v.cmp(a);g++)v=v.redSqr();r(g<p);var m=this.pow(l,new o(1).iushln(p-g-1));d=d.redMul(m),l=m.redSqr(),h=h.redMul(l),p=g}return d},A.prototype.invm=function(e){var t=e._invmp(this.m);return 0!==t.negative?(t.negative=0,this.imod(t).redNeg()):this.imod(t)},A.prototype.pow=function(e,t){if(t.isZero())return new o(1).toRed(this);if(0===t.cmpn(1))return e.clone();var n=new Array(16);n[0]=new o(1).toRed(this),n[1]=e;for(var r=2;r<n.length;r++)n[r]=this.mul(n[r-1],e);var i=n[0],s=0,a=0,u=t.bitLength()%26;for(0===u&&(u=26),r=t.length-1;r>=0;r--){for(var c=t.words[r],f=u-1;f>=0;f--){var l=c>>f&1;i!==n[0]&&(i=this.sqr(i)),0!==l||0!==s?(s<<=1,s|=l,(4===++a||0===r&&0===f)&&(i=this.mul(i,n[s]),a=0,s=0)):a=0}u=26}return i},A.prototype.convertTo=function(e){var t=e.umod(this.m);return t===e?t.clone():t},A.prototype.convertFrom=function(e){var t=e.clone();return t.red=null,t},o.mont=function(e){return new I(e)},i(I,A),I.prototype.convertTo=function(e){return this.imod(e.ushln(this.shift))},I.prototype.convertFrom=function(e){var t=this.imod(e.mul(this.rinv));return t.red=null,t},I.prototype.imul=function(e,t){if(e.isZero()||t.isZero())return e.words[0]=0,e.length=1,e;var n=e.imul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),o=i;return i.cmp(this.m)>=0?o=i.isub(this.m):i.cmpn(0)<0&&(o=i.iadd(this.m)),o._forceRed(this)},I.prototype.mul=function(e,t){if(e.isZero()||t.isZero())return new o(0)._forceRed(this);var n=e.mul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),s=i;return i.cmp(this.m)>=0?s=i.isub(this.m):i.cmpn(0)<0&&(s=i.iadd(this.m)),s._forceRed(this)},I.prototype.invm=function(e){return this.imod(e._invmp(this.m).mul(this.r2))._forceRed(this)}}(e,this)}).call(this,n(57)(e))},function(e,t,n){"use strict";const r=t;r.bignum=n(29),r.define=n(351).define,r.base=n(354),r.constants=n(355),r.decoders=n(207),r.encoders=n(205)},function(e,t,n){"use strict";const r=t;r.der=n(206),r.pem=n(352)},function(e,t,n){"use strict";const r=n(7),i=n(130).Buffer,o=n(131),s=n(133);function a(e){this.enc="der",this.name=e.name,this.entity=e,this.tree=new u,this.tree._init(e.body)}function u(e){o.call(this,"der",e)}function c(e){return e<10?"0"+e:e}e.exports=a,a.prototype.encode=function(e,t){return this.tree._encode(e,t).join()},r(u,o),u.prototype._encodeComposite=function(e,t,n,r){const o=function(e,t,n,r){let i;"seqof"===e?e="seq":"setof"===e&&(e="set");if(s.tagByName.hasOwnProperty(e))i=s.tagByName[e];else{if("number"!=typeof e||(0|e)!==e)return r.error("Unknown tag: "+e);i=e}if(i>=31)return r.error("Multi-octet tag encoding unsupported");t||(i|=32);return i|=s.tagClassByName[n||"universal"]<<6,i}(e,t,n,this.reporter);if(r.length<128){const e=i.alloc(2);return e[0]=o,e[1]=r.length,this._createEncoderBuffer([e,r])}let a=1;for(let e=r.length;e>=256;e>>=8)a++;const u=i.alloc(2+a);u[0]=o,u[1]=128|a;for(let e=1+a,t=r.length;t>0;e--,t>>=8)u[e]=255&t;return this._createEncoderBuffer([u,r])},u.prototype._encodeStr=function(e,t){if("bitstr"===t)return this._createEncoderBuffer([0|e.unused,e.data]);if("bmpstr"===t){const t=i.alloc(2*e.length);for(let n=0;n<e.length;n++)t.writeUInt16BE(e.charCodeAt(n),2*n);return this._createEncoderBuffer(t)}return"numstr"===t?this._isNumstr(e)?this._createEncoderBuffer(e):this.reporter.error("Encoding of string type: numstr supports only digits and space"):"printstr"===t?this._isPrintstr(e)?this._createEncoderBuffer(e):this.reporter.error("Encoding of string type: printstr supports only latin upper and lower case letters, digits, space, apostrophe, left and rigth parenthesis, plus sign, comma, hyphen, dot, slash, colon, equal sign, question mark"):/str$/.test(t)||"objDesc"===t?this._createEncoderBuffer(e):this.reporter.error("Encoding of string type: "+t+" unsupported")},u.prototype._encodeObjid=function(e,t,n){if("string"==typeof e){if(!t)return this.reporter.error("string objid given, but no values map found");if(!t.hasOwnProperty(e))return this.reporter.error("objid not found in values map");e=t[e].split(/[\s.]+/g);for(let t=0;t<e.length;t++)e[t]|=0}else if(Array.isArray(e)){e=e.slice();for(let t=0;t<e.length;t++)e[t]|=0}if(!Array.isArray(e))return this.reporter.error("objid() should be either array or string, got: "+JSON.stringify(e));if(!n){if(e[1]>=40)return this.reporter.error("Second objid identifier OOB");e.splice(0,2,40*e[0]+e[1])}let r=0;for(let t=0;t<e.length;t++){let n=e[t];for(r++;n>=128;n>>=7)r++}const o=i.alloc(r);let s=o.length-1;for(let t=e.length-1;t>=0;t--){let n=e[t];for(o[s--]=127&n;(n>>=7)>0;)o[s--]=128|127&n}return this._createEncoderBuffer(o)},u.prototype._encodeTime=function(e,t){let n;const r=new Date(e);return"gentime"===t?n=[c(r.getUTCFullYear()),c(r.getUTCMonth()+1),c(r.getUTCDate()),c(r.getUTCHours()),c(r.getUTCMinutes()),c(r.getUTCSeconds()),"Z"].join(""):"utctime"===t?n=[c(r.getUTCFullYear()%100),c(r.getUTCMonth()+1),c(r.getUTCDate()),c(r.getUTCHours()),c(r.getUTCMinutes()),c(r.getUTCSeconds()),"Z"].join(""):this.reporter.error("Encoding "+t+" time is not supported yet"),this._encodeStr(n,"octstr")},u.prototype._encodeNull=function(){return this._createEncoderBuffer("")},u.prototype._encodeInt=function(e,t){if("string"==typeof e){if(!t)return this.reporter.error("String int or enum given, but no values map");if(!t.hasOwnProperty(e))return this.reporter.error("Values map doesn't contain: "+JSON.stringify(e));e=t[e]}if("number"!=typeof e&&!i.isBuffer(e)){const t=e.toArray();!e.sign&&128&t[0]&&t.unshift(0),e=i.from(t)}if(i.isBuffer(e)){let t=e.length;0===e.length&&t++;const n=i.alloc(t);return e.copy(n),0===e.length&&(n[0]=0),this._createEncoderBuffer(n)}if(e<128)return this._createEncoderBuffer(e);if(e<256)return this._createEncoderBuffer([0,e]);let n=1;for(let t=e;t>=256;t>>=8)n++;const r=new Array(n);for(let t=r.length-1;t>=0;t--)r[t]=255&e,e>>=8;return 128&r[0]&&r.unshift(0),this._createEncoderBuffer(i.from(r))},u.prototype._encodeBool=function(e){return this._createEncoderBuffer(e?255:0)},u.prototype._use=function(e,t){return"function"==typeof e&&(e=e(t)),e._getEncoder("der").tree},u.prototype._skipDefault=function(e,t,n){const r=this._baseState;let i;if(null===r.default)return!1;const o=e.join();if(void 0===r.defaultBuffer&&(r.defaultBuffer=this._encodeValue(r.default,t,n).join()),o.length!==r.defaultBuffer.length)return!1;for(i=0;i<o.length;i++)if(o[i]!==r.defaultBuffer[i])return!1;return!0}},function(e,t,n){"use strict";const r=t;r.der=n(208),r.pem=n(353)},function(e,t,n){"use strict";const r=n(7),i=n(29),o=n(83).DecoderBuffer,s=n(131),a=n(133);function u(e){this.enc="der",this.name=e.name,this.entity=e,this.tree=new c,this.tree._init(e.body)}function c(e){s.call(this,"der",e)}function f(e,t){let n=e.readUInt8(t);if(e.isError(n))return n;const r=a.tagClass[n>>6],i=0==(32&n);if(31==(31&n)){let r=n;for(n=0;128==(128&r);){if(r=e.readUInt8(t),e.isError(r))return r;n<<=7,n|=127&r}}else n&=31;return{cls:r,primitive:i,tag:n,tagStr:a.tag[n]}}function l(e,t,n){let r=e.readUInt8(n);if(e.isError(r))return r;if(!t&&128===r)return null;if(0==(128&r))return r;const i=127&r;if(i>4)return e.error("length octect is too long");r=0;for(let t=0;t<i;t++){r<<=8;const t=e.readUInt8(n);if(e.isError(t))return t;r|=t}return r}e.exports=u,u.prototype.decode=function(e,t){return o.isDecoderBuffer(e)||(e=new o(e,t)),this.tree._decode(e,t)},r(c,s),c.prototype._peekTag=function(e,t,n){if(e.isEmpty())return!1;const r=e.save(),i=f(e,'Failed to peek tag: "'+t+'"');return e.isError(i)?i:(e.restore(r),i.tag===t||i.tagStr===t||i.tagStr+"of"===t||n)},c.prototype._decodeTag=function(e,t,n){const r=f(e,'Failed to decode tag of "'+t+'"');if(e.isError(r))return r;let i=l(e,r.primitive,'Failed to get length of "'+t+'"');if(e.isError(i))return i;if(!n&&r.tag!==t&&r.tagStr!==t&&r.tagStr+"of"!==t)return e.error('Failed to match tag: "'+t+'"');if(r.primitive||null!==i)return e.skip(i,'Failed to match body of: "'+t+'"');const o=e.save(),s=this._skipUntilEnd(e,'Failed to skip indefinite length body: "'+this.tag+'"');return e.isError(s)?s:(i=e.offset-o.offset,e.restore(o),e.skip(i,'Failed to match body of: "'+t+'"'))},c.prototype._skipUntilEnd=function(e,t){for(;;){const n=f(e,t);if(e.isError(n))return n;const r=l(e,n.primitive,t);if(e.isError(r))return r;let i;if(i=n.primitive||null!==r?e.skip(r):this._skipUntilEnd(e,t),e.isError(i))return i;if("end"===n.tagStr)break}},c.prototype._decodeList=function(e,t,n,r){const i=[];for(;!e.isEmpty();){const t=this._peekTag(e,"end");if(e.isError(t))return t;const o=n.decode(e,"der",r);if(e.isError(o)&&t)break;i.push(o)}return i},c.prototype._decodeStr=function(e,t){if("bitstr"===t){const t=e.readUInt8();return e.isError(t)?t:{unused:t,data:e.raw()}}if("bmpstr"===t){const t=e.raw();if(t.length%2==1)return e.error("Decoding of string type: bmpstr length mismatch");let n="";for(let e=0;e<t.length/2;e++)n+=String.fromCharCode(t.readUInt16BE(2*e));return n}if("numstr"===t){const t=e.raw().toString("ascii");return this._isNumstr(t)?t:e.error("Decoding of string type: numstr unsupported characters")}if("octstr"===t)return e.raw();if("objDesc"===t)return e.raw();if("printstr"===t){const t=e.raw().toString("ascii");return this._isPrintstr(t)?t:e.error("Decoding of string type: printstr unsupported characters")}return/str$/.test(t)?e.raw().toString():e.error("Decoding of string type: "+t+" unsupported")},c.prototype._decodeObjid=function(e,t,n){let r;const i=[];let o=0,s=0;for(;!e.isEmpty();)s=e.readUInt8(),o<<=7,o|=127&s,0==(128&s)&&(i.push(o),o=0);128&s&&i.push(o);const a=i[0]/40|0,u=i[0]%40;if(r=n?i:[a,u].concat(i.slice(1)),t){let e=t[r.join(" ")];void 0===e&&(e=t[r.join(".")]),void 0!==e&&(r=e)}return r},c.prototype._decodeTime=function(e,t){const n=e.raw().toString();let r,i,o,s,a,u;if("gentime"===t)r=0|n.slice(0,4),i=0|n.slice(4,6),o=0|n.slice(6,8),s=0|n.slice(8,10),a=0|n.slice(10,12),u=0|n.slice(12,14);else{if("utctime"!==t)return e.error("Decoding "+t+" time is not supported yet");r=0|n.slice(0,2),i=0|n.slice(2,4),o=0|n.slice(4,6),s=0|n.slice(6,8),a=0|n.slice(8,10),u=0|n.slice(10,12),r=r<70?2e3+r:1900+r}return Date.UTC(r,i-1,o,s,a,u,0)},c.prototype._decodeNull=function(){return null},c.prototype._decodeBool=function(e){const t=e.readUInt8();return e.isError(t)?t:0!==t},c.prototype._decodeInt=function(e,t){const n=e.raw();let r=new i(n);return t&&(r=t[r.toString(10)]||r),r},c.prototype._use=function(e,t){return"function"==typeof e&&(e=e(t)),e._getDecoder("der").tree}},function(e){e.exports=JSON.parse('{"1.3.132.0.10":"secp256k1","1.3.132.0.33":"p224","1.2.840.10045.3.1.1":"p192","1.2.840.10045.3.1.7":"p256","1.3.132.0.34":"p384","1.3.132.0.35":"p521"}')},function(e,t,n){var r=n(79),i=n(8).Buffer;function o(e){var t=i.allocUnsafe(4);return t.writeUInt32BE(e,0),t}e.exports=function(e,t){for(var n,s=i.alloc(0),a=0;s.length<t;)n=o(a++),s=i.concat([s,r("sha1").update(e).update(n).digest()]);return s.slice(0,t)}},function(e,t){e.exports=function(e,t){for(var n=e.length,r=-1;++r<n;)e[r]^=t[r];return e}},function(e,t,n){var r=n(29),i=n(8).Buffer;e.exports=function(e,t){return i.from(e.toRed(r.mont(t.modulus)).redPow(new r(t.publicExponent)).fromRed().toArray())}},function(e,t,n){"use strict";n.r(t),t.default=function(e,t){return t=t||{},new Promise((function(n,r){var i=new XMLHttpRequest,o=[],s=[],a={},u=function(){return{ok:2==(i.status/100|0),statusText:i.statusText,status:i.status,url:i.responseURL,text:function(){return Promise.resolve(i.responseText)},json:function(){return Promise.resolve(i.responseText).then(JSON.parse)},blob:function(){return Promise.resolve(new Blob([i.response]))},clone:u,headers:{keys:function(){return o},entries:function(){return s},get:function(e){return a[e.toLowerCase()]},has:function(e){return e.toLowerCase()in a}}}};for(var c in i.open(t.method||"get",e,!0),i.onload=function(){i.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm,(function(e,t,n){o.push(t=t.toLowerCase()),s.push([t,n]),a[t]=a[t]?a[t]+","+n:n})),n(u())},i.onerror=r,i.withCredentials="include"==t.credentials,t.headers)i.setRequestHeader(c,t.headers[c]);i.send(t.body||null)}))}},function(e,t){var n="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof window.msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto);if(n){var r=new Uint8Array(16);e.exports=function(){return n(r),r}}else{var i=new Array(16);e.exports=function(){for(var e,t=0;t<16;t++)0==(3&t)&&(e=4294967296*Math.random()),i[t]=e>>>((3&t)<<3)&255;return i}}},function(e,t){for(var n=[],r=0;r<256;++r)n[r]=(r+256).toString(16).substr(1);e.exports=function(e,t){var r=t||0,i=n;return[i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]]].join("")}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Sha256=void 0;var r=n(217),i=n(218),o=n(249),s=n(134),a=function(){function e(e){e?(this.operation=function(e){return new Promise((function(t,n){var r=s.locateWindow().msCrypto.subtle.importKey("raw",u(e),i.SHA_256_HMAC_ALGO,!1,["sign"]);r.oncomplete=function(){r.result&&t(r.result),n("ImportKey completed without importing key.")},r.onerror=function(){n("ImportKey failed to import key.")}}))}(e).then((function(e){return s.locateWindow().msCrypto.subtle.sign(i.SHA_256_HMAC_ALGO,e)})),this.operation.catch((function(){}))):this.operation=Promise.resolve(s.locateWindow().msCrypto.subtle.digest("SHA-256"))}return e.prototype.update=function(e){var t=this;r.isEmptyData(e)||(this.operation=this.operation.then((function(n){return n.onerror=function(){t.operation=Promise.reject(new Error("Error encountered updating hash"))},n.process(u(e)),n})),this.operation.catch((function(){})))},e.prototype.digest=function(){return this.operation.then((function(e){return new Promise((function(t,n){e.onerror=function(){n("Error encountered finalizing hash")},e.oncomplete=function(){e.result&&t(new Uint8Array(e.result)),n("Error encountered finalizing hash")},e.finish()}))}))},e}();function u(e){return"string"==typeof e?o.fromUtf8(e):ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength/Uint8Array.BYTES_PER_ELEMENT):new Uint8Array(e)}t.Sha256=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isEmptyData=void 0,t.isEmptyData=function(e){return"string"==typeof e?0===e.length:0===e.byteLength}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.EMPTY_DATA_SHA_256=t.SHA_256_HMAC_ALGO=t.SHA_256_HASH=void 0,t.SHA_256_HASH={name:"SHA-256"},t.SHA_256_HMAC_ALGO={name:"HMAC",hash:t.SHA_256_HASH},t.EMPTY_DATA_SHA_256=new Uint8Array([227,176,196,66,152,252,28,20,154,251,244,200,153,111,185,36,39,174,65,228,100,155,147,76,164,149,153,27,120,82,184,85])},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Sha256=void 0;var r=n(249),i=n(217),o=n(218),s=n(134),a=function(){function e(e){this.toHash=new Uint8Array(0),void 0!==e&&(this.key=new Promise((function(t,n){s.locateWindow().crypto.subtle.importKey("raw",u(e),o.SHA_256_HMAC_ALGO,!1,["sign"]).then(t,n)})),this.key.catch((function(){})))}return e.prototype.update=function(e){if(!i.isEmptyData(e)){var t=u(e),n=new Uint8Array(this.toHash.byteLength+t.byteLength);n.set(this.toHash,0),n.set(t,this.toHash.byteLength),this.toHash=n}},e.prototype.digest=function(){var e=this;return this.key?this.key.then((function(t){return s.locateWindow().crypto.subtle.sign(o.SHA_256_HMAC_ALGO,t,e.toHash).then((function(e){return new Uint8Array(e)}))})):i.isEmptyData(this.toHash)?Promise.resolve(o.EMPTY_DATA_SHA_256):Promise.resolve().then((function(){return s.locateWindow().crypto.subtle.digest(o.SHA_256_HASH,e.toHash)})).then((function(e){return Promise.resolve(new Uint8Array(e))}))},e}();function u(e){return"string"==typeof e?r.fromUtf8(e):ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength/Uint8Array.BYTES_PER_ELEMENT):new Uint8Array(e)}t.Sha256=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.MAX_HASHABLE_LENGTH=t.INIT=t.KEY=t.DIGEST_LENGTH=t.BLOCK_SIZE=void 0,t.BLOCK_SIZE=64,t.DIGEST_LENGTH=32,t.KEY=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),t.INIT=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],t.MAX_HASHABLE_LENGTH=Math.pow(2,53)-1},function(e,t,n){"use strict";n.d(t,"a",(function(){return o}));var r=new(n(44).a)("Parser"),i=function(e){var t,n={};if(e.aws_mobile_analytics_app_id){var i={AWSPinpoint:{appId:e.aws_mobile_analytics_app_id,region:e.aws_mobile_analytics_app_region}};n.Analytics=i}return(e.aws_cognito_identity_pool_id||e.aws_user_pools_id)&&(n.Auth={userPoolId:e.aws_user_pools_id,userPoolWebClientId:e.aws_user_pools_web_client_id,region:e.aws_cognito_region,identityPoolId:e.aws_cognito_identity_pool_id,identityPoolRegion:e.aws_cognito_region,mandatorySignIn:"enable"===e.aws_mandatory_sign_in}),t=e.aws_user_files_s3_bucket?{AWSS3:{bucket:e.aws_user_files_s3_bucket,region:e.aws_user_files_s3_bucket_region,dangerouslyConnectToHttpEndpointForTesting:e.aws_user_files_s3_dangerously_connect_to_http_endpoint_for_testing}}:e?e.Storage||e:{},n.Analytics=Object.assign({},n.Analytics,e.Analytics),n.Auth=Object.assign({},n.Auth,e.Auth),n.Storage=Object.assign({},t),r.debug("parse config",e,"to amplifyconfig",n),n},o=function(){function e(){}return e.parseMobilehubConfig=i,e}()},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BLOCK_SIZE=64,t.DIGEST_LENGTH=32,t.KEY=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298]),t.INIT=[1779033703,3144134277,1013904242,2773480762,1359893119,2600822924,528734635,1541459225],t.MAX_HASHABLE_LENGTH=Math.pow(2,53)-1},function(e,t,n){(function(t){var n="object"==typeof t&&t&&t.Object===Object&&t;e.exports=n}).call(this,n(31))},function(e,t,n){var r=n(84),i=n(225);e.exports=function(e){if(!i(e))return!1;var t=r(e);return"[object Function]"==t||"[object GeneratorFunction]"==t||"[object AsyncFunction]"==t||"[object Proxy]"==t}},function(e,t){e.exports=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}},function(e,t){var n=Function.prototype.toString;e.exports=function(e){if(null!=e){try{return n.call(e)}catch(e){}try{return e+""}catch(e){}}return""}},function(e,t){e.exports=function(e,t){return e===t||e!=e&&t!=t}},function(e,t,n){var r=n(229),i=n(420),o=Object.prototype.hasOwnProperty;e.exports=function(e){if(!r(e))return i(e);var t=[];for(var n in Object(e))o.call(e,n)&&"constructor"!=n&&t.push(n);return t}},function(e,t){var n=Object.prototype;e.exports=function(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||n)}},function(e,t,n){var r=n(422),i=n(137),o=n(423),s=n(424),a=n(425),u=n(84),c=n(226),f=c(r),l=c(i),d=c(o),h=c(s),p=c(a),v=u;(r&&"[object DataView]"!=v(new r(new ArrayBuffer(1)))||i&&"[object Map]"!=v(new i)||o&&"[object Promise]"!=v(o.resolve())||s&&"[object Set]"!=v(new s)||a&&"[object WeakMap]"!=v(new a))&&(v=function(e){var t=u(e),n="[object Object]"==t?e.constructor:void 0,r=n?c(n):"";if(r)switch(r){case f:return"[object DataView]";case l:return"[object Map]";case d:return"[object Promise]";case h:return"[object Set]";case p:return"[object WeakMap]"}return t}),e.exports=v},function(e,t,n){var r=n(426),i=n(85),o=Object.prototype,s=o.hasOwnProperty,a=o.propertyIsEnumerable,u=r(function(){return arguments}())?r:function(e){return i(e)&&s.call(e,"callee")&&!a.call(e,"callee")};e.exports=u},function(e,t,n){var r=n(224),i=n(233);e.exports=function(e){return null!=e&&i(e.length)&&!r(e)}},function(e,t){e.exports=function(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991}},function(e,t,n){var r=n(439),i=n(442),o=n(443);e.exports=function(e,t,n,s,a,u){var c=1&n,f=e.length,l=t.length;if(f!=l&&!(c&&l>f))return!1;var d=u.get(e),h=u.get(t);if(d&&h)return d==t&&h==e;var p=-1,v=!0,g=2&n?new r:void 0;for(u.set(e,t),u.set(t,e);++p<f;){var m=e[p],b=t[p];if(s)var y=c?s(b,m,p,t,e,u):s(m,b,p,e,t,u);if(void 0!==y){if(y)continue;v=!1;break}if(g){if(!i(t,(function(e,t){if(!o(g,t)&&(m===e||a(m,e,n,s,u)))return g.push(t)}))){v=!1;break}}else if(m!==b&&!a(m,b,n,s,u)){v=!1;break}}return u.delete(e),u.delete(t),v}},function(e,t,n){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r<n.length;r++)n[r]=arguments[r];return e.apply(t,n)}}},function(e,t,n){"use strict";var r=n(45);function i(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}e.exports=function(e,t,n){if(!t)return e;var o;if(n)o=n(t);else if(r.isURLSearchParams(t))o=t.toString();else{var s=[];r.forEach(t,(function(e,t){null!=e&&(r.isArray(e)?t+="[]":e=[e],r.forEach(e,(function(e){r.isDate(e)?e=e.toISOString():r.isObject(e)&&(e=JSON.stringify(e)),s.push(i(t)+"="+i(e))})))})),o=s.join("&")}if(o){var a=e.indexOf("#");-1!==a&&(e=e.slice(0,a)),e+=(-1===e.indexOf("?")?"?":"&")+o}return e}},function(e,t,n){"use strict";e.exports=function(e){return!(!e||!e.__CANCEL__)}},function(e,t,n){"use strict";(function(t){var r=n(45),i=n(470),o={"Content-Type":"application/x-www-form-urlencoded"};function s(e,t){!r.isUndefined(e)&&r.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}var a,u={adapter:(("undefined"!=typeof XMLHttpRequest||void 0!==t&&"[object process]"===Object.prototype.toString.call(t))&&(a=n(239)),a),transformRequest:[function(e,t){return i(t,"Accept"),i(t,"Content-Type"),r.isFormData(e)||r.isArrayBuffer(e)||r.isBuffer(e)||r.isStream(e)||r.isFile(e)||r.isBlob(e)?e:r.isArrayBufferView(e)?e.buffer:r.isURLSearchParams(e)?(s(t,"application/x-www-form-urlencoded;charset=utf-8"),e.toString()):r.isObject(e)?(s(t,"application/json;charset=utf-8"),JSON.stringify(e)):e}],transformResponse:[function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(e){return e>=200&&e<300}};u.headers={common:{Accept:"application/json, text/plain, */*"}},r.forEach(["delete","get","head"],(function(e){u.headers[e]={}})),r.forEach(["post","put","patch"],(function(e){u.headers[e]=r.merge(o)})),e.exports=u}).call(this,n(20))},function(e,t,n){"use strict";var r=n(45),i=n(471),o=n(473),s=n(236),a=n(474),u=n(477),c=n(478),f=n(240);e.exports=function(e){return new Promise((function(t,n){var l=e.data,d=e.headers;r.isFormData(l)&&delete d["Content-Type"];var h=new XMLHttpRequest;if(e.auth){var p=e.auth.username||"",v=e.auth.password?unescape(encodeURIComponent(e.auth.password)):"";d.Authorization="Basic "+btoa(p+":"+v)}var g=a(e.baseURL,e.url);if(h.open(e.method.toUpperCase(),s(g,e.params,e.paramsSerializer),!0),h.timeout=e.timeout,h.onreadystatechange=function(){if(h&&4===h.readyState&&(0!==h.status||h.responseURL&&0===h.responseURL.indexOf("file:"))){var r="getAllResponseHeaders"in h?u(h.getAllResponseHeaders()):null,o={data:e.responseType&&"text"!==e.responseType?h.response:h.responseText,status:h.status,statusText:h.statusText,headers:r,config:e,request:h};i(t,n,o),h=null}},h.onabort=function(){h&&(n(f("Request aborted",e,"ECONNABORTED",h)),h=null)},h.onerror=function(){n(f("Network Error",e,null,h)),h=null},h.ontimeout=function(){var t="timeout of "+e.timeout+"ms exceeded";e.timeoutErrorMessage&&(t=e.timeoutErrorMessage),n(f(t,e,"ECONNABORTED",h)),h=null},r.isStandardBrowserEnv()){var m=(e.withCredentials||c(g))&&e.xsrfCookieName?o.read(e.xsrfCookieName):void 0;m&&(d[e.xsrfHeaderName]=m)}if("setRequestHeader"in h&&r.forEach(d,(function(e,t){void 0===l&&"content-type"===t.toLowerCase()?delete d[t]:h.setRequestHeader(t,e)})),r.isUndefined(e.withCredentials)||(h.withCredentials=!!e.withCredentials),e.responseType)try{h.responseType=e.responseType}catch(t){if("json"!==e.responseType)throw t}"function"==typeof e.onDownloadProgress&&h.addEventListener("progress",e.onDownloadProgress),"function"==typeof e.onUploadProgress&&h.upload&&h.upload.addEventListener("progress",e.onUploadProgress),e.cancelToken&&e.cancelToken.promise.then((function(e){h&&(h.abort(),n(e),h=null)})),l||(l=null),h.send(l)}))}},function(e,t,n){"use strict";var r=n(472);e.exports=function(e,t,n,i,o){var s=new Error(e);return r(s,t,n,i,o)}},function(e,t,n){"use strict";var r=n(45);e.exports=function(e,t){t=t||{};var n={},i=["url","method","data"],o=["headers","auth","proxy","params"],s=["baseURL","transformRequest","transformResponse","paramsSerializer","timeout","timeoutMessage","withCredentials","adapter","responseType","xsrfCookieName","xsrfHeaderName","onUploadProgress","onDownloadProgress","decompress","maxContentLength","maxBodyLength","maxRedirects","transport","httpAgent","httpsAgent","cancelToken","socketPath","responseEncoding"],a=["validateStatus"];function u(e,t){return r.isPlainObject(e)&&r.isPlainObject(t)?r.merge(e,t):r.isPlainObject(t)?r.merge({},t):r.isArray(t)?t.slice():t}function c(i){r.isUndefined(t[i])?r.isUndefined(e[i])||(n[i]=u(void 0,e[i])):n[i]=u(e[i],t[i])}r.forEach(i,(function(e){r.isUndefined(t[e])||(n[e]=u(void 0,t[e]))})),r.forEach(o,c),r.forEach(s,(function(i){r.isUndefined(t[i])?r.isUndefined(e[i])||(n[i]=u(void 0,e[i])):n[i]=u(void 0,t[i])})),r.forEach(a,(function(r){r in t?n[r]=u(e[r],t[r]):r in e&&(n[r]=u(void 0,e[r]))}));var f=i.concat(o).concat(s).concat(a),l=Object.keys(e).concat(Object.keys(t)).filter((function(e){return-1===f.indexOf(e)}));return r.forEach(l,c),n}},function(e,t,n){"use strict";function r(e){this.message=e}r.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},r.prototype.__CANCEL__=!0,e.exports=r},function(e,t){var n="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof window.msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto);if(n){var r=new Uint8Array(16);e.exports=function(){return n(r),r}}else{var i=new Array(16);e.exports=function(){for(var e,t=0;t<16;t++)0==(3&t)&&(e=4294967296*Math.random()),i[t]=e>>>((3&t)<<3)&255;return i}}},function(e,t){for(var n=[],r=0;r<256;++r)n[r]=(r+256).toString(16).substr(1);e.exports=function(e,t){var r=t||0,i=n;return[i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]]].join("")}},function(e,t,n){"use strict";n.d(t,"a",(function(){return r}));var r=function(){function e(){}return e.createPredicateBuilder=function(t){var n=t.name,r=new Set(Object.keys(t.fields)),i=new Proxy({},{get:function(t,i,o){var s=i;if(!r.has(s))throw new Error("Invalid field for model. field: "+s+", model: "+n);return function(t){return e.sortPredicateGroupsMap.get(o).push({field:s,sortDirection:t}),o}}});return e.sortPredicateGroupsMap.set(i,[]),i},e.isValidPredicate=function(t){return e.sortPredicateGroupsMap.has(t)},e.getPredicates=function(t,n){if(void 0===n&&(n=!0),n&&!e.isValidPredicate(t))throw new Error("The predicate is not valid");return e.sortPredicateGroupsMap.get(t)},e.createFromExisting=function(t,n){if(n&&t)return n(e.createPredicateBuilder(t))},e.sortPredicateGroupsMap=new WeakMap,e}()},function(e,t,n){(function(e){var n,r,i,o;function s(e){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}o=function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==s(e)&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}Object.defineProperty(t,"__esModule",{value:!0}),r(n(1)),r(n(2)),r(n(3)),r(n(4)),r(n(5)),r(n(6)),r(n(7)),r(n(8)),r(n(9)),r(n(10)),r(n(11)),r(n(12)),r(n(13))},function(e,t,n){e.exports={a:"Anchor__a___1_Iz8"}},function(e,t,n){e.exports={button:"Button__button___vS7Mv",signInButton:"Button__signInButton___3bUH-",googleSignInButton:"Button__googleSignInButton___1YiCu",signInButtonIcon:"Button__signInButtonIcon___ihN75",auth0SignInButton:"Button__auth0SignInButton___znnCj",facebookSignInButton:"Button__facebookSignInButton___34Txh",amazonSignInButton:"Button__amazonSignInButton___2EMtl",oAuthSignInButton:"Button__oAuthSignInButton___3UGOl",signInButtonContent:"Button__signInButtonContent___xqTXJ"}},function(e,t,n){e.exports={formContainer:"Form__formContainer___1GA3x",formSection:"Form__formSection___1PPvW",formField:"Form__formField___38Ikl",formRow:"Form__formRow___2mwRs"}},function(e,t,n){e.exports={hint:"Hint__hint___2XngB"}},function(e,t,n){e.exports={input:"Input__input___3e_bf",inputLabel:"Input__inputLabel___3VF0S",label:"Input__label___23sO8",radio:"Input__radio___2hllK"}},function(e,t,n){e.exports={navBar:"Nav__navBar___xtCFA",navRight:"Nav__navRight___1QG2J",nav:"Nav__nav___2Dx2Y",navItem:"Nav__navItem___1LtFQ"}},function(e,t,n){e.exports={photoPickerButton:"PhotoPicker__photoPickerButton___2XdVn",photoPlaceholder:"PhotoPicker__photoPlaceholder___2JXO4",photoPlaceholderIcon:"PhotoPicker__photoPlaceholderIcon___3Et71"}},function(e,t,n){e.exports={container:"Section__container___3YYTG",actionRow:"Section__actionRow___2LWSU",sectionHeader:"Section__sectionHeader___2djyg",sectionHeaderHint:"Section__sectionHeaderHint___3Wxdc",sectionBody:"Section__sectionBody___ihqqd",sectionHeaderContent:"Section__sectionHeaderContent___1UCqa",sectionFooter:"Section__sectionFooter___1T54C",sectionFooterPrimaryContent:"Section__sectionFooterPrimaryContent___2r9ZX",sectionFooterSecondaryContent:"Section__sectionFooterSecondaryContent___Nj41Q"}},function(e,t,n){e.exports={selectInput:"SelectInput__selectInput___3efO4"}},function(e,t,n){e.exports={strike:"Strike__strike___1XV1b",strikeContent:"Strike__strikeContent___10gLb"}},function(e,t,n){e.exports={toast:"Toast__toast___XXr3v",toastClose:"Toast__toastClose___18lU4"}},function(e,t,n){e.exports={totpQrcode:"Totp__totpQrcode___1crLx"}},function(e,t,n){e.exports={sumerianSceneContainer:"XR__sumerianSceneContainer___3nVMt",sumerianScene:"XR__sumerianScene___2Tt7-",loadingOverlay:"XR__loadingOverlay___IbqcI",loadingContainer:"XR__loadingContainer___2Itxb",loadingLogo:"XR__loadingLogo___Ub7xQ",loadingSceneName:"XR__loadingSceneName___3__ne",loadingBar:"XR__loadingBar___2vcke",loadingBarFill:"XR__loadingBarFill___3M-D9",sceneErrorText:"XR__sceneErrorText___2y0tp",sceneBar:"XR__sceneBar___2ShrP",sceneName:"XR__sceneName___1ApHr",sceneActions:"XR__sceneActions___7plGs",actionButton:"XR__actionButton___2poIM",tooltip:"XR__tooltip___UYyhn",actionIcon:"XR__actionIcon___2qnd2",autoShowTooltip:"XR__autoShowTooltip___V1QH7"}}])},"object"==s(t)&&"object"==s(e)?e.exports=o():(r=[],void 0===(i="function"==typeof(n=o)?n.apply(t,r):n)||(e.exports=i))}).call(this,n(57)(e))},function(e,t,n){"use strict";n.d(t,"a",(function(){return d}));var r=n(52),i=n(63),o=n(89),s=n(19),a=n(146),u=n(258),c=function(){return(c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},f=[i.a,o.a],l=[r.a,i.a,u.a];function d(e){void 0===e&&(e={});var t=e.modules,n=void 0===t?l:t,r=e.req,i=s.a.configure(),o=new s.b,u=new a.a({req:r});return f.forEach((function(e){n.includes(e)||o.register(new e.constructor)})),n.forEach((function(e){o.register(new e.constructor)})),o.configure(c(c({},i),{storage:u})),o}},function(e,t,n){"use strict";n.d(t,"b",(function(){return We})),n.d(t,"a",(function(){return $e}));var r=n(91),i={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},o={};function s(e){return Boolean(e&&"string"==typeof e.kind)}function a(e,t,n){var r=e[t];if(r){if(!n&&"function"==typeof r)return r;var i=n?r.leave:r.enter;if("function"==typeof i)return i}else{var o=n?e.leave:e.enter;if(o){if("function"==typeof o)return o;var s=o[t];if("function"==typeof s)return s}}}function u(e){return function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:i,r=void 0,u=Array.isArray(e),c=[e],f=-1,l=[],d=void 0,h=void 0,p=void 0,v=[],g=[],m=e;do{var b=++f===c.length,y=b&&0!==l.length;if(b){if(h=0===g.length?void 0:v[v.length-1],d=p,p=g.pop(),y){if(u)d=d.slice();else{var w={};for(var _ in d)d.hasOwnProperty(_)&&(w[_]=d[_]);d=w}for(var S=0,E=0;E<l.length;E++){var M=l[E][0],A=l[E][1];u&&(M-=S),u&&null===A?(d.splice(M,1),S++):d[M]=A}}f=r.index,c=r.keys,l=r.edits,u=r.inArray,r=r.prev}else{if(h=p?u?f:c[f]:void 0,null==(d=p?p[h]:m))continue;p&&v.push(h)}var I=void 0;if(!Array.isArray(d)){if(!s(d))throw new Error("Invalid AST Node: "+JSON.stringify(d));var k=a(t,d.kind,b);if(k){if((I=k.call(t,d,h,p,v,g))===o)break;if(!1===I){if(!b){v.pop();continue}}else if(void 0!==I&&(l.push([h,I]),!b)){if(!s(I)){v.pop();continue}d=I}}}void 0===I&&y&&l.push([h,d]),b?v.pop():(r={inArray:u,index:f,keys:c,edits:l,prev:r},c=(u=Array.isArray(d))?d:n[d.kind]||[],f=-1,l=[],p&&g.push(p),p=d)}while(void 0!==r);return 0!==l.length&&(m=l[l.length-1][1]),m}(e,{leave:c})}var c={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return l(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=h("(",l(e.variableDefinitions,", "),")"),i=l(e.directives," "),o=e.selectionSet;return n||i||r||"query"!==t?l([t,l([n,r]),i,o]," "):o},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+h(" = ",r)+h(" ",l(i," "))},SelectionSet:function(e){return d(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,o=e.selectionSet;return l([h("",t,": ")+n+h("(",l(r,", "),")"),l(i," "),o]," ")},Argument:function(e){return e.name+": "+e.value},FragmentSpread:function(e){return"..."+e.name+h(" ",l(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return l(["...",h("on ",t),l(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,o=e.selectionSet;return"fragment ".concat(t).concat(h("(",l(r,", "),")")," ")+"on ".concat(n," ").concat(h("",l(i," ")," "))+o},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?function(e,t){var n=e.replace(/"""/g,'\\"""');return" "!==e[0]&&"\t"!==e[0]||-1!==e.indexOf("\n")?'"""\n'.concat(t?n:p(n),'\n"""'):'"""'.concat(n.replace(/"$/,'"\n'),'"""')}(n,"description"===t):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+l(e.values,", ")+"]"},ObjectValue:function(e){return"{"+l(e.fields,", ")+"}"},ObjectField:function(e){return e.name+": "+e.value},Directive:function(e){return"@"+e.name+h("(",l(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:function(e){var t=e.directives,n=e.operationTypes;return l(["schema",l(t," "),d(n)]," ")},OperationTypeDefinition:function(e){return e.operation+": "+e.type},ScalarTypeDefinition:f((function(e){return l(["scalar",e.name,l(e.directives," ")]," ")})),ObjectTypeDefinition:f((function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return l(["type",t,h("implements ",l(n," & ")),l(r," "),d(i)]," ")})),FieldDefinition:f((function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(n.every((function(e){return-1===e.indexOf("\n")}))?h("(",l(n,", "),")"):h("(\n",p(l(n,"\n")),"\n)"))+": "+r+h(" ",l(i," "))})),InputValueDefinition:f((function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return l([t+": "+n,h("= ",r),l(i," ")]," ")})),InterfaceTypeDefinition:f((function(e){var t=e.name,n=e.directives,r=e.fields;return l(["interface",t,l(n," "),d(r)]," ")})),UnionTypeDefinition:f((function(e){var t=e.name,n=e.directives,r=e.types;return l(["union",t,l(n," "),r&&0!==r.length?"= "+l(r," | "):""]," ")})),EnumTypeDefinition:f((function(e){var t=e.name,n=e.directives,r=e.values;return l(["enum",t,l(n," "),d(r)]," ")})),EnumValueDefinition:f((function(e){return l([e.name,l(e.directives," ")]," ")})),InputObjectTypeDefinition:f((function(e){var t=e.name,n=e.directives,r=e.fields;return l(["input",t,l(n," "),d(r)]," ")})),DirectiveDefinition:f((function(e){var t=e.name,n=e.arguments,r=e.locations;return"directive @"+t+(n.every((function(e){return-1===e.indexOf("\n")}))?h("(",l(n,", "),")"):h("(\n",p(l(n,"\n")),"\n)"))+" on "+l(r," | ")})),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return l(["extend schema",l(t," "),d(n)]," ")},ScalarTypeExtension:function(e){return l(["extend scalar",e.name,l(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return l(["extend type",t,h("implements ",l(n," & ")),l(r," "),d(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return l(["extend interface",t,l(n," "),d(r)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return l(["extend union",t,l(n," "),r&&0!==r.length?"= "+l(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return l(["extend enum",t,l(n," "),d(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return l(["extend input",t,l(n," "),d(r)]," ")}};function f(e){return function(t){return l([t.description,e(t)],"\n")}}function l(e,t){return e?e.filter((function(e){return e})).join(t||""):""}function d(e){return e&&0!==e.length?"{\n"+p(l(e,"\n"))+"\n}":""}function h(e,t,n){return t?e+t+(n||""):""}function p(e){return e&&" "+e.replace(/\n/g,"\n ")}function v(e){return(v="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function g(e){return e&&"object"===v(e)?"function"==typeof e.inspect?e.inspect():Array.isArray(e)?"["+e.map(g).join(", ")+"]":"{"+Object.keys(e).map((function(t){return"".concat(t,": ").concat(g(e[t]))})).join(", ")+"}":"string"==typeof e?'"'+e+'"':"function"==typeof e?"[function ".concat(e.name,"]"):String(e)}function m(e,t){if(!e)throw new Error(t)}function b(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var y,w=function(e,t,n){b(this,"body",void 0),b(this,"name",void 0),b(this,"locationOffset",void 0),this.body=e,this.name=t||"GraphQL request",this.locationOffset=n||{line:1,column:1},this.locationOffset.line>0||m(0,"line in locationOffset is 1-indexed and must be positive"),this.locationOffset.column>0||m(0,"column in locationOffset is 1-indexed and must be positive")};function _(e,t,n){return new r.a("Syntax Error: ".concat(n),void 0,e,[t])}function S(e){for(var t=e.split(/\r\n|[\n\r]/g),n=null,r=1;r<t.length;r++){var i=t[r],o=E(i);if(o<i.length&&(null===n||o<n)&&0===(n=o))break}if(n)for(var s=1;s<t.length;s++)t[s]=t[s].slice(n);for(;t.length>0&&M(t[0]);)t.shift();for(;t.length>0&&M(t[t.length-1]);)t.pop();return t.join("\n")}function E(e){for(var t=0;t<e.length&&(" "===e[t]||"\t"===e[t]);)t++;return t}function M(e){return E(e)===e.length}function A(e,t){var n=new P(O.SOF,0,0,0,0,null);return{source:e,options:t,lastToken:n,token:n,line:1,lineStart:0,advance:I,lookahead:k}}function I(){return this.lastToken=this.token,this.token=this.lookahead()}function k(){var e=this.token;if(e.kind!==O.EOF)do{e=e.next||(e.next=R(this,e))}while(e.kind===O.COMMENT);return e}y=w,"function"==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(y.prototype,Symbol.toStringTag,{get:function(){return this.constructor.name}});var O=Object.freeze({SOF:"<SOF>",EOF:"<EOF>",BANG:"!",DOLLAR:"$",AMP:"&",PAREN_L:"(",PAREN_R:")",SPREAD:"...",COLON:":",EQUALS:"=",AT:"@",BRACKET_L:"[",BRACKET_R:"]",BRACE_L:"{",PIPE:"|",BRACE_R:"}",NAME:"Name",INT:"Int",FLOAT:"Float",STRING:"String",BLOCK_STRING:"BlockString",COMMENT:"Comment"});function x(e){var t=e.value;return t?"".concat(e.kind,' "').concat(t,'"'):e.kind}var C=String.prototype.charCodeAt,T=String.prototype.slice;function P(e,t,n,r,i,o,s){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=s,this.prev=o,this.next=null}function N(e){return isNaN(e)?O.EOF:e<127?JSON.stringify(String.fromCharCode(e)):'"\\u'.concat(("00"+e.toString(16).toUpperCase()).slice(-4),'"')}function R(e,t){var n=e.source,r=n.body,i=r.length,o=function(e,t,n){var r=e.length,i=t;for(;i<r;){var o=C.call(e,i);if(9===o||32===o||44===o||65279===o)++i;else if(10===o)++i,++n.line,n.lineStart=i;else{if(13!==o)break;10===C.call(e,i+1)?i+=2:++i,++n.line,n.lineStart=i}}return i}(r,t.end,e),s=e.line,a=1+o-e.lineStart;if(o>=i)return new P(O.EOF,i,i,s,a,t);var u=C.call(r,o);switch(u){case 33:return new P(O.BANG,o,o+1,s,a,t);case 35:return function(e,t,n,r,i){var o,s=e.body,a=t;do{o=C.call(s,++a)}while(null!==o&&(o>31||9===o));return new P(O.COMMENT,t,a,n,r,i,T.call(s,t+1,a))}(n,o,s,a,t);case 36:return new P(O.DOLLAR,o,o+1,s,a,t);case 38:return new P(O.AMP,o,o+1,s,a,t);case 40:return new P(O.PAREN_L,o,o+1,s,a,t);case 41:return new P(O.PAREN_R,o,o+1,s,a,t);case 46:if(46===C.call(r,o+1)&&46===C.call(r,o+2))return new P(O.SPREAD,o,o+3,s,a,t);break;case 58:return new P(O.COLON,o,o+1,s,a,t);case 61:return new P(O.EQUALS,o,o+1,s,a,t);case 64:return new P(O.AT,o,o+1,s,a,t);case 91:return new P(O.BRACKET_L,o,o+1,s,a,t);case 93:return new P(O.BRACKET_R,o,o+1,s,a,t);case 123:return new P(O.BRACE_L,o,o+1,s,a,t);case 124:return new P(O.PIPE,o,o+1,s,a,t);case 125:return new P(O.BRACE_R,o,o+1,s,a,t);case 65:case 66:case 67:case 68:case 69:case 70:case 71:case 72:case 73:case 74:case 75:case 76:case 77:case 78:case 79:case 80:case 81:case 82:case 83:case 84:case 85:case 86:case 87:case 88:case 89:case 90:case 95:case 97:case 98:case 99:case 100:case 101:case 102:case 103:case 104:case 105:case 106:case 107:case 108:case 109:case 110:case 111:case 112:case 113:case 114:case 115:case 116:case 117:case 118:case 119:case 120:case 121:case 122:return function(e,t,n,r,i){var o=e.body,s=o.length,a=t+1,u=0;for(;a!==s&&null!==(u=C.call(o,a))&&(95===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122);)++a;return new P(O.NAME,t,a,n,r,i,T.call(o,t,a))}(n,o,s,a,t);case 45:case 48:case 49:case 50:case 51:case 52:case 53:case 54:case 55:case 56:case 57:return function(e,t,n,r,i,o){var s=e.body,a=n,u=t,c=!1;45===a&&(a=C.call(s,++u));if(48===a){if((a=C.call(s,++u))>=48&&a<=57)throw _(e,u,"Invalid number, unexpected digit after 0: ".concat(N(a),"."))}else u=L(e,u,a),a=C.call(s,u);46===a&&(c=!0,a=C.call(s,++u),u=L(e,u,a),a=C.call(s,u));69!==a&&101!==a||(c=!0,43!==(a=C.call(s,++u))&&45!==a||(a=C.call(s,++u)),u=L(e,u,a));return new P(c?O.FLOAT:O.INT,t,u,r,i,o,T.call(s,t,u))}(n,o,u,s,a,t);case 34:return 34===C.call(r,o+1)&&34===C.call(r,o+2)?function(e,t,n,r,i){var o=e.body,s=t+3,a=s,u=0,c="";for(;s<o.length&&null!==(u=C.call(o,s));){if(34===u&&34===C.call(o,s+1)&&34===C.call(o,s+2))return c+=T.call(o,a,s),new P(O.BLOCK_STRING,t,s+3,n,r,i,S(c));if(u<32&&9!==u&&10!==u&&13!==u)throw _(e,s,"Invalid character within String: ".concat(N(u),"."));92===u&&34===C.call(o,s+1)&&34===C.call(o,s+2)&&34===C.call(o,s+3)?(c+=T.call(o,a,s)+'"""',a=s+=4):++s}throw _(e,s,"Unterminated string.")}(n,o,s,a,t):function(e,t,n,r,i){var o=e.body,s=t+1,a=s,u=0,c="";for(;s<o.length&&null!==(u=C.call(o,s))&&10!==u&&13!==u;){if(34===u)return c+=T.call(o,a,s),new P(O.STRING,t,s+1,n,r,i,c);if(u<32&&9!==u)throw _(e,s,"Invalid character within String: ".concat(N(u),"."));if(++s,92===u){switch(c+=T.call(o,a,s-1),u=C.call(o,s)){case 34:c+='"';break;case 47:c+="/";break;case 92:c+="\\";break;case 98:c+="\b";break;case 102:c+="\f";break;case 110:c+="\n";break;case 114:c+="\r";break;case 116:c+="\t";break;case 117:var f=(l=C.call(o,s+1),d=C.call(o,s+2),h=C.call(o,s+3),p=C.call(o,s+4),j(l)<<12|j(d)<<8|j(h)<<4|j(p));if(f<0)throw _(e,s,"Invalid character escape sequence: "+"\\u".concat(o.slice(s+1,s+5),"."));c+=String.fromCharCode(f),s+=4;break;default:throw _(e,s,"Invalid character escape sequence: \\".concat(String.fromCharCode(u),"."))}++s,a=s}}var l,d,h,p;throw _(e,s,"Unterminated string.")}(n,o,s,a,t)}throw _(n,o,function(e){if(e<32&&9!==e&&10!==e&&13!==e)return"Cannot contain the invalid character ".concat(N(e),".");if(39===e)return"Unexpected single quote character ('), did you mean to use a double quote (\")?";return"Cannot parse the unexpected character ".concat(N(e),".")}(u))}function L(e,t,n){var r=e.body,i=t,o=n;if(o>=48&&o<=57){do{o=C.call(r,++i)}while(o>=48&&o<=57);return i}throw _(e,i,"Invalid number, expected digit but got: ".concat(N(o),"."))}function j(e){return e>=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}P.prototype.toJSON=P.prototype.inspect=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}};var D=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"}),U=Object.freeze({QUERY:"QUERY",MUTATION:"MUTATION",SUBSCRIPTION:"SUBSCRIPTION",FIELD:"FIELD",FRAGMENT_DEFINITION:"FRAGMENT_DEFINITION",FRAGMENT_SPREAD:"FRAGMENT_SPREAD",INLINE_FRAGMENT:"INLINE_FRAGMENT",VARIABLE_DEFINITION:"VARIABLE_DEFINITION",SCHEMA:"SCHEMA",SCALAR:"SCALAR",OBJECT:"OBJECT",FIELD_DEFINITION:"FIELD_DEFINITION",ARGUMENT_DEFINITION:"ARGUMENT_DEFINITION",INTERFACE:"INTERFACE",UNION:"UNION",ENUM:"ENUM",ENUM_VALUE:"ENUM_VALUE",INPUT_OBJECT:"INPUT_OBJECT",INPUT_FIELD_DEFINITION:"INPUT_FIELD_DEFINITION"});function B(e,t){var n="string"==typeof e?new w(e):e;if(!(n instanceof w))throw new TypeError("Must provide Source. Received: ".concat(g(n)));return function(e){var t=e.token;return{kind:D.DOCUMENT,definitions:Te(e,O.SOF,z,O.EOF),loc:Ee(e,t)}}(A(n,t||{}))}function F(e){var t=ke(e,O.NAME);return{kind:D.NAME,value:t.value,loc:Ee(e,t)}}function z(e){if(Ae(e,O.NAME))switch(e.token.value){case"query":case"mutation":case"subscription":case"fragment":return q(e);case"schema":case"scalar":case"type":case"interface":case"union":case"enum":case"input":case"directive":return ce(e);case"extend":return function(e){var t=e.lookahead();if(t.kind===O.NAME)switch(t.value){case"schema":return function(e){var t=e.token;Oe(e,"extend"),Oe(e,"schema");var n=oe(e,!0),r=Ae(e,O.BRACE_L)?Te(e,O.BRACE_L,de,O.BRACE_R):[];if(0===n.length&&0===r.length)throw xe(e);return{kind:D.SCHEMA_EXTENSION,directives:n,operationTypes:r,loc:Ee(e,t)}}(e);case"scalar":return function(e){var t=e.token;Oe(e,"extend"),Oe(e,"scalar");var n=F(e),r=oe(e,!0);if(0===r.length)throw xe(e);return{kind:D.SCALAR_TYPE_EXTENSION,name:n,directives:r,loc:Ee(e,t)}}(e);case"type":return function(e){var t=e.token;Oe(e,"extend"),Oe(e,"type");var n=F(e),r=he(e),i=oe(e,!0),o=pe(e);if(0===r.length&&0===i.length&&0===o.length)throw xe(e);return{kind:D.OBJECT_TYPE_EXTENSION,name:n,interfaces:r,directives:i,fields:o,loc:Ee(e,t)}}(e);case"interface":return function(e){var t=e.token;Oe(e,"extend"),Oe(e,"interface");var n=F(e),r=oe(e,!0),i=pe(e);if(0===r.length&&0===i.length)throw xe(e);return{kind:D.INTERFACE_TYPE_EXTENSION,name:n,directives:r,fields:i,loc:Ee(e,t)}}(e);case"union":return function(e){var t=e.token;Oe(e,"extend"),Oe(e,"union");var n=F(e),r=oe(e,!0),i=be(e);if(0===r.length&&0===i.length)throw xe(e);return{kind:D.UNION_TYPE_EXTENSION,name:n,directives:r,types:i,loc:Ee(e,t)}}(e);case"enum":return function(e){var t=e.token;Oe(e,"extend"),Oe(e,"enum");var n=F(e),r=oe(e,!0),i=ye(e);if(0===r.length&&0===i.length)throw xe(e);return{kind:D.ENUM_TYPE_EXTENSION,name:n,directives:r,values:i,loc:Ee(e,t)}}(e);case"input":return function(e){var t=e.token;Oe(e,"extend"),Oe(e,"input");var n=F(e),r=oe(e,!0),i=_e(e);if(0===r.length&&0===i.length)throw xe(e);return{kind:D.INPUT_OBJECT_TYPE_EXTENSION,name:n,directives:r,fields:i,loc:Ee(e,t)}}(e)}throw xe(e,t)}(e)}else{if(Ae(e,O.BRACE_L))return q(e);if(fe(e))return ce(e)}throw xe(e)}function q(e){if(Ae(e,O.NAME))switch(e.token.value){case"query":case"mutation":case"subscription":return K(e);case"fragment":return function(e){var t=e.token;if(Oe(e,"fragment"),e.options.experimentalFragmentVariables)return{kind:D.FRAGMENT_DEFINITION,name:Q(e),variableDefinitions:V(e),typeCondition:(Oe(e,"on"),ue(e)),directives:oe(e,!1),selectionSet:$(e),loc:Ee(e,t)};return{kind:D.FRAGMENT_DEFINITION,name:Q(e),typeCondition:(Oe(e,"on"),ue(e)),directives:oe(e,!1),selectionSet:$(e),loc:Ee(e,t)}}(e)}else if(Ae(e,O.BRACE_L))return K(e);throw xe(e)}function K(e){var t=e.token;if(Ae(e,O.BRACE_L))return{kind:D.OPERATION_DEFINITION,operation:"query",name:void 0,variableDefinitions:[],directives:[],selectionSet:$(e),loc:Ee(e,t)};var n,r=H(e);return Ae(e,O.NAME)&&(n=F(e)),{kind:D.OPERATION_DEFINITION,operation:r,name:n,variableDefinitions:V(e),directives:oe(e,!1),selectionSet:$(e),loc:Ee(e,t)}}function H(e){var t=ke(e,O.NAME);switch(t.value){case"query":return"query";case"mutation":return"mutation";case"subscription":return"subscription"}throw xe(e,t)}function V(e){return Ae(e,O.PAREN_L)?Te(e,O.PAREN_L,G,O.PAREN_R):[]}function G(e){var t=e.token;return e.options.experimentalVariableDefinitionDirectives?{kind:D.VARIABLE_DEFINITION,variable:W(e),type:(ke(e,O.COLON),ae(e)),defaultValue:Ie(e,O.EQUALS)?ee(e,!0):void 0,directives:oe(e,!0),loc:Ee(e,t)}:{kind:D.VARIABLE_DEFINITION,variable:W(e),type:(ke(e,O.COLON),ae(e)),defaultValue:Ie(e,O.EQUALS)?ee(e,!0):void 0,loc:Ee(e,t)}}function W(e){var t=e.token;return ke(e,O.DOLLAR),{kind:D.VARIABLE,name:F(e),loc:Ee(e,t)}}function $(e){var t=e.token;return{kind:D.SELECTION_SET,selections:Te(e,O.BRACE_L,Y,O.BRACE_R),loc:Ee(e,t)}}function Y(e){return Ae(e,O.SPREAD)?function(e){var t,n=e.token;if(ke(e,O.SPREAD),Ae(e,O.NAME)&&"on"!==e.token.value)return{kind:D.FRAGMENT_SPREAD,name:Q(e),directives:oe(e,!1),loc:Ee(e,n)};"on"===e.token.value&&(e.advance(),t=ue(e));return{kind:D.INLINE_FRAGMENT,typeCondition:t,directives:oe(e,!1),selectionSet:$(e),loc:Ee(e,n)}}(e):function(e){var t,n,r=e.token,i=F(e);Ie(e,O.COLON)?(t=i,n=F(e)):n=i;return{kind:D.FIELD,alias:t,name:n,arguments:J(e,!1),directives:oe(e,!1),selectionSet:Ae(e,O.BRACE_L)?$(e):void 0,loc:Ee(e,r)}}(e)}function J(e,t){var n=t?X:Z;return Ae(e,O.PAREN_L)?Te(e,O.PAREN_L,n,O.PAREN_R):[]}function Z(e){var t=e.token;return{kind:D.ARGUMENT,name:F(e),value:(ke(e,O.COLON),ee(e,!1)),loc:Ee(e,t)}}function X(e){var t=e.token;return{kind:D.ARGUMENT,name:F(e),value:(ke(e,O.COLON),ne(e)),loc:Ee(e,t)}}function Q(e){if("on"===e.token.value)throw xe(e);return F(e)}function ee(e,t){var n=e.token;switch(n.kind){case O.BRACKET_L:return function(e,t){var n=e.token,r=t?ne:re;return{kind:D.LIST,values:Ce(e,O.BRACKET_L,r,O.BRACKET_R),loc:Ee(e,n)}}(e,t);case O.BRACE_L:return function(e,t){var n=e.token;ke(e,O.BRACE_L);var r=[];for(;!Ie(e,O.BRACE_R);)r.push(ie(e,t));return{kind:D.OBJECT,fields:r,loc:Ee(e,n)}}(e,t);case O.INT:return e.advance(),{kind:D.INT,value:n.value,loc:Ee(e,n)};case O.FLOAT:return e.advance(),{kind:D.FLOAT,value:n.value,loc:Ee(e,n)};case O.STRING:case O.BLOCK_STRING:return te(e);case O.NAME:return"true"===n.value||"false"===n.value?(e.advance(),{kind:D.BOOLEAN,value:"true"===n.value,loc:Ee(e,n)}):"null"===n.value?(e.advance(),{kind:D.NULL,loc:Ee(e,n)}):(e.advance(),{kind:D.ENUM,value:n.value,loc:Ee(e,n)});case O.DOLLAR:if(!t)return W(e)}throw xe(e)}function te(e){var t=e.token;return e.advance(),{kind:D.STRING,value:t.value,block:t.kind===O.BLOCK_STRING,loc:Ee(e,t)}}function ne(e){return ee(e,!0)}function re(e){return ee(e,!1)}function ie(e,t){var n=e.token;return{kind:D.OBJECT_FIELD,name:F(e),value:(ke(e,O.COLON),ee(e,t)),loc:Ee(e,n)}}function oe(e,t){for(var n=[];Ae(e,O.AT);)n.push(se(e,t));return n}function se(e,t){var n=e.token;return ke(e,O.AT),{kind:D.DIRECTIVE,name:F(e),arguments:J(e,t),loc:Ee(e,n)}}function ae(e){var t,n=e.token;return Ie(e,O.BRACKET_L)?(t=ae(e),ke(e,O.BRACKET_R),t={kind:D.LIST_TYPE,type:t,loc:Ee(e,n)}):t=ue(e),Ie(e,O.BANG)?{kind:D.NON_NULL_TYPE,type:t,loc:Ee(e,n)}:t}function ue(e){var t=e.token;return{kind:D.NAMED_TYPE,name:F(e),loc:Ee(e,t)}}function ce(e){var t=fe(e)?e.lookahead():e.token;if(t.kind===O.NAME)switch(t.value){case"schema":return function(e){var t=e.token;Oe(e,"schema");var n=oe(e,!0),r=Te(e,O.BRACE_L,de,O.BRACE_R);return{kind:D.SCHEMA_DEFINITION,directives:n,operationTypes:r,loc:Ee(e,t)}}(e);case"scalar":return function(e){var t=e.token,n=le(e);Oe(e,"scalar");var r=F(e),i=oe(e,!0);return{kind:D.SCALAR_TYPE_DEFINITION,description:n,name:r,directives:i,loc:Ee(e,t)}}(e);case"type":return function(e){var t=e.token,n=le(e);Oe(e,"type");var r=F(e),i=he(e),o=oe(e,!0),s=pe(e);return{kind:D.OBJECT_TYPE_DEFINITION,description:n,name:r,interfaces:i,directives:o,fields:s,loc:Ee(e,t)}}(e);case"interface":return function(e){var t=e.token,n=le(e);Oe(e,"interface");var r=F(e),i=oe(e,!0),o=pe(e);return{kind:D.INTERFACE_TYPE_DEFINITION,description:n,name:r,directives:i,fields:o,loc:Ee(e,t)}}(e);case"union":return function(e){var t=e.token,n=le(e);Oe(e,"union");var r=F(e),i=oe(e,!0),o=be(e);return{kind:D.UNION_TYPE_DEFINITION,description:n,name:r,directives:i,types:o,loc:Ee(e,t)}}(e);case"enum":return function(e){var t=e.token,n=le(e);Oe(e,"enum");var r=F(e),i=oe(e,!0),o=ye(e);return{kind:D.ENUM_TYPE_DEFINITION,description:n,name:r,directives:i,values:o,loc:Ee(e,t)}}(e);case"input":return function(e){var t=e.token,n=le(e);Oe(e,"input");var r=F(e),i=oe(e,!0),o=_e(e);return{kind:D.INPUT_OBJECT_TYPE_DEFINITION,description:n,name:r,directives:i,fields:o,loc:Ee(e,t)}}(e);case"directive":return function(e){var t=e.token,n=le(e);Oe(e,"directive"),ke(e,O.AT);var r=F(e),i=ge(e);Oe(e,"on");var o=function(e){Ie(e,O.PIPE);var t=[];do{t.push(Se(e))}while(Ie(e,O.PIPE));return t}(e);return{kind:D.DIRECTIVE_DEFINITION,description:n,name:r,arguments:i,locations:o,loc:Ee(e,t)}}(e)}throw xe(e,t)}function fe(e){return Ae(e,O.STRING)||Ae(e,O.BLOCK_STRING)}function le(e){if(fe(e))return te(e)}function de(e){var t=e.token,n=H(e);ke(e,O.COLON);var r=ue(e);return{kind:D.OPERATION_TYPE_DEFINITION,operation:n,type:r,loc:Ee(e,t)}}function he(e){var t=[];if("implements"===e.token.value){e.advance(),Ie(e,O.AMP);do{t.push(ue(e))}while(Ie(e,O.AMP)||e.options.allowLegacySDLImplementsInterfaces&&Ae(e,O.NAME))}return t}function pe(e){return e.options.allowLegacySDLEmptyFields&&Ae(e,O.BRACE_L)&&e.lookahead().kind===O.BRACE_R?(e.advance(),e.advance(),[]):Ae(e,O.BRACE_L)?Te(e,O.BRACE_L,ve,O.BRACE_R):[]}function ve(e){var t=e.token,n=le(e),r=F(e),i=ge(e);ke(e,O.COLON);var o=ae(e),s=oe(e,!0);return{kind:D.FIELD_DEFINITION,description:n,name:r,arguments:i,type:o,directives:s,loc:Ee(e,t)}}function ge(e){return Ae(e,O.PAREN_L)?Te(e,O.PAREN_L,me,O.PAREN_R):[]}function me(e){var t=e.token,n=le(e),r=F(e);ke(e,O.COLON);var i,o=ae(e);Ie(e,O.EQUALS)&&(i=ne(e));var s=oe(e,!0);return{kind:D.INPUT_VALUE_DEFINITION,description:n,name:r,type:o,defaultValue:i,directives:s,loc:Ee(e,t)}}function be(e){var t=[];if(Ie(e,O.EQUALS)){Ie(e,O.PIPE);do{t.push(ue(e))}while(Ie(e,O.PIPE))}return t}function ye(e){return Ae(e,O.BRACE_L)?Te(e,O.BRACE_L,we,O.BRACE_R):[]}function we(e){var t=e.token,n=le(e),r=F(e),i=oe(e,!0);return{kind:D.ENUM_VALUE_DEFINITION,description:n,name:r,directives:i,loc:Ee(e,t)}}function _e(e){return Ae(e,O.BRACE_L)?Te(e,O.BRACE_L,me,O.BRACE_R):[]}function Se(e){var t=e.token,n=F(e);if(U.hasOwnProperty(n.value))return n;throw xe(e,t)}function Ee(e,t){if(!e.options.noLocation)return new Me(t,e.lastToken,e.source)}function Me(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}function Ae(e,t){return e.token.kind===t}function Ie(e,t){var n=e.token.kind===t;return n&&e.advance(),n}function ke(e,t){var n=e.token;if(n.kind===t)return e.advance(),n;throw _(e.source,n.start,"Expected ".concat(t,", found ").concat(x(n)))}function Oe(e,t){var n=e.token;if(n.kind===O.NAME&&n.value===t)return e.advance(),n;throw _(e.source,n.start,'Expected "'.concat(t,'", found ').concat(x(n)))}function xe(e,t){var n=t||e.token;return _(e.source,n.start,"Unexpected ".concat(x(n)))}function Ce(e,t,n,r){ke(e,t);for(var i=[];!Ie(e,r);)i.push(n(e));return i}function Te(e,t,n,r){ke(e,t);for(var i=[n(e)];!Ie(e,r);)i.push(n(e));return i}Me.prototype.toJSON=Me.prototype.inspect=function(){return{start:this.start,end:this.end}};var Pe=n(44),Ne=n(89),Re=n(5),Le=n(103),je=n(19),De=n(34),Ue=n(42),Be=n(26),Fe=n(254),ze=function(){return(ze=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},qe=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},Ke=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},He=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n},Ve=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},Ge=new Pe.a("GraphQLAPI"),We=function(e,t){return void 0===t&&(t={}),{query:e,variables:t}},$e=function(){function e(e){this._api=null,this.Auth=Ue.a,this.Cache=Be.a,this.Credentials=Ne.a,this._options=e,Ge.debug("API Options",this._options)}return e.prototype.getModuleName=function(){return"GraphQLAPI"},e.prototype.configure=function(e){var t=e||{},n=t.API,r=void 0===n?{}:n,i=He(t,["API"]),o=ze(ze({},i),r);return Ge.debug("configure GraphQL API",{opt:o}),o.aws_project_region&&(o=Object.assign({},o,{region:o.aws_project_region,header:{}})),void 0!==o.graphql_headers&&"function"!=typeof o.graphql_headers&&(Ge.warn("graphql_headers should be a function"),o.graphql_headers=void 0),this._options=Object.assign({},this._options,o),this.createInstance(),this._options},e.prototype.createInstance=function(){return Ge.debug("create Rest instance"),this._options?(this._api=new Fe.a(this._options),this._api.Credentials=this.Credentials,!0):Promise.reject("API not configured")},e.prototype._headerBasedAuth=function(e){return qe(this,void 0,void 0,(function(){var t,n,r,i,o,s,a,u;return Ke(this,(function(c){switch(c.label){case 0:switch(t=this._options,n=t.aws_appsync_authenticationType,r=t.aws_appsync_apiKey,i={},e||n||"AWS_IAM"){case"API_KEY":return[3,1];case"AWS_IAM":return[3,2];case"OPENID_CONNECT":return[3,4];case"AMAZON_COGNITO_USER_POOLS":return[3,9]}return[3,11];case 1:if(!r)throw new Error("No api-key configured");return i={Authorization:null,"X-Api-Key":r},[3,12];case 2:return[4,this._ensureCredentials()];case 3:if(!c.sent())throw new Error("No credentials");return[3,12];case 4:return o=void 0,[4,Be.a.getItem("federatedInfo")];case 5:return(s=c.sent())?(o=s.token,[3,8]):[3,6];case 6:return[4,Ue.a.currentAuthenticatedUser()];case 7:(a=c.sent())&&(o=a.token),c.label=8;case 8:if(!o)throw new Error("No federated jwt");return i={Authorization:o},[3,12];case 9:return[4,this.Auth.currentSession()];case 10:return u=c.sent(),i={Authorization:u.getAccessToken().getJwtToken()},[3,12];case 11:return i={Authorization:null},[3,12];case 12:return[2,i]}}))}))},e.prototype.getGraphqlOperationType=function(e){var t=B(e);return Ve(t.definitions,1)[0].operation},e.prototype.graphql=function(e,t){var n=e.query,r=e.variables,i=void 0===r?{}:r,o=e.authMode,s=B("string"==typeof n?n:u(n)),a=Ve(s.definitions.filter((function(e){return"OperationDefinition"===e.kind})),1)[0],c=(void 0===a?{}:a).operation;switch(c){case"query":case"mutation":var f=this._api.getCancellableToken(),l={cancellableToken:f},d=this._graphql({query:s,variables:i,authMode:o},t,l);return this._api.updateRequestToBeCancellable(d,f),d;case"subscription":return this._graphqlSubscribe({query:s,variables:i,authMode:o},t)}throw new Error("invalid operation type: "+c)},e.prototype._graphql=function(e,t,n){var i=e.query,o=e.variables,s=e.authMode;return void 0===t&&(t={}),void 0===n&&(n={}),qe(this,void 0,void 0,(function(){var e,a,c,f,l,d,h,p,v,g,m,b,y,w,_,S,E,M,A,I,k;return Ke(this,(function(O){switch(O.label){case 0:return this._api?[3,2]:[4,this.createInstance()];case 1:O.sent(),O.label=2;case 2:return e=this._options,a=e.aws_appsync_region,c=e.aws_appsync_graphqlEndpoint,f=e.graphql_headers,l=void 0===f?function(){return{}}:f,d=e.graphql_endpoint,h=e.graphql_endpoint_iam_region,v=[{}],(g=!d)?[4,this._headerBasedAuth(s)]:[3,4];case 3:g=O.sent(),O.label=4;case 4:return m=[ze.apply(void 0,v.concat([g]))],(b=d)?h?[4,this._headerBasedAuth(s)]:[3,6]:[3,8];case 5:return y=O.sent(),[3,7];case 6:y={Authorization:null},O.label=7;case 7:b=y,O.label=8;case 8:return w=[ze.apply(void 0,m.concat([b]))],[4,l({query:i,variables:o})];case 9:if(p=ze.apply(void 0,[ze.apply(void 0,[ze.apply(void 0,w.concat([O.sent()])),t]),!d&&(k={},k["x-amz-user-agent"]=Re.a.userAgent,k)]),_={query:u(i),variables:o},S=Object.assign({headers:p,body:_,signerServiceInfo:{service:d?"execute-api":"appsync",region:d?h:a}},n),!(E=d||c))throw{data:{},errors:[new r.a("No graphql endpoint provided.")]};O.label=10;case 10:return O.trys.push([10,12,,13]),[4,this._api.post(E,S)];case 11:return M=O.sent(),[3,13];case 12:if(A=O.sent(),this._api.isCancel(A))throw A;return M={data:{},errors:[new r.a(A.message)]},[3,13];case 13:if((I=M.errors)&&I.length)throw M;return[2,M]}}))}))},e.prototype.isCancel=function(e){return this._api.isCancel(e)},e.prototype.cancel=function(e,t){return this._api.cancel(e,t)},e.prototype._graphqlSubscribe=function(e,t){var n=e.query,r=e.variables,i=e.authMode;void 0===t&&(t={});var o=this._options,s=o.aws_appsync_region,a=o.aws_appsync_graphqlEndpoint,c=o.aws_appsync_authenticationType,f=o.aws_appsync_apiKey,l=o.graphql_headers,d=void 0===l?function(){return{}}:l,h=i||c||"AWS_IAM";if(De.b&&"function"==typeof De.b.subscribe)return De.b.subscribe("",{provider:Le.b,appSyncGraphqlEndpoint:a,authenticationType:h,apiKey:f,query:u(n),region:s,variables:r,graphql_headers:d,additionalHeaders:t});throw Ge.debug("No pubsub module applied for subscription"),new Error("No pubsub module applied for subscription")},e.prototype._ensureCredentials=function(){var e=this;return this.Credentials.get().then((function(t){if(!t)return!1;var n=e.Credentials.shear(t);return Ge.debug("set credentials for api",n),!0})).catch((function(e){return Ge.warn("ensure credentials error",e),!1}))},e}(),Ye=new $e(null);je.a.register(Ye)},function(e,t,n){"use strict";n.r(t),n.d(t,"fromUtf8",(function(){return r})),n.d(t,"toUtf8",(function(){return i}));var r=function(e){return"function"==typeof TextEncoder?function(e){return(new TextEncoder).encode(e)}(e):function(e){for(var t=[],n=0,r=e.length;n<r;n++){var i=e.charCodeAt(n);if(i<128)t.push(i);else if(i<2048)t.push(i>>6|192,63&i|128);else if(n+1<e.length&&55296==(64512&i)&&56320==(64512&e.charCodeAt(n+1))){var o=65536+((1023&i)<<10)+(1023&e.charCodeAt(++n));t.push(o>>18|240,o>>12&63|128,o>>6&63|128,63&o|128)}else t.push(i>>12|224,i>>6&63|128,63&i|128)}return Uint8Array.from(t)}(e)},i=function(e){return"function"==typeof TextDecoder?function(e){return new TextDecoder("utf-8").decode(e)}(e):function(e){for(var t="",n=0,r=e.length;n<r;n++){var i=e[n];if(i<128)t+=String.fromCharCode(i);else if(192<=i&&i<224){var o=e[++n];t+=String.fromCharCode((31&i)<<6|63&o)}else if(240<=i&&i<365){var s="%"+[i,e[++n],e[++n],e[++n]].map((function(e){return e.toString(16)})).join("%");t+=decodeURIComponent(s)}else t+=String.fromCharCode((15&i)<<12|(63&e[++n])<<6|63&e[++n])}return t}(e)}},function(e,t,n){"use strict";(function(e){var r;if(n.d(t,"a",(function(){return i})),"undefined"!=typeof window&&window.crypto&&(r=window.crypto),!r&&"undefined"!=typeof window&&window.msCrypto&&(r=window.msCrypto),!r&&void 0!==e&&e.crypto&&(r=e.crypto),!r)try{r=n(272)}catch(e){}function i(){if(r){if("function"==typeof r.getRandomValues)try{return r.getRandomValues(new Uint32Array(1))[0]}catch(e){}if("function"==typeof r.randomBytes)try{return r.randomBytes(4).readInt32LE()}catch(e){}}throw new Error("Native crypto module could not be used to get secure random number.")}}).call(this,n(31))},function(e,t,n){"use strict";n.d(t,"a",(function(){return r}));var r=function(e){return"function"==typeof ArrayBuffer&&e instanceof ArrayBuffer||"[object ArrayBuffer]"===Object.prototype.toString.call(e)}},function(e,t,n){var r=n(387);e.exports=function(e,t,n){var i=null==e?void 0:r(e,t);return void 0===i?n:i}},function(e,t,n){"use strict";const r=n(459),i=n(102),o=n(102),s=n(54).buildOptions,a=n(461);t.parse=function(e,t,n){if(n){!0===n&&(n={});const t=a.validate(e,n);if(!0!==t)throw Error(t.err.msg)}t=s(t,o.defaultOptions,o.props);const u=i.getTraversalObj(e,t);return r.convertToJson(u,t)},t.convertTonimn=n(462).convert2nimn,t.getTraversalObj=i.getTraversalObj,t.convertToJson=r.convertToJson,t.convertToJsonString=n(463).convertToJsonString,t.validate=a.validate,t.j2xParser=n(464),t.parseToNimn=function(e,n,r){return t.convertTonimn(t.getTraversalObj(e,r),n,r)}},function(e,t,n){"use strict";n.d(t,"a",(function(){return g}));var r=n(44),i=n(89),o=n(50),s=n(77),a=n(104),u=n(64),c=n.n(u),f=n(16),l=function(){return(l=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},d=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},h=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},p=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n},v=new r.a("RestClient"),g=function(){function e(e){this._region="us-east-1",this._service="execute-api",this._custom_header=void 0,this._cancelTokenMap=null,this.Credentials=i.a,this._options=e,v.debug("API Options",this._options),null==this._cancelTokenMap&&(this._cancelTokenMap=new WeakMap)}return e.prototype.ajax=function(e,t,n){return d(this,void 0,void 0,(function(){var r,i,a,u,c,d,g,m,b,y,w,_,S,E,M=this;return h(this,(function(h){switch(h.label){case 0:return v.debug(t,e),a="us-east-1",u="execute-api",c=void 0,"string"==typeof e?(r=this._parseUrl(e),i=e):(i=e.endpoint,c=e.custom_header,a=e.region,u=e.service,r=this._parseUrl(e.endpoint)),d={method:t,url:i,host:r.host,path:r.path,headers:{},data:null,responseType:"json",timeout:0,cancelToken:null},g={},o.a.isReactNative&&(m=o.a.userAgent||"aws-amplify/0.1.x",g={"User-Agent":m}),b=Object.assign({},n),y=b.response,b.body&&("function"==typeof FormData&&b.body instanceof FormData?(g["Content-Type"]="multipart/form-data",d.data=b.body):(g["Content-Type"]="application/json; charset=UTF-8",d.data=JSON.stringify(b.body))),b.responseType&&(d.responseType=b.responseType),b.withCredentials&&(d.withCredentials=b.withCredentials),b.timeout&&(d.timeout=b.timeout),b.cancellableToken&&(d.cancelToken=b.cancellableToken.token),d.signerServiceInfo=b.signerServiceInfo,"function"!=typeof c?[3,2]:[4,c()];case 1:return _=h.sent(),[3,3];case 2:_=void 0,h.label=3;case 3:return w=_,d.headers=l(l(l({},g),w),b.headers),S=Object(f.parse)(i,!0,!0),S.search,E=p(S,["search"]),d.url=Object(f.format)(l(l({},E),{query:l(l({},E.query),b.queryStringParameters||{})})),void 0!==d.headers.Authorization?(d.headers=Object.keys(d.headers).reduce((function(e,t){return d.headers[t]&&(e[t]=d.headers[t]),e}),{}),[2,this._request(d,y)]):[2,this.Credentials.get().then((function(r){return M._signed(l({},d),r,y,{region:a,service:u}).catch((function(r){if(s.a.isClockSkewError(r)){var i=r.response.headers,o=i&&(i.date||i.Date),a=new Date(o),u=s.a.getDateFromHeaderString(d.headers["x-amz-date"]);if(s.a.isClockSkewed(u,a))return s.a.setClockOffset(a.getTime()-u.getTime()),M.ajax(e,t,n)}throw r}))}),(function(e){return v.debug("No credentials available, the request will be unsigned"),M._request(d,y)}))]}}))}))},e.prototype.get=function(e,t){return this.ajax(e,"GET",t)},e.prototype.put=function(e,t){return this.ajax(e,"PUT",t)},e.prototype.patch=function(e,t){return this.ajax(e,"PATCH",t)},e.prototype.post=function(e,t){return this.ajax(e,"POST",t)},e.prototype.del=function(e,t){return this.ajax(e,"DELETE",t)},e.prototype.head=function(e,t){return this.ajax(e,"HEAD",t)},e.prototype.cancel=function(e,t){var n=this._cancelTokenMap.get(e);return n&&n.cancel(t),!0},e.prototype.isCancel=function(e){return c.a.isCancel(e)},e.prototype.getCancellableToken=function(){return c.a.CancelToken.source()},e.prototype.updateRequestToBeCancellable=function(e,t){this._cancelTokenMap.set(e,t)},e.prototype.endpoint=function(e){var t=this,n=this._options.endpoints,r="";return Array.isArray(n)?(n.forEach((function(n){n.name===e&&(r=n.endpoint,"string"==typeof n.region?t._region=n.region:"string"==typeof t._options.region&&(t._region=t._options.region),"string"==typeof n.service?t._service=n.service||"execute-api":t._service="execute-api","function"==typeof n.custom_header?t._custom_header=n.custom_header:t._custom_header=void 0)})),r):r},e.prototype._signed=function(e,t,n,r){var i=r.service,o=r.region,s=e.signerServiceInfo,u=p(e,["signerServiceInfo"]),f=o||this._region||this._options.region,l=i||this._service||this._options.service,d={secret_key:t.secretAccessKey,access_key:t.accessKeyId,session_token:t.sessionToken},h={region:f,service:l},g=Object.assign(h,s),m=a.a.sign(u,d,g);return m.data&&(m.body=m.data),v.debug("Signed Request: ",m),delete m.headers.host,c()(m).then((function(e){return n?e:e.data})).catch((function(e){throw v.debug(e),e}))},e.prototype._request=function(e,t){return void 0===t&&(t=!1),c()(e).then((function(e){return t?e:e.data})).catch((function(e){throw v.debug(e),e}))},e.prototype._parseUrl=function(e){var t=e.split("/");return{host:t[2],path:"/"+t.slice(3).join("/")}},e}()},function(e,t,n){e.exports=n(482).Observable},function(e,t,n){(function(t){var n;n=function(){return function(e){var t,n=e.localStorage||(t={},{setItem:function(e,n){t[e]=n},getItem:function(e){return t[e]},removeItem:function(e){delete t[e]}}),r=1,i=2,o=3,s=4,a=5,u=6,c=7,f=8,l=9,d=10,h=11,p=12,v=13,g=14,m=function(e,t){for(var n in e)if(e.hasOwnProperty(n)){if(!t.hasOwnProperty(n)){var r="Unknown property, "+n+". Valid properties are:";for(var i in t)t.hasOwnProperty(i)&&(r=r+" "+i);throw new Error(r)}if(typeof e[n]!==t[n])throw new Error(_(y.INVALID_TYPE,[typeof e[n],n]))}},b=function(e,t){return function(){return e.apply(t,arguments)}},y={OK:{code:0,text:"AMQJSC0000I OK."},CONNECT_TIMEOUT:{code:1,text:"AMQJSC0001E Connect timed out."},SUBSCRIBE_TIMEOUT:{code:2,text:"AMQJS0002E Subscribe timed out."},UNSUBSCRIBE_TIMEOUT:{code:3,text:"AMQJS0003E Unsubscribe timed out."},PING_TIMEOUT:{code:4,text:"AMQJS0004E Ping timed out."},INTERNAL_ERROR:{code:5,text:"AMQJS0005E Internal error. Error Message: {0}, Stack trace: {1}"},CONNACK_RETURNCODE:{code:6,text:"AMQJS0006E Bad Connack return code:{0} {1}."},SOCKET_ERROR:{code:7,text:"AMQJS0007E Socket error:{0}."},SOCKET_CLOSE:{code:8,text:"AMQJS0008I Socket closed."},MALFORMED_UTF:{code:9,text:"AMQJS0009E Malformed UTF data:{0} {1} {2}."},UNSUPPORTED:{code:10,text:"AMQJS0010E {0} is not supported by this browser."},INVALID_STATE:{code:11,text:"AMQJS0011E Invalid state {0}."},INVALID_TYPE:{code:12,text:"AMQJS0012E Invalid type {0} for {1}."},INVALID_ARGUMENT:{code:13,text:"AMQJS0013E Invalid argument {0} for {1}."},UNSUPPORTED_OPERATION:{code:14,text:"AMQJS0014E Unsupported operation."},INVALID_STORED_DATA:{code:15,text:"AMQJS0015E Invalid data in local storage key={0} value={1}."},INVALID_MQTT_MESSAGE_TYPE:{code:16,text:"AMQJS0016E Invalid MQTT message type {0}."},MALFORMED_UNICODE:{code:17,text:"AMQJS0017E Malformed Unicode string:{0} {1}."},BUFFER_FULL:{code:18,text:"AMQJS0018E Message buffer is full, maximum buffer size: {0}."}},w={0:"Connection Accepted",1:"Connection Refused: unacceptable protocol version",2:"Connection Refused: identifier rejected",3:"Connection Refused: server unavailable",4:"Connection Refused: bad user name or password",5:"Connection Refused: not authorized"},_=function(e,t){var n=e.text;if(t)for(var r,i,o=0;o<t.length;o++)if(r="{"+o+"}",(i=n.indexOf(r))>0){var s=n.substring(0,i),a=n.substring(i+r.length);n=s+t[o]+a}return n},S=[0,6,77,81,73,115,100,112,3],E=[0,4,77,81,84,84,4],M=function(e,t){for(var n in this.type=e,t)t.hasOwnProperty(n)&&(this[n]=t[n])};function A(e,t){var n,r=t,f=e[t],d=f>>4,p=f&=15;t+=1;var v=0,g=1;do{if(t==e.length)return[null,r];v+=(127&(n=e[t++]))*g,g*=128}while(0!=(128&n));var m=t+v;if(m>e.length)return[null,r];var b=new M(d);switch(d){case i:1&e[t++]&&(b.sessionPresent=!0),b.returnCode=e[t++];break;case o:var y=p>>1&3,w=O(e,t),_=T(e,t+=2,w);t+=w,y>0&&(b.messageIdentifier=O(e,t),t+=2);var S=new L(e.subarray(t,m));1==(1&p)&&(S.retained=!0),8==(8&p)&&(S.duplicate=!0),S.qos=y,S.destinationName=_,b.payloadMessage=S;break;case s:case a:case u:case c:case h:b.messageIdentifier=O(e,t);break;case l:b.messageIdentifier=O(e,t),t+=2,b.returnCode=e.subarray(t,m)}return[b,m]}function I(e,t,n){return t[n++]=e>>8,t[n++]=e%256,n}function k(e,t,n,r){return C(e,n,r=I(t,n,r)),r+t}function O(e,t){return 256*e[t]+e[t+1]}function x(e){for(var t=0,n=0;n<e.length;n++){var r=e.charCodeAt(n);r>2047?(55296<=r&&r<=56319&&(n++,t++),t+=3):r>127?t+=2:t++}return t}function C(e,t,n){for(var r=n,i=0;i<e.length;i++){var o=e.charCodeAt(i);if(55296<=o&&o<=56319){var s=e.charCodeAt(++i);if(isNaN(s))throw new Error(_(y.MALFORMED_UNICODE,[o,s]));o=s-56320+(o-55296<<10)+65536}o<=127?t[r++]=o:o<=2047?(t[r++]=o>>6&31|192,t[r++]=63&o|128):o<=65535?(t[r++]=o>>12&15|224,t[r++]=o>>6&63|128,t[r++]=63&o|128):(t[r++]=o>>18&7|240,t[r++]=o>>12&63|128,t[r++]=o>>6&63|128,t[r++]=63&o|128)}return t}function T(e,t,n){for(var r,i="",o=t;o<t+n;){var s=e[o++];if(s<128)r=s;else{var a=e[o++]-128;if(a<0)throw new Error(_(y.MALFORMED_UTF,[s.toString(16),a.toString(16),""]));if(s<224)r=64*(s-192)+a;else{var u=e[o++]-128;if(u<0)throw new Error(_(y.MALFORMED_UTF,[s.toString(16),a.toString(16),u.toString(16)]));if(s<240)r=4096*(s-224)+64*a+u;else{var c=e[o++]-128;if(c<0)throw new Error(_(y.MALFORMED_UTF,[s.toString(16),a.toString(16),u.toString(16),c.toString(16)]));if(!(s<248))throw new Error(_(y.MALFORMED_UTF,[s.toString(16),a.toString(16),u.toString(16),c.toString(16)]));r=262144*(s-240)+4096*a+64*u+c}}}r>65535&&(r-=65536,i+=String.fromCharCode(55296+(r>>10)),r=56320+(1023&r)),i+=String.fromCharCode(r)}return i}M.prototype.encode=function(){var e,t=(15&this.type)<<4,n=0,i=[],s=0;switch(void 0!==this.messageIdentifier&&(n+=2),this.type){case r:switch(this.mqttVersion){case 3:n+=S.length+3;break;case 4:n+=E.length+3}n+=x(this.clientId)+2,void 0!==this.willMessage&&(n+=x(this.willMessage.destinationName)+2,(e=this.willMessage.payloadBytes)instanceof Uint8Array||(e=new Uint8Array(c)),n+=e.byteLength+2),void 0!==this.userName&&(n+=x(this.userName)+2),void 0!==this.password&&(n+=x(this.password)+2);break;case f:t|=2;for(var a=0;a<this.topics.length;a++)i[a]=x(this.topics[a]),n+=i[a]+2;n+=this.requestedQos.length;break;case d:for(t|=2,a=0;a<this.topics.length;a++)i[a]=x(this.topics[a]),n+=i[a]+2;break;case u:t|=2;break;case o:this.payloadMessage.duplicate&&(t|=8),t=t|=this.payloadMessage.qos<<1,this.payloadMessage.retained&&(t|=1),n+=(s=x(this.payloadMessage.destinationName))+2;var c=this.payloadMessage.payloadBytes;n+=c.byteLength,c instanceof ArrayBuffer?c=new Uint8Array(c):c instanceof Uint8Array||(c=new Uint8Array(c.buffer))}var l=function(e){var t=new Array(1),n=0;do{var r=e%128;(e>>=7)>0&&(r|=128),t[n++]=r}while(e>0&&n<4);return t}(n),h=l.length+1,p=new ArrayBuffer(n+h),v=new Uint8Array(p);if(v[0]=t,v.set(l,1),this.type==o)h=k(this.payloadMessage.destinationName,s,v,h);else if(this.type==r){switch(this.mqttVersion){case 3:v.set(S,h),h+=S.length;break;case 4:v.set(E,h),h+=E.length}var g=0;this.cleanSession&&(g=2),void 0!==this.willMessage&&(g|=4,g|=this.willMessage.qos<<3,this.willMessage.retained&&(g|=32)),void 0!==this.userName&&(g|=128),void 0!==this.password&&(g|=64),v[h++]=g,h=I(this.keepAliveInterval,v,h)}switch(void 0!==this.messageIdentifier&&(h=I(this.messageIdentifier,v,h)),this.type){case r:h=k(this.clientId,x(this.clientId),v,h),void 0!==this.willMessage&&(h=k(this.willMessage.destinationName,x(this.willMessage.destinationName),v,h),h=I(e.byteLength,v,h),v.set(e,h),h+=e.byteLength),void 0!==this.userName&&(h=k(this.userName,x(this.userName),v,h)),void 0!==this.password&&(h=k(this.password,x(this.password),v,h));break;case o:v.set(c,h);break;case f:for(a=0;a<this.topics.length;a++)h=k(this.topics[a],i[a],v,h),v[h++]=this.requestedQos[a];break;case d:for(a=0;a<this.topics.length;a++)h=k(this.topics[a],i[a],v,h)}return p};var P=function(e,t){this._client=e,this._keepAliveInterval=1e3*t,this.isReset=!1;var n=new M(p).encode(),r=function(e){return function(){return i.apply(e)}},i=function(){this.isReset?(this.isReset=!1,this._client._trace("Pinger.doPing","send PINGREQ"),this._client.socket.send(n),this.timeout=setTimeout(r(this),this._keepAliveInterval)):(this._client._trace("Pinger.doPing","Timed out"),this._client._disconnected(y.PING_TIMEOUT.code,_(y.PING_TIMEOUT)))};this.reset=function(){this.isReset=!0,clearTimeout(this.timeout),this._keepAliveInterval>0&&(this.timeout=setTimeout(r(this),this._keepAliveInterval))},this.cancel=function(){clearTimeout(this.timeout)}},N=function(e,t,n,r){t||(t=30),this.timeout=setTimeout(function(e,t,n){return function(){return e.apply(t,n)}}(n,e,r),1e3*t),this.cancel=function(){clearTimeout(this.timeout)}},R=function(t,r,i,o,s){if(!("WebSocket"in e)||null===e.WebSocket)throw new Error(_(y.UNSUPPORTED,["WebSocket"]));if(!("ArrayBuffer"in e)||null===e.ArrayBuffer)throw new Error(_(y.UNSUPPORTED,["ArrayBuffer"]));for(var a in this._trace("Paho.Client",t,r,i,o,s),this.host=r,this.port=i,this.path=o,this.uri=t,this.clientId=s,this._wsuri=null,this._localKey=r+":"+i+("/mqtt"!=o?":"+o:"")+":"+s+":",this._msg_queue=[],this._buffered_msg_queue=[],this._sentMessages={},this._receivedMessages={},this._notify_msg_sent={},this._message_identifier=1,this._sequence=0,n)0!==a.indexOf("Sent:"+this._localKey)&&0!==a.indexOf("Received:"+this._localKey)||this.restore(a)};R.prototype.host=null,R.prototype.port=null,R.prototype.path=null,R.prototype.uri=null,R.prototype.clientId=null,R.prototype.socket=null,R.prototype.connected=!1,R.prototype.maxMessageIdentifier=65536,R.prototype.connectOptions=null,R.prototype.hostIndex=null,R.prototype.onConnected=null,R.prototype.onConnectionLost=null,R.prototype.onMessageDelivered=null,R.prototype.onMessageArrived=null,R.prototype.traceFunction=null,R.prototype._msg_queue=null,R.prototype._buffered_msg_queue=null,R.prototype._connectTimeout=null,R.prototype.sendPinger=null,R.prototype.receivePinger=null,R.prototype._reconnectInterval=1,R.prototype._reconnecting=!1,R.prototype._reconnectTimeout=null,R.prototype.disconnectedPublishing=!1,R.prototype.disconnectedBufferSize=5e3,R.prototype.receiveBuffer=null,R.prototype._traceBuffer=null,R.prototype._MAX_TRACE_ENTRIES=100,R.prototype.connect=function(e){var t=this._traceMask(e,"password");if(this._trace("Client.connect",t,this.socket,this.connected),this.connected)throw new Error(_(y.INVALID_STATE,["already connected"]));if(this.socket)throw new Error(_(y.INVALID_STATE,["already connected"]));this._reconnecting&&(this._reconnectTimeout.cancel(),this._reconnectTimeout=null,this._reconnecting=!1),this.connectOptions=e,this._reconnectInterval=1,this._reconnecting=!1,e.uris?(this.hostIndex=0,this._doConnect(e.uris[0])):this._doConnect(this.uri)},R.prototype.subscribe=function(e,t){if(this._trace("Client.subscribe",e,t),!this.connected)throw new Error(_(y.INVALID_STATE,["not connected"]));var n=new M(f);n.topics=e.constructor===Array?e:[e],void 0===t.qos&&(t.qos=0),n.requestedQos=[];for(var r=0;r<n.topics.length;r++)n.requestedQos[r]=t.qos;t.onSuccess&&(n.onSuccess=function(e){t.onSuccess({invocationContext:t.invocationContext,grantedQos:e})}),t.onFailure&&(n.onFailure=function(e){t.onFailure({invocationContext:t.invocationContext,errorCode:e,errorMessage:_(e)})}),t.timeout&&(n.timeOut=new N(this,t.timeout,t.onFailure,[{invocationContext:t.invocationContext,errorCode:y.SUBSCRIBE_TIMEOUT.code,errorMessage:_(y.SUBSCRIBE_TIMEOUT)}])),this._requires_ack(n),this._schedule_message(n)},R.prototype.unsubscribe=function(e,t){if(this._trace("Client.unsubscribe",e,t),!this.connected)throw new Error(_(y.INVALID_STATE,["not connected"]));var n=new M(d);n.topics=e.constructor===Array?e:[e],t.onSuccess&&(n.callback=function(){t.onSuccess({invocationContext:t.invocationContext})}),t.timeout&&(n.timeOut=new N(this,t.timeout,t.onFailure,[{invocationContext:t.invocationContext,errorCode:y.UNSUBSCRIBE_TIMEOUT.code,errorMessage:_(y.UNSUBSCRIBE_TIMEOUT)}])),this._requires_ack(n),this._schedule_message(n)},R.prototype.send=function(e){this._trace("Client.send",e);var t=new M(o);if(t.payloadMessage=e,this.connected)e.qos>0?this._requires_ack(t):this.onMessageDelivered&&(this._notify_msg_sent[t]=this.onMessageDelivered(t.payloadMessage)),this._schedule_message(t);else{if(!this._reconnecting||!this.disconnectedPublishing)throw new Error(_(y.INVALID_STATE,["not connected"]));if(Object.keys(this._sentMessages).length+this._buffered_msg_queue.length>this.disconnectedBufferSize)throw new Error(_(y.BUFFER_FULL,[this.disconnectedBufferSize]));e.qos>0?this._requires_ack(t):(t.sequence=++this._sequence,this._buffered_msg_queue.unshift(t))}},R.prototype.disconnect=function(){if(this._trace("Client.disconnect"),this._reconnecting&&(this._reconnectTimeout.cancel(),this._reconnectTimeout=null,this._reconnecting=!1),!this.socket)throw new Error(_(y.INVALID_STATE,["not connecting or connected"]));var e=new M(g);this._notify_msg_sent[e]=b(this._disconnected,this),this._schedule_message(e)},R.prototype.getTraceLog=function(){if(null!==this._traceBuffer){for(var e in this._trace("Client.getTraceLog",new Date),this._trace("Client.getTraceLog in flight messages",this._sentMessages.length),this._sentMessages)this._trace("_sentMessages ",e,this._sentMessages[e]);for(var e in this._receivedMessages)this._trace("_receivedMessages ",e,this._receivedMessages[e]);return this._traceBuffer}},R.prototype.startTrace=function(){null===this._traceBuffer&&(this._traceBuffer=[]),this._trace("Client.startTrace",new Date,"@VERSION@-@BUILDLEVEL@")},R.prototype.stopTrace=function(){delete this._traceBuffer},R.prototype._doConnect=function(e){if(this.connectOptions.useSSL){var t=e.split(":");t[0]="wss",e=t.join(":")}this._wsuri=e,this.connected=!1,this.connectOptions.mqttVersion<4?this.socket=new WebSocket(e,["mqttv3.1"]):this.socket=new WebSocket(e,["mqtt"]),this.socket.binaryType="arraybuffer",this.socket.onopen=b(this._on_socket_open,this),this.socket.onmessage=b(this._on_socket_message,this),this.socket.onerror=b(this._on_socket_error,this),this.socket.onclose=b(this._on_socket_close,this),this.sendPinger=new P(this,this.connectOptions.keepAliveInterval),this.receivePinger=new P(this,this.connectOptions.keepAliveInterval),this._connectTimeout&&(this._connectTimeout.cancel(),this._connectTimeout=null),this._connectTimeout=new N(this,this.connectOptions.timeout,this._disconnected,[y.CONNECT_TIMEOUT.code,_(y.CONNECT_TIMEOUT)])},R.prototype._schedule_message=function(e){this._msg_queue.unshift(e),this.connected&&this._process_queue()},R.prototype.store=function(e,t){var r={type:t.type,messageIdentifier:t.messageIdentifier,version:1};switch(t.type){case o:t.pubRecReceived&&(r.pubRecReceived=!0),r.payloadMessage={};for(var i="",s=t.payloadMessage.payloadBytes,a=0;a<s.length;a++)s[a]<=15?i=i+"0"+s[a].toString(16):i+=s[a].toString(16);r.payloadMessage.payloadHex=i,r.payloadMessage.qos=t.payloadMessage.qos,r.payloadMessage.destinationName=t.payloadMessage.destinationName,t.payloadMessage.duplicate&&(r.payloadMessage.duplicate=!0),t.payloadMessage.retained&&(r.payloadMessage.retained=!0),0===e.indexOf("Sent:")&&(void 0===t.sequence&&(t.sequence=++this._sequence),r.sequence=t.sequence);break;default:throw Error(_(y.INVALID_STORED_DATA,[e+this._localKey+t.messageIdentifier,r]))}n.setItem(e+this._localKey+t.messageIdentifier,JSON.stringify(r))},R.prototype.restore=function(e){var t=n.getItem(e),r=JSON.parse(t),i=new M(r.type,r);switch(r.type){case o:for(var s=r.payloadMessage.payloadHex,a=new ArrayBuffer(s.length/2),u=new Uint8Array(a),c=0;s.length>=2;){var f=parseInt(s.substring(0,2),16);s=s.substring(2,s.length),u[c++]=f}var l=new L(u);l.qos=r.payloadMessage.qos,l.destinationName=r.payloadMessage.destinationName,r.payloadMessage.duplicate&&(l.duplicate=!0),r.payloadMessage.retained&&(l.retained=!0),i.payloadMessage=l;break;default:throw Error(_(y.INVALID_STORED_DATA,[e,t]))}0===e.indexOf("Sent:"+this._localKey)?(i.payloadMessage.duplicate=!0,this._sentMessages[i.messageIdentifier]=i):0===e.indexOf("Received:"+this._localKey)&&(this._receivedMessages[i.messageIdentifier]=i)},R.prototype._process_queue=function(){for(var e=null;e=this._msg_queue.pop();)this._socket_send(e),this._notify_msg_sent[e]&&(this._notify_msg_sent[e](),delete this._notify_msg_sent[e])},R.prototype._requires_ack=function(e){var t=Object.keys(this._sentMessages).length;if(t>this.maxMessageIdentifier)throw Error("Too many messages:"+t);for(;void 0!==this._sentMessages[this._message_identifier];)this._message_identifier++;e.messageIdentifier=this._message_identifier,this._sentMessages[e.messageIdentifier]=e,e.type===o&&this.store("Sent:",e),this._message_identifier===this.maxMessageIdentifier&&(this._message_identifier=1)},R.prototype._on_socket_open=function(){var e=new M(r,this.connectOptions);e.clientId=this.clientId,this._socket_send(e)},R.prototype._on_socket_message=function(e){this._trace("Client._on_socket_message",e.data);for(var t=this._deframeMessages(e.data),n=0;n<t.length;n+=1)this._handleMessage(t[n])},R.prototype._deframeMessages=function(e){var t=new Uint8Array(e),n=[];if(this.receiveBuffer){var r=new Uint8Array(this.receiveBuffer.length+t.length);r.set(this.receiveBuffer),r.set(t,this.receiveBuffer.length),t=r,delete this.receiveBuffer}try{for(var i=0;i<t.length;){var o=A(t,i),s=o[0];if(i=o[1],null===s)break;n.push(s)}i<t.length&&(this.receiveBuffer=t.subarray(i))}catch(e){var a="undefined"==e.hasOwnProperty("stack")?e.stack.toString():"No Error Stack Available";return void this._disconnected(y.INTERNAL_ERROR.code,_(y.INTERNAL_ERROR,[e.message,a]))}return n},R.prototype._handleMessage=function(e){this._trace("Client._handleMessage",e);try{switch(e.type){case i:if(this._connectTimeout.cancel(),this._reconnectTimeout&&this._reconnectTimeout.cancel(),this.connectOptions.cleanSession){for(var t in this._sentMessages){var r=this._sentMessages[t];n.removeItem("Sent:"+this._localKey+r.messageIdentifier)}for(var t in this._sentMessages={},this._receivedMessages){var f=this._receivedMessages[t];n.removeItem("Received:"+this._localKey+f.messageIdentifier)}this._receivedMessages={}}if(0!==e.returnCode){this._disconnected(y.CONNACK_RETURNCODE.code,_(y.CONNACK_RETURNCODE,[e.returnCode,w[e.returnCode]]));break}this.connected=!0,this.connectOptions.uris&&(this.hostIndex=this.connectOptions.uris.length);var d=[];for(var p in this._sentMessages)this._sentMessages.hasOwnProperty(p)&&d.push(this._sentMessages[p]);if(this._buffered_msg_queue.length>0)for(var m=null;m=this._buffered_msg_queue.pop();)d.push(m),this.onMessageDelivered&&(this._notify_msg_sent[m]=this.onMessageDelivered(m.payloadMessage));d=d.sort((function(e,t){return e.sequence-t.sequence}));for(var b=0,S=d.length;b<S;b++)if((r=d[b]).type==o&&r.pubRecReceived){var E=new M(u,{messageIdentifier:r.messageIdentifier});this._schedule_message(E)}else this._schedule_message(r);this.connectOptions.onSuccess&&this.connectOptions.onSuccess({invocationContext:this.connectOptions.invocationContext});var A=!1;this._reconnecting&&(A=!0,this._reconnectInterval=1,this._reconnecting=!1),this._connected(A,this._wsuri),this._process_queue();break;case o:this._receivePublish(e);break;case s:(r=this._sentMessages[e.messageIdentifier])&&(delete this._sentMessages[e.messageIdentifier],n.removeItem("Sent:"+this._localKey+e.messageIdentifier),this.onMessageDelivered&&this.onMessageDelivered(r.payloadMessage));break;case a:(r=this._sentMessages[e.messageIdentifier])&&(r.pubRecReceived=!0,E=new M(u,{messageIdentifier:e.messageIdentifier}),this.store("Sent:",r),this._schedule_message(E));break;case u:f=this._receivedMessages[e.messageIdentifier],n.removeItem("Received:"+this._localKey+e.messageIdentifier),f&&(this._receiveMessage(f),delete this._receivedMessages[e.messageIdentifier]);var I=new M(c,{messageIdentifier:e.messageIdentifier});this._schedule_message(I);break;case c:r=this._sentMessages[e.messageIdentifier],delete this._sentMessages[e.messageIdentifier],n.removeItem("Sent:"+this._localKey+e.messageIdentifier),this.onMessageDelivered&&this.onMessageDelivered(r.payloadMessage);break;case l:(r=this._sentMessages[e.messageIdentifier])&&(r.timeOut&&r.timeOut.cancel(),128===e.returnCode[0]?r.onFailure&&r.onFailure(e.returnCode):r.onSuccess&&r.onSuccess(e.returnCode),delete this._sentMessages[e.messageIdentifier]);break;case h:(r=this._sentMessages[e.messageIdentifier])&&(r.timeOut&&r.timeOut.cancel(),r.callback&&r.callback(),delete this._sentMessages[e.messageIdentifier]);break;case v:this.sendPinger.reset();break;case g:this._disconnected(y.INVALID_MQTT_MESSAGE_TYPE.code,_(y.INVALID_MQTT_MESSAGE_TYPE,[e.type]));break;default:this._disconnected(y.INVALID_MQTT_MESSAGE_TYPE.code,_(y.INVALID_MQTT_MESSAGE_TYPE,[e.type]))}}catch(e){var k="undefined"==e.hasOwnProperty("stack")?e.stack.toString():"No Error Stack Available";return void this._disconnected(y.INTERNAL_ERROR.code,_(y.INTERNAL_ERROR,[e.message,k]))}},R.prototype._on_socket_error=function(e){this._reconnecting||this._disconnected(y.SOCKET_ERROR.code,_(y.SOCKET_ERROR,[e.data]))},R.prototype._on_socket_close=function(){this._reconnecting||this._disconnected(y.SOCKET_CLOSE.code,_(y.SOCKET_CLOSE))},R.prototype._socket_send=function(e){if(1==e.type){var t=this._traceMask(e,"password");this._trace("Client._socket_send",t)}else this._trace("Client._socket_send",e);this.socket.send(e.encode()),this.sendPinger.reset()},R.prototype._receivePublish=function(e){switch(e.payloadMessage.qos){case"undefined":case 0:this._receiveMessage(e);break;case 1:var t=new M(s,{messageIdentifier:e.messageIdentifier});this._schedule_message(t),this._receiveMessage(e);break;case 2:this._receivedMessages[e.messageIdentifier]=e,this.store("Received:",e);var n=new M(a,{messageIdentifier:e.messageIdentifier});this._schedule_message(n);break;default:throw Error("Invaild qos="+e.payloadMessage.qos)}},R.prototype._receiveMessage=function(e){this.onMessageArrived&&this.onMessageArrived(e.payloadMessage)},R.prototype._connected=function(e,t){this.onConnected&&this.onConnected(e,t)},R.prototype._reconnect=function(){this._trace("Client._reconnect"),this.connected||(this._reconnecting=!0,this.sendPinger.cancel(),this.receivePinger.cancel(),this._reconnectInterval<128&&(this._reconnectInterval=2*this._reconnectInterval),this.connectOptions.uris?(this.hostIndex=0,this._doConnect(this.connectOptions.uris[0])):this._doConnect(this.uri))},R.prototype._disconnected=function(e,t){if(this._trace("Client._disconnected",e,t),void 0!==e&&this._reconnecting)this._reconnectTimeout=new N(this,this._reconnectInterval,this._reconnect);else if(this.sendPinger.cancel(),this.receivePinger.cancel(),this._connectTimeout&&(this._connectTimeout.cancel(),this._connectTimeout=null),this._msg_queue=[],this._buffered_msg_queue=[],this._notify_msg_sent={},this.socket&&(this.socket.onopen=null,this.socket.onmessage=null,this.socket.onerror=null,this.socket.onclose=null,1===this.socket.readyState&&this.socket.close(),delete this.socket),this.connectOptions.uris&&this.hostIndex<this.connectOptions.uris.length-1)this.hostIndex++,this._doConnect(this.connectOptions.uris[this.hostIndex]);else if(void 0===e&&(e=y.OK.code,t=_(y.OK)),this.connected){if(this.connected=!1,this.onConnectionLost&&this.onConnectionLost({errorCode:e,errorMessage:t,reconnect:this.connectOptions.reconnect,uri:this._wsuri}),e!==y.OK.code&&this.connectOptions.reconnect)return this._reconnectInterval=1,void this._reconnect()}else 4===this.connectOptions.mqttVersion&&!1===this.connectOptions.mqttVersionExplicit?(this._trace("Failed to connect V4, dropping back to V3"),this.connectOptions.mqttVersion=3,this.connectOptions.uris?(this.hostIndex=0,this._doConnect(this.connectOptions.uris[0])):this._doConnect(this.uri)):this.connectOptions.onFailure&&this.connectOptions.onFailure({invocationContext:this.connectOptions.invocationContext,errorCode:e,errorMessage:t})},R.prototype._trace=function(){if(this.traceFunction){var e=Array.prototype.slice.call(arguments);for(var t in e)void 0!==e[t]&&e.splice(t,1,JSON.stringify(e[t]));var n=e.join("");this.traceFunction({severity:"Debug",message:n})}if(null!==this._traceBuffer){t=0;for(var r=arguments.length;t<r;t++)this._traceBuffer.length==this._MAX_TRACE_ENTRIES&&this._traceBuffer.shift(),0===t||void 0===arguments[t]?this._traceBuffer.push(arguments[t]):this._traceBuffer.push(" "+JSON.stringify(arguments[t]))}},R.prototype._traceMask=function(e,t){var n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]=r==t?"******":e[r]);return n};var L=function(e){var t,n;if(!("string"==typeof e||e instanceof ArrayBuffer||ArrayBuffer.isView(e)&&!(e instanceof DataView)))throw _(y.INVALID_ARGUMENT,[e,"newPayload"]);t=e;var r=0,i=!1,o=!1;Object.defineProperties(this,{payloadString:{enumerable:!0,get:function(){return"string"==typeof t?t:T(t,0,t.length)}},payloadBytes:{enumerable:!0,get:function(){if("string"==typeof t){var e=new ArrayBuffer(x(t)),n=new Uint8Array(e);return C(t,n,0),n}return t}},destinationName:{enumerable:!0,get:function(){return n},set:function(e){if("string"!=typeof e)throw new Error(_(y.INVALID_ARGUMENT,[e,"newDestinationName"]));n=e}},qos:{enumerable:!0,get:function(){return r},set:function(e){if(0!==e&&1!==e&&2!==e)throw new Error("Invalid argument:"+e);r=e}},retained:{enumerable:!0,get:function(){return i},set:function(e){if("boolean"!=typeof e)throw new Error(_(y.INVALID_ARGUMENT,[e,"newRetained"]));i=e}},topic:{enumerable:!0,get:function(){return n},set:function(e){n=e}},duplicate:{enumerable:!0,get:function(){return o},set:function(e){o=e}}})};return{Client:function(e,t,n,r){var i;if("string"!=typeof e)throw new Error(_(y.INVALID_TYPE,[typeof e,"host"]));if(2==arguments.length){r=t;var o=(i=e).match(/^(wss?):\/\/((\[(.+)\])|([^\/]+?))(:(\d+))?(\/.*)$/);if(!o)throw new Error(_(y.INVALID_ARGUMENT,[e,"host"]));e=o[4]||o[2],t=parseInt(o[7]),n=o[8]}else{if(3==arguments.length&&(r=n,n="/mqtt"),"number"!=typeof t||t<0)throw new Error(_(y.INVALID_TYPE,[typeof t,"port"]));if("string"!=typeof n)throw new Error(_(y.INVALID_TYPE,[typeof n,"path"]));var s=-1!==e.indexOf(":")&&"["!==e.slice(0,1)&&"]"!==e.slice(-1);i="ws://"+(s?"["+e+"]":e)+":"+t+n}for(var a=0,u=0;u<r.length;u++){var c=r.charCodeAt(u);55296<=c&&c<=56319&&u++,a++}if("string"!=typeof r||a>65535)throw new Error(_(y.INVALID_ARGUMENT,[r,"clientId"]));var f=new R(i,e,t,n,r);Object.defineProperties(this,{host:{get:function(){return e},set:function(){throw new Error(_(y.UNSUPPORTED_OPERATION))}},port:{get:function(){return t},set:function(){throw new Error(_(y.UNSUPPORTED_OPERATION))}},path:{get:function(){return n},set:function(){throw new Error(_(y.UNSUPPORTED_OPERATION))}},uri:{get:function(){return i},set:function(){throw new Error(_(y.UNSUPPORTED_OPERATION))}},clientId:{get:function(){return f.clientId},set:function(){throw new Error(_(y.UNSUPPORTED_OPERATION))}},onConnected:{get:function(){return f.onConnected},set:function(e){if("function"!=typeof e)throw new Error(_(y.INVALID_TYPE,[typeof e,"onConnected"]));f.onConnected=e}},disconnectedPublishing:{get:function(){return f.disconnectedPublishing},set:function(e){f.disconnectedPublishing=e}},disconnectedBufferSize:{get:function(){return f.disconnectedBufferSize},set:function(e){f.disconnectedBufferSize=e}},onConnectionLost:{get:function(){return f.onConnectionLost},set:function(e){if("function"!=typeof e)throw new Error(_(y.INVALID_TYPE,[typeof e,"onConnectionLost"]));f.onConnectionLost=e}},onMessageDelivered:{get:function(){return f.onMessageDelivered},set:function(e){if("function"!=typeof e)throw new Error(_(y.INVALID_TYPE,[typeof e,"onMessageDelivered"]));f.onMessageDelivered=e}},onMessageArrived:{get:function(){return f.onMessageArrived},set:function(e){if("function"!=typeof e)throw new Error(_(y.INVALID_TYPE,[typeof e,"onMessageArrived"]));f.onMessageArrived=e}},trace:{get:function(){return f.traceFunction},set:function(e){if("function"!=typeof e)throw new Error(_(y.INVALID_TYPE,[typeof e,"onTrace"]));f.traceFunction=e}}}),this.connect=function(e){if(m(e=e||{},{timeout:"number",userName:"string",password:"string",willMessage:"object",keepAliveInterval:"number",cleanSession:"boolean",useSSL:"boolean",invocationContext:"object",onSuccess:"function",onFailure:"function",hosts:"object",ports:"object",reconnect:"boolean",mqttVersion:"number",mqttVersionExplicit:"boolean",uris:"object"}),void 0===e.keepAliveInterval&&(e.keepAliveInterval=60),e.mqttVersion>4||e.mqttVersion<3)throw new Error(_(y.INVALID_ARGUMENT,[e.mqttVersion,"connectOptions.mqttVersion"]));if(void 0===e.mqttVersion?(e.mqttVersionExplicit=!1,e.mqttVersion=4):e.mqttVersionExplicit=!0,void 0!==e.password&&void 0===e.userName)throw new Error(_(y.INVALID_ARGUMENT,[e.password,"connectOptions.password"]));if(e.willMessage){if(!(e.willMessage instanceof L))throw new Error(_(y.INVALID_TYPE,[e.willMessage,"connectOptions.willMessage"]));if(e.willMessage.stringPayload=null,void 0===e.willMessage.destinationName)throw new Error(_(y.INVALID_TYPE,[typeof e.willMessage.destinationName,"connectOptions.willMessage.destinationName"]))}if(void 0===e.cleanSession&&(e.cleanSession=!0),e.hosts){if(!(e.hosts instanceof Array))throw new Error(_(y.INVALID_ARGUMENT,[e.hosts,"connectOptions.hosts"]));if(e.hosts.length<1)throw new Error(_(y.INVALID_ARGUMENT,[e.hosts,"connectOptions.hosts"]));for(var t=!1,r=0;r<e.hosts.length;r++){if("string"!=typeof e.hosts[r])throw new Error(_(y.INVALID_TYPE,[typeof e.hosts[r],"connectOptions.hosts["+r+"]"]));if(/^(wss?):\/\/((\[(.+)\])|([^\/]+?))(:(\d+))?(\/.*)$/.test(e.hosts[r])){if(0===r)t=!0;else if(!t)throw new Error(_(y.INVALID_ARGUMENT,[e.hosts[r],"connectOptions.hosts["+r+"]"]))}else if(t)throw new Error(_(y.INVALID_ARGUMENT,[e.hosts[r],"connectOptions.hosts["+r+"]"]))}if(t)e.uris=e.hosts;else{if(!e.ports)throw new Error(_(y.INVALID_ARGUMENT,[e.ports,"connectOptions.ports"]));if(!(e.ports instanceof Array))throw new Error(_(y.INVALID_ARGUMENT,[e.ports,"connectOptions.ports"]));if(e.hosts.length!==e.ports.length)throw new Error(_(y.INVALID_ARGUMENT,[e.ports,"connectOptions.ports"]));for(e.uris=[],r=0;r<e.hosts.length;r++){if("number"!=typeof e.ports[r]||e.ports[r]<0)throw new Error(_(y.INVALID_TYPE,[typeof e.ports[r],"connectOptions.ports["+r+"]"]));var o=e.hosts[r],s=e.ports[r],a=-1!==o.indexOf(":");i="ws://"+(a?"["+o+"]":o)+":"+s+n,e.uris.push(i)}}}f.connect(e)},this.subscribe=function(e,t){if("string"!=typeof e&&e.constructor!==Array)throw new Error("Invalid argument:"+e);if(m(t=t||{},{qos:"number",invocationContext:"object",onSuccess:"function",onFailure:"function",timeout:"number"}),t.timeout&&!t.onFailure)throw new Error("subscribeOptions.timeout specified with no onFailure callback.");if(void 0!==t.qos&&0!==t.qos&&1!==t.qos&&2!==t.qos)throw new Error(_(y.INVALID_ARGUMENT,[t.qos,"subscribeOptions.qos"]));f.subscribe(e,t)},this.unsubscribe=function(e,t){if("string"!=typeof e&&e.constructor!==Array)throw new Error("Invalid argument:"+e);if(m(t=t||{},{invocationContext:"object",onSuccess:"function",onFailure:"function",timeout:"number"}),t.timeout&&!t.onFailure)throw new Error("unsubscribeOptions.timeout specified with no onFailure callback.");f.unsubscribe(e,t)},this.send=function(e,t,n,r){var i;if(0===arguments.length)throw new Error("Invalid argument.length");if(1==arguments.length){if(!(e instanceof L)&&"string"!=typeof e)throw new Error("Invalid argument:"+typeof e);if(void 0===(i=e).destinationName)throw new Error(_(y.INVALID_ARGUMENT,[i.destinationName,"Message.destinationName"]));f.send(i)}else(i=new L(t)).destinationName=e,arguments.length>=3&&(i.qos=n),arguments.length>=4&&(i.retained=r),f.send(i)},this.publish=function(e,t,n,r){var i;if(0===arguments.length)throw new Error("Invalid argument.length");if(1==arguments.length){if(!(e instanceof L)&&"string"!=typeof e)throw new Error("Invalid argument:"+typeof e);if(void 0===(i=e).destinationName)throw new Error(_(y.INVALID_ARGUMENT,[i.destinationName,"Message.destinationName"]));f.send(i)}else(i=new L(t)).destinationName=e,arguments.length>=3&&(i.qos=n),arguments.length>=4&&(i.retained=r),f.send(i)},this.disconnect=function(){f.disconnect()},this.getTraceLog=function(){return f.getTraceLog()},this.startTrace=function(){f.startTrace()},this.stopTrace=function(){f.stopTrace()},this.isConnected=function(){return f.connected}},Message:L}}(void 0!==t?t:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},e.exports=n()}).call(this,n(31))},function(e,t,n){"use strict";var r,i,o=n(486);function s(e,t,n){if(e._observer)a(e._observer,t,n);else if(e._observers){var r=[];e._observers.forEach((function(e){r.push(e)})),r.forEach((function(e){a(e,t,n)}))}}function a(e,t,n){if(!e.closed)switch(t){case"next":return e.next(n);case"error":return e.error(n);case"complete":return e.complete(n)}}function u(e){return e._observer||e._observers&&e._observers.size>0}function c(e){var t=this;this._observer=null,this._observers=null,this._observable=new o((function(n){return function(e,t){!u(e)&&t&&t.start&&t.start()}(t,e),function(e,t){e._observers?e._observers.add(t):e._observer?(e._observers=new Set,e._observers.add(e._observer),e._observers.add(t),e._observer=null):e._observer=t}(t,n),function(){!function(e,t){e._observers?e._observers.delete(t):e._observer===t&&(e._observer=null)}(t,n),function(e,t){!u(e)&&t&&t.pause&&t.pause()}(t,e)}}))}r=c.prototype,i={get observable(){return this._observable},get observed(){return u(this)},next:function(e){s(this,"next",e)},error:function(e){s(this,"error",e)},complete:function(e){s(this,"complete",e)}},Object.keys(i).forEach((function(e){var t=Object.getOwnPropertyDescriptor(i,e);t.enumerable=!1,Object.defineProperty(r,e,t)})),e.exports=c},function(e,t,n){"use strict";n.d(t,"a",(function(){return Nt}));var r=n(44),i=n(33),o=n(88),s=n(19);function a(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];throw Error("[Immer] minified error nr: "+e+(n.length?" "+n.map((function(e){return"'"+e+"'"})).join(","):"")+". Find the full error at: https://bit.ly/3cXEKWf")}function u(e){return!!e&&!!e[Z]}function c(e){return!!e&&(function(e){if(!e||"object"!=typeof e)return!1;var t=Object.getPrototypeOf(e);return!t||t===Object.prototype}(e)||Array.isArray(e)||!!e[J]||!!e.constructor[J]||g(e)||m(e))}function f(e,t,n){void 0===n&&(n=!1),0===l(e)?(n?Object.keys:X)(e).forEach((function(r){n&&"symbol"==typeof r||t(r,e[r],e)})):e.forEach((function(n,r){return t(r,n,e)}))}function l(e){var t=e[Z];return t?t.i>3?t.i-4:t.i:Array.isArray(e)?1:g(e)?2:m(e)?3:0}function d(e,t){return 2===l(e)?e.has(t):Object.prototype.hasOwnProperty.call(e,t)}function h(e,t){return 2===l(e)?e.get(t):e[t]}function p(e,t,n){var r=l(e);2===r?e.set(t,n):3===r?(e.delete(t),e.add(n)):e[t]=n}function v(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t}function g(e){return G&&e instanceof Map}function m(e){return W&&e instanceof Set}function b(e){return e.o||e.t}function y(e){if(Array.isArray(e))return Array.prototype.slice.call(e);var t=Q(e);delete t[Z];for(var n=X(t),r=0;r<n.length;r++){var i=n[r],o=t[i];!1===o.writable&&(o.writable=!0,o.configurable=!0),(o.get||o.set)&&(t[i]={configurable:!0,writable:!0,enumerable:o.enumerable,value:e[i]})}return Object.create(Object.getPrototypeOf(e),t)}function w(e,t){return void 0===t&&(t=!1),S(e)||u(e)||!c(e)||(l(e)>1&&(e.set=e.add=e.clear=e.delete=_),Object.freeze(e),t&&f(e,(function(e,t){return w(t,!0)}),!0)),e}function _(){a(2)}function S(e){return null==e||"object"!=typeof e||Object.isFrozen(e)}function E(e){var t=ee[e];return t||a(18,e),t}function M(e,t){ee[e]||(ee[e]=t)}function A(){return H}function I(e,t){t&&(E("Patches"),e.u=[],e.s=[],e.v=t)}function k(e){O(e),e.p.forEach(C),e.p=null}function O(e){e===H&&(H=e.l)}function x(e){return H={p:[],l:H,h:e,m:!0,_:0}}function C(e){var t=e[Z];0===t.i||1===t.i?t.j():t.g=!0}function T(e,t){t._=t.p.length;var n=t.p[0],r=void 0!==e&&e!==n;return t.h.O||E("ES5").S(t,e,r),r?(n[Z].P&&(k(t),a(4)),c(e)&&(e=P(t,e),t.l||R(t,e)),t.u&&E("Patches").M(n[Z],e,t.u,t.s)):e=P(t,n,[]),k(t),t.u&&t.v(t.u,t.s),e!==Y?e:void 0}function P(e,t,n){if(S(t))return t;var r=t[Z];if(!r)return f(t,(function(i,o){return N(e,r,t,i,o,n)}),!0),t;if(r.A!==e)return t;if(!r.P)return R(e,r.t,!0),r.t;if(!r.I){r.I=!0,r.A._--;var i=4===r.i||5===r.i?r.o=y(r.k):r.o;f(3===r.i?new Set(i):i,(function(t,o){return N(e,r,i,t,o,n)})),R(e,i,!1),n&&e.u&&E("Patches").R(r,n,e.u,e.s)}return r.o}function N(e,t,n,r,i,o){if(u(i)){var s=P(e,i,o&&t&&3!==t.i&&!d(t.D,r)?o.concat(r):void 0);if(p(n,r,s),!u(s))return;e.m=!1}if(c(i)&&!S(i)){if(!e.h.N&&e._<1)return;P(e,i),t&&t.A.l||R(e,i)}}function R(e,t,n){void 0===n&&(n=!1),e.h.N&&e.m&&w(t,n)}function L(e,t){var n=e[Z];return(n?b(n):e)[t]}function j(e,t){if(t in e)for(var n=Object.getPrototypeOf(e);n;){var r=Object.getOwnPropertyDescriptor(n,t);if(r)return r;n=Object.getPrototypeOf(n)}}function D(e){e.P||(e.P=!0,e.l&&D(e.l))}function U(e){e.o||(e.o=y(e.t))}function B(e,t,n){var r=g(t)?E("MapSet").T(t,n):m(t)?E("MapSet").F(t,n):e.O?function(e,t){var n=Array.isArray(e),r={i:n?1:0,A:t?t.A:A(),P:!1,I:!1,D:{},l:t,t:e,k:null,o:null,j:null,C:!1},i=r,o=te;n&&(i=[r],o=ne);var s=Proxy.revocable(i,o),a=s.revoke,u=s.proxy;return r.k=u,r.j=a,u}(t,n):E("ES5").J(t,n);return(n?n.A:A()).p.push(r),r}function F(e){return u(e)||a(22,e),function e(t){if(!c(t))return t;var n,r=t[Z],i=l(t);if(r){if(!r.P&&(r.i<4||!E("ES5").K(r)))return r.t;r.I=!0,n=z(t,i),r.I=!1}else n=z(t,i);return f(n,(function(t,i){r&&h(r.t,t)===i||p(n,t,e(i))})),3===i?new Set(n):n}(e)}function z(e,t){switch(t){case 2:return new Map(e);case 3:return Array.from(e)}return y(e)}function q(){function e(t){if(!c(t))return t;if(Array.isArray(t))return t.map(e);if(g(t))return new Map(Array.from(t.entries()).map((function(t){return[t[0],e(t[1])]})));if(m(t))return new Set(Array.from(t).map(e));var n=Object.create(Object.getPrototypeOf(t));for(var r in t)n[r]=e(t[r]);return n}function t(t){return u(t)?e(t):t}var n="add";M("Patches",{$:function(t,r){return r.forEach((function(r){for(var i=r.path,o=r.op,s=t,u=0;u<i.length-1;u++){var c=l(s),f=i[u];0!==c&&1!==c||"__proto__"!==f&&"constructor"!==f||a(24),"function"==typeof s&&"prototype"===f&&a(24),"object"!=typeof(s=h(s,f))&&a(15,i.join("/"))}var d=l(s),p=e(r.value),v=i[i.length-1];switch(o){case"replace":switch(d){case 2:return s.set(v,p);case 3:a(16);default:return s[v]=p}case n:switch(d){case 1:return s.splice(v,0,p);case 2:return s.set(v,p);case 3:return s.add(p);default:return s[v]=p}case"remove":switch(d){case 1:return s.splice(v,1);case 2:return s.delete(v);case 3:return s.delete(r.value);default:return delete s[v]}default:a(17,o)}})),t},R:function(e,r,i,o){switch(e.i){case 0:case 4:case 2:return function(e,r,i,o){var s=e.t,a=e.o;f(e.D,(function(e,u){var c=h(s,e),f=h(a,e),l=u?d(s,e)?"replace":n:"remove";if(c!==f||"replace"!==l){var p=r.concat(e);i.push("remove"===l?{op:l,path:p}:{op:l,path:p,value:f}),o.push(l===n?{op:"remove",path:p}:"remove"===l?{op:n,path:p,value:t(c)}:{op:"replace",path:p,value:t(c)})}}))}(e,r,i,o);case 5:case 1:return function(e,r,i,o){var s=e.t,a=e.D,u=e.o;if(u.length<s.length){var c=[u,s];s=c[0],u=c[1];var f=[o,i];i=f[0],o=f[1]}for(var l=0;l<s.length;l++)if(a[l]&&u[l]!==s[l]){var d=r.concat([l]);i.push({op:"replace",path:d,value:t(u[l])}),o.push({op:"replace",path:d,value:t(s[l])})}for(var h=s.length;h<u.length;h++){var p=r.concat([h]);i.push({op:n,path:p,value:t(u[h])})}s.length<u.length&&o.push({op:"replace",path:r.concat(["length"]),value:s.length})}(e,r,i,o);case 3:return function(e,t,r,i){var o=e.t,s=e.o,a=0;o.forEach((function(e){if(!s.has(e)){var o=t.concat([a]);r.push({op:"remove",path:o,value:e}),i.unshift({op:n,path:o,value:e})}a++})),a=0,s.forEach((function(e){if(!o.has(e)){var s=t.concat([a]);r.push({op:n,path:s,value:e}),i.unshift({op:"remove",path:s,value:e})}a++}))}(e,r,i,o)}},M:function(e,t,n,r){n.push({op:"replace",path:[],value:t}),r.push({op:"replace",path:[],value:e.t})}})}var K,H,V="undefined"!=typeof Symbol&&"symbol"==typeof Symbol("x"),G="undefined"!=typeof Map,W="undefined"!=typeof Set,$="undefined"!=typeof Proxy&&void 0!==Proxy.revocable&&"undefined"!=typeof Reflect,Y=V?Symbol.for("immer-nothing"):((K={})["immer-nothing"]=!0,K),J=V?Symbol.for("immer-draftable"):"__$immer_draftable",Z=V?Symbol.for("immer-state"):"__$immer_state",X=("undefined"!=typeof Symbol&&Symbol.iterator,"undefined"!=typeof Reflect&&Reflect.ownKeys?Reflect.ownKeys:void 0!==Object.getOwnPropertySymbols?function(e){return Object.getOwnPropertyNames(e).concat(Object.getOwnPropertySymbols(e))}:Object.getOwnPropertyNames),Q=Object.getOwnPropertyDescriptors||function(e){var t={};return X(e).forEach((function(n){t[n]=Object.getOwnPropertyDescriptor(e,n)})),t},ee={},te={get:function(e,t){if(t===Z)return e;var n=b(e);if(!d(n,t))return function(e,t,n){var r,i=j(t,n);return i?"value"in i?i.value:null===(r=i.get)||void 0===r?void 0:r.call(e.k):void 0}(e,n,t);var r=n[t];return e.I||!c(r)?r:r===L(e.t,t)?(U(e),e.o[t]=B(e.A.h,r,e)):r},has:function(e,t){return t in b(e)},ownKeys:function(e){return Reflect.ownKeys(b(e))},set:function(e,t,n){var r=j(b(e),t);if(null==r?void 0:r.set)return r.set.call(e.k,n),!0;if(!e.P){var i=L(b(e),t),o=null==i?void 0:i[Z];if(o&&o.t===n)return e.o[t]=n,e.D[t]=!1,!0;if(v(n,i)&&(void 0!==n||d(e.t,t)))return!0;U(e),D(e)}return e.o[t]=n,e.D[t]=!0,!0},deleteProperty:function(e,t){return void 0!==L(e.t,t)||t in e.t?(e.D[t]=!1,U(e),D(e)):delete e.D[t],e.o&&delete e.o[t],!0},getOwnPropertyDescriptor:function(e,t){var n=b(e),r=Reflect.getOwnPropertyDescriptor(n,t);return r?{writable:!0,configurable:1!==e.i||"length"!==t,enumerable:r.enumerable,value:n[t]}:r},defineProperty:function(){a(11)},getPrototypeOf:function(e){return Object.getPrototypeOf(e.t)},setPrototypeOf:function(){a(12)}},ne={};f(te,(function(e,t){ne[e]=function(){return arguments[0]=arguments[0][0],t.apply(this,arguments)}})),ne.deleteProperty=function(e,t){return te.deleteProperty.call(this,e[0],t)},ne.set=function(e,t,n){return te.set.call(this,e[0],t,n,e[0])};var re,ie=new(function(){function e(e){this.O=$,this.N=!0,"boolean"==typeof(null==e?void 0:e.useProxies)&&this.setUseProxies(e.useProxies),"boolean"==typeof(null==e?void 0:e.autoFreeze)&&this.setAutoFreeze(e.autoFreeze),this.produce=this.produce.bind(this),this.produceWithPatches=this.produceWithPatches.bind(this)}var t=e.prototype;return t.produce=function(e,t,n){if("function"==typeof e&&"function"!=typeof t){var r=t;t=e;var i=this;return function(e){var n=this;void 0===e&&(e=r);for(var o=arguments.length,s=Array(o>1?o-1:0),a=1;a<o;a++)s[a-1]=arguments[a];return i.produce(e,(function(e){var r;return(r=t).call.apply(r,[n,e].concat(s))}))}}var o;if("function"!=typeof t&&a(6),void 0!==n&&"function"!=typeof n&&a(7),c(e)){var s=x(this),u=B(this,e,void 0),f=!0;try{o=t(u),f=!1}finally{f?k(s):O(s)}return"undefined"!=typeof Promise&&o instanceof Promise?o.then((function(e){return I(s,n),T(e,s)}),(function(e){throw k(s),e})):(I(s,n),T(o,s))}if(!e||"object"!=typeof e){if((o=t(e))===Y)return;return void 0===o&&(o=e),this.N&&w(o,!0),o}a(21,e)},t.produceWithPatches=function(e,t){var n,r,i=this;return"function"==typeof e?function(t){for(var n=arguments.length,r=Array(n>1?n-1:0),o=1;o<n;o++)r[o-1]=arguments[o];return i.produceWithPatches(t,(function(t){return e.apply(void 0,[t].concat(r))}))}:[this.produce(e,t,(function(e,t){n=e,r=t})),n,r]},t.createDraft=function(e){c(e)||a(8),u(e)&&(e=F(e));var t=x(this),n=B(this,e,void 0);return n[Z].C=!0,O(t),n},t.finishDraft=function(e,t){var n=(e&&e[Z]).A;return I(n,t),T(void 0,n)},t.setAutoFreeze=function(e){this.N=e},t.setUseProxies=function(e){e&&!$&&a(20),this.O=e},t.applyPatches=function(e,t){var n;for(n=t.length-1;n>=0;n--){var r=t[n];if(0===r.path.length&&"replace"===r.op){e=r.value;break}}var i=E("Patches").$;return u(e)?i(e,t):this.produce(e,(function(e){return i(e,t.slice(n+1))}))},e}()),oe=(ie.produce,ie.produceWithPatches.bind(ie),ie.setAutoFreeze.bind(ie)),se=(ie.setUseProxies.bind(ie),ie.applyPatches.bind(ie),ie.createDraft.bind(ie),ie.finishDraft.bind(ie),n(109),n(14)),ae=n(9),ue=n(245),ce=function(){function e(){this._queue=[],this._pending=!1}return e.prototype.isLocked=function(){return this._pending},e.prototype.acquire=function(){var e=this,t=new Promise((function(t){return e._queue.push(t)}));return this._pending||this._dispatchNext(),t},e.prototype.runExclusive=function(e){return this.acquire().then((function(t){var n;try{n=e()}catch(e){throw t(),e}return Promise.resolve(n).then((function(e){return t(),e}),(function(e){throw t(),e}))}))},e.prototype._dispatchNext=function(){this._queue.length>0?(this._pending=!0,this._queue.shift()(this._dispatchNext.bind(this))):this._pending=!1},e}(),fe=n(257),le=n.n(fe),de=n(4),he=n(3),pe=function(){return Object(i.b)().isBrowser&&window.indexedDB||Object(i.c)()&&self.indexedDB?n(495).default:new(0,n(496).AsyncStorageAdapter)},ve=function(){return(ve=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},ge=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},me=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},be=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n},ye=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},we=new r.a("DataStore"),_e=function(){function e(e,t,n,r,i,o){this.schema=e,this.namespaceResolver=t,this.getModelConstructorByModelName=n,this.modelInstanceCreator=r,this.adapter=i,this.sessionId=o,this.adapter=pe(),this.pushStream=new le.a}return e.getNamespace=function(){return{name:he.b,relationships:{},enums:{},models:{},nonModels:{}}},e.prototype.init=function(){return ge(this,void 0,void 0,(function(){var e,t;return me(this,(function(n){switch(n.label){case 0:return void 0===this.initialized?[3,2]:[4,this.initialized];case 1:return n.sent(),[2];case 2:return we.debug("Starting Storage"),this.initialized=new Promise((function(n,r){e=n,t=r})),this.adapter.setUp(this.schema,this.namespaceResolver,this.modelInstanceCreator,this.getModelConstructorByModelName,this.sessionId).then(e,t),[4,this.initialized];case 3:return n.sent(),[2]}}))}))},e.prototype.save=function(e,t,n,r){return ge(this,void 0,void 0,(function(){var i,o=this;return me(this,(function(s){switch(s.label){case 0:return[4,this.init()];case 1:return s.sent(),[4,this.adapter.save(e,t)];case 2:return(i=s.sent()).forEach((function(e){var i,s=ye(e,2),a=s[0],u=s[1];if(u===de.c.UPDATE&&r&&r.length){i={},r.map((function(e){return e.path&&e.path[0]})).forEach((function(e){i[e]=a[e]}));var c=a.id,f=a._version,l=a._lastChangedAt,d=a._deleted;i=ve(ve({},i),{id:c,_version:f,_lastChangedAt:l,_deleted:d})}var h=i||a,p=Object.getPrototypeOf(a).constructor;o.pushStream.next({model:p,opType:u,element:h,mutator:n,condition:ae.a.getPredicates(t,!1)})})),[2,i]}}))}))},e.prototype.delete=function(e,t,n){return ge(this,void 0,void 0,(function(){var r,i,o,s,a=this;return me(this,(function(u){switch(u.label){case 0:return[4,this.init()];case 1:return u.sent(),[4,this.adapter.delete(e,t)];case 2:return s=ye.apply(void 0,[u.sent(),2]),i=s[0],r=s[1],o=new Set(i.map((function(e){return e.id}))),Object(he.s)(e)||Array.isArray(r)||(r=[r]),r.forEach((function(r){var i,s=Object.getPrototypeOf(r).constructor;Object(he.s)(e)||(i=o.has(r.id)?ae.a.getPredicates(t,!1):void 0),a.pushStream.next({model:s,opType:de.c.DELETE,element:r,mutator:n,condition:i})})),[2,[i,r]]}}))}))},e.prototype.query=function(e,t,n){return ge(this,void 0,void 0,(function(){return me(this,(function(r){switch(r.label){case 0:return[4,this.init()];case 1:return r.sent(),[4,this.adapter.query(e,t,n)];case 2:return[2,r.sent()]}}))}))},e.prototype.queryOne=function(e,t){return void 0===t&&(t=de.d.FIRST),ge(this,void 0,void 0,(function(){return me(this,(function(n){switch(n.label){case 0:return[4,this.init()];case 1:return n.sent(),[4,this.adapter.queryOne(e,t)];case 2:return[2,n.sent()]}}))}))},e.prototype.observe=function(e,t,n){var r=!e,i=ae.a.getPredicates(t,!1)||{},o=i.predicates,s=i.type,a=!!o,u=this.pushStream.observable.filter((function(e){var t=e.mutator;return!n||t!==n})).map((function(e){e.mutator;return be(e,["mutator"])}));return r||(u=u.filter((function(t){var n=t.model,r=t.element;return e===n&&(!a||Object(he.y)(r,s,o))}))),u},e.prototype.clear=function(e){return void 0===e&&(e=!0),ge(this,void 0,void 0,(function(){return me(this,(function(t){switch(t.label){case 0:return this.initialized=void 0,[4,this.adapter.clear()];case 1:return t.sent(),e&&this.pushStream.complete(),[2]}}))}))},e.prototype.batchSave=function(e,t,n){return ge(this,void 0,void 0,(function(){var r,i=this;return me(this,(function(o){switch(o.label){case 0:return[4,this.init()];case 1:return o.sent(),[4,this.adapter.batchSave(e,t)];case 2:return(r=o.sent()).forEach((function(t){var r=ye(t,2),o=r[0],s=r[1];i.pushStream.next({model:e,opType:s,element:o,mutator:n,condition:void 0})})),[2,r]}}))}))},e}(),Se=function(){function e(e,t,n,r,i,o){this.mutex=new ce,this.storage=new _e(e,t,n,r,i,o)}return e.prototype.runExclusive=function(e){return this.mutex.runExclusive(e.bind(this,this.storage))},e.prototype.save=function(e,t,n,r){return ge(this,void 0,void 0,(function(){return me(this,(function(i){return[2,this.runExclusive((function(i){return i.save(e,t,n,r)}))]}))}))},e.prototype.delete=function(e,t,n){return ge(this,void 0,void 0,(function(){return me(this,(function(r){return[2,this.runExclusive((function(r){if(Object(he.s)(e)){var i=e;return r.delete(i,t,n)}var o=e;return r.delete(o,t,n)}))]}))}))},e.prototype.query=function(e,t,n){return ge(this,void 0,void 0,(function(){return me(this,(function(r){return[2,this.runExclusive((function(r){return r.query(e,t,n)}))]}))}))},e.prototype.queryOne=function(e,t){return void 0===t&&(t=de.d.FIRST),ge(this,void 0,void 0,(function(){return me(this,(function(n){return[2,this.runExclusive((function(n){return n.queryOne(e,t)}))]}))}))},e.getNamespace=function(){return _e.getNamespace()},e.prototype.observe=function(e,t,n){return this.storage.observe(e,t,n)},e.prototype.clear=function(){return ge(this,void 0,void 0,(function(){return me(this,(function(e){switch(e.label){case 0:return[4,this.storage.clear()];case 1:return e.sent(),[2]}}))}))},e.prototype.batchSave=function(e,t){return this.storage.batchSave(e,t)},e.prototype.init=function(){return ge(this,void 0,void 0,(function(){return me(this,(function(e){return[2,this.storage.init()]}))}))},e}(),Ee=n(34),Me=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},Ae=(new(function(){function e(){}return e.prototype.networkMonitor=function(t){if(Object(i.b)().isNode)return se.a.from([{online:!0}]);var n=Object(i.c)()?self:window;return new se.a((function(t){t.next({online:n.navigator.onLine});var r=function(){return t.next({online:!0})},i=function(){return t.next({online:!1})};return n.addEventListener("online",r),n.addEventListener("offline",i),e._observers.push(t),function(){n.removeEventListener("online",r),n.removeEventListener("offline",i),e._observers=e._observers.filter((function(e){return e!==t}))}}))},e._observerOverride=function(t){var n,r,i=function(n){if(n.closed)return e._observers=e._observers.filter((function(e){return e!==n})),"continue";n.next(t)};try{for(var o=Me(e._observers),s=o.next();!s.done;s=o.next()){i(s.value)}}catch(e){n={error:e}}finally{try{s&&!s.done&&(r=o.return)&&r.call(o)}finally{if(n)throw n.error}}},e._observers=[],e}())).networkMonitor(),Ie=function(){return(Ie=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},ke=(new r.a("DataStore"),function(){function e(){this.connectionStatus={online:!1}}return e.prototype.status=function(){var e=this;if(this.observer)throw new Error("Subscriber already exists");return new se.a((function(t){return e.observer=t,e.subscription=Ae.subscribe((function(n){var r=n.online;e.connectionStatus.online=r;var i=Ie({},e.connectionStatus);t.next(i)})),function(){e.unsubscribe()}}))},e.prototype.unsubscribe=function(){this.subscription&&this.subscription.unsubscribe()},e.prototype.socketDisconnected=function(){var e=this;this.observer&&"function"==typeof this.observer.next&&(this.observer.next({online:!1}),setTimeout((function(){var t=Ie({},e.connectionStatus);e.observer.next(t)}),5e3))},e}()),Oe=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},xe=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},Ce=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},Te=function(){function e(e,t){this.outbox=e,this.ownSymbol=t}return e.prototype.merge=function(e,t){return Oe(this,void 0,void 0,(function(){var n,r,i,o,s;return xe(this,(function(a){switch(a.label){case 0:return[4,this.outbox.getForModel(e,t)];case 1:return r=a.sent(),i=t._deleted,0!==r.length?[3,5]:i?(n=de.c.DELETE,[4,e.delete(t,void 0,this.ownSymbol)]):[3,3];case 2:return a.sent(),[3,5];case 3:return[4,e.save(t,void 0,this.ownSymbol)];case 4:o=Ce.apply(void 0,[a.sent(),1]),s=Ce(o[0],2),n=s[1],a.label=5;case 5:return[2,n]}}))}))},e.prototype.mergePage=function(e,t,n){return Oe(this,void 0,void 0,(function(){return xe(this,(function(r){switch(r.label){case 0:return[4,e.batchSave(t,n,this.ownSymbol)];case 1:return[2,r.sent()]}}))}))},e}(),Pe=n(13),Ne=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},Re=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},Le=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},je=function(){function e(e,t,n,r){this.schema=e,this.namespaceResolver=t,this.MutationEvent=n,this.ownSymbol=r}return e.prototype.enqueue=function(e,t){return Ne(this,void 0,void 0,(function(){var n=this;return Re(this,(function(r){return e.runExclusive((function(e){return Ne(n,void 0,void 0,(function(){var n,r,i,o,s,a,u,c=this;return Re(this,(function(f){switch(f.label){case 0:return n=this.schema.namespaces[he.c].models.MutationEvent,r=ae.a.createFromExisting(n,(function(e){return e.modelId("eq",t.modelId).id("ne",c.inProgressMutationEventId)})),[4,e.query(this.MutationEvent,r)];case 1:return i=Le.apply(void 0,[f.sent(),1]),void 0!==(o=i[0])?[3,3]:[4,e.save(t,void 0,this.ownSymbol)];case 2:return f.sent(),[2];case 3:return s=t.operation,o.operation!==Pe.a.CREATE?[3,8]:s!==Pe.a.DELETE?[3,5]:[4,e.delete(this.MutationEvent,r)];case 4:return f.sent(),[3,7];case 5:return[4,e.save(this.MutationEvent.copyOf(o,(function(e){e.data=t.data})),void 0,this.ownSymbol)];case 6:f.sent(),f.label=7;case 7:return[3,12];case 8:return a=t.condition,u=JSON.parse(a),0!==Object.keys(u).length?[3,10]:[4,e.delete(this.MutationEvent,r)];case 9:f.sent(),f.label=10;case 10:return[4,e.save(t,void 0,this.ownSymbol)];case 11:f.sent(),f.label=12;case 12:return[2]}}))}))})),[2]}))}))},e.prototype.dequeue=function(e){return Ne(this,void 0,void 0,(function(){var t;return Re(this,(function(n){switch(n.label){case 0:return[4,this.peek(e)];case 1:return t=n.sent(),[4,e.delete(t)];case 2:return n.sent(),this.inProgressMutationEventId=void 0,[2,t]}}))}))},e.prototype.peek=function(e){return Ne(this,void 0,void 0,(function(){var t;return Re(this,(function(n){switch(n.label){case 0:return[4,e.queryOne(this.MutationEvent,de.d.FIRST)];case 1:return t=n.sent(),this.inProgressMutationEventId=t?t.id:void 0,[2,t]}}))}))},e.prototype.getForModel=function(e,t){return Ne(this,void 0,void 0,(function(){var n;return Re(this,(function(r){switch(r.label){case 0:return n=this.schema.namespaces[he.c].models.MutationEvent,[4,e.query(this.MutationEvent,ae.a.createFromExisting(n,(function(e){return e.modelId("eq",t.id)})))];case 1:return[2,r.sent()]}}))}))},e.prototype.getModelIds=function(e){return Ne(this,void 0,void 0,(function(){var t,n;return Re(this,(function(r){switch(r.label){case 0:return[4,e.query(this.MutationEvent)];case 1:return t=r.sent(),n=new Set,t.forEach((function(e){var t=e.modelId;return n.add(t)})),[2,n]}}))}))},e}(),De=n(52),Ue=n(514),Be=function(){return(Be=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},Fe=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},ze=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},qe=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n},Ke=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},He=new r.a("DataStore"),Ve=function(){function e(e,t,n,r,i,o,s,a){this.schema=e,this.storage=t,this.userClasses=n,this.outbox=r,this.modelInstanceCreator=i,this.MutationEvent=o,this.conflictHandler=s,this.errorHandler=a,this.typeQuery=new WeakMap,this.processing=!1,this.generateQueries()}return e.prototype.generateQueries=function(){var e=this;Object.values(this.schema.namespaces).forEach((function(t){Object.values(t.models).filter((function(e){return e.syncable})).forEach((function(n){var r=Ke(Object(Pe.b)(t,n,"CREATE"),1)[0],i=Ke(Object(Pe.b)(t,n,"UPDATE"),1)[0],o=Ke(Object(Pe.b)(t,n,"DELETE"),1)[0];e.typeQuery.set(n,[r,i,o])}))}))},e.prototype.isReady=function(){return void 0!==this.observer},e.prototype.start=function(){var e=this;return new se.a((function(t){return e.observer=t,e.resume(),function(){e.pause()}}))},e.prototype.resume=function(){return Fe(this,void 0,void 0,(function(){var e,t,n,r,i,o,s,a,u,c,f,l,d,h,p;return ze(this,(function(v){switch(v.label){case 0:if(this.processing||!this.isReady())return[2];this.processing=!0,t=he.d,v.label=1;case 1:return(n=this.processing)?[4,this.outbox.peek(this.storage)]:[3,3];case 2:n=void 0!==(e=v.sent()),v.label=3;case 3:if(!n)return[3,12];r=e.model,i=e.operation,o=e.data,s=e.condition,a=this.userClasses[r],u=void 0,c=void 0,f=void 0,v.label=4;case 4:return v.trys.push([4,6,,7]),[4,this.jitteredRetry(t,r,i,o,s,a,this.MutationEvent,e)];case 5:return p=Ke.apply(void 0,[v.sent(),3]),u=p[0],c=p[1],f=p[2],[3,7];case 6:return"Offline"===(l=v.sent()).message||"RetryMutation"===l.message?[3,1]:[3,7];case 7:return void 0!==u?[3,9]:(He.debug("done retrying"),[4,this.outbox.dequeue(this.storage)]);case 8:return v.sent(),[3,1];case 9:return d=u.data[c],[4,this.outbox.dequeue(this.storage)];case 10:return v.sent(),[4,this.outbox.peek(this.storage)];case 11:return h=void 0!==v.sent(),this.observer.next({operation:i,modelDefinition:f,model:d,hasMore:h}),[3,1];case 12:return this.pause(),[2]}}))}))},e.prototype.jitteredRetry=function(e,t,n,r,i,o,s,a){return Fe(this,void 0,void 0,(function(){var u=this;return ze(this,(function(c){switch(c.label){case 0:return[4,Object(Ue.b)((function(t,n,r,i,o,s,a){return Fe(u,void 0,void 0,(function(){var u,c,f,l,d,h,p,v,g,m,b,y,w,_,S,E,M,A,I,k,O;return ze(this,(function(x){switch(x.label){case 0:u=Ke(this.createQueryVariables(e,t,n,r,i),5),c=u[0],f=u[1],l=u[2],d=u[3],h=u[4],p={query:c,variables:f},v=0,g=this.opTypeFromTransformerOperation(n),x.label=1;case 1:return x.trys.push([1,3,,13]),[4,De.a.graphql(p)];case 2:return[2,[x.sent(),d,h]];case 3:if(!((m=x.sent()).errors&&m.errors.length>0))return[3,12];if(b=Ke(m.errors,1),"Network Error"===(y=b[0]).message){if(!this.processing)throw new Ue.a("Offline");throw new Error("Network Error")}return"ConflictUnhandled"!==y.errorType?[3,11]:(v++,w=void 0,v>10?(w=de.a,[3,7]):[3,4]);case 4:return x.trys.push([4,6,,7]),[4,this.conflictHandler({modelConstructor:o,localModel:this.modelInstanceCreator(o,f.input),remoteModel:this.modelInstanceCreator(o,y.data),operation:g,attempts:v})];case 5:return w=x.sent(),[3,7];case 6:return _=x.sent(),He.warn("conflict trycatch",_),[3,13];case 7:return w!==de.a?[3,9]:(S=Ke(Object(Pe.b)(this.schema.namespaces[e],h,"GET"),1),E=Ke(S[0],3),M=E[1],A=E[2],[4,De.a.graphql({query:A,variables:{id:f.input.id}})]);case 8:return[2,[x.sent(),M,h]];case 9:return I=this.schema.namespaces[e],k=Object(Pe.d)(I.relationships,h,g,o,w,l,s,this.modelInstanceCreator,a.id),[4,this.storage.save(k)];case 10:throw x.sent(),new Ue.a("RetryMutation");case 11:try{this.errorHandler({localModel:this.modelInstanceCreator(o,f.input),message:y.message,operation:n,errorType:y.errorType,errorInfo:y.errorInfo,remoteModel:y.data?this.modelInstanceCreator(o,y.data):null})}catch(e){He.warn("failed to execute errorHandler",e)}finally{return[2,y.data?[{data:(O={},O[d]=y.data,O)},d,h]:[]]}x.label=12;case 12:return[3,13];case 13:if(p)return[3,1];x.label=14;case 14:return[2]}}))}))}),[t,n,r,i,o,s,a])];case 1:return[2,c.sent()]}}))}))},e.prototype.createQueryVariables=function(e,t,n,r,i){var o=this.schema.namespaces[e].models[t],s=this.typeQuery.get(o),a=Ke(s.find((function(e){return Ke(e,1)[0]===n})),3),u=a[1],c=a[2],f=JSON.parse(r),l=f._version,d=qe(f,["_version"]),h=n===Pe.a.DELETE?{id:d.id}:Object.values(o.fields).filter((function(e){var t=e.name,r=e.type,i=e.association;return Object(de.h)(r)?!(!Object(de.m)(i)||"BELONGS_TO"!==i.connectionType):n!==Pe.a.UPDATE||d.hasOwnProperty(t)})).map((function(e){var t=e.name,n=e.type,r=e.association,i=t,o=d[t];return Object(de.h)(n)&&Object(de.m)(r)&&(i=r.targetName,o=d[i]),[i,o]})).reduce((function(e,t){var n=Ke(t,2),r=n[0],i=n[1];return e[r]=i,e}),{}),p=Be(Be({},h),{_version:l}),v=JSON.parse(i);return[c,Be({input:p},n===Pe.a.CREATE?{}:{condition:Object.keys(v).length>0?v:null}),v,u,o]},e.prototype.opTypeFromTransformerOperation=function(e){switch(e){case Pe.a.CREATE:return de.c.INSERT;case Pe.a.DELETE:return de.c.DELETE;case Pe.a.UPDATE:return de.c.UPDATE;case Pe.a.GET:break;default:Object(he.f)(e)}},e.prototype.pause=function(){this.processing=!1},e}(),Ge=n(154),We=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},$e=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},Ye=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},Je=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},Ze=new r.a("DataStore"),Xe=function(){function e(e,t,n,r){void 0===t&&(t=1e4),void 0===n&&(n=1e3),this.schema=e,this.maxRecordsToSync=t,this.syncPageSize=n,this.syncPredicates=r,this.typeQuery=new WeakMap,this.generateQueries()}return e.prototype.generateQueries=function(){var e=this;Object.values(this.schema.namespaces).forEach((function(t){Object.values(t.models).filter((function(e){return e.syncable})).forEach((function(n){var r=Ye(Object(Pe.b)(t,n,"LIST"),1),i=Ye(r[0]).slice(1);e.typeQuery.set(n,i)}))}))},e.prototype.graphqlFilterFromPredicate=function(e){if(!this.syncPredicates)return null;var t=ae.a.getPredicates(this.syncPredicates.get(e),!1);return t?Object(Pe.h)(t):null},e.prototype.retrievePage=function(e,t,n,r,i){return void 0===r&&(r=null),We(this,void 0,void 0,(function(){var o,s,a,u,c,f,l,d,h;return $e(this,(function(p){switch(p.label){case 0:return o=Ye(this.typeQuery.get(e),2),s=o[0],a=o[1],u={limit:r,nextToken:n,lastSync:t,filter:i},[4,this.jitteredRetry(a,u,s)];case 1:return c=p.sent().data,f=c[s],l=f.items,d=f.nextToken,h=f.startedAt,[2,{nextToken:d,startedAt:h,items:l}]}}))}))},e.prototype.jitteredRetry=function(e,t,n){return We(this,void 0,void 0,(function(){var r=this;return $e(this,(function(i){switch(i.label){case 0:return[4,Object(Ue.b)((function(e,t){return We(r,void 0,void 0,(function(){var r,i;return $e(this,(function(o){switch(o.label){case 0:return o.trys.push([0,2,,3]),[4,De.a.graphql({query:e,variables:t})];case 1:return[2,o.sent()];case 2:if(r=o.sent(),r.errors.some((function(e){return"Unauthorized"===e.errorType})))return(i=r).data[n].items=i.data[n].items.filter((function(e){return null!==e})),Ze.warn("queryError","User is unauthorized, some items could not be returned."),[2,i];throw r;case 3:return[2]}}))}))}),[e,t])];case 1:return[2,i.sent()]}}))}))},e.prototype.start=function(e){var t=this,n=!0,r=void 0!==this.maxRecordsToSync?this.maxRecordsToSync:1e4,i=void 0!==this.syncPageSize?this.syncPageSize:1e3,o=new Map;return new se.a((function(s){var a=Object.values(t.schema.namespaces).reduce((function(t,n){var r,i;try{for(var o=Je(Array.from(n.modelTopologicalOrdering.keys())),s=o.next();!s.done;s=o.next()){var a=s.value,u=e.get(n.models[a]);t.set(n.models[a],u)}}catch(e){r={error:e}}finally{try{s&&!s.done&&(i=o.return)&&i.call(o)}finally{if(r)throw r.error}}return t}),new Map),u=Array.from(a.entries()).filter((function(e){return Ye(e,1)[0].syncable})).map((function(e){var a=Ye(e,2),u=a[0],c=Ye(a[1],2),f=c[0],l=c[1];return We(t,void 0,void 0,(function(){var e,t,a,c,d,h,p,v,g,m=this;return $e(this,(function(b){switch(b.label){case 0:return e=!1,t=null,a=null,c=null,d=0,h=this.graphqlFilterFromPredicate(u),p=this.schema.namespaces[f].modelTopologicalOrdering.get(u.name),v=p.map((function(e){return o.get(f+"_"+e)})),g=new Promise((function(o){return We(m,void 0,void 0,(function(){var p,g;return $e(this,(function(m){switch(m.label){case 0:return[4,Promise.all(v)];case 1:m.sent(),m.label=2;case 2:return n?(p=Math.min(r-d,i),[4,this.retrievePage(u,l,t,p,h)]):[2];case 3:g=m.sent(),c=g.items,t=g.nextToken,a=g.startedAt,d+=c.length,e=null===t||d>=r,s.next({namespace:f,modelDefinition:u,items:c,done:e,startedAt:a,isFullSync:!l}),m.label=4;case 4:if(!e)return[3,2];m.label=5;case 5:return o(),[2]}}))}))})),o.set(f+"_"+u.name,g),[4,g];case 1:return b.sent(),[2]}}))}))}));return Promise.all(u).then((function(){s.complete()})),function(){n=!1}}))},e}(),Qe=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},et=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},tt=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},nt=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},rt=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(tt(arguments[t]));return e},it=Object(i.b)().isNode,ot=new r.a("DataStore"),st=Symbol("sync");!function(e){e.SYNC_ENGINE_STORAGE_SUBSCRIBED="storageSubscribed",e.SYNC_ENGINE_SUBSCRIPTIONS_ESTABLISHED="subscriptionsEstablished",e.SYNC_ENGINE_SYNC_QUERIES_STARTED="syncQueriesStarted",e.SYNC_ENGINE_SYNC_QUERIES_READY="syncQueriesReady",e.SYNC_ENGINE_MODEL_SYNCED="modelSynced",e.SYNC_ENGINE_OUTBOX_MUTATION_ENQUEUED="outboxMutationEnqueued",e.SYNC_ENGINE_OUTBOX_MUTATION_PROCESSED="outboxMutationProcessed",e.SYNC_ENGINE_OUTBOX_STATUS="outboxStatus",e.SYNC_ENGINE_NETWORK_STATUS="networkStatus",e.SYNC_ENGINE_READY="ready"}(re||(re={}));var at=function(){function e(e,t,n,r,i,o,s,a,u,c,f,l){void 0===l&&(l={}),this.schema=e,this.namespaceResolver=t,this.modelClasses=n,this.userModelClasses=r,this.storage=i,this.modelInstanceCreator=o,this.maxRecordsToSync=s,this.syncPageSize=a,this.syncPredicates=f,this.amplifyConfig=l,this.online=!1;var d=this.modelClasses.MutationEvent;this.outbox=new je(this.schema,this.namespaceResolver,d,st),this.modelMerger=new Te(this.outbox,st),this.syncQueriesProcessor=new Xe(this.schema,this.maxRecordsToSync,this.syncPageSize,this.syncPredicates),this.subscriptionsProcessor=new Ge.b(this.schema,this.syncPredicates,this.amplifyConfig),this.mutationsProcessor=new Ve(this.schema,this.storage,this.userModelClasses,this.outbox,this.modelInstanceCreator,d,u,c),this.datastoreConnectivity=new ke}return e.prototype.start=function(e){var t=this;return new se.a((function(n){ot.log("starting sync engine...");var r=[];return Qe(t,void 0,void 0,(function(){var t,i,o,s=this;return et(this,(function(a){switch(a.label){case 0:return a.trys.push([0,2,,3]),[4,this.setupModels(e)];case 1:return a.sent(),[3,3];case 2:return t=a.sent(),n.error(t),[2];case 3:return i=new Promise((function(e){s.datastoreConnectivity.status().subscribe((function(t){var i=t.online;return Qe(s,void 0,void 0,(function(){var t,o,s,a,u,c=this;return et(this,(function(f){switch(f.label){case 0:return!i||this.online?[3,10]:(this.online=i,n.next({type:re.SYNC_ENGINE_NETWORK_STATUS,data:{active:this.online}}),o=void 0,it?(ot.warn("Realtime disabled when in a server-side environment"),[3,6]):[3,1]);case 1:u=tt(this.subscriptionsProcessor.start(),2),t=u[0],o=u[1],f.label=2;case 2:return f.trys.push([2,4,,5]),[4,new Promise((function(e,n){var i=t.subscribe({next:function(t){t===Ge.a.CONNECTED&&e()},error:function(e){n(e),c.disconnectionHandler()(e)}});r.push(i)}))];case 3:return f.sent(),[3,5];case 4:return s=f.sent(),n.error(s),[2];case 5:ot.log("Realtime ready"),n.next({type:re.SYNC_ENGINE_SUBSCRIPTIONS_ESTABLISHED}),f.label=6;case 6:return f.trys.push([6,8,,9]),[4,new Promise((function(e,t){var i=c.syncQueriesObservable().subscribe({next:function(t){t.type===re.SYNC_ENGINE_SYNC_QUERIES_READY&&e(),n.next(t)},complete:function(){e()},error:function(e){t(e)}});i&&r.push(i)}))];case 7:return f.sent(),[3,9];case 8:return a=f.sent(),n.error(a),[2];case 9:return r.push(this.mutationsProcessor.start().subscribe((function(e){var t=e.modelDefinition,r=e.model,i=e.hasMore,o=c.userModelClasses[t.name],s=c.modelInstanceCreator(o,r);c.storage.runExclusive((function(e){return c.modelMerger.merge(e,s)})),n.next({type:re.SYNC_ENGINE_OUTBOX_MUTATION_PROCESSED,data:{model:o,element:s}}),n.next({type:re.SYNC_ENGINE_OUTBOX_STATUS,data:{isEmpty:!i}})}))),it||r.push(o.subscribe((function(e){var t=tt(e,3),n=(t[0],t[1]),r=t[2],i=c.userModelClasses[n.name],o=c.modelInstanceCreator(i,r);c.storage.runExclusive((function(e){return c.modelMerger.merge(e,o)}))}))),[3,11];case 10:i||(this.online=i,n.next({type:re.SYNC_ENGINE_NETWORK_STATUS,data:{active:this.online}}),r.forEach((function(e){return e.unsubscribe()})),r=[]),f.label=11;case 11:return e(),[2]}}))}))}))})),this.storage.observe(null,null,st).filter((function(e){var t=e.model;return!0===s.getModelDefinition(t).syncable})).subscribe({next:function(e){var t=e.opType,r=e.model,o=e.element,a=e.condition;return Qe(s,void 0,void 0,(function(){var e,s,u,c;return et(this,(function(f){switch(f.label){case 0:return e=this.schema.namespaces[this.namespaceResolver(r)],s=this.modelClasses.MutationEvent,u=Object(Pe.g)(a),c=Object(Pe.d)(e.relationships,this.getModelDefinition(r),t,r,o,u,s,this.modelInstanceCreator),[4,this.outbox.enqueue(this.storage,c)];case 1:return f.sent(),n.next({type:re.SYNC_ENGINE_OUTBOX_MUTATION_ENQUEUED,data:{model:r,element:o}}),n.next({type:re.SYNC_ENGINE_OUTBOX_STATUS,data:{isEmpty:!1}}),[4,i];case 2:return f.sent(),this.online&&this.mutationsProcessor.resume(),[2]}}))}))}}),n.next({type:re.SYNC_ENGINE_STORAGE_SUBSCRIBED}),[4,this.outbox.peek(this.storage)];case 4:return o=void 0===a.sent(),n.next({type:re.SYNC_ENGINE_OUTBOX_STATUS,data:{isEmpty:o}}),[4,i];case 5:return a.sent(),n.next({type:re.SYNC_ENGINE_READY}),[2]}}))})),function(){r.forEach((function(e){return e.unsubscribe()}))}}))},e.prototype.getModelsMetadataWithNextFullSync=function(e){return Qe(this,void 0,void 0,(function(){var t,n=this;return et(this,(function(r){switch(r.label){case 0:return t=Map.bind,[4,this.getModelsMetadata()];case 1:return[2,new(t.apply(Map,[void 0,r.sent().map((function(t){var r=t.namespace,i=t.model,o=t.lastSync,s=t.lastFullSync,a=t.fullSyncInterval,u=(t.lastSyncPredicate,!s||s+a<e?0:o);return[n.schema.namespaces[r].models[i],[r,u]]}))]))]}}))}))},e.prototype.syncQueriesObservable=function(){var e=this;return this.online?new se.a((function(t){var n,r;return Qe(e,void 0,void 0,(function(){var e,i,o=this;return et(this,(function(s){switch(s.label){case 0:e=function(){var e,s,a,u,c,f,l,d,h;return et(this,(function(p){switch(p.label){case 0:return e=new WeakMap,[4,i.getModelsMetadataWithNextFullSync(Date.now())];case 1:return s=p.sent(),a=new Set(s.keys()),[4,new Promise((function(r){n=o.syncQueriesProcessor.start(s).subscribe({next:function(i){var s=i.namespace,h=i.modelDefinition,p=i.items,v=i.done,g=i.startedAt,m=i.isFullSync;return Qe(o,void 0,void 0,(function(){var i,o,b,y,w,_,S=this;return et(this,(function(E){switch(E.label){case 0:return i=this.userModelClasses[h.name],e.has(i)||(e.set(i,{new:0,updated:0,deleted:0}),f=Object(he.i)(),d=void 0===d?g:Math.max(d,g)),[4,this.storage.runExclusive((function(t){return Qe(S,void 0,void 0,(function(){var n,r,o,s,a,u,c,f,l,d,h,v,g,m,b;return et(this,(function(y){switch(y.label){case 0:return[4,this.outbox.getModelIds(t)];case 1:n=y.sent(),r=[],o=p.filter((function(e){return!n.has(e.id)||(r.push(e),!1)})),s=[],y.label=2;case 2:y.trys.push([2,7,8,9]),a=nt(r),u=a.next(),y.label=3;case 3:return u.done?[3,6]:(c=u.value,[4,this.modelMerger.merge(t,c)]);case 4:void 0!==(f=y.sent())&&s.push([c,f]),y.label=5;case 5:return u=a.next(),[3,3];case 6:return[3,9];case 7:return l=y.sent(),m={error:l},[3,9];case 8:try{u&&!u.done&&(b=a.return)&&b.call(a)}finally{if(m)throw m.error}return[7];case 9:return h=(d=s.push).apply,v=[s],[4,this.modelMerger.mergePage(t,i,o)];case 10:return h.apply(d,v.concat([rt.apply(void 0,[y.sent()])])),g=e.get(i),s.forEach((function(e){var t=tt(e,2)[1];switch(t){case de.c.INSERT:g.new++;break;case de.c.UPDATE:g.updated++;break;case de.c.DELETE:g.deleted++;break;default:Object(he.f)(t)}})),[2]}}))}))}))];case 1:return E.sent(),v?(o=h.name,[4,this.getModelMetadata(s,o)]):[3,4];case 2:return b=E.sent(),y=b.lastFullSync,w=b.fullSyncInterval,c=w,u=void 0===u?y:Math.max(u,m?g:y),b=this.modelClasses.ModelMetadata.copyOf(b,(function(e){e.lastSync=g,e.lastFullSync=m?g:b.lastFullSync})),[4,this.storage.save(b,void 0,st)];case 3:E.sent(),_=e.get(i),t.next({type:re.SYNC_ENGINE_MODEL_SYNCED,data:{model:i,isFullSync:m,isDeltaSync:!m,counts:_}}),a.delete(h),0===a.size&&(l=Object(he.i)()-f,r(),t.next({type:re.SYNC_ENGINE_SYNC_QUERIES_READY}),n.unsubscribe()),E.label=4;case 4:return[2]}}))}))},error:function(e){t.error(e)}}),t.next({type:re.SYNC_ENGINE_SYNC_QUERIES_STARTED,data:{models:Array.from(a).map((function(e){return e.name}))}})}))];case 2:return p.sent(),h=u+c-(d+l),ot.debug("Next fullSync in "+h/1e3+" seconds. ("+new Date(Date.now()+h)+")"),[4,new Promise((function(e){r=setTimeout(e,h)}))];case 3:return p.sent(),[2]}}))},i=this,s.label=1;case 1:return t.closed?[3,3]:[5,e()];case 2:return s.sent(),[3,1];case 3:return[2]}}))})),function(){n&&n.unsubscribe(),r&&clearTimeout(r)}})):se.a.of()},e.prototype.disconnectionHandler=function(){var e=this;return function(t){Ee.a.CONNECTION_CLOSED!==t&&Ee.a.TIMEOUT_DISCONNECT!==t||e.datastoreConnectivity.socketDisconnected()}},e.prototype.unsubscribeConnectivity=function(){this.datastoreConnectivity.unsubscribe()},e.prototype.setupModels=function(e){return Qe(this,void 0,void 0,(function(){var t,n,r,i,o,s,a,u,c,f,l,d,h,p=this;return et(this,(function(v){switch(v.label){case 0:t=e.fullSyncInterval,n=this.modelClasses.ModelMetadata,r=[],Object.values(this.schema.namespaces).forEach((function(e){Object.values(e.models).filter((function(e){return e.syncable})).forEach((function(t){r.push([e.name,t])}))})),o=r.map((function(e){var r=tt(e,2),o=r[0],s=r[1];return Qe(p,void 0,void 0,(function(){var e,r,a,u,c,f,l,d,h;return et(this,(function(p){switch(p.label){case 0:return[4,this.getModelMetadata(o,s.name)];case 1:return e=p.sent(),r=ae.a.getPredicates(this.syncPredicates.get(s),!1),a=r?JSON.stringify(r):null,void 0!==e?[3,3]:[4,this.storage.save(this.modelInstanceCreator(n,{model:s.name,namespace:o,lastSync:null,fullSyncInterval:t,lastFullSync:null,lastSyncPredicate:a}),void 0,st)];case 2:return f=tt.apply(void 0,[p.sent(),1]),l=tt(f[0],1),i=l[0],[3,5];case 3:return u=e.lastSyncPredicate?e.lastSyncPredicate:null,c=u!==a,[4,this.storage.save(this.modelClasses.ModelMetadata.copyOf(e,(function(e){e.fullSyncInterval=t,c&&(e.lastSync=null,e.lastFullSync=null,e.lastSyncPredicate=a)})))];case 4:d=tt.apply(void 0,[p.sent(),1]),h=tt(d[0],1),i=h[0],p.label=5;case 5:return[2,i]}}))}))})),s={},v.label=1;case 1:return v.trys.push([1,6,7,8]),[4,Promise.all(o)];case 2:a=nt.apply(void 0,[v.sent()]),u=a.next(),v.label=3;case 3:if(u.done)return[3,5];c=u.value,f=c.model,s[f]=c,v.label=4;case 4:return u=a.next(),[3,3];case 5:return[3,8];case 6:return l=v.sent(),d={error:l},[3,8];case 7:try{u&&!u.done&&(h=a.return)&&h.call(a)}finally{if(d)throw d.error}return[7];case 8:return[2,s]}}))}))},e.prototype.getModelsMetadata=function(){return Qe(this,void 0,void 0,(function(){var e;return et(this,(function(t){switch(t.label){case 0:return e=this.modelClasses.ModelMetadata,[4,this.storage.query(e)];case 1:return[2,t.sent()]}}))}))},e.prototype.getModelMetadata=function(e,t){return Qe(this,void 0,void 0,(function(){var n,r,i;return et(this,(function(o){switch(o.label){case 0:return n=this.modelClasses.ModelMetadata,r=ae.a.createFromExisting(this.schema.namespaces[he.c].models[n.name],(function(n){return n.namespace("eq",e).model("eq",t)})),[4,this.storage.query(n,r,{page:0,limit:1})];case 1:return i=tt.apply(void 0,[o.sent(),1]),[2,i[0]]}}))}))},e.prototype.getModelDefinition=function(e){var t=this.namespaceResolver(e);return this.schema.namespaces[t].models[e.name]},e.getNamespace=function(){return{name:he.c,relationships:{},enums:{OperationType:{name:"OperationType",values:["CREATE","UPDATE","DELETE"]}},nonModels:{},models:{MutationEvent:{name:"MutationEvent",pluralName:"MutationEvents",syncable:!1,fields:{id:{name:"id",type:"ID",isRequired:!0,isArray:!1},model:{name:"model",type:"String",isRequired:!0,isArray:!1},data:{name:"data",type:"String",isRequired:!0,isArray:!1},modelId:{name:"modelId",type:"String",isRequired:!0,isArray:!1},operation:{name:"operation",type:{enum:"Operationtype"},isArray:!1,isRequired:!0},condition:{name:"condition",type:"String",isArray:!1,isRequired:!0}}},ModelMetadata:{name:"ModelMetadata",pluralName:"ModelsMetadata",syncable:!1,fields:{id:{name:"id",type:"ID",isRequired:!0,isArray:!1},namespace:{name:"namespace",type:"String",isRequired:!0,isArray:!1},model:{name:"model",type:"String",isRequired:!0,isArray:!1},lastSync:{name:"lastSync",type:"Int",isRequired:!1,isArray:!1},lastFullSync:{name:"lastFullSync",type:"Int",isRequired:!1,isArray:!1},fullSyncInterval:{name:"fullSyncInterval",type:"Int",isRequired:!0,isArray:!1}}}}}},e}();var ut=function(){return(ut=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},ct=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},ft=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},lt=function(e,t){var n={};for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(r=Object.getOwnPropertySymbols(e);i<r.length;i++)t.indexOf(r[i])<0&&Object.prototype.propertyIsEnumerable.call(e,r[i])&&(n[r[i]]=e[r[i]])}return n},dt=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s};oe(!0),q();var ht,pt,vt,gt,mt,bt=new r.a("DataStore"),yt=(Object(he.v)(Date.now()),i.a.browserOrNode().isNode),wt=new WeakMap,_t=new WeakMap,St=function(e){var t=wt.get(e);return ht.namespaces[t].models[e.name]},Et=function(e){return Object(he.s)(e)&&wt.has(e)},Mt=function(e){return wt.get(e)},At=new WeakSet;function It(e,t){return At.add(t),new e(t)}var kt;function Ot(e){return"string"==typeof e}function xt(e){var t=e.localModel,n=e.modelConstructor,r=e.remoteModel._version;return It(n,ut(ut({},t),{_version:r}))}function Ct(e){bt.warn(e)}function Tt(e,t){var n;switch(e){case he.a:n=pt[t];break;case he.d:n=vt[t];break;case he.c:n=gt[t];break;case he.b:n=mt[t];break;default:Object(he.f)(e)}if(Et(n))return n;var r="Model name is not valid for namespace. modelName: "+t+", namespace: "+e;throw bt.error(r),new Error(r)}function Pt(e,t){return ct(this,void 0,void 0,(function(){var n,r,i=this;return ft(this,(function(o){switch(o.label){case 0:return n=pt.Setting,r=ht.namespaces[he.a].models.Setting,[4,e.runExclusive((function(e){return ct(i,void 0,void 0,(function(){var i,o;return ft(this,(function(s){switch(s.label){case 0:return[4,e.query(n,ae.a.createFromExisting(r,(function(e){return e.key("eq","schemaVersion")})),{page:0,limit:1})];case 1:return i=dt.apply(void 0,[s.sent(),1]),void 0===(o=i[0])||void 0===o.value?[3,4]:JSON.parse(o.value)===t?[3,3]:[4,e.clear(!1)];case 2:s.sent(),s.label=3;case 3:return[3,6];case 4:return[4,e.save(It(n,{key:"schemaVersion",value:JSON.stringify(t)}))];case 5:s.sent(),s.label=6;case 6:return[2]}}))}))}))];case 1:return o.sent(),[2]}}))}))}var Nt=new(function(){function e(){var e=this;this.amplifyConfig={},this.syncPredicates=new WeakMap,this.start=function(){return ct(e,void 0,void 0,(function(){var e,t,n,r=this;return ft(this,(function(i){switch(i.label){case 0:return void 0!==this.initialized?[3,1]:(bt.debug("Starting DataStore"),this.initialized=new Promise((function(e,t){r.initResolve=e,r.initReject=t})),[3,3]);case 1:return[4,this.initialized];case 2:return i.sent(),[2];case 3:return this.storage=new Se(ht,Mt,Tt,It,void 0,this.sessionId),[4,this.storage.init()];case 4:return i.sent(),[4,Pt(this.storage,ht.version)];case 5:return i.sent(),(e=this.amplifyConfig.aws_appsync_graphqlEndpoint)?(bt.debug("GraphQL endpoint available",e),t=this,[4,this.processSyncExpressions()]):[3,7];case 6:return t.syncPredicates=i.sent(),this.sync=new at(ht,Mt,gt,vt,this.storage,It,this.maxRecordsToSync,this.syncPageSize,this.conflictHandler,this.errorHandler,this.syncPredicates,this.amplifyConfig),n=1e3*this.fullSyncInterval*60,kt=this.sync.start({fullSyncInterval:n}).subscribe({next:function(e){var t=e.type,n=e.data;t===(yt?re.SYNC_ENGINE_SYNC_QUERIES_READY:re.SYNC_ENGINE_STORAGE_SUBSCRIBED)&&r.initResolve(),o.a.dispatch("datastore",{event:t,data:n})},error:function(e){bt.warn("Sync error",e),r.initReject()}}),[3,8];case 7:bt.warn("Data won't be synchronized. No GraphQL endpoint configured. Did you forget `Amplify.configure(awsconfig)`?",{config:this.amplifyConfig}),this.initResolve(),i.label=8;case 8:return[4,this.initialized];case 9:return i.sent(),[2]}}))}))},this.query=function(t,n,r){return ct(e,void 0,void 0,(function(){var e,i,o,s,a;return ft(this,(function(u){switch(u.label){case 0:return[4,this.start()];case 1:if(u.sent(),!Et(t))throw e="Constructor is not for a valid model",bt.error(e,{modelConstructor:t}),new Error(e);return"string"==typeof n&&void 0!==r&&bt.warn("Pagination is ignored when querying by id"),i=St(t),o=Ot(n)?ae.a.createForId(i,n):Object(ae.c)(n)?void 0:ae.a.createFromExisting(i,n),s=this.processPagination(i,r),bt.debug("params ready",{modelConstructor:t,predicate:ae.a.getPredicates(o,!1),pagination:ut(ut({},s),{sort:ue.a.getPredicates(s.sort,!1)})}),[4,this.storage.query(t,o,s)];case 2:return a=u.sent(),[2,Ot(n)?a[0]:a]}}))}))},this.save=function(t,n){return ct(e,void 0,void 0,(function(){var e,r,i,o,s,a,u=this;return ft(this,(function(c){switch(c.label){case 0:return[4,this.start()];case 1:if(c.sent(),e=_t.get(t),r=t?t.constructor:void 0,!Et(r))throw i="Object is not an instance of a valid model",bt.error(i,{model:t}),new Error(i);return o=St(r),s=ae.a.createFromExisting(o,n),[4,this.storage.runExclusive((function(n){return ct(u,void 0,void 0,(function(){return ft(this,(function(i){switch(i.label){case 0:return[4,n.save(t,s,void 0,e)];case 1:return i.sent(),[2,n.query(r,ae.a.createForId(o,t.id))]}}))}))}))];case 2:return a=dt.apply(void 0,[c.sent(),1]),[2,a[0]]}}))}))},this.setConflictHandler=function(t){var n=t.DataStore;return n?n.conflictHandler:e.conflictHandler===xt&&t.conflictHandler?t.conflictHandler:e.conflictHandler||xt},this.setErrorHandler=function(t){var n=t.DataStore;return n?n.errorHandler:e.errorHandler===Ct&&t.errorHandler?t.errorHandler:e.errorHandler||Ct},this.delete=function(t,n){return ct(e,void 0,void 0,(function(){var e,r,i,o,s,a,u,c,f;return ft(this,(function(l){switch(l.label){case 0:return[4,this.start()];case 1:if(l.sent(),!t)throw u="Model or Model Constructor required",bt.error(u,{modelOrConstructor:t}),new Error(u);if(!Et(t))return[3,3];if(o=t,!n)throw u="Id to delete or criteria required. Do you want to delete all? Pass Predicates.ALL",bt.error(u,{idOrCriteria:n}),new Error(u);if("string"==typeof n)e=ae.a.createForId(St(o),n);else if(!(e=ae.a.createFromExisting(St(o),n))||!ae.a.isValidPredicate(e))throw u="Criteria required. Do you want to delete all? Pass Predicates.ALL",bt.error(u,{condition:e}),new Error(u);return[4,this.storage.delete(o,e)];case 2:return r=dt.apply(void 0,[l.sent(),1]),[2,r[0]];case 3:if(i=t,o=Object.getPrototypeOf(i||{}).constructor,!Et(o))throw u="Object is not an instance of a valid model",bt.error(u,{model:i}),new Error(u);if(s=St(o),a=ae.a.createForId(s,i.id),n){if("function"!=typeof n)throw u="Invalid criteria",bt.error(u,{idOrCriteria:n}),new Error(u);e=n(a)}else e=a;return[4,this.storage.delete(i,e)];case 4:return c=dt.apply(void 0,[l.sent(),1]),f=dt(c[0],1),[2,f[0]]}}))}))},this.observe=function(t,n){var r,i=t&&Et(t)?t:void 0;if(t&&void 0===i){var o=t,s=o&&Object.getPrototypeOf(o).constructor;if(Et(s))return n&&bt.warn("idOrCriteria is ignored when using a model instance",{model:o,idOrCriteria:n}),e.observe(s,o.id);var a="The model is not an instance of a PersistentModelConstructor";throw bt.error(a,{model:o}),new Error(a)}if(void 0!==n&&void 0===i){a="Cannot provide criteria without a modelConstructor";throw bt.error(a,n),new Error(a)}if(i&&!Et(i)){a="Constructor is not for a valid model";throw bt.error(a,{modelConstructor:i}),new Error(a)}return r="string"==typeof n?ae.a.createForId(St(i),n):i&&ae.a.createFromExisting(St(i),n),new se.a((function(t){var n;return ct(e,void 0,void 0,(function(){return ft(this,(function(e){switch(e.label){case 0:return[4,this.start()];case 1:return e.sent(),n=this.storage.observe(i,r).filter((function(e){var t=e.model;return Mt(t)===he.d})).subscribe(t),[2]}}))})),function(){n&&n.unsubscribe()}}))},this.configure=function(t){void 0===t&&(t={});var n=t.DataStore,r=(t.conflictHandler,t.errorHandler,t.maxRecordsToSync),i=t.syncPageSize,o=t.fullSyncInterval,s=t.syncExpressions,a=lt(t,["DataStore","conflictHandler","errorHandler","maxRecordsToSync","syncPageSize","fullSyncInterval","syncExpressions"]);e.amplifyConfig=ut(ut({},a),e.amplifyConfig),e.conflictHandler=e.setConflictHandler(t),e.errorHandler=e.setErrorHandler(t),e.syncExpressions=n&&n.syncExpressions||e.syncExpressions||s,e.maxRecordsToSync=n&&n.maxRecordsToSync||e.maxRecordsToSync||r,e.syncPageSize=n&&n.syncPageSize||e.syncPageSize||i,e.fullSyncInterval=n&&n.fullSyncInterval||e.fullSyncInterval||o||1440,e.sessionId=e.retrieveSessionId()},this.clear=function(){return ct(this,void 0,void 0,(function(){return ft(this,(function(e){switch(e.label){case 0:return void 0===this.storage?[2]:(kt&&!kt.closed&&kt.unsubscribe(),[4,this.storage.clear()]);case 1:return e.sent(),this.sync&&this.sync.unsubscribeConnectivity(),this.initialized=void 0,this.storage=void 0,this.sync=void 0,this.syncPredicates=new WeakMap,[2]}}))}))},this.stop=function(){return ct(this,void 0,void 0,(function(){return ft(this,(function(e){switch(e.label){case 0:return void 0===this.initialized?[3,2]:[4,this.start()];case 1:e.sent(),e.label=2;case 2:return kt&&!kt.closed&&kt.unsubscribe(),this.sync&&this.sync.unsubscribeConnectivity(),this.initialized=void 0,this.sync=void 0,[2]}}))}))}}return e.prototype.getModuleName=function(){return"DataStore"},e.prototype.processPagination=function(e,t){var n,r=t||{},i=r.limit,o=r.page,s=r.sort;if(void 0!==o&&void 0===i)throw new Error("Limit is required when requesting a page");if(void 0!==o){if("number"!=typeof o)throw new Error("Page should be a number");if(o<0)throw new Error("Page can't be negative")}if(void 0!==i){if("number"!=typeof i)throw new Error("Limit should be a number");if(i<0)throw new Error("Limit can't be negative")}return s&&(n=ue.a.createFromExisting(e,t.sort)),{limit:i,page:o,sort:n}},e.prototype.processSyncExpressions=function(){return ct(this,void 0,void 0,(function(){var e,t=this;return ft(this,(function(n){switch(n.label){case 0:return this.syncExpressions&&this.syncExpressions.length?[4,Promise.all(this.syncExpressions.map((function(e){return ct(t,void 0,void 0,(function(){var t,n,r,i,o,s;return ft(this,(function(a){switch(a.label){case 0:return[4,e];case 1:return t=a.sent(),n=t.modelConstructor,r=t.conditionProducer,i=St(n),[4,this.unwrapPromise(r)];case 2:return o=a.sent(),Object(ae.c)(o)?[2,[i,null]]:(s=this.createFromCondition(i,o),[2,[i,s]])}}))}))})))]:[2,new WeakMap];case 1:return e=n.sent(),[2,this.weakMapFromEntries(e)]}}))}))},e.prototype.createFromCondition=function(e,t){try{return ae.a.createFromExisting(e,t)}catch(e){throw bt.error("Error creating Sync Predicate"),e}},e.prototype.unwrapPromise=function(e){return ct(this,void 0,void 0,(function(){var t;return ft(this,(function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,e()];case 1:return[2,n.sent()];case 2:if((t=n.sent())instanceof TypeError)return[2,e];throw t;case 3:return[2]}}))}))},e.prototype.weakMapFromEntries=function(e){return e.reduce((function(e,t){var n=dt(t,2),r=n[0],i=n[1];if(e.has(r)){var o=r.name;return bt.warn("You can only utilize one Sync Expression per model.\n Subsequent sync expressions for the "+o+" model will be ignored."),e}return i&&e.set(r,i),e}),new WeakMap)},e.prototype.retrieveSessionId=function(){try{var e=sessionStorage.getItem("datastoreSessionId");if(e){var t=this.amplifyConfig.aws_appsync_graphqlEndpoint.split("/")[2];return e+"-"+dt(t.split("."),1)[0]}}catch(e){return}},e}());s.a.register(Nt)},,,,,,,,,,,function(e,t,n){"use strict";t.byteLength=function(e){var t=c(e),n=t[0],r=t[1];return 3*(n+r)/4-r},t.toByteArray=function(e){var t,n,r=c(e),s=r[0],a=r[1],u=new o(function(e,t,n){return 3*(t+n)/4-n}(0,s,a)),f=0,l=a>0?s-4:s;for(n=0;n<l;n+=4)t=i[e.charCodeAt(n)]<<18|i[e.charCodeAt(n+1)]<<12|i[e.charCodeAt(n+2)]<<6|i[e.charCodeAt(n+3)],u[f++]=t>>16&255,u[f++]=t>>8&255,u[f++]=255&t;2===a&&(t=i[e.charCodeAt(n)]<<2|i[e.charCodeAt(n+1)]>>4,u[f++]=255&t);1===a&&(t=i[e.charCodeAt(n)]<<10|i[e.charCodeAt(n+1)]<<4|i[e.charCodeAt(n+2)]>>2,u[f++]=t>>8&255,u[f++]=255&t);return u},t.fromByteArray=function(e){for(var t,n=e.length,i=n%3,o=[],s=0,a=n-i;s<a;s+=16383)o.push(f(e,s,s+16383>a?a:s+16383));1===i?(t=e[n-1],o.push(r[t>>2]+r[t<<4&63]+"==")):2===i&&(t=(e[n-2]<<8)+e[n-1],o.push(r[t>>10]+r[t>>4&63]+r[t<<2&63]+"="));return o.join("")};for(var r=[],i=[],o="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,u=s.length;a<u;++a)r[a]=s[a],i[s.charCodeAt(a)]=a;function c(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var n=e.indexOf("=");return-1===n&&(n=t),[n,n===t?0:4-n%4]}function f(e,t,n){for(var i,o,s=[],a=t;a<n;a+=3)i=(e[a]<<16&16711680)+(e[a+1]<<8&65280)+(255&e[a+2]),s.push(r[(o=i)>>18&63]+r[o>>12&63]+r[o>>6&63]+r[63&o]);return s.join("")}i["-".charCodeAt(0)]=62,i["_".charCodeAt(0)]=63},function(e,t){ -/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */ -t.read=function(e,t,n,r,i){var o,s,a=8*i-r-1,u=(1<<a)-1,c=u>>1,f=-7,l=n?i-1:0,d=n?-1:1,h=e[t+l];for(l+=d,o=h&(1<<-f)-1,h>>=-f,f+=a;f>0;o=256*o+e[t+l],l+=d,f-=8);for(s=o&(1<<-f)-1,o>>=-f,f+=r;f>0;s=256*s+e[t+l],l+=d,f-=8);if(0===o)o=1-c;else{if(o===u)return s?NaN:1/0*(h?-1:1);s+=Math.pow(2,r),o-=c}return(h?-1:1)*s*Math.pow(2,o-r)},t.write=function(e,t,n,r,i,o){var s,a,u,c=8*o-i-1,f=(1<<c)-1,l=f>>1,d=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,h=r?0:o-1,p=r?1:-1,v=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,s=f):(s=Math.floor(Math.log(t)/Math.LN2),t*(u=Math.pow(2,-s))<1&&(s--,u*=2),(t+=s+l>=1?d/u:d*Math.pow(2,1-l))*u>=2&&(s++,u/=2),s+l>=f?(a=0,s=f):s+l>=1?(a=(t*u-1)*Math.pow(2,i),s+=l):(a=t*Math.pow(2,l-1)*Math.pow(2,i),s=0));i>=8;e[n+h]=255&a,h+=p,a/=256,i-=8);for(s=s<<i|a,c+=i;c>0;e[n+h]=255&s,h+=p,s/=256,c-=8);e[n+h-p]|=128*v}},function(e,t,n){var r,i,o,s;e.exports=(r=n(32),o=(i=r).lib.Base,s=i.enc.Utf8,void(i.algo.HMAC=o.extend({init:function(e,t){e=this._hasher=new e.init,"string"==typeof t&&(t=s.parse(t));var n=e.blockSize,r=4*n;t.sigBytes>r&&(t=e.finalize(t)),t.clamp();for(var i=this._oKey=t.clone(),o=this._iKey=t.clone(),a=i.words,u=o.words,c=0;c<n;c++)a[c]^=1549556828,u[c]^=909522486;i.sigBytes=o.sigBytes=r,this.reset()},reset:function(){var e=this._hasher;e.reset(),e.update(this._iKey)},update:function(e){return this._hasher.update(e),this},finalize:function(e){var t=this._hasher,n=t.finalize(e);return t.reset(),t.finalize(this._oKey.clone().concat(n))}})))},function(e,t,n){"use strict";t.randomBytes=t.rng=t.pseudoRandomBytes=t.prng=n(66),t.createHash=t.Hash=n(79),t.createHmac=t.Hmac=n(175);var r=n(297),i=Object.keys(r),o=["sha1","sha224","sha256","sha384","sha512","md5","rmd160"].concat(i);t.getHashes=function(){return o};var s=n(178);t.pbkdf2=s.pbkdf2,t.pbkdf2Sync=s.pbkdf2Sync;var a=n(299);t.Cipher=a.Cipher,t.createCipher=a.createCipher,t.Cipheriv=a.Cipheriv,t.createCipheriv=a.createCipheriv,t.Decipher=a.Decipher,t.createDecipher=a.createDecipher,t.Decipheriv=a.Decipheriv,t.createDecipheriv=a.createDecipheriv,t.getCiphers=a.getCiphers,t.listCiphers=a.listCiphers;var u=n(314);t.DiffieHellmanGroup=u.DiffieHellmanGroup,t.createDiffieHellmanGroup=u.createDiffieHellmanGroup,t.getDiffieHellman=u.getDiffieHellman,t.createDiffieHellman=u.createDiffieHellman,t.DiffieHellman=u.DiffieHellman;var c=n(319);t.createSign=c.createSign,t.Sign=c.Sign,t.createVerify=c.createVerify,t.Verify=c.Verify,t.createECDH=n(360);var f=n(361);t.publicEncrypt=f.publicEncrypt,t.privateEncrypt=f.privateEncrypt,t.publicDecrypt=f.publicDecrypt,t.privateDecrypt=f.privateDecrypt;var l=n(364);t.randomFill=l.randomFill,t.randomFillSync=l.randomFillSync,t.createCredentials=function(){throw new Error(["sorry, createCredentials is not implemented yet","we accept pull requests","https://github.com/crypto-browserify/crypto-browserify"].join("\n"))},t.constants={DH_CHECK_P_NOT_SAFE_PRIME:2,DH_CHECK_P_NOT_PRIME:1,DH_UNABLE_TO_CHECK_GENERATOR:4,DH_NOT_SUITABLE_GENERATOR:8,NPN_ENABLED:1,ALPN_ENABLED:1,RSA_PKCS1_PADDING:1,RSA_SSLV23_PADDING:2,RSA_NO_PADDING:3,RSA_PKCS1_OAEP_PADDING:4,RSA_X931_PADDING:5,RSA_PKCS1_PSS_PADDING:6,POINT_CONVERSION_COMPRESSED:2,POINT_CONVERSION_UNCOMPRESSED:4,POINT_CONVERSION_HYBRID:6}},function(e,t,n){(t=e.exports=n(163)).Stream=t,t.Readable=t,t.Writable=n(167),t.Duplex=n(68),t.Transform=n(168),t.PassThrough=n(279),t.finished=n(115),t.pipeline=n(280)},function(e,t){},function(e,t,n){"use strict";function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var s=n(6).Buffer,a=n(276).inspect,u=a&&a.custom||"inspect";e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}var t,n,c;return t=e,(n=[{key:"push",value:function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length}},{key:"unshift",value:function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length}},{key:"shift",value:function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}}},{key:"clear",value:function(){this.head=this.tail=null,this.length=0}},{key:"join",value:function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n}},{key:"concat",value:function(e){if(0===this.length)return s.alloc(0);for(var t,n,r,i=s.allocUnsafe(e>>>0),o=this.head,a=0;o;)t=o.data,n=i,r=a,s.prototype.copy.call(t,n,r),a+=o.data.length,o=o.next;return i}},{key:"consume",value:function(e,t){var n;return e<this.head.data.length?(n=this.head.data.slice(0,e),this.head.data=this.head.data.slice(e)):n=e===this.head.data.length?this.shift():t?this._getString(e):this._getBuffer(e),n}},{key:"first",value:function(){return this.head.data}},{key:"_getString",value:function(e){var t=this.head,n=1,r=t.data;for(e-=r.length;t=t.next;){var i=t.data,o=e>i.length?i.length:e;if(o===i.length?r+=i:r+=i.slice(0,e),0==(e-=o)){o===i.length?(++n,t.next?this.head=t.next:this.head=this.tail=null):(this.head=t,t.data=i.slice(o));break}++n}return this.length-=n,r}},{key:"_getBuffer",value:function(e){var t=s.allocUnsafe(e),n=this.head,r=1;for(n.data.copy(t),e-=n.data.length;n=n.next;){var i=n.data,o=e>i.length?i.length:e;if(i.copy(t,t.length-e,0,o),0==(e-=o)){o===i.length?(++r,n.next?this.head=n.next:this.head=this.tail=null):(this.head=n,n.data=i.slice(o));break}++r}return this.length-=r,t}},{key:u,value:function(e,t){return a(this,function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}({},t,{depth:0,customInspect:!1}))}}])&&o(t.prototype,n),c&&o(t,c),e}()},function(e,t){},function(e,t,n){"use strict";(function(t){var r;function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var o=n(115),s=Symbol("lastResolve"),a=Symbol("lastReject"),u=Symbol("error"),c=Symbol("ended"),f=Symbol("lastPromise"),l=Symbol("handlePromise"),d=Symbol("stream");function h(e,t){return{value:e,done:t}}function p(e){var t=e[s];if(null!==t){var n=e[d].read();null!==n&&(e[f]=null,e[s]=null,e[a]=null,t(h(n,!1)))}}function v(e){t.nextTick(p,e)}var g=Object.getPrototypeOf((function(){})),m=Object.setPrototypeOf((i(r={get stream(){return this[d]},next:function(){var e=this,n=this[u];if(null!==n)return Promise.reject(n);if(this[c])return Promise.resolve(h(void 0,!0));if(this[d].destroyed)return new Promise((function(n,r){t.nextTick((function(){e[u]?r(e[u]):n(h(void 0,!0))}))}));var r,i=this[f];if(i)r=new Promise(function(e,t){return function(n,r){e.then((function(){t[c]?n(h(void 0,!0)):t[l](n,r)}),r)}}(i,this));else{var o=this[d].read();if(null!==o)return Promise.resolve(h(o,!1));r=new Promise(this[l])}return this[f]=r,r}},Symbol.asyncIterator,(function(){return this})),i(r,"return",(function(){var e=this;return new Promise((function(t,n){e[d].destroy(null,(function(e){e?n(e):t(h(void 0,!0))}))}))})),r),g);e.exports=function(e){var t,n=Object.create(m,(i(t={},d,{value:e,writable:!0}),i(t,s,{value:null,writable:!0}),i(t,a,{value:null,writable:!0}),i(t,u,{value:null,writable:!0}),i(t,c,{value:e._readableState.endEmitted,writable:!0}),i(t,l,{value:function(e,t){var r=n[d].read();r?(n[f]=null,n[s]=null,n[a]=null,e(h(r,!1))):(n[s]=e,n[a]=t)},writable:!0}),t));return n[f]=null,o(e,(function(e){if(e&&"ERR_STREAM_PREMATURE_CLOSE"!==e.code){var t=n[a];return null!==t&&(n[f]=null,n[s]=null,n[a]=null,t(e)),void(n[u]=e)}var r=n[s];null!==r&&(n[f]=null,n[s]=null,n[a]=null,r(h(void 0,!0))),n[c]=!0})),e.on("readable",v.bind(null,n)),n}}).call(this,n(20))},function(e,t){e.exports=function(){throw new Error("Readable.from is not available in the browser")}},function(e,t,n){"use strict";e.exports=i;var r=n(168);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}n(7)(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){"use strict";var r;var i=n(67).codes,o=i.ERR_MISSING_ARGS,s=i.ERR_STREAM_DESTROYED;function a(e){if(e)throw e}function u(e,t,i,o){o=function(e){var t=!1;return function(){t||(t=!0,e.apply(void 0,arguments))}}(o);var a=!1;e.on("close",(function(){a=!0})),void 0===r&&(r=n(115)),r(e,{readable:t,writable:i},(function(e){if(e)return o(e);a=!0,o()}));var u=!1;return function(t){if(!a&&!u)return u=!0,function(e){return e.setHeader&&"function"==typeof e.abort}(e)?e.abort():"function"==typeof e.destroy?e.destroy():void o(t||new s("pipe"))}}function c(e){e()}function f(e,t){return e.pipe(t)}function l(e){return e.length?"function"!=typeof e[e.length-1]?a:e.pop():a}e.exports=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var r,i=l(t);if(Array.isArray(t[0])&&(t=t[0]),t.length<2)throw new o("streams");var s=t.map((function(e,n){var o=n<t.length-1;return u(e,o,n>0,(function(e){r||(r=e),e&&s.forEach(c),o||(s.forEach(c),i(r))}))}));return t.reduce(f)}},function(e,t,n){var r=n(7),i=n(69),o=n(8).Buffer,s=[1518500249,1859775393,-1894007588,-899497514],a=new Array(80);function u(){this.init(),this._w=a,i.call(this,64,56)}function c(e){return e<<30|e>>>2}function f(e,t,n,r){return 0===e?t&n|~t&r:2===e?t&n|t&r|n&r:t^n^r}r(u,i),u.prototype.init=function(){return this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520,this},u.prototype._update=function(e){for(var t,n=this._w,r=0|this._a,i=0|this._b,o=0|this._c,a=0|this._d,u=0|this._e,l=0;l<16;++l)n[l]=e.readInt32BE(4*l);for(;l<80;++l)n[l]=n[l-3]^n[l-8]^n[l-14]^n[l-16];for(var d=0;d<80;++d){var h=~~(d/20),p=0|((t=r)<<5|t>>>27)+f(h,i,o,a)+u+n[d]+s[h];u=a,a=o,o=c(i),i=r,r=p}this._a=r+this._a|0,this._b=i+this._b|0,this._c=o+this._c|0,this._d=a+this._d|0,this._e=u+this._e|0},u.prototype._hash=function(){var e=o.allocUnsafe(20);return e.writeInt32BE(0|this._a,0),e.writeInt32BE(0|this._b,4),e.writeInt32BE(0|this._c,8),e.writeInt32BE(0|this._d,12),e.writeInt32BE(0|this._e,16),e},e.exports=u},function(e,t,n){var r=n(7),i=n(69),o=n(8).Buffer,s=[1518500249,1859775393,-1894007588,-899497514],a=new Array(80);function u(){this.init(),this._w=a,i.call(this,64,56)}function c(e){return e<<5|e>>>27}function f(e){return e<<30|e>>>2}function l(e,t,n,r){return 0===e?t&n|~t&r:2===e?t&n|t&r|n&r:t^n^r}r(u,i),u.prototype.init=function(){return this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520,this},u.prototype._update=function(e){for(var t,n=this._w,r=0|this._a,i=0|this._b,o=0|this._c,a=0|this._d,u=0|this._e,d=0;d<16;++d)n[d]=e.readInt32BE(4*d);for(;d<80;++d)n[d]=(t=n[d-3]^n[d-8]^n[d-14]^n[d-16])<<1|t>>>31;for(var h=0;h<80;++h){var p=~~(h/20),v=c(r)+l(p,i,o,a)+u+n[h]+s[p]|0;u=a,a=o,o=f(i),i=r,r=v}this._a=r+this._a|0,this._b=i+this._b|0,this._c=o+this._c|0,this._d=a+this._d|0,this._e=u+this._e|0},u.prototype._hash=function(){var e=o.allocUnsafe(20);return e.writeInt32BE(0|this._a,0),e.writeInt32BE(0|this._b,4),e.writeInt32BE(0|this._c,8),e.writeInt32BE(0|this._d,12),e.writeInt32BE(0|this._e,16),e},e.exports=u},function(e,t,n){var r=n(7),i=n(169),o=n(69),s=n(8).Buffer,a=new Array(64);function u(){this.init(),this._w=a,o.call(this,64,56)}r(u,i),u.prototype.init=function(){return this._a=3238371032,this._b=914150663,this._c=812702999,this._d=4144912697,this._e=4290775857,this._f=1750603025,this._g=1694076839,this._h=3204075428,this},u.prototype._hash=function(){var e=s.allocUnsafe(28);return e.writeInt32BE(this._a,0),e.writeInt32BE(this._b,4),e.writeInt32BE(this._c,8),e.writeInt32BE(this._d,12),e.writeInt32BE(this._e,16),e.writeInt32BE(this._f,20),e.writeInt32BE(this._g,24),e},e.exports=u},function(e,t,n){var r=n(7),i=n(170),o=n(69),s=n(8).Buffer,a=new Array(160);function u(){this.init(),this._w=a,o.call(this,128,112)}r(u,i),u.prototype.init=function(){return this._ah=3418070365,this._bh=1654270250,this._ch=2438529370,this._dh=355462360,this._eh=1731405415,this._fh=2394180231,this._gh=3675008525,this._hh=1203062813,this._al=3238371032,this._bl=914150663,this._cl=812702999,this._dl=4144912697,this._el=4290775857,this._fl=1750603025,this._gl=1694076839,this._hl=3204075428,this},u.prototype._hash=function(){var e=s.allocUnsafe(48);function t(t,n,r){e.writeInt32BE(t,r),e.writeInt32BE(n,r+4)}return t(this._ah,this._al,0),t(this._bh,this._bl,8),t(this._ch,this._cl,16),t(this._dh,this._dl,24),t(this._eh,this._el,32),t(this._fh,this._fl,40),e},e.exports=u},function(e,t,n){e.exports=i;var r=n(49).EventEmitter;function i(){r.call(this)}n(7)(i,r),i.Readable=n(118),i.Writable=n(292),i.Duplex=n(293),i.Transform=n(294),i.PassThrough=n(295),i.Stream=i,i.prototype.pipe=function(e,t){var n=this;function i(t){e.writable&&!1===e.write(t)&&n.pause&&n.pause()}function o(){n.readable&&n.resume&&n.resume()}n.on("data",i),e.on("drain",o),e._isStdio||t&&!1===t.end||(n.on("end",a),n.on("close",u));var s=!1;function a(){s||(s=!0,e.end())}function u(){s||(s=!0,"function"==typeof e.destroy&&e.destroy())}function c(e){if(f(),0===r.listenerCount(this,"error"))throw e}function f(){n.removeListener("data",i),e.removeListener("drain",o),n.removeListener("end",a),n.removeListener("close",u),n.removeListener("error",c),e.removeListener("error",c),n.removeListener("end",f),n.removeListener("close",f),e.removeListener("close",f)}return n.on("error",c),e.on("error",c),n.on("end",f),n.on("close",f),e.on("close",f),e.emit("pipe",n),e}},function(e,t){},function(e,t,n){"use strict";var r=n(119).Buffer,i=n(288);e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}return e.prototype.push=function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length},e.prototype.unshift=function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length},e.prototype.shift=function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}},e.prototype.clear=function(){this.head=this.tail=null,this.length=0},e.prototype.join=function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n},e.prototype.concat=function(e){if(0===this.length)return r.alloc(0);if(1===this.length)return this.head.data;for(var t,n,i,o=r.allocUnsafe(e>>>0),s=this.head,a=0;s;)t=s.data,n=o,i=a,t.copy(n,i),a+=s.data.length,s=s.next;return o},e}(),i&&i.inspect&&i.inspect.custom&&(e.exports.prototype[i.inspect.custom]=function(){var e=i.inspect({length:this.length});return this.constructor.name+" "+e})},function(e,t){},function(e,t,n){(function(e){var r=void 0!==e&&e||"undefined"!=typeof self&&self||window,i=Function.prototype.apply;function o(e,t){this._id=e,this._clearFn=t}t.setTimeout=function(){return new o(i.call(setTimeout,r,arguments),clearTimeout)},t.setInterval=function(){return new o(i.call(setInterval,r,arguments),clearInterval)},t.clearTimeout=t.clearInterval=function(e){e&&e.close()},o.prototype.unref=o.prototype.ref=function(){},o.prototype.close=function(){this._clearFn.call(r,this._id)},t.enroll=function(e,t){clearTimeout(e._idleTimeoutId),e._idleTimeout=t},t.unenroll=function(e){clearTimeout(e._idleTimeoutId),e._idleTimeout=-1},t._unrefActive=t.active=function(e){clearTimeout(e._idleTimeoutId);var t=e._idleTimeout;t>=0&&(e._idleTimeoutId=setTimeout((function(){e._onTimeout&&e._onTimeout()}),t))},n(290),t.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==e&&e.setImmediate||this&&this.setImmediate,t.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==e&&e.clearImmediate||this&&this.clearImmediate}).call(this,n(31))},function(e,t,n){(function(e,t){!function(e,n){"use strict";if(!e.setImmediate){var r,i,o,s,a,u=1,c={},f=!1,l=e.document,d=Object.getPrototypeOf&&Object.getPrototypeOf(e);d=d&&d.setTimeout?d:e,"[object process]"==={}.toString.call(e.process)?r=function(e){t.nextTick((function(){p(e)}))}:!function(){if(e.postMessage&&!e.importScripts){var t=!0,n=e.onmessage;return e.onmessage=function(){t=!1},e.postMessage("","*"),e.onmessage=n,t}}()?e.MessageChannel?((o=new MessageChannel).port1.onmessage=function(e){p(e.data)},r=function(e){o.port2.postMessage(e)}):l&&"onreadystatechange"in l.createElement("script")?(i=l.documentElement,r=function(e){var t=l.createElement("script");t.onreadystatechange=function(){p(e),t.onreadystatechange=null,i.removeChild(t),t=null},i.appendChild(t)}):r=function(e){setTimeout(p,0,e)}:(s="setImmediate$"+Math.random()+"$",a=function(t){t.source===e&&"string"==typeof t.data&&0===t.data.indexOf(s)&&p(+t.data.slice(s.length))},e.addEventListener?e.addEventListener("message",a,!1):e.attachEvent("onmessage",a),r=function(t){e.postMessage(s+t,"*")}),d.setImmediate=function(e){"function"!=typeof e&&(e=new Function(""+e));for(var t=new Array(arguments.length-1),n=0;n<t.length;n++)t[n]=arguments[n+1];var i={callback:e,args:t};return c[u]=i,r(u),u++},d.clearImmediate=h}function h(e){delete c[e]}function p(e){if(f)setTimeout(p,0,e);else{var t=c[e];if(t){f=!0;try{!function(e){var t=e.callback,n=e.args;switch(n.length){case 0:t();break;case 1:t(n[0]);break;case 2:t(n[0],n[1]);break;case 3:t(n[0],n[1],n[2]);break;default:t.apply(void 0,n)}}(t)}finally{h(e),f=!1}}}}}("undefined"==typeof self?void 0===e?this:e:self)}).call(this,n(31),n(20))},function(e,t,n){"use strict";e.exports=o;var r=n(174),i=Object.create(n(80));function o(e){if(!(this instanceof o))return new o(e);r.call(this,e)}i.inherits=n(7),i.inherits(o,r),o.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){e.exports=n(120)},function(e,t,n){e.exports=n(60)},function(e,t,n){e.exports=n(118).Transform},function(e,t,n){e.exports=n(118).PassThrough},function(e,t,n){"use strict";var r=n(7),i=n(8).Buffer,o=n(56),s=i.alloc(128);function a(e,t){o.call(this,"digest"),"string"==typeof t&&(t=i.from(t)),this._alg=e,this._key=t,t.length>64?t=e(t):t.length<64&&(t=i.concat([t,s],64));for(var n=this._ipad=i.allocUnsafe(64),r=this._opad=i.allocUnsafe(64),a=0;a<64;a++)n[a]=54^t[a],r[a]=92^t[a];this._hash=[n]}r(a,o),a.prototype._update=function(e){this._hash.push(e)},a.prototype._final=function(){var e=this._alg(i.concat(this._hash));return this._alg(i.concat([this._opad,e]))},e.exports=a},function(e,t,n){e.exports=n(177)},function(e,t,n){(function(t,r){var i,o=n(8).Buffer,s=n(179),a=n(180),u=n(181),c=n(182),f=t.crypto&&t.crypto.subtle,l={sha:"SHA-1","sha-1":"SHA-1",sha1:"SHA-1",sha256:"SHA-256","sha-256":"SHA-256",sha384:"SHA-384","sha-384":"SHA-384","sha-512":"SHA-512",sha512:"SHA-512"},d=[];function h(e,t,n,r,i){return f.importKey("raw",e,{name:"PBKDF2"},!1,["deriveBits"]).then((function(e){return f.deriveBits({name:"PBKDF2",salt:t,iterations:n,hash:{name:i}},e,r<<3)})).then((function(e){return o.from(e)}))}e.exports=function(e,n,p,v,g,m){"function"==typeof g&&(m=g,g=void 0);var b=l[(g=g||"sha1").toLowerCase()];if(!b||"function"!=typeof t.Promise)return r.nextTick((function(){var t;try{t=u(e,n,p,v,g)}catch(e){return m(e)}m(null,t)}));if(s(p,v),e=c(e,a,"Password"),n=c(n,a,"Salt"),"function"!=typeof m)throw new Error("No callback provided to pbkdf2");!function(e,t){e.then((function(e){r.nextTick((function(){t(null,e)}))}),(function(e){r.nextTick((function(){t(e)}))}))}(function(e){if(t.process&&!t.process.browser)return Promise.resolve(!1);if(!f||!f.importKey||!f.deriveBits)return Promise.resolve(!1);if(void 0!==d[e])return d[e];var n=h(i=i||o.alloc(8),i,10,128,e).then((function(){return!0})).catch((function(){return!1}));return d[e]=n,n}(b).then((function(t){return t?h(e,n,p,v,b):u(e,n,p,v,g)})),m)}}).call(this,n(31),n(20))},function(e,t,n){var r=n(300),i=n(122),o=n(123),s=n(313),a=n(94);function u(e,t,n){if(e=e.toLowerCase(),o[e])return i.createCipheriv(e,t,n);if(s[e])return new r({key:t,iv:n,mode:e});throw new TypeError("invalid suite type")}function c(e,t,n){if(e=e.toLowerCase(),o[e])return i.createDecipheriv(e,t,n);if(s[e])return new r({key:t,iv:n,mode:e,decrypt:!0});throw new TypeError("invalid suite type")}t.createCipher=t.Cipher=function(e,t){var n,r;if(e=e.toLowerCase(),o[e])n=o[e].key,r=o[e].iv;else{if(!s[e])throw new TypeError("invalid suite type");n=8*s[e].key,r=s[e].iv}var i=a(t,!1,n,r);return u(e,i.key,i.iv)},t.createCipheriv=t.Cipheriv=u,t.createDecipher=t.Decipher=function(e,t){var n,r;if(e=e.toLowerCase(),o[e])n=o[e].key,r=o[e].iv;else{if(!s[e])throw new TypeError("invalid suite type");n=8*s[e].key,r=s[e].iv}var i=a(t,!1,n,r);return c(e,i.key,i.iv)},t.createDecipheriv=t.Decipheriv=c,t.listCiphers=t.getCiphers=function(){return Object.keys(s).concat(i.getCiphers())}},function(e,t,n){var r=n(56),i=n(301),o=n(7),s=n(8).Buffer,a={"des-ede3-cbc":i.CBC.instantiate(i.EDE),"des-ede3":i.EDE,"des-ede-cbc":i.CBC.instantiate(i.EDE),"des-ede":i.EDE,"des-cbc":i.CBC.instantiate(i.DES),"des-ecb":i.DES};function u(e){r.call(this);var t,n=e.mode.toLowerCase(),i=a[n];t=e.decrypt?"decrypt":"encrypt";var o=e.key;s.isBuffer(o)||(o=s.from(o)),"des-ede"!==n&&"des-ede-cbc"!==n||(o=s.concat([o,o.slice(0,8)]));var u=e.iv;s.isBuffer(u)||(u=s.from(u)),this._des=i.create({key:o,iv:u,type:t})}a.des=a["des-cbc"],a.des3=a["des-ede3-cbc"],e.exports=u,o(u,r),u.prototype._update=function(e){return s.from(this._des.update(e))},u.prototype._final=function(){return s.from(this._des.final())}},function(e,t,n){"use strict";t.utils=n(183),t.Cipher=n(121),t.DES=n(184),t.CBC=n(302),t.EDE=n(303)},function(e,t,n){"use strict";var r=n(46),i=n(7),o={};function s(e){r.equal(e.length,8,"Invalid IV length"),this.iv=new Array(8);for(var t=0;t<this.iv.length;t++)this.iv[t]=e[t]}t.instantiate=function(e){function t(t){e.call(this,t),this._cbcInit()}i(t,e);for(var n=Object.keys(o),r=0;r<n.length;r++){var s=n[r];t.prototype[s]=o[s]}return t.create=function(e){return new t(e)},t},o._cbcInit=function(){var e=new s(this.options.iv);this._cbcState=e},o._update=function(e,t,n,r){var i=this._cbcState,o=this.constructor.super_.prototype,s=i.iv;if("encrypt"===this.type){for(var a=0;a<this.blockSize;a++)s[a]^=e[t+a];o._update.call(this,s,0,n,r);for(a=0;a<this.blockSize;a++)s[a]=n[r+a]}else{o._update.call(this,e,t,n,r);for(a=0;a<this.blockSize;a++)n[r+a]^=s[a];for(a=0;a<this.blockSize;a++)s[a]=e[t+a]}}},function(e,t,n){"use strict";var r=n(46),i=n(7),o=n(121),s=n(184);function a(e,t){r.equal(t.length,24,"Invalid key length");var n=t.slice(0,8),i=t.slice(8,16),o=t.slice(16,24);this.ciphers="encrypt"===e?[s.create({type:"encrypt",key:n}),s.create({type:"decrypt",key:i}),s.create({type:"encrypt",key:o})]:[s.create({type:"decrypt",key:o}),s.create({type:"encrypt",key:i}),s.create({type:"decrypt",key:n})]}function u(e){o.call(this,e);var t=new a(this.type,this.options.key);this._edeState=t}i(u,o),e.exports=u,u.create=function(e){return new u(e)},u.prototype._update=function(e,t,n,r){var i=this._edeState;i.ciphers[0]._update(e,t,n,r),i.ciphers[1]._update(n,r,n,r),i.ciphers[2]._update(n,r,n,r)},u.prototype._pad=s.prototype._pad,u.prototype._unpad=s.prototype._unpad},function(e,t,n){var r=n(123),i=n(188),o=n(8).Buffer,s=n(189),a=n(56),u=n(93),c=n(94);function f(e,t,n){a.call(this),this._cache=new d,this._cipher=new u.AES(t),this._prev=o.from(n),this._mode=e,this._autopadding=!0}n(7)(f,a),f.prototype._update=function(e){var t,n;this._cache.add(e);for(var r=[];t=this._cache.get();)n=this._mode.encrypt(this,t),r.push(n);return o.concat(r)};var l=o.alloc(16,16);function d(){this.cache=o.allocUnsafe(0)}function h(e,t,n){var a=r[e.toLowerCase()];if(!a)throw new TypeError("invalid suite type");if("string"==typeof t&&(t=o.from(t)),t.length!==a.key/8)throw new TypeError("invalid key length "+t.length);if("string"==typeof n&&(n=o.from(n)),"GCM"!==a.mode&&n.length!==a.iv)throw new TypeError("invalid iv length "+n.length);return"stream"===a.type?new s(a.module,t,n):"auth"===a.type?new i(a.module,t,n):new f(a.module,t,n)}f.prototype._final=function(){var e=this._cache.flush();if(this._autopadding)return e=this._mode.encrypt(this,e),this._cipher.scrub(),e;if(!e.equals(l))throw this._cipher.scrub(),new Error("data not multiple of block length")},f.prototype.setAutoPadding=function(e){return this._autopadding=!!e,this},d.prototype.add=function(e){this.cache=o.concat([this.cache,e])},d.prototype.get=function(){if(this.cache.length>15){var e=this.cache.slice(0,16);return this.cache=this.cache.slice(16),e}return null},d.prototype.flush=function(){for(var e=16-this.cache.length,t=o.allocUnsafe(e),n=-1;++n<e;)t.writeUInt8(e,n);return o.concat([this.cache,t])},t.createCipheriv=h,t.createCipher=function(e,t){var n=r[e.toLowerCase()];if(!n)throw new TypeError("invalid suite type");var i=c(t,!1,n.key,n.iv);return h(e,i.key,i.iv)}},function(e,t){t.encrypt=function(e,t){return e._cipher.encryptBlock(t)},t.decrypt=function(e,t){return e._cipher.decryptBlock(t)}},function(e,t,n){var r=n(81);t.encrypt=function(e,t){var n=r(t,e._prev);return e._prev=e._cipher.encryptBlock(n),e._prev},t.decrypt=function(e,t){var n=e._prev;e._prev=t;var i=e._cipher.decryptBlock(t);return r(i,n)}},function(e,t,n){var r=n(8).Buffer,i=n(81);function o(e,t,n){var o=t.length,s=i(t,e._cache);return e._cache=e._cache.slice(o),e._prev=r.concat([e._prev,n?t:s]),s}t.encrypt=function(e,t,n){for(var i,s=r.allocUnsafe(0);t.length;){if(0===e._cache.length&&(e._cache=e._cipher.encryptBlock(e._prev),e._prev=r.allocUnsafe(0)),!(e._cache.length<=t.length)){s=r.concat([s,o(e,t,n)]);break}i=e._cache.length,s=r.concat([s,o(e,t.slice(0,i),n)]),t=t.slice(i)}return s}},function(e,t,n){var r=n(8).Buffer;function i(e,t,n){var i=e._cipher.encryptBlock(e._prev)[0]^t;return e._prev=r.concat([e._prev.slice(1),r.from([n?t:i])]),i}t.encrypt=function(e,t,n){for(var o=t.length,s=r.allocUnsafe(o),a=-1;++a<o;)s[a]=i(e,t[a],n);return s}},function(e,t,n){var r=n(8).Buffer;function i(e,t,n){for(var r,i,s=-1,a=0;++s<8;)r=t&1<<7-s?128:0,a+=(128&(i=e._cipher.encryptBlock(e._prev)[0]^r))>>s%8,e._prev=o(e._prev,n?r:i);return a}function o(e,t){var n=e.length,i=-1,o=r.allocUnsafe(e.length);for(e=r.concat([e,r.from([t])]);++i<n;)o[i]=e[i]<<1|e[i+1]>>7;return o}t.encrypt=function(e,t,n){for(var o=t.length,s=r.allocUnsafe(o),a=-1;++a<o;)s[a]=i(e,t[a],n);return s}},function(e,t,n){(function(e){var r=n(81);function i(e){return e._prev=e._cipher.encryptBlock(e._prev),e._prev}t.encrypt=function(t,n){for(;t._cache.length<n.length;)t._cache=e.concat([t._cache,i(t)]);var o=t._cache.slice(0,n.length);return t._cache=t._cache.slice(n.length),r(n,o)}}).call(this,n(6).Buffer)},function(e,t,n){var r=n(8).Buffer,i=r.alloc(16,0);function o(e){var t=r.allocUnsafe(16);return t.writeUInt32BE(e[0]>>>0,0),t.writeUInt32BE(e[1]>>>0,4),t.writeUInt32BE(e[2]>>>0,8),t.writeUInt32BE(e[3]>>>0,12),t}function s(e){this.h=e,this.state=r.alloc(16,0),this.cache=r.allocUnsafe(0)}s.prototype.ghash=function(e){for(var t=-1;++t<e.length;)this.state[t]^=e[t];this._multiply()},s.prototype._multiply=function(){for(var e,t,n,r=[(e=this.h).readUInt32BE(0),e.readUInt32BE(4),e.readUInt32BE(8),e.readUInt32BE(12)],i=[0,0,0,0],s=-1;++s<128;){for(0!=(this.state[~~(s/8)]&1<<7-s%8)&&(i[0]^=r[0],i[1]^=r[1],i[2]^=r[2],i[3]^=r[3]),n=0!=(1&r[3]),t=3;t>0;t--)r[t]=r[t]>>>1|(1&r[t-1])<<31;r[0]=r[0]>>>1,n&&(r[0]=r[0]^225<<24)}this.state=o(i)},s.prototype.update=function(e){var t;for(this.cache=r.concat([this.cache,e]);this.cache.length>=16;)t=this.cache.slice(0,16),this.cache=this.cache.slice(16),this.ghash(t)},s.prototype.final=function(e,t){return this.cache.length&&this.ghash(r.concat([this.cache,i],16)),this.ghash(o([0,e,0,t])),this.state},e.exports=s},function(e,t,n){var r=n(188),i=n(8).Buffer,o=n(123),s=n(189),a=n(56),u=n(93),c=n(94);function f(e,t,n){a.call(this),this._cache=new l,this._last=void 0,this._cipher=new u.AES(t),this._prev=i.from(n),this._mode=e,this._autopadding=!0}function l(){this.cache=i.allocUnsafe(0)}function d(e,t,n){var a=o[e.toLowerCase()];if(!a)throw new TypeError("invalid suite type");if("string"==typeof n&&(n=i.from(n)),"GCM"!==a.mode&&n.length!==a.iv)throw new TypeError("invalid iv length "+n.length);if("string"==typeof t&&(t=i.from(t)),t.length!==a.key/8)throw new TypeError("invalid key length "+t.length);return"stream"===a.type?new s(a.module,t,n,!0):"auth"===a.type?new r(a.module,t,n,!0):new f(a.module,t,n)}n(7)(f,a),f.prototype._update=function(e){var t,n;this._cache.add(e);for(var r=[];t=this._cache.get(this._autopadding);)n=this._mode.decrypt(this,t),r.push(n);return i.concat(r)},f.prototype._final=function(){var e=this._cache.flush();if(this._autopadding)return function(e){var t=e[15];if(t<1||t>16)throw new Error("unable to decrypt data");var n=-1;for(;++n<t;)if(e[n+(16-t)]!==t)throw new Error("unable to decrypt data");if(16===t)return;return e.slice(0,16-t)}(this._mode.decrypt(this,e));if(e)throw new Error("data not multiple of block length")},f.prototype.setAutoPadding=function(e){return this._autopadding=!!e,this},l.prototype.add=function(e){this.cache=i.concat([this.cache,e])},l.prototype.get=function(e){var t;if(e){if(this.cache.length>16)return t=this.cache.slice(0,16),this.cache=this.cache.slice(16),t}else if(this.cache.length>=16)return t=this.cache.slice(0,16),this.cache=this.cache.slice(16),t;return null},l.prototype.flush=function(){if(this.cache.length)return this.cache},t.createDecipher=function(e,t){var n=o[e.toLowerCase()];if(!n)throw new TypeError("invalid suite type");var r=c(t,!1,n.key,n.iv);return d(e,r.key,r.iv)},t.createDecipheriv=d},function(e,t){t["des-ecb"]={key:8,iv:0},t["des-cbc"]=t.des={key:8,iv:8},t["des-ede3-cbc"]=t.des3={key:24,iv:8},t["des-ede3"]={key:24,iv:0},t["des-ede-cbc"]={key:16,iv:8},t["des-ede"]={key:16,iv:0}},function(e,t,n){(function(e){var r=n(190),i=n(317),o=n(318);var s={binary:!0,hex:!0,base64:!0};t.DiffieHellmanGroup=t.createDiffieHellmanGroup=t.getDiffieHellman=function(t){var n=new e(i[t].prime,"hex"),r=new e(i[t].gen,"hex");return new o(n,r)},t.createDiffieHellman=t.DiffieHellman=function t(n,i,a,u){return e.isBuffer(i)||void 0===s[i]?t(n,"binary",i,a):(i=i||"binary",u=u||"binary",a=a||new e([2]),e.isBuffer(a)||(a=new e(a,u)),"number"==typeof n?new o(r(n,a),a,!0):(e.isBuffer(n)||(n=new e(n,i)),new o(n,a,!0)))}}).call(this,n(6).Buffer)},function(e,t){},function(e,t){},function(e){e.exports=JSON.parse('{"modp1":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a63a3620ffffffffffffffff"},"modp2":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece65381ffffffffffffffff"},"modp5":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff"},"modp14":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aacaa68ffffffffffffffff"},"modp15":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a93ad2caffffffffffffffff"},"modp16":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c934063199ffffffffffffffff"},"modp17":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dcc4024ffffffffffffffff"},"modp18":{"gen":"02","prime":"ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca18217c32905e462e36ce3be39e772c180e86039b2783a2ec07a28fb5c55df06f4c52c9de2bcbf6955817183995497cea956ae515d2261898fa051015728e5a8aaac42dad33170d04507a33a85521abdf1cba64ecfb850458dbef0a8aea71575d060c7db3970f85a6e1e4c7abf5ae8cdb0933d71e8c94e04a25619dcee3d2261ad2ee6bf12ffa06d98a0864d87602733ec86a64521f2b18177b200cbbe117577a615d6c770988c0bad946e208e24fa074e5ab3143db5bfce0fd108e4b82d120a92108011a723c12a787e6d788719a10bdba5b2699c327186af4e23c1a946834b6150bda2583e9ca2ad44ce8dbbbc2db04de8ef92e8efc141fbecaa6287c59474e6bc05d99b2964fa090c3a2233ba186515be7ed1f612970cee2d7afb81bdd762170481cd0069127d5b05aa993b4ea988d8fddc186ffb7dc90a6c08f4df435c93402849236c3fab4d27c7026c1d4dcb2602646dec9751e763dba37bdf8ff9406ad9e530ee5db382f413001aeb06a53ed9027d831179727b0865a8918da3edbebcf9b14ed44ce6cbaced4bb1bdb7f1447e6cc254b332051512bd7af426fb8f401378cd2bf5983ca01c64b92ecf032ea15d1721d03f482d7ce6e74fef6d55e702f46980c82b5a84031900b1c9e59e7c97fbec7e8f323a97a7e36cc88be0f1d45b7ff585ac54bd407b22b4154aacc8f6d7ebf48e1d814cc5ed20f8037e0a79715eef29be32806a1d58bb7c5da76f550aa3d8a1fbff0eb19ccb1a313d55cda56c9ec2ef29632387fe8d76e3c0468043e8f663f4860ee12bf2d5b0b7474d6e694f91e6dbe115974a3926f12fee5e438777cb6a932df8cd8bec4d073b931ba3bc832b68d9dd300741fa7bf8afc47ed2576f6936ba424663aab639c5ae4f5683423b4742bf1c978238f16cbe39d652de3fdb8befc848ad922222e04a4037c0713eb57a81a23f0c73473fc646cea306b4bcbc8862f8385ddfa9d4b7fa2c087e879683303ed5bdd3a062b3cf5b3a278a66d2a13f83f44f82ddf310ee074ab6a364597e899a0255dc164f31cc50846851df9ab48195ded7ea1b1d510bd7ee74d73faf36bc31ecfa268359046f4eb879f924009438b481c6cd7889a002ed5ee382bc9190da6fc026e479558e4475677e9aa9e3050e2765694dfc81f56e880b96e7160c980dd98edd3dfffffffffffffffff"}}')},function(e,t,n){(function(t){var r=n(29),i=new(n(191)),o=new r(24),s=new r(11),a=new r(10),u=new r(3),c=new r(7),f=n(190),l=n(66);function d(e,n){return n=n||"utf8",t.isBuffer(e)||(e=new t(e,n)),this._pub=new r(e),this}function h(e,n){return n=n||"utf8",t.isBuffer(e)||(e=new t(e,n)),this._priv=new r(e),this}e.exports=v;var p={};function v(e,t,n){this.setGenerator(t),this.__prime=new r(e),this._prime=r.mont(this.__prime),this._primeLen=e.length,this._pub=void 0,this._priv=void 0,this._primeCode=void 0,n?(this.setPublicKey=d,this.setPrivateKey=h):this._primeCode=8}function g(e,n){var r=new t(e.toArray());return n?r.toString(n):r}Object.defineProperty(v.prototype,"verifyError",{enumerable:!0,get:function(){return"number"!=typeof this._primeCode&&(this._primeCode=function(e,t){var n=t.toString("hex"),r=[n,e.toString(16)].join("_");if(r in p)return p[r];var l,d=0;if(e.isEven()||!f.simpleSieve||!f.fermatTest(e)||!i.test(e))return d+=1,d+="02"===n||"05"===n?8:4,p[r]=d,d;switch(i.test(e.shrn(1))||(d+=2),n){case"02":e.mod(o).cmp(s)&&(d+=8);break;case"05":(l=e.mod(a)).cmp(u)&&l.cmp(c)&&(d+=8);break;default:d+=4}return p[r]=d,d}(this.__prime,this.__gen)),this._primeCode}}),v.prototype.generateKeys=function(){return this._priv||(this._priv=new r(l(this._primeLen))),this._pub=this._gen.toRed(this._prime).redPow(this._priv).fromRed(),this.getPublicKey()},v.prototype.computeSecret=function(e){var n=(e=(e=new r(e)).toRed(this._prime)).redPow(this._priv).fromRed(),i=new t(n.toArray()),o=this.getPrime();if(i.length<o.length){var s=new t(o.length-i.length);s.fill(0),i=t.concat([s,i])}return i},v.prototype.getPublicKey=function(e){return g(this._pub,e)},v.prototype.getPrivateKey=function(e){return g(this._priv,e)},v.prototype.getPrime=function(e){return g(this.__prime,e)},v.prototype.getGenerator=function(e){return g(this._gen,e)},v.prototype.setGenerator=function(e,n){return n=n||"utf8",t.isBuffer(e)||(e=new t(e,n)),this.__gen=e,this._gen=new r(e),this}}).call(this,n(6).Buffer)},function(e,t,n){var r=n(8).Buffer,i=n(79),o=n(320),s=n(7),a=n(328),u=n(359),c=n(177);function f(e){o.Writable.call(this);var t=c[e];if(!t)throw new Error("Unknown message digest");this._hashType=t.hash,this._hash=i(t.hash),this._tag=t.id,this._signType=t.sign}function l(e){o.Writable.call(this);var t=c[e];if(!t)throw new Error("Unknown message digest");this._hash=i(t.hash),this._tag=t.id,this._signType=t.sign}function d(e){return new f(e)}function h(e){return new l(e)}Object.keys(c).forEach((function(e){c[e].id=r.from(c[e].id,"hex"),c[e.toLowerCase()]=c[e]})),s(f,o.Writable),f.prototype._write=function(e,t,n){this._hash.update(e),n()},f.prototype.update=function(e,t){return"string"==typeof e&&(e=r.from(e,t)),this._hash.update(e),this},f.prototype.sign=function(e,t){this.end();var n=this._hash.digest(),r=a(n,e,this._hashType,this._signType,this._tag);return t?r.toString(t):r},s(l,o.Writable),l.prototype._write=function(e,t,n){this._hash.update(e),n()},l.prototype.update=function(e,t){return"string"==typeof e&&(e=r.from(e,t)),this._hash.update(e),this},l.prototype.verify=function(e,t,n){"string"==typeof t&&(t=r.from(t,n)),this.end();var i=this._hash.digest();return u(t,i,e,this._signType,this._tag)},e.exports={Sign:d,Verify:h,createSign:d,createVerify:h}},function(e,t,n){(t=e.exports=n(192)).Stream=t,t.Readable=t,t.Writable=n(196),t.Duplex=n(71),t.Transform=n(197),t.PassThrough=n(326),t.finished=n(125),t.pipeline=n(327)},function(e,t){},function(e,t,n){"use strict";function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var s=n(6).Buffer,a=n(323).inspect,u=a&&a.custom||"inspect";e.exports=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.head=null,this.tail=null,this.length=0}var t,n,c;return t=e,(n=[{key:"push",value:function(e){var t={data:e,next:null};this.length>0?this.tail.next=t:this.head=t,this.tail=t,++this.length}},{key:"unshift",value:function(e){var t={data:e,next:this.head};0===this.length&&(this.tail=t),this.head=t,++this.length}},{key:"shift",value:function(){if(0!==this.length){var e=this.head.data;return 1===this.length?this.head=this.tail=null:this.head=this.head.next,--this.length,e}}},{key:"clear",value:function(){this.head=this.tail=null,this.length=0}},{key:"join",value:function(e){if(0===this.length)return"";for(var t=this.head,n=""+t.data;t=t.next;)n+=e+t.data;return n}},{key:"concat",value:function(e){if(0===this.length)return s.alloc(0);for(var t,n,r,i=s.allocUnsafe(e>>>0),o=this.head,a=0;o;)t=o.data,n=i,r=a,s.prototype.copy.call(t,n,r),a+=o.data.length,o=o.next;return i}},{key:"consume",value:function(e,t){var n;return e<this.head.data.length?(n=this.head.data.slice(0,e),this.head.data=this.head.data.slice(e)):n=e===this.head.data.length?this.shift():t?this._getString(e):this._getBuffer(e),n}},{key:"first",value:function(){return this.head.data}},{key:"_getString",value:function(e){var t=this.head,n=1,r=t.data;for(e-=r.length;t=t.next;){var i=t.data,o=e>i.length?i.length:e;if(o===i.length?r+=i:r+=i.slice(0,e),0==(e-=o)){o===i.length?(++n,t.next?this.head=t.next:this.head=this.tail=null):(this.head=t,t.data=i.slice(o));break}++n}return this.length-=n,r}},{key:"_getBuffer",value:function(e){var t=s.allocUnsafe(e),n=this.head,r=1;for(n.data.copy(t),e-=n.data.length;n=n.next;){var i=n.data,o=e>i.length?i.length:e;if(i.copy(t,t.length-e,0,o),0==(e-=o)){o===i.length?(++r,n.next?this.head=n.next:this.head=this.tail=null):(this.head=n,n.data=i.slice(o));break}++r}return this.length-=r,t}},{key:u,value:function(e,t){return a(this,function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}({},t,{depth:0,customInspect:!1}))}}])&&o(t.prototype,n),c&&o(t,c),e}()},function(e,t){},function(e,t,n){"use strict";(function(t){var r;function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var o=n(125),s=Symbol("lastResolve"),a=Symbol("lastReject"),u=Symbol("error"),c=Symbol("ended"),f=Symbol("lastPromise"),l=Symbol("handlePromise"),d=Symbol("stream");function h(e,t){return{value:e,done:t}}function p(e){var t=e[s];if(null!==t){var n=e[d].read();null!==n&&(e[f]=null,e[s]=null,e[a]=null,t(h(n,!1)))}}function v(e){t.nextTick(p,e)}var g=Object.getPrototypeOf((function(){})),m=Object.setPrototypeOf((i(r={get stream(){return this[d]},next:function(){var e=this,n=this[u];if(null!==n)return Promise.reject(n);if(this[c])return Promise.resolve(h(void 0,!0));if(this[d].destroyed)return new Promise((function(n,r){t.nextTick((function(){e[u]?r(e[u]):n(h(void 0,!0))}))}));var r,i=this[f];if(i)r=new Promise(function(e,t){return function(n,r){e.then((function(){t[c]?n(h(void 0,!0)):t[l](n,r)}),r)}}(i,this));else{var o=this[d].read();if(null!==o)return Promise.resolve(h(o,!1));r=new Promise(this[l])}return this[f]=r,r}},Symbol.asyncIterator,(function(){return this})),i(r,"return",(function(){var e=this;return new Promise((function(t,n){e[d].destroy(null,(function(e){e?n(e):t(h(void 0,!0))}))}))})),r),g);e.exports=function(e){var t,n=Object.create(m,(i(t={},d,{value:e,writable:!0}),i(t,s,{value:null,writable:!0}),i(t,a,{value:null,writable:!0}),i(t,u,{value:null,writable:!0}),i(t,c,{value:e._readableState.endEmitted,writable:!0}),i(t,l,{value:function(e,t){var r=n[d].read();r?(n[f]=null,n[s]=null,n[a]=null,e(h(r,!1))):(n[s]=e,n[a]=t)},writable:!0}),t));return n[f]=null,o(e,(function(e){if(e&&"ERR_STREAM_PREMATURE_CLOSE"!==e.code){var t=n[a];return null!==t&&(n[f]=null,n[s]=null,n[a]=null,t(e)),void(n[u]=e)}var r=n[s];null!==r&&(n[f]=null,n[s]=null,n[a]=null,r(h(void 0,!0))),n[c]=!0})),e.on("readable",v.bind(null,n)),n}}).call(this,n(20))},function(e,t){e.exports=function(){throw new Error("Readable.from is not available in the browser")}},function(e,t,n){"use strict";e.exports=i;var r=n(197);function i(e){if(!(this instanceof i))return new i(e);r.call(this,e)}n(7)(i,r),i.prototype._transform=function(e,t,n){n(null,e)}},function(e,t,n){"use strict";var r;var i=n(70).codes,o=i.ERR_MISSING_ARGS,s=i.ERR_STREAM_DESTROYED;function a(e){if(e)throw e}function u(e,t,i,o){o=function(e){var t=!1;return function(){t||(t=!0,e.apply(void 0,arguments))}}(o);var a=!1;e.on("close",(function(){a=!0})),void 0===r&&(r=n(125)),r(e,{readable:t,writable:i},(function(e){if(e)return o(e);a=!0,o()}));var u=!1;return function(t){if(!a&&!u)return u=!0,function(e){return e.setHeader&&"function"==typeof e.abort}(e)?e.abort():"function"==typeof e.destroy?e.destroy():void o(t||new s("pipe"))}}function c(e){e()}function f(e,t){return e.pipe(t)}function l(e){return e.length?"function"!=typeof e[e.length-1]?a:e.pop():a}e.exports=function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var r,i=l(t);if(Array.isArray(t[0])&&(t=t[0]),t.length<2)throw new o("streams");var s=t.map((function(e,n){var o=n<t.length-1;return u(e,o,n>0,(function(e){r||(r=e),e&&s.forEach(c),o||(s.forEach(c),i(r))}))}));return t.reduce(f)}},function(e,t,n){var r=n(8).Buffer,i=n(175),o=n(126),s=n(127).ec,a=n(203),u=n(96),c=n(209);function f(e,t,n,o){if((e=r.from(e.toArray())).length<t.byteLength()){var s=r.alloc(t.byteLength()-e.length);e=r.concat([s,e])}var a=n.length,u=function(e,t){e=(e=l(e,t)).mod(t);var n=r.from(e.toArray());if(n.length<t.byteLength()){var i=r.alloc(t.byteLength()-n.length);n=r.concat([i,n])}return n}(n,t),c=r.alloc(a);c.fill(1);var f=r.alloc(a);return f=i(o,f).update(c).update(r.from([0])).update(e).update(u).digest(),c=i(o,f).update(c).digest(),{k:f=i(o,f).update(c).update(r.from([1])).update(e).update(u).digest(),v:c=i(o,f).update(c).digest()}}function l(e,t){var n=new a(e),r=(e.length<<3)-t.bitLength();return r>0&&n.ishrn(r),n}function d(e,t,n){var o,s;do{for(o=r.alloc(0);8*o.length<e.bitLength();)t.v=i(n,t.k).update(t.v).digest(),o=r.concat([o,t.v]);s=l(o,e),t.k=i(n,t.k).update(t.v).update(r.from([0])).digest(),t.v=i(n,t.k).update(t.v).digest()}while(-1!==s.cmp(e));return s}function h(e,t,n,r){return e.toRed(a.mont(n)).redPow(t).fromRed().mod(r)}e.exports=function(e,t,n,i,p){var v=u(t);if(v.curve){if("ecdsa"!==i&&"ecdsa/rsa"!==i)throw new Error("wrong private key type");return function(e,t){var n=c[t.curve.join(".")];if(!n)throw new Error("unknown curve "+t.curve.join("."));var i=new s(n).keyFromPrivate(t.privateKey).sign(e);return r.from(i.toDER())}(e,v)}if("dsa"===v.type){if("dsa"!==i)throw new Error("wrong private key type");return function(e,t,n){var i,o=t.params.priv_key,s=t.params.p,u=t.params.q,c=t.params.g,p=new a(0),v=l(e,u).mod(u),g=!1,m=f(o,u,e,n);for(;!1===g;)i=d(u,m,n),p=h(c,i,s,u),0===(g=i.invm(u).imul(v.add(o.mul(p))).mod(u)).cmpn(0)&&(g=!1,p=new a(0));return function(e,t){e=e.toArray(),t=t.toArray(),128&e[0]&&(e=[0].concat(e));128&t[0]&&(t=[0].concat(t));var n=[48,e.length+t.length+4,2,e.length];return n=n.concat(e,[2,t.length],t),r.from(n)}(p,g)}(e,v,n)}if("rsa"!==i&&"ecdsa/rsa"!==i)throw new Error("wrong private key type");e=r.concat([p,e]);for(var g=v.modulus.byteLength(),m=[0,1];e.length+m.length+1<g;)m.push(255);m.push(0);for(var b=-1;++b<e.length;)m.push(e[b]);return o(m,v)},e.exports.getKey=f,e.exports.makeKey=d},function(e,t,n){(function(e){!function(e,t){"use strict";function r(e,t){if(!e)throw new Error(t||"Assertion failed")}function i(e,t){e.super_=t;var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}function o(e,t,n){if(o.isBN(e))return e;this.negative=0,this.words=null,this.length=0,this.red=null,null!==e&&("le"!==t&&"be"!==t||(n=t,t=10),this._init(e||0,t||10,n||"be"))}var s;"object"==typeof e?e.exports=o:t.BN=o,o.BN=o,o.wordSize=26;try{s=n(330).Buffer}catch(e){}function a(e,t,n){for(var i=0,o=Math.min(e.length,n),s=0,a=t;a<o;a++){var u,c=e.charCodeAt(a)-48;i<<=4,i|=u=c>=49&&c<=54?c-49+10:c>=17&&c<=22?c-17+10:c,s|=u}return r(!(240&s),"Invalid character in "+e),i}function u(e,t,n,i){for(var o=0,s=0,a=Math.min(e.length,n),u=t;u<a;u++){var c=e.charCodeAt(u)-48;o*=i,s=c>=49?c-49+10:c>=17?c-17+10:c,r(c>=0&&s<i,"Invalid character"),o+=s}return o}function c(e,t){e.words=t.words,e.length=t.length,e.negative=t.negative,e.red=t.red}if(o.isBN=function(e){return e instanceof o||null!==e&&"object"==typeof e&&e.constructor.wordSize===o.wordSize&&Array.isArray(e.words)},o.max=function(e,t){return e.cmp(t)>0?e:t},o.min=function(e,t){return e.cmp(t)<0?e:t},o.prototype._init=function(e,t,n){if("number"==typeof e)return this._initNumber(e,t,n);if("object"==typeof e)return this._initArray(e,t,n);"hex"===t&&(t=16),r(t===(0|t)&&t>=2&&t<=36);var i=0;"-"===(e=e.toString().replace(/\s+/g,""))[0]&&i++,16===t?this._parseHex(e,i):this._parseBase(e,t,i),"-"===e[0]&&(this.negative=1),this._strip(),"le"===n&&this._initArray(this.toArray(),t,n)},o.prototype._initNumber=function(e,t,n){e<0&&(this.negative=1,e=-e),e<67108864?(this.words=[67108863&e],this.length=1):e<4503599627370496?(this.words=[67108863&e,e/67108864&67108863],this.length=2):(r(e<9007199254740992),this.words=[67108863&e,e/67108864&67108863,1],this.length=3),"le"===n&&this._initArray(this.toArray(),t,n)},o.prototype._initArray=function(e,t,n){if(r("number"==typeof e.length),e.length<=0)return this.words=[0],this.length=1,this;this.length=Math.ceil(e.length/3),this.words=new Array(this.length);for(var i=0;i<this.length;i++)this.words[i]=0;var o,s,a=0;if("be"===n)for(i=e.length-1,o=0;i>=0;i-=3)s=e[i]|e[i-1]<<8|e[i-2]<<16,this.words[o]|=s<<a&67108863,this.words[o+1]=s>>>26-a&67108863,(a+=24)>=26&&(a-=26,o++);else if("le"===n)for(i=0,o=0;i<e.length;i+=3)s=e[i]|e[i+1]<<8|e[i+2]<<16,this.words[o]|=s<<a&67108863,this.words[o+1]=s>>>26-a&67108863,(a+=24)>=26&&(a-=26,o++);return this._strip()},o.prototype._parseHex=function(e,t){this.length=Math.ceil((e.length-t)/6),this.words=new Array(this.length);for(var n=0;n<this.length;n++)this.words[n]=0;var r,i,o=0;for(n=e.length-6,r=0;n>=t;n-=6)i=a(e,n,n+6),this.words[r]|=i<<o&67108863,this.words[r+1]|=i>>>26-o&4194303,(o+=24)>=26&&(o-=26,r++);n+6!==t&&(i=a(e,t,n+6),this.words[r]|=i<<o&67108863,this.words[r+1]|=i>>>26-o&4194303),this._strip()},o.prototype._parseBase=function(e,t,n){this.words=[0],this.length=1;for(var r=0,i=1;i<=67108863;i*=t)r++;r--,i=i/t|0;for(var o=e.length-n,s=o%r,a=Math.min(o,o-s)+n,c=0,f=n;f<a;f+=r)c=u(e,f,f+r,t),this.imuln(i),this.words[0]+c<67108864?this.words[0]+=c:this._iaddn(c);if(0!==s){var l=1;for(c=u(e,f,e.length,t),f=0;f<s;f++)l*=t;this.imuln(l),this.words[0]+c<67108864?this.words[0]+=c:this._iaddn(c)}},o.prototype.copy=function(e){e.words=new Array(this.length);for(var t=0;t<this.length;t++)e.words[t]=this.words[t];e.length=this.length,e.negative=this.negative,e.red=this.red},o.prototype._move=function(e){c(e,this)},o.prototype.clone=function(){var e=new o(null);return this.copy(e),e},o.prototype._expand=function(e){for(;this.length<e;)this.words[this.length++]=0;return this},o.prototype._strip=function(){for(;this.length>1&&0===this.words[this.length-1];)this.length--;return this._normSign()},o.prototype._normSign=function(){return 1===this.length&&0===this.words[0]&&(this.negative=0),this},"undefined"!=typeof Symbol&&"function"==typeof Symbol.for)try{o.prototype[Symbol.for("nodejs.util.inspect.custom")]=f}catch(e){o.prototype.inspect=f}else o.prototype.inspect=f;function f(){return(this.red?"<BN-R: ":"<BN: ")+this.toString(16)+">"}var l=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],d=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],h=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];o.prototype.toString=function(e,t){var n;if(t=0|t||1,16===(e=e||10)||"hex"===e){n="";for(var i=0,o=0,s=0;s<this.length;s++){var a=this.words[s],u=(16777215&(a<<i|o)).toString(16);n=0!==(o=a>>>24-i&16777215)||s!==this.length-1?l[6-u.length]+u+n:u+n,(i+=2)>=26&&(i-=26,s--)}for(0!==o&&(n=o.toString(16)+n);n.length%t!=0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}if(e===(0|e)&&e>=2&&e<=36){var c=d[e],f=h[e];n="";var p=this.clone();for(p.negative=0;!p.isZero();){var v=p.modrn(f).toString(e);n=(p=p.idivn(f)).isZero()?v+n:l[c-v.length]+v+n}for(this.isZero()&&(n="0"+n);n.length%t!=0;)n="0"+n;return 0!==this.negative&&(n="-"+n),n}r(!1,"Base should be between 2 and 36")},o.prototype.toNumber=function(){var e=this.words[0];return 2===this.length?e+=67108864*this.words[1]:3===this.length&&1===this.words[2]?e+=4503599627370496+67108864*this.words[1]:this.length>2&&r(!1,"Number can only safely store up to 53 bits"),0!==this.negative?-e:e},o.prototype.toJSON=function(){return this.toString(16,2)},s&&(o.prototype.toBuffer=function(e,t){return this.toArrayLike(s,e,t)}),o.prototype.toArray=function(e,t){return this.toArrayLike(Array,e,t)};function p(e,t,n){n.negative=t.negative^e.negative;var r=e.length+t.length|0;n.length=r,r=r-1|0;var i=0|e.words[0],o=0|t.words[0],s=i*o,a=67108863&s,u=s/67108864|0;n.words[0]=a;for(var c=1;c<r;c++){for(var f=u>>>26,l=67108863&u,d=Math.min(c,t.length-1),h=Math.max(0,c-e.length+1);h<=d;h++){var p=c-h|0;f+=(s=(i=0|e.words[p])*(o=0|t.words[h])+l)/67108864|0,l=67108863&s}n.words[c]=0|l,u=0|f}return 0!==u?n.words[c]=0|u:n.length--,n._strip()}o.prototype.toArrayLike=function(e,t,n){this._strip();var i=this.byteLength(),o=n||Math.max(1,i);r(i<=o,"byte array longer than desired length"),r(o>0,"Requested array length <= 0");var s=function(e,t){return e.allocUnsafe?e.allocUnsafe(t):new e(t)}(e,o);return this["_toArrayLike"+("le"===t?"LE":"BE")](s,i),s},o.prototype._toArrayLikeLE=function(e,t){for(var n=0,r=0,i=0,o=0;i<this.length;i++){var s=this.words[i]<<o|r;e[n++]=255&s,n<e.length&&(e[n++]=s>>8&255),n<e.length&&(e[n++]=s>>16&255),6===o?(n<e.length&&(e[n++]=s>>24&255),r=0,o=0):(r=s>>>24,o+=2)}if(n<e.length)for(e[n++]=r;n<e.length;)e[n++]=0},o.prototype._toArrayLikeBE=function(e,t){for(var n=e.length-1,r=0,i=0,o=0;i<this.length;i++){var s=this.words[i]<<o|r;e[n--]=255&s,n>=0&&(e[n--]=s>>8&255),n>=0&&(e[n--]=s>>16&255),6===o?(n>=0&&(e[n--]=s>>24&255),r=0,o=0):(r=s>>>24,o+=2)}if(n>=0)for(e[n--]=r;n>=0;)e[n--]=0},Math.clz32?o.prototype._countBits=function(e){return 32-Math.clz32(e)}:o.prototype._countBits=function(e){var t=e,n=0;return t>=4096&&(n+=13,t>>>=13),t>=64&&(n+=7,t>>>=7),t>=8&&(n+=4,t>>>=4),t>=2&&(n+=2,t>>>=2),n+t},o.prototype._zeroBits=function(e){if(0===e)return 26;var t=e,n=0;return 0==(8191&t)&&(n+=13,t>>>=13),0==(127&t)&&(n+=7,t>>>=7),0==(15&t)&&(n+=4,t>>>=4),0==(3&t)&&(n+=2,t>>>=2),0==(1&t)&&n++,n},o.prototype.bitLength=function(){var e=this.words[this.length-1],t=this._countBits(e);return 26*(this.length-1)+t},o.prototype.zeroBits=function(){if(this.isZero())return 0;for(var e=0,t=0;t<this.length;t++){var n=this._zeroBits(this.words[t]);if(e+=n,26!==n)break}return e},o.prototype.byteLength=function(){return Math.ceil(this.bitLength()/8)},o.prototype.toTwos=function(e){return 0!==this.negative?this.abs().inotn(e).iaddn(1):this.clone()},o.prototype.fromTwos=function(e){return this.testn(e-1)?this.notn(e).iaddn(1).ineg():this.clone()},o.prototype.isNeg=function(){return 0!==this.negative},o.prototype.neg=function(){return this.clone().ineg()},o.prototype.ineg=function(){return this.isZero()||(this.negative^=1),this},o.prototype.iuor=function(e){for(;this.length<e.length;)this.words[this.length++]=0;for(var t=0;t<e.length;t++)this.words[t]=this.words[t]|e.words[t];return this._strip()},o.prototype.ior=function(e){return r(0==(this.negative|e.negative)),this.iuor(e)},o.prototype.or=function(e){return this.length>e.length?this.clone().ior(e):e.clone().ior(this)},o.prototype.uor=function(e){return this.length>e.length?this.clone().iuor(e):e.clone().iuor(this)},o.prototype.iuand=function(e){var t;t=this.length>e.length?e:this;for(var n=0;n<t.length;n++)this.words[n]=this.words[n]&e.words[n];return this.length=t.length,this._strip()},o.prototype.iand=function(e){return r(0==(this.negative|e.negative)),this.iuand(e)},o.prototype.and=function(e){return this.length>e.length?this.clone().iand(e):e.clone().iand(this)},o.prototype.uand=function(e){return this.length>e.length?this.clone().iuand(e):e.clone().iuand(this)},o.prototype.iuxor=function(e){var t,n;this.length>e.length?(t=this,n=e):(t=e,n=this);for(var r=0;r<n.length;r++)this.words[r]=t.words[r]^n.words[r];if(this!==t)for(;r<t.length;r++)this.words[r]=t.words[r];return this.length=t.length,this._strip()},o.prototype.ixor=function(e){return r(0==(this.negative|e.negative)),this.iuxor(e)},o.prototype.xor=function(e){return this.length>e.length?this.clone().ixor(e):e.clone().ixor(this)},o.prototype.uxor=function(e){return this.length>e.length?this.clone().iuxor(e):e.clone().iuxor(this)},o.prototype.inotn=function(e){r("number"==typeof e&&e>=0);var t=0|Math.ceil(e/26),n=e%26;this._expand(t),n>0&&t--;for(var i=0;i<t;i++)this.words[i]=67108863&~this.words[i];return n>0&&(this.words[i]=~this.words[i]&67108863>>26-n),this._strip()},o.prototype.notn=function(e){return this.clone().inotn(e)},o.prototype.setn=function(e,t){r("number"==typeof e&&e>=0);var n=e/26|0,i=e%26;return this._expand(n+1),this.words[n]=t?this.words[n]|1<<i:this.words[n]&~(1<<i),this._strip()},o.prototype.iadd=function(e){var t,n,r;if(0!==this.negative&&0===e.negative)return this.negative=0,t=this.isub(e),this.negative^=1,this._normSign();if(0===this.negative&&0!==e.negative)return e.negative=0,t=this.isub(e),e.negative=1,t._normSign();this.length>e.length?(n=this,r=e):(n=e,r=this);for(var i=0,o=0;o<r.length;o++)t=(0|n.words[o])+(0|r.words[o])+i,this.words[o]=67108863&t,i=t>>>26;for(;0!==i&&o<n.length;o++)t=(0|n.words[o])+i,this.words[o]=67108863&t,i=t>>>26;if(this.length=n.length,0!==i)this.words[this.length]=i,this.length++;else if(n!==this)for(;o<n.length;o++)this.words[o]=n.words[o];return this},o.prototype.add=function(e){var t;return 0!==e.negative&&0===this.negative?(e.negative=0,t=this.sub(e),e.negative^=1,t):0===e.negative&&0!==this.negative?(this.negative=0,t=e.sub(this),this.negative=1,t):this.length>e.length?this.clone().iadd(e):e.clone().iadd(this)},o.prototype.isub=function(e){if(0!==e.negative){e.negative=0;var t=this.iadd(e);return e.negative=1,t._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(e),this.negative=1,this._normSign();var n,r,i=this.cmp(e);if(0===i)return this.negative=0,this.length=1,this.words[0]=0,this;i>0?(n=this,r=e):(n=e,r=this);for(var o=0,s=0;s<r.length;s++)o=(t=(0|n.words[s])-(0|r.words[s])+o)>>26,this.words[s]=67108863&t;for(;0!==o&&s<n.length;s++)o=(t=(0|n.words[s])+o)>>26,this.words[s]=67108863&t;if(0===o&&s<n.length&&n!==this)for(;s<n.length;s++)this.words[s]=n.words[s];return this.length=Math.max(this.length,s),n!==this&&(this.negative=1),this._strip()},o.prototype.sub=function(e){return this.clone().isub(e)};var v=function(e,t,n){var r,i,o,s=e.words,a=t.words,u=n.words,c=0,f=0|s[0],l=8191&f,d=f>>>13,h=0|s[1],p=8191&h,v=h>>>13,g=0|s[2],m=8191&g,b=g>>>13,y=0|s[3],w=8191&y,_=y>>>13,S=0|s[4],E=8191&S,M=S>>>13,A=0|s[5],I=8191&A,k=A>>>13,O=0|s[6],x=8191&O,C=O>>>13,T=0|s[7],P=8191&T,N=T>>>13,R=0|s[8],L=8191&R,j=R>>>13,D=0|s[9],U=8191&D,B=D>>>13,F=0|a[0],z=8191&F,q=F>>>13,K=0|a[1],H=8191&K,V=K>>>13,G=0|a[2],W=8191&G,$=G>>>13,Y=0|a[3],J=8191&Y,Z=Y>>>13,X=0|a[4],Q=8191&X,ee=X>>>13,te=0|a[5],ne=8191&te,re=te>>>13,ie=0|a[6],oe=8191&ie,se=ie>>>13,ae=0|a[7],ue=8191&ae,ce=ae>>>13,fe=0|a[8],le=8191&fe,de=fe>>>13,he=0|a[9],pe=8191&he,ve=he>>>13;n.negative=e.negative^t.negative,n.length=19;var ge=(c+(r=Math.imul(l,z))|0)+((8191&(i=(i=Math.imul(l,q))+Math.imul(d,z)|0))<<13)|0;c=((o=Math.imul(d,q))+(i>>>13)|0)+(ge>>>26)|0,ge&=67108863,r=Math.imul(p,z),i=(i=Math.imul(p,q))+Math.imul(v,z)|0,o=Math.imul(v,q);var me=(c+(r=r+Math.imul(l,H)|0)|0)+((8191&(i=(i=i+Math.imul(l,V)|0)+Math.imul(d,H)|0))<<13)|0;c=((o=o+Math.imul(d,V)|0)+(i>>>13)|0)+(me>>>26)|0,me&=67108863,r=Math.imul(m,z),i=(i=Math.imul(m,q))+Math.imul(b,z)|0,o=Math.imul(b,q),r=r+Math.imul(p,H)|0,i=(i=i+Math.imul(p,V)|0)+Math.imul(v,H)|0,o=o+Math.imul(v,V)|0;var be=(c+(r=r+Math.imul(l,W)|0)|0)+((8191&(i=(i=i+Math.imul(l,$)|0)+Math.imul(d,W)|0))<<13)|0;c=((o=o+Math.imul(d,$)|0)+(i>>>13)|0)+(be>>>26)|0,be&=67108863,r=Math.imul(w,z),i=(i=Math.imul(w,q))+Math.imul(_,z)|0,o=Math.imul(_,q),r=r+Math.imul(m,H)|0,i=(i=i+Math.imul(m,V)|0)+Math.imul(b,H)|0,o=o+Math.imul(b,V)|0,r=r+Math.imul(p,W)|0,i=(i=i+Math.imul(p,$)|0)+Math.imul(v,W)|0,o=o+Math.imul(v,$)|0;var ye=(c+(r=r+Math.imul(l,J)|0)|0)+((8191&(i=(i=i+Math.imul(l,Z)|0)+Math.imul(d,J)|0))<<13)|0;c=((o=o+Math.imul(d,Z)|0)+(i>>>13)|0)+(ye>>>26)|0,ye&=67108863,r=Math.imul(E,z),i=(i=Math.imul(E,q))+Math.imul(M,z)|0,o=Math.imul(M,q),r=r+Math.imul(w,H)|0,i=(i=i+Math.imul(w,V)|0)+Math.imul(_,H)|0,o=o+Math.imul(_,V)|0,r=r+Math.imul(m,W)|0,i=(i=i+Math.imul(m,$)|0)+Math.imul(b,W)|0,o=o+Math.imul(b,$)|0,r=r+Math.imul(p,J)|0,i=(i=i+Math.imul(p,Z)|0)+Math.imul(v,J)|0,o=o+Math.imul(v,Z)|0;var we=(c+(r=r+Math.imul(l,Q)|0)|0)+((8191&(i=(i=i+Math.imul(l,ee)|0)+Math.imul(d,Q)|0))<<13)|0;c=((o=o+Math.imul(d,ee)|0)+(i>>>13)|0)+(we>>>26)|0,we&=67108863,r=Math.imul(I,z),i=(i=Math.imul(I,q))+Math.imul(k,z)|0,o=Math.imul(k,q),r=r+Math.imul(E,H)|0,i=(i=i+Math.imul(E,V)|0)+Math.imul(M,H)|0,o=o+Math.imul(M,V)|0,r=r+Math.imul(w,W)|0,i=(i=i+Math.imul(w,$)|0)+Math.imul(_,W)|0,o=o+Math.imul(_,$)|0,r=r+Math.imul(m,J)|0,i=(i=i+Math.imul(m,Z)|0)+Math.imul(b,J)|0,o=o+Math.imul(b,Z)|0,r=r+Math.imul(p,Q)|0,i=(i=i+Math.imul(p,ee)|0)+Math.imul(v,Q)|0,o=o+Math.imul(v,ee)|0;var _e=(c+(r=r+Math.imul(l,ne)|0)|0)+((8191&(i=(i=i+Math.imul(l,re)|0)+Math.imul(d,ne)|0))<<13)|0;c=((o=o+Math.imul(d,re)|0)+(i>>>13)|0)+(_e>>>26)|0,_e&=67108863,r=Math.imul(x,z),i=(i=Math.imul(x,q))+Math.imul(C,z)|0,o=Math.imul(C,q),r=r+Math.imul(I,H)|0,i=(i=i+Math.imul(I,V)|0)+Math.imul(k,H)|0,o=o+Math.imul(k,V)|0,r=r+Math.imul(E,W)|0,i=(i=i+Math.imul(E,$)|0)+Math.imul(M,W)|0,o=o+Math.imul(M,$)|0,r=r+Math.imul(w,J)|0,i=(i=i+Math.imul(w,Z)|0)+Math.imul(_,J)|0,o=o+Math.imul(_,Z)|0,r=r+Math.imul(m,Q)|0,i=(i=i+Math.imul(m,ee)|0)+Math.imul(b,Q)|0,o=o+Math.imul(b,ee)|0,r=r+Math.imul(p,ne)|0,i=(i=i+Math.imul(p,re)|0)+Math.imul(v,ne)|0,o=o+Math.imul(v,re)|0;var Se=(c+(r=r+Math.imul(l,oe)|0)|0)+((8191&(i=(i=i+Math.imul(l,se)|0)+Math.imul(d,oe)|0))<<13)|0;c=((o=o+Math.imul(d,se)|0)+(i>>>13)|0)+(Se>>>26)|0,Se&=67108863,r=Math.imul(P,z),i=(i=Math.imul(P,q))+Math.imul(N,z)|0,o=Math.imul(N,q),r=r+Math.imul(x,H)|0,i=(i=i+Math.imul(x,V)|0)+Math.imul(C,H)|0,o=o+Math.imul(C,V)|0,r=r+Math.imul(I,W)|0,i=(i=i+Math.imul(I,$)|0)+Math.imul(k,W)|0,o=o+Math.imul(k,$)|0,r=r+Math.imul(E,J)|0,i=(i=i+Math.imul(E,Z)|0)+Math.imul(M,J)|0,o=o+Math.imul(M,Z)|0,r=r+Math.imul(w,Q)|0,i=(i=i+Math.imul(w,ee)|0)+Math.imul(_,Q)|0,o=o+Math.imul(_,ee)|0,r=r+Math.imul(m,ne)|0,i=(i=i+Math.imul(m,re)|0)+Math.imul(b,ne)|0,o=o+Math.imul(b,re)|0,r=r+Math.imul(p,oe)|0,i=(i=i+Math.imul(p,se)|0)+Math.imul(v,oe)|0,o=o+Math.imul(v,se)|0;var Ee=(c+(r=r+Math.imul(l,ue)|0)|0)+((8191&(i=(i=i+Math.imul(l,ce)|0)+Math.imul(d,ue)|0))<<13)|0;c=((o=o+Math.imul(d,ce)|0)+(i>>>13)|0)+(Ee>>>26)|0,Ee&=67108863,r=Math.imul(L,z),i=(i=Math.imul(L,q))+Math.imul(j,z)|0,o=Math.imul(j,q),r=r+Math.imul(P,H)|0,i=(i=i+Math.imul(P,V)|0)+Math.imul(N,H)|0,o=o+Math.imul(N,V)|0,r=r+Math.imul(x,W)|0,i=(i=i+Math.imul(x,$)|0)+Math.imul(C,W)|0,o=o+Math.imul(C,$)|0,r=r+Math.imul(I,J)|0,i=(i=i+Math.imul(I,Z)|0)+Math.imul(k,J)|0,o=o+Math.imul(k,Z)|0,r=r+Math.imul(E,Q)|0,i=(i=i+Math.imul(E,ee)|0)+Math.imul(M,Q)|0,o=o+Math.imul(M,ee)|0,r=r+Math.imul(w,ne)|0,i=(i=i+Math.imul(w,re)|0)+Math.imul(_,ne)|0,o=o+Math.imul(_,re)|0,r=r+Math.imul(m,oe)|0,i=(i=i+Math.imul(m,se)|0)+Math.imul(b,oe)|0,o=o+Math.imul(b,se)|0,r=r+Math.imul(p,ue)|0,i=(i=i+Math.imul(p,ce)|0)+Math.imul(v,ue)|0,o=o+Math.imul(v,ce)|0;var Me=(c+(r=r+Math.imul(l,le)|0)|0)+((8191&(i=(i=i+Math.imul(l,de)|0)+Math.imul(d,le)|0))<<13)|0;c=((o=o+Math.imul(d,de)|0)+(i>>>13)|0)+(Me>>>26)|0,Me&=67108863,r=Math.imul(U,z),i=(i=Math.imul(U,q))+Math.imul(B,z)|0,o=Math.imul(B,q),r=r+Math.imul(L,H)|0,i=(i=i+Math.imul(L,V)|0)+Math.imul(j,H)|0,o=o+Math.imul(j,V)|0,r=r+Math.imul(P,W)|0,i=(i=i+Math.imul(P,$)|0)+Math.imul(N,W)|0,o=o+Math.imul(N,$)|0,r=r+Math.imul(x,J)|0,i=(i=i+Math.imul(x,Z)|0)+Math.imul(C,J)|0,o=o+Math.imul(C,Z)|0,r=r+Math.imul(I,Q)|0,i=(i=i+Math.imul(I,ee)|0)+Math.imul(k,Q)|0,o=o+Math.imul(k,ee)|0,r=r+Math.imul(E,ne)|0,i=(i=i+Math.imul(E,re)|0)+Math.imul(M,ne)|0,o=o+Math.imul(M,re)|0,r=r+Math.imul(w,oe)|0,i=(i=i+Math.imul(w,se)|0)+Math.imul(_,oe)|0,o=o+Math.imul(_,se)|0,r=r+Math.imul(m,ue)|0,i=(i=i+Math.imul(m,ce)|0)+Math.imul(b,ue)|0,o=o+Math.imul(b,ce)|0,r=r+Math.imul(p,le)|0,i=(i=i+Math.imul(p,de)|0)+Math.imul(v,le)|0,o=o+Math.imul(v,de)|0;var Ae=(c+(r=r+Math.imul(l,pe)|0)|0)+((8191&(i=(i=i+Math.imul(l,ve)|0)+Math.imul(d,pe)|0))<<13)|0;c=((o=o+Math.imul(d,ve)|0)+(i>>>13)|0)+(Ae>>>26)|0,Ae&=67108863,r=Math.imul(U,H),i=(i=Math.imul(U,V))+Math.imul(B,H)|0,o=Math.imul(B,V),r=r+Math.imul(L,W)|0,i=(i=i+Math.imul(L,$)|0)+Math.imul(j,W)|0,o=o+Math.imul(j,$)|0,r=r+Math.imul(P,J)|0,i=(i=i+Math.imul(P,Z)|0)+Math.imul(N,J)|0,o=o+Math.imul(N,Z)|0,r=r+Math.imul(x,Q)|0,i=(i=i+Math.imul(x,ee)|0)+Math.imul(C,Q)|0,o=o+Math.imul(C,ee)|0,r=r+Math.imul(I,ne)|0,i=(i=i+Math.imul(I,re)|0)+Math.imul(k,ne)|0,o=o+Math.imul(k,re)|0,r=r+Math.imul(E,oe)|0,i=(i=i+Math.imul(E,se)|0)+Math.imul(M,oe)|0,o=o+Math.imul(M,se)|0,r=r+Math.imul(w,ue)|0,i=(i=i+Math.imul(w,ce)|0)+Math.imul(_,ue)|0,o=o+Math.imul(_,ce)|0,r=r+Math.imul(m,le)|0,i=(i=i+Math.imul(m,de)|0)+Math.imul(b,le)|0,o=o+Math.imul(b,de)|0;var Ie=(c+(r=r+Math.imul(p,pe)|0)|0)+((8191&(i=(i=i+Math.imul(p,ve)|0)+Math.imul(v,pe)|0))<<13)|0;c=((o=o+Math.imul(v,ve)|0)+(i>>>13)|0)+(Ie>>>26)|0,Ie&=67108863,r=Math.imul(U,W),i=(i=Math.imul(U,$))+Math.imul(B,W)|0,o=Math.imul(B,$),r=r+Math.imul(L,J)|0,i=(i=i+Math.imul(L,Z)|0)+Math.imul(j,J)|0,o=o+Math.imul(j,Z)|0,r=r+Math.imul(P,Q)|0,i=(i=i+Math.imul(P,ee)|0)+Math.imul(N,Q)|0,o=o+Math.imul(N,ee)|0,r=r+Math.imul(x,ne)|0,i=(i=i+Math.imul(x,re)|0)+Math.imul(C,ne)|0,o=o+Math.imul(C,re)|0,r=r+Math.imul(I,oe)|0,i=(i=i+Math.imul(I,se)|0)+Math.imul(k,oe)|0,o=o+Math.imul(k,se)|0,r=r+Math.imul(E,ue)|0,i=(i=i+Math.imul(E,ce)|0)+Math.imul(M,ue)|0,o=o+Math.imul(M,ce)|0,r=r+Math.imul(w,le)|0,i=(i=i+Math.imul(w,de)|0)+Math.imul(_,le)|0,o=o+Math.imul(_,de)|0;var ke=(c+(r=r+Math.imul(m,pe)|0)|0)+((8191&(i=(i=i+Math.imul(m,ve)|0)+Math.imul(b,pe)|0))<<13)|0;c=((o=o+Math.imul(b,ve)|0)+(i>>>13)|0)+(ke>>>26)|0,ke&=67108863,r=Math.imul(U,J),i=(i=Math.imul(U,Z))+Math.imul(B,J)|0,o=Math.imul(B,Z),r=r+Math.imul(L,Q)|0,i=(i=i+Math.imul(L,ee)|0)+Math.imul(j,Q)|0,o=o+Math.imul(j,ee)|0,r=r+Math.imul(P,ne)|0,i=(i=i+Math.imul(P,re)|0)+Math.imul(N,ne)|0,o=o+Math.imul(N,re)|0,r=r+Math.imul(x,oe)|0,i=(i=i+Math.imul(x,se)|0)+Math.imul(C,oe)|0,o=o+Math.imul(C,se)|0,r=r+Math.imul(I,ue)|0,i=(i=i+Math.imul(I,ce)|0)+Math.imul(k,ue)|0,o=o+Math.imul(k,ce)|0,r=r+Math.imul(E,le)|0,i=(i=i+Math.imul(E,de)|0)+Math.imul(M,le)|0,o=o+Math.imul(M,de)|0;var Oe=(c+(r=r+Math.imul(w,pe)|0)|0)+((8191&(i=(i=i+Math.imul(w,ve)|0)+Math.imul(_,pe)|0))<<13)|0;c=((o=o+Math.imul(_,ve)|0)+(i>>>13)|0)+(Oe>>>26)|0,Oe&=67108863,r=Math.imul(U,Q),i=(i=Math.imul(U,ee))+Math.imul(B,Q)|0,o=Math.imul(B,ee),r=r+Math.imul(L,ne)|0,i=(i=i+Math.imul(L,re)|0)+Math.imul(j,ne)|0,o=o+Math.imul(j,re)|0,r=r+Math.imul(P,oe)|0,i=(i=i+Math.imul(P,se)|0)+Math.imul(N,oe)|0,o=o+Math.imul(N,se)|0,r=r+Math.imul(x,ue)|0,i=(i=i+Math.imul(x,ce)|0)+Math.imul(C,ue)|0,o=o+Math.imul(C,ce)|0,r=r+Math.imul(I,le)|0,i=(i=i+Math.imul(I,de)|0)+Math.imul(k,le)|0,o=o+Math.imul(k,de)|0;var xe=(c+(r=r+Math.imul(E,pe)|0)|0)+((8191&(i=(i=i+Math.imul(E,ve)|0)+Math.imul(M,pe)|0))<<13)|0;c=((o=o+Math.imul(M,ve)|0)+(i>>>13)|0)+(xe>>>26)|0,xe&=67108863,r=Math.imul(U,ne),i=(i=Math.imul(U,re))+Math.imul(B,ne)|0,o=Math.imul(B,re),r=r+Math.imul(L,oe)|0,i=(i=i+Math.imul(L,se)|0)+Math.imul(j,oe)|0,o=o+Math.imul(j,se)|0,r=r+Math.imul(P,ue)|0,i=(i=i+Math.imul(P,ce)|0)+Math.imul(N,ue)|0,o=o+Math.imul(N,ce)|0,r=r+Math.imul(x,le)|0,i=(i=i+Math.imul(x,de)|0)+Math.imul(C,le)|0,o=o+Math.imul(C,de)|0;var Ce=(c+(r=r+Math.imul(I,pe)|0)|0)+((8191&(i=(i=i+Math.imul(I,ve)|0)+Math.imul(k,pe)|0))<<13)|0;c=((o=o+Math.imul(k,ve)|0)+(i>>>13)|0)+(Ce>>>26)|0,Ce&=67108863,r=Math.imul(U,oe),i=(i=Math.imul(U,se))+Math.imul(B,oe)|0,o=Math.imul(B,se),r=r+Math.imul(L,ue)|0,i=(i=i+Math.imul(L,ce)|0)+Math.imul(j,ue)|0,o=o+Math.imul(j,ce)|0,r=r+Math.imul(P,le)|0,i=(i=i+Math.imul(P,de)|0)+Math.imul(N,le)|0,o=o+Math.imul(N,de)|0;var Te=(c+(r=r+Math.imul(x,pe)|0)|0)+((8191&(i=(i=i+Math.imul(x,ve)|0)+Math.imul(C,pe)|0))<<13)|0;c=((o=o+Math.imul(C,ve)|0)+(i>>>13)|0)+(Te>>>26)|0,Te&=67108863,r=Math.imul(U,ue),i=(i=Math.imul(U,ce))+Math.imul(B,ue)|0,o=Math.imul(B,ce),r=r+Math.imul(L,le)|0,i=(i=i+Math.imul(L,de)|0)+Math.imul(j,le)|0,o=o+Math.imul(j,de)|0;var Pe=(c+(r=r+Math.imul(P,pe)|0)|0)+((8191&(i=(i=i+Math.imul(P,ve)|0)+Math.imul(N,pe)|0))<<13)|0;c=((o=o+Math.imul(N,ve)|0)+(i>>>13)|0)+(Pe>>>26)|0,Pe&=67108863,r=Math.imul(U,le),i=(i=Math.imul(U,de))+Math.imul(B,le)|0,o=Math.imul(B,de);var Ne=(c+(r=r+Math.imul(L,pe)|0)|0)+((8191&(i=(i=i+Math.imul(L,ve)|0)+Math.imul(j,pe)|0))<<13)|0;c=((o=o+Math.imul(j,ve)|0)+(i>>>13)|0)+(Ne>>>26)|0,Ne&=67108863;var Re=(c+(r=Math.imul(U,pe))|0)+((8191&(i=(i=Math.imul(U,ve))+Math.imul(B,pe)|0))<<13)|0;return c=((o=Math.imul(B,ve))+(i>>>13)|0)+(Re>>>26)|0,Re&=67108863,u[0]=ge,u[1]=me,u[2]=be,u[3]=ye,u[4]=we,u[5]=_e,u[6]=Se,u[7]=Ee,u[8]=Me,u[9]=Ae,u[10]=Ie,u[11]=ke,u[12]=Oe,u[13]=xe,u[14]=Ce,u[15]=Te,u[16]=Pe,u[17]=Ne,u[18]=Re,0!==c&&(u[19]=c,n.length++),n};function g(e,t,n){n.negative=t.negative^e.negative,n.length=e.length+t.length;for(var r=0,i=0,o=0;o<n.length-1;o++){var s=i;i=0;for(var a=67108863&r,u=Math.min(o,t.length-1),c=Math.max(0,o-e.length+1);c<=u;c++){var f=o-c,l=(0|e.words[f])*(0|t.words[c]),d=67108863&l;a=67108863&(d=d+a|0),i+=(s=(s=s+(l/67108864|0)|0)+(d>>>26)|0)>>>26,s&=67108863}n.words[o]=a,r=s,s=i}return 0!==r?n.words[o]=r:n.length--,n._strip()}function m(e,t,n){return g(e,t,n)}function b(e,t){this.x=e,this.y=t}Math.imul||(v=p),o.prototype.mulTo=function(e,t){var n=this.length+e.length;return 10===this.length&&10===e.length?v(this,e,t):n<63?p(this,e,t):n<1024?g(this,e,t):m(this,e,t)},b.prototype.makeRBT=function(e){for(var t=new Array(e),n=o.prototype._countBits(e)-1,r=0;r<e;r++)t[r]=this.revBin(r,n,e);return t},b.prototype.revBin=function(e,t,n){if(0===e||e===n-1)return e;for(var r=0,i=0;i<t;i++)r|=(1&e)<<t-i-1,e>>=1;return r},b.prototype.permute=function(e,t,n,r,i,o){for(var s=0;s<o;s++)r[s]=t[e[s]],i[s]=n[e[s]]},b.prototype.transform=function(e,t,n,r,i,o){this.permute(o,e,t,n,r,i);for(var s=1;s<i;s<<=1)for(var a=s<<1,u=Math.cos(2*Math.PI/a),c=Math.sin(2*Math.PI/a),f=0;f<i;f+=a)for(var l=u,d=c,h=0;h<s;h++){var p=n[f+h],v=r[f+h],g=n[f+h+s],m=r[f+h+s],b=l*g-d*m;m=l*m+d*g,g=b,n[f+h]=p+g,r[f+h]=v+m,n[f+h+s]=p-g,r[f+h+s]=v-m,h!==a&&(b=u*l-c*d,d=u*d+c*l,l=b)}},b.prototype.guessLen13b=function(e,t){var n=1|Math.max(t,e),r=1&n,i=0;for(n=n/2|0;n;n>>>=1)i++;return 1<<i+1+r},b.prototype.conjugate=function(e,t,n){if(!(n<=1))for(var r=0;r<n/2;r++){var i=e[r];e[r]=e[n-r-1],e[n-r-1]=i,i=t[r],t[r]=-t[n-r-1],t[n-r-1]=-i}},b.prototype.normalize13b=function(e,t){for(var n=0,r=0;r<t/2;r++){var i=8192*Math.round(e[2*r+1]/t)+Math.round(e[2*r]/t)+n;e[r]=67108863&i,n=i<67108864?0:i/67108864|0}return e},b.prototype.convert13b=function(e,t,n,i){for(var o=0,s=0;s<t;s++)o+=0|e[s],n[2*s]=8191&o,o>>>=13,n[2*s+1]=8191&o,o>>>=13;for(s=2*t;s<i;++s)n[s]=0;r(0===o),r(0==(-8192&o))},b.prototype.stub=function(e){for(var t=new Array(e),n=0;n<e;n++)t[n]=0;return t},b.prototype.mulp=function(e,t,n){var r=2*this.guessLen13b(e.length,t.length),i=this.makeRBT(r),o=this.stub(r),s=new Array(r),a=new Array(r),u=new Array(r),c=new Array(r),f=new Array(r),l=new Array(r),d=n.words;d.length=r,this.convert13b(e.words,e.length,s,r),this.convert13b(t.words,t.length,c,r),this.transform(s,o,a,u,r,i),this.transform(c,o,f,l,r,i);for(var h=0;h<r;h++){var p=a[h]*f[h]-u[h]*l[h];u[h]=a[h]*l[h]+u[h]*f[h],a[h]=p}return this.conjugate(a,u,r),this.transform(a,u,d,o,r,i),this.conjugate(d,o,r),this.normalize13b(d,r),n.negative=e.negative^t.negative,n.length=e.length+t.length,n._strip()},o.prototype.mul=function(e){var t=new o(null);return t.words=new Array(this.length+e.length),this.mulTo(e,t)},o.prototype.mulf=function(e){var t=new o(null);return t.words=new Array(this.length+e.length),m(this,e,t)},o.prototype.imul=function(e){return this.clone().mulTo(e,this)},o.prototype.imuln=function(e){var t=e<0;t&&(e=-e),r("number"==typeof e),r(e<67108864);for(var n=0,i=0;i<this.length;i++){var o=(0|this.words[i])*e,s=(67108863&o)+(67108863&n);n>>=26,n+=o/67108864|0,n+=s>>>26,this.words[i]=67108863&s}return 0!==n&&(this.words[i]=n,this.length++),t?this.ineg():this},o.prototype.muln=function(e){return this.clone().imuln(e)},o.prototype.sqr=function(){return this.mul(this)},o.prototype.isqr=function(){return this.imul(this.clone())},o.prototype.pow=function(e){var t=function(e){for(var t=new Array(e.bitLength()),n=0;n<t.length;n++){var r=n/26|0,i=n%26;t[n]=e.words[r]>>>i&1}return t}(e);if(0===t.length)return new o(1);for(var n=this,r=0;r<t.length&&0===t[r];r++,n=n.sqr());if(++r<t.length)for(var i=n.sqr();r<t.length;r++,i=i.sqr())0!==t[r]&&(n=n.mul(i));return n},o.prototype.iushln=function(e){r("number"==typeof e&&e>=0);var t,n=e%26,i=(e-n)/26,o=67108863>>>26-n<<26-n;if(0!==n){var s=0;for(t=0;t<this.length;t++){var a=this.words[t]&o,u=(0|this.words[t])-a<<n;this.words[t]=u|s,s=a>>>26-n}s&&(this.words[t]=s,this.length++)}if(0!==i){for(t=this.length-1;t>=0;t--)this.words[t+i]=this.words[t];for(t=0;t<i;t++)this.words[t]=0;this.length+=i}return this._strip()},o.prototype.ishln=function(e){return r(0===this.negative),this.iushln(e)},o.prototype.iushrn=function(e,t,n){var i;r("number"==typeof e&&e>=0),i=t?(t-t%26)/26:0;var o=e%26,s=Math.min((e-o)/26,this.length),a=67108863^67108863>>>o<<o,u=n;if(i-=s,i=Math.max(0,i),u){for(var c=0;c<s;c++)u.words[c]=this.words[c];u.length=s}if(0===s);else if(this.length>s)for(this.length-=s,c=0;c<this.length;c++)this.words[c]=this.words[c+s];else this.words[0]=0,this.length=1;var f=0;for(c=this.length-1;c>=0&&(0!==f||c>=i);c--){var l=0|this.words[c];this.words[c]=f<<26-o|l>>>o,f=l&a}return u&&0!==f&&(u.words[u.length++]=f),0===this.length&&(this.words[0]=0,this.length=1),this._strip()},o.prototype.ishrn=function(e,t,n){return r(0===this.negative),this.iushrn(e,t,n)},o.prototype.shln=function(e){return this.clone().ishln(e)},o.prototype.ushln=function(e){return this.clone().iushln(e)},o.prototype.shrn=function(e){return this.clone().ishrn(e)},o.prototype.ushrn=function(e){return this.clone().iushrn(e)},o.prototype.testn=function(e){r("number"==typeof e&&e>=0);var t=e%26,n=(e-t)/26,i=1<<t;return!(this.length<=n)&&!!(this.words[n]&i)},o.prototype.imaskn=function(e){r("number"==typeof e&&e>=0);var t=e%26,n=(e-t)/26;if(r(0===this.negative,"imaskn works only with positive numbers"),this.length<=n)return this;if(0!==t&&n++,this.length=Math.min(n,this.length),0!==t){var i=67108863^67108863>>>t<<t;this.words[this.length-1]&=i}return this._strip()},o.prototype.maskn=function(e){return this.clone().imaskn(e)},o.prototype.iaddn=function(e){return r("number"==typeof e),r(e<67108864),e<0?this.isubn(-e):0!==this.negative?1===this.length&&(0|this.words[0])<=e?(this.words[0]=e-(0|this.words[0]),this.negative=0,this):(this.negative=0,this.isubn(e),this.negative=1,this):this._iaddn(e)},o.prototype._iaddn=function(e){this.words[0]+=e;for(var t=0;t<this.length&&this.words[t]>=67108864;t++)this.words[t]-=67108864,t===this.length-1?this.words[t+1]=1:this.words[t+1]++;return this.length=Math.max(this.length,t+1),this},o.prototype.isubn=function(e){if(r("number"==typeof e),r(e<67108864),e<0)return this.iaddn(-e);if(0!==this.negative)return this.negative=0,this.iaddn(e),this.negative=1,this;if(this.words[0]-=e,1===this.length&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var t=0;t<this.length&&this.words[t]<0;t++)this.words[t]+=67108864,this.words[t+1]-=1;return this._strip()},o.prototype.addn=function(e){return this.clone().iaddn(e)},o.prototype.subn=function(e){return this.clone().isubn(e)},o.prototype.iabs=function(){return this.negative=0,this},o.prototype.abs=function(){return this.clone().iabs()},o.prototype._ishlnsubmul=function(e,t,n){var i,o,s=e.length+n;this._expand(s);var a=0;for(i=0;i<e.length;i++){o=(0|this.words[i+n])+a;var u=(0|e.words[i])*t;a=((o-=67108863&u)>>26)-(u/67108864|0),this.words[i+n]=67108863&o}for(;i<this.length-n;i++)a=(o=(0|this.words[i+n])+a)>>26,this.words[i+n]=67108863&o;if(0===a)return this._strip();for(r(-1===a),a=0,i=0;i<this.length;i++)a=(o=-(0|this.words[i])+a)>>26,this.words[i]=67108863&o;return this.negative=1,this._strip()},o.prototype._wordDiv=function(e,t){var n=(this.length,e.length),r=this.clone(),i=e,s=0|i.words[i.length-1];0!==(n=26-this._countBits(s))&&(i=i.ushln(n),r.iushln(n),s=0|i.words[i.length-1]);var a,u=r.length-i.length;if("mod"!==t){(a=new o(null)).length=u+1,a.words=new Array(a.length);for(var c=0;c<a.length;c++)a.words[c]=0}var f=r.clone()._ishlnsubmul(i,1,u);0===f.negative&&(r=f,a&&(a.words[u]=1));for(var l=u-1;l>=0;l--){var d=67108864*(0|r.words[i.length+l])+(0|r.words[i.length+l-1]);for(d=Math.min(d/s|0,67108863),r._ishlnsubmul(i,d,l);0!==r.negative;)d--,r.negative=0,r._ishlnsubmul(i,1,l),r.isZero()||(r.negative^=1);a&&(a.words[l]=d)}return a&&a._strip(),r._strip(),"div"!==t&&0!==n&&r.iushrn(n),{div:a||null,mod:r}},o.prototype.divmod=function(e,t,n){return r(!e.isZero()),this.isZero()?{div:new o(0),mod:new o(0)}:0!==this.negative&&0===e.negative?(a=this.neg().divmod(e,t),"mod"!==t&&(i=a.div.neg()),"div"!==t&&(s=a.mod.neg(),n&&0!==s.negative&&s.iadd(e)),{div:i,mod:s}):0===this.negative&&0!==e.negative?(a=this.divmod(e.neg(),t),"mod"!==t&&(i=a.div.neg()),{div:i,mod:a.mod}):0!=(this.negative&e.negative)?(a=this.neg().divmod(e.neg(),t),"div"!==t&&(s=a.mod.neg(),n&&0!==s.negative&&s.isub(e)),{div:a.div,mod:s}):e.length>this.length||this.cmp(e)<0?{div:new o(0),mod:this}:1===e.length?"div"===t?{div:this.divn(e.words[0]),mod:null}:"mod"===t?{div:null,mod:new o(this.modrn(e.words[0]))}:{div:this.divn(e.words[0]),mod:new o(this.modrn(e.words[0]))}:this._wordDiv(e,t);var i,s,a},o.prototype.div=function(e){return this.divmod(e,"div",!1).div},o.prototype.mod=function(e){return this.divmod(e,"mod",!1).mod},o.prototype.umod=function(e){return this.divmod(e,"mod",!0).mod},o.prototype.divRound=function(e){var t=this.divmod(e);if(t.mod.isZero())return t.div;var n=0!==t.div.negative?t.mod.isub(e):t.mod,r=e.ushrn(1),i=e.andln(1),o=n.cmp(r);return o<0||1===i&&0===o?t.div:0!==t.div.negative?t.div.isubn(1):t.div.iaddn(1)},o.prototype.modrn=function(e){var t=e<0;t&&(e=-e),r(e<=67108863);for(var n=(1<<26)%e,i=0,o=this.length-1;o>=0;o--)i=(n*i+(0|this.words[o]))%e;return t?-i:i},o.prototype.modn=function(e){return this.modrn(e)},o.prototype.idivn=function(e){var t=e<0;t&&(e=-e),r(e<=67108863);for(var n=0,i=this.length-1;i>=0;i--){var o=(0|this.words[i])+67108864*n;this.words[i]=o/e|0,n=o%e}return this._strip(),t?this.ineg():this},o.prototype.divn=function(e){return this.clone().idivn(e)},o.prototype.egcd=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i=new o(1),s=new o(0),a=new o(0),u=new o(1),c=0;t.isEven()&&n.isEven();)t.iushrn(1),n.iushrn(1),++c;for(var f=n.clone(),l=t.clone();!t.isZero();){for(var d=0,h=1;0==(t.words[0]&h)&&d<26;++d,h<<=1);if(d>0)for(t.iushrn(d);d-- >0;)(i.isOdd()||s.isOdd())&&(i.iadd(f),s.isub(l)),i.iushrn(1),s.iushrn(1);for(var p=0,v=1;0==(n.words[0]&v)&&p<26;++p,v<<=1);if(p>0)for(n.iushrn(p);p-- >0;)(a.isOdd()||u.isOdd())&&(a.iadd(f),u.isub(l)),a.iushrn(1),u.iushrn(1);t.cmp(n)>=0?(t.isub(n),i.isub(a),s.isub(u)):(n.isub(t),a.isub(i),u.isub(s))}return{a:a,b:u,gcd:n.iushln(c)}},o.prototype._invmp=function(e){r(0===e.negative),r(!e.isZero());var t=this,n=e.clone();t=0!==t.negative?t.umod(e):t.clone();for(var i,s=new o(1),a=new o(0),u=n.clone();t.cmpn(1)>0&&n.cmpn(1)>0;){for(var c=0,f=1;0==(t.words[0]&f)&&c<26;++c,f<<=1);if(c>0)for(t.iushrn(c);c-- >0;)s.isOdd()&&s.iadd(u),s.iushrn(1);for(var l=0,d=1;0==(n.words[0]&d)&&l<26;++l,d<<=1);if(l>0)for(n.iushrn(l);l-- >0;)a.isOdd()&&a.iadd(u),a.iushrn(1);t.cmp(n)>=0?(t.isub(n),s.isub(a)):(n.isub(t),a.isub(s))}return(i=0===t.cmpn(1)?s:a).cmpn(0)<0&&i.iadd(e),i},o.prototype.gcd=function(e){if(this.isZero())return e.abs();if(e.isZero())return this.abs();var t=this.clone(),n=e.clone();t.negative=0,n.negative=0;for(var r=0;t.isEven()&&n.isEven();r++)t.iushrn(1),n.iushrn(1);for(;;){for(;t.isEven();)t.iushrn(1);for(;n.isEven();)n.iushrn(1);var i=t.cmp(n);if(i<0){var o=t;t=n,n=o}else if(0===i||0===n.cmpn(1))break;t.isub(n)}return n.iushln(r)},o.prototype.invm=function(e){return this.egcd(e).a.umod(e)},o.prototype.isEven=function(){return 0==(1&this.words[0])},o.prototype.isOdd=function(){return 1==(1&this.words[0])},o.prototype.andln=function(e){return this.words[0]&e},o.prototype.bincn=function(e){r("number"==typeof e);var t=e%26,n=(e-t)/26,i=1<<t;if(this.length<=n)return this._expand(n+1),this.words[n]|=i,this;for(var o=i,s=n;0!==o&&s<this.length;s++){var a=0|this.words[s];o=(a+=o)>>>26,a&=67108863,this.words[s]=a}return 0!==o&&(this.words[s]=o,this.length++),this},o.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},o.prototype.cmpn=function(e){var t,n=e<0;if(0!==this.negative&&!n)return-1;if(0===this.negative&&n)return 1;if(this._strip(),this.length>1)t=1;else{n&&(e=-e),r(e<=67108863,"Number is too big");var i=0|this.words[0];t=i===e?0:i<e?-1:1}return 0!==this.negative?0|-t:t},o.prototype.cmp=function(e){if(0!==this.negative&&0===e.negative)return-1;if(0===this.negative&&0!==e.negative)return 1;var t=this.ucmp(e);return 0!==this.negative?0|-t:t},o.prototype.ucmp=function(e){if(this.length>e.length)return 1;if(this.length<e.length)return-1;for(var t=0,n=this.length-1;n>=0;n--){var r=0|this.words[n],i=0|e.words[n];if(r!==i){r<i?t=-1:r>i&&(t=1);break}}return t},o.prototype.gtn=function(e){return 1===this.cmpn(e)},o.prototype.gt=function(e){return 1===this.cmp(e)},o.prototype.gten=function(e){return this.cmpn(e)>=0},o.prototype.gte=function(e){return this.cmp(e)>=0},o.prototype.ltn=function(e){return-1===this.cmpn(e)},o.prototype.lt=function(e){return-1===this.cmp(e)},o.prototype.lten=function(e){return this.cmpn(e)<=0},o.prototype.lte=function(e){return this.cmp(e)<=0},o.prototype.eqn=function(e){return 0===this.cmpn(e)},o.prototype.eq=function(e){return 0===this.cmp(e)},o.red=function(e){return new A(e)},o.prototype.toRed=function(e){return r(!this.red,"Already a number in reduction context"),r(0===this.negative,"red works only with positives"),e.convertTo(this)._forceRed(e)},o.prototype.fromRed=function(){return r(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},o.prototype._forceRed=function(e){return this.red=e,this},o.prototype.forceRed=function(e){return r(!this.red,"Already a number in reduction context"),this._forceRed(e)},o.prototype.redAdd=function(e){return r(this.red,"redAdd works only with red numbers"),this.red.add(this,e)},o.prototype.redIAdd=function(e){return r(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,e)},o.prototype.redSub=function(e){return r(this.red,"redSub works only with red numbers"),this.red.sub(this,e)},o.prototype.redISub=function(e){return r(this.red,"redISub works only with red numbers"),this.red.isub(this,e)},o.prototype.redShl=function(e){return r(this.red,"redShl works only with red numbers"),this.red.shl(this,e)},o.prototype.redMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.mul(this,e)},o.prototype.redIMul=function(e){return r(this.red,"redMul works only with red numbers"),this.red._verify2(this,e),this.red.imul(this,e)},o.prototype.redSqr=function(){return r(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},o.prototype.redISqr=function(){return r(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},o.prototype.redSqrt=function(){return r(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},o.prototype.redInvm=function(){return r(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},o.prototype.redNeg=function(){return r(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},o.prototype.redPow=function(e){return r(this.red&&!e.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,e)};var y={k256:null,p224:null,p192:null,p25519:null};function w(e,t){this.name=e,this.p=new o(t,16),this.n=this.p.bitLength(),this.k=new o(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function _(){w.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function S(){w.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function E(){w.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function M(){w.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function A(e){if("string"==typeof e){var t=o._prime(e);this.m=t.p,this.prime=t}else r(e.gtn(1),"modulus must be greater than 1"),this.m=e,this.prime=null}function I(e){A.call(this,e),this.shift=this.m.bitLength(),this.shift%26!=0&&(this.shift+=26-this.shift%26),this.r=new o(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}w.prototype._tmp=function(){var e=new o(null);return e.words=new Array(Math.ceil(this.n/13)),e},w.prototype.ireduce=function(e){var t,n=e;do{this.split(n,this.tmp),t=(n=(n=this.imulK(n)).iadd(this.tmp)).bitLength()}while(t>this.n);var r=t<this.n?-1:n.ucmp(this.p);return 0===r?(n.words[0]=0,n.length=1):r>0?n.isub(this.p):void 0!==n.strip?n.strip():n._strip(),n},w.prototype.split=function(e,t){e.iushrn(this.n,0,t)},w.prototype.imulK=function(e){return e.imul(this.k)},i(_,w),_.prototype.split=function(e,t){for(var n=Math.min(e.length,9),r=0;r<n;r++)t.words[r]=e.words[r];if(t.length=n,e.length<=9)return e.words[0]=0,void(e.length=1);var i=e.words[9];for(t.words[t.length++]=4194303&i,r=10;r<e.length;r++){var o=0|e.words[r];e.words[r-10]=(4194303&o)<<4|i>>>22,i=o}i>>>=22,e.words[r-10]=i,0===i&&e.length>10?e.length-=10:e.length-=9},_.prototype.imulK=function(e){e.words[e.length]=0,e.words[e.length+1]=0,e.length+=2;for(var t=0,n=0;n<e.length;n++){var r=0|e.words[n];t+=977*r,e.words[n]=67108863&t,t=64*r+(t/67108864|0)}return 0===e.words[e.length-1]&&(e.length--,0===e.words[e.length-1]&&e.length--),e},i(S,w),i(E,w),i(M,w),M.prototype.imulK=function(e){for(var t=0,n=0;n<e.length;n++){var r=19*(0|e.words[n])+t,i=67108863&r;r>>>=26,e.words[n]=i,t=r}return 0!==t&&(e.words[e.length++]=t),e},o._prime=function(e){if(y[e])return y[e];var t;if("k256"===e)t=new _;else if("p224"===e)t=new S;else if("p192"===e)t=new E;else{if("p25519"!==e)throw new Error("Unknown prime "+e);t=new M}return y[e]=t,t},A.prototype._verify1=function(e){r(0===e.negative,"red works only with positives"),r(e.red,"red works only with red numbers")},A.prototype._verify2=function(e,t){r(0==(e.negative|t.negative),"red works only with positives"),r(e.red&&e.red===t.red,"red works only with red numbers")},A.prototype.imod=function(e){return this.prime?this.prime.ireduce(e)._forceRed(this):(c(e,e.umod(this.m)._forceRed(this)),e)},A.prototype.neg=function(e){return e.isZero()?e.clone():this.m.sub(e)._forceRed(this)},A.prototype.add=function(e,t){this._verify2(e,t);var n=e.add(t);return n.cmp(this.m)>=0&&n.isub(this.m),n._forceRed(this)},A.prototype.iadd=function(e,t){this._verify2(e,t);var n=e.iadd(t);return n.cmp(this.m)>=0&&n.isub(this.m),n},A.prototype.sub=function(e,t){this._verify2(e,t);var n=e.sub(t);return n.cmpn(0)<0&&n.iadd(this.m),n._forceRed(this)},A.prototype.isub=function(e,t){this._verify2(e,t);var n=e.isub(t);return n.cmpn(0)<0&&n.iadd(this.m),n},A.prototype.shl=function(e,t){return this._verify1(e),this.imod(e.ushln(t))},A.prototype.imul=function(e,t){return this._verify2(e,t),this.imod(e.imul(t))},A.prototype.mul=function(e,t){return this._verify2(e,t),this.imod(e.mul(t))},A.prototype.isqr=function(e){return this.imul(e,e.clone())},A.prototype.sqr=function(e){return this.mul(e,e)},A.prototype.sqrt=function(e){if(e.isZero())return e.clone();var t=this.m.andln(3);if(r(t%2==1),3===t){var n=this.m.add(new o(1)).iushrn(2);return this.pow(e,n)}for(var i=this.m.subn(1),s=0;!i.isZero()&&0===i.andln(1);)s++,i.iushrn(1);r(!i.isZero());var a=new o(1).toRed(this),u=a.redNeg(),c=this.m.subn(1).iushrn(1),f=this.m.bitLength();for(f=new o(2*f*f).toRed(this);0!==this.pow(f,c).cmp(u);)f.redIAdd(u);for(var l=this.pow(f,i),d=this.pow(e,i.addn(1).iushrn(1)),h=this.pow(e,i),p=s;0!==h.cmp(a);){for(var v=h,g=0;0!==v.cmp(a);g++)v=v.redSqr();r(g<p);var m=this.pow(l,new o(1).iushln(p-g-1));d=d.redMul(m),l=m.redSqr(),h=h.redMul(l),p=g}return d},A.prototype.invm=function(e){var t=e._invmp(this.m);return 0!==t.negative?(t.negative=0,this.imod(t).redNeg()):this.imod(t)},A.prototype.pow=function(e,t){if(t.isZero())return new o(1).toRed(this);if(0===t.cmpn(1))return e.clone();var n=new Array(16);n[0]=new o(1).toRed(this),n[1]=e;for(var r=2;r<n.length;r++)n[r]=this.mul(n[r-1],e);var i=n[0],s=0,a=0,u=t.bitLength()%26;for(0===u&&(u=26),r=t.length-1;r>=0;r--){for(var c=t.words[r],f=u-1;f>=0;f--){var l=c>>f&1;i!==n[0]&&(i=this.sqr(i)),0!==l||0!==s?(s<<=1,s|=l,(4===++a||0===r&&0===f)&&(i=this.mul(i,n[s]),a=0,s=0)):a=0}u=26}return i},A.prototype.convertTo=function(e){var t=e.umod(this.m);return t===e?t.clone():t},A.prototype.convertFrom=function(e){var t=e.clone();return t.red=null,t},o.mont=function(e){return new I(e)},i(I,A),I.prototype.convertTo=function(e){return this.imod(e.ushln(this.shift))},I.prototype.convertFrom=function(e){var t=this.imod(e.mul(this.rinv));return t.red=null,t},I.prototype.imul=function(e,t){if(e.isZero()||t.isZero())return e.words[0]=0,e.length=1,e;var n=e.imul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),o=i;return i.cmp(this.m)>=0?o=i.isub(this.m):i.cmpn(0)<0&&(o=i.iadd(this.m)),o._forceRed(this)},I.prototype.mul=function(e,t){if(e.isZero()||t.isZero())return new o(0)._forceRed(this);var n=e.mul(t),r=n.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=n.isub(r).iushrn(this.shift),s=i;return i.cmp(this.m)>=0?s=i.isub(this.m):i.cmpn(0)<0&&(s=i.iadd(this.m)),s._forceRed(this)},I.prototype.invm=function(e){return this.imod(e._invmp(this.m).mul(this.r2))._forceRed(this)}}(e,this)}).call(this,n(57)(e))},function(e,t){},function(e){e.exports=JSON.parse('{"name":"elliptic","version":"6.5.4","description":"EC cryptography","main":"lib/elliptic.js","files":["lib"],"scripts":{"lint":"eslint lib test","lint:fix":"npm run lint -- --fix","unit":"istanbul test _mocha --reporter=spec test/index.js","test":"npm run lint && npm run unit","version":"grunt dist && git add dist/"},"repository":{"type":"git","url":"git@github.com:indutny/elliptic"},"keywords":["EC","Elliptic","curve","Cryptography"],"author":"Fedor Indutny <fedor@indutny.com>","license":"MIT","bugs":{"url":"https://github.com/indutny/elliptic/issues"},"homepage":"https://github.com/indutny/elliptic","devDependencies":{"brfs":"^2.0.2","coveralls":"^3.1.0","eslint":"^7.6.0","grunt":"^1.2.1","grunt-browserify":"^5.3.0","grunt-cli":"^1.3.2","grunt-contrib-connect":"^3.0.0","grunt-contrib-copy":"^1.0.0","grunt-contrib-uglify":"^5.0.0","grunt-mocha-istanbul":"^5.0.2","grunt-saucelabs":"^9.0.1","istanbul":"^0.4.5","mocha":"^8.0.1"},"dependencies":{"bn.js":"^4.11.9","brorand":"^1.1.0","hash.js":"^1.0.0","hmac-drbg":"^1.0.1","inherits":"^2.0.4","minimalistic-assert":"^1.0.1","minimalistic-crypto-utils":"^1.0.1"}}')},function(e,t,n){"use strict";var r=n(47),i=n(29),o=n(7),s=n(95),a=r.assert;function u(e){s.call(this,"short",e),this.a=new i(e.a,16).toRed(this.red),this.b=new i(e.b,16).toRed(this.red),this.tinv=this.two.redInvm(),this.zeroA=0===this.a.fromRed().cmpn(0),this.threeA=0===this.a.fromRed().sub(this.p).cmpn(-3),this.endo=this._getEndomorphism(e),this._endoWnafT1=new Array(4),this._endoWnafT2=new Array(4)}function c(e,t,n,r){s.BasePoint.call(this,e,"affine"),null===t&&null===n?(this.x=null,this.y=null,this.inf=!0):(this.x=new i(t,16),this.y=new i(n,16),r&&(this.x.forceRed(this.curve.red),this.y.forceRed(this.curve.red)),this.x.red||(this.x=this.x.toRed(this.curve.red)),this.y.red||(this.y=this.y.toRed(this.curve.red)),this.inf=!1)}function f(e,t,n,r){s.BasePoint.call(this,e,"jacobian"),null===t&&null===n&&null===r?(this.x=this.curve.one,this.y=this.curve.one,this.z=new i(0)):(this.x=new i(t,16),this.y=new i(n,16),this.z=new i(r,16)),this.x.red||(this.x=this.x.toRed(this.curve.red)),this.y.red||(this.y=this.y.toRed(this.curve.red)),this.z.red||(this.z=this.z.toRed(this.curve.red)),this.zOne=this.z===this.curve.one}o(u,s),e.exports=u,u.prototype._getEndomorphism=function(e){if(this.zeroA&&this.g&&this.n&&1===this.p.modn(3)){var t,n;if(e.beta)t=new i(e.beta,16).toRed(this.red);else{var r=this._getEndoRoots(this.p);t=(t=r[0].cmp(r[1])<0?r[0]:r[1]).toRed(this.red)}if(e.lambda)n=new i(e.lambda,16);else{var o=this._getEndoRoots(this.n);0===this.g.mul(o[0]).x.cmp(this.g.x.redMul(t))?n=o[0]:(n=o[1],a(0===this.g.mul(n).x.cmp(this.g.x.redMul(t))))}return{beta:t,lambda:n,basis:e.basis?e.basis.map((function(e){return{a:new i(e.a,16),b:new i(e.b,16)}})):this._getEndoBasis(n)}}},u.prototype._getEndoRoots=function(e){var t=e===this.p?this.red:i.mont(e),n=new i(2).toRed(t).redInvm(),r=n.redNeg(),o=new i(3).toRed(t).redNeg().redSqrt().redMul(n);return[r.redAdd(o).fromRed(),r.redSub(o).fromRed()]},u.prototype._getEndoBasis=function(e){for(var t,n,r,o,s,a,u,c,f,l=this.n.ushrn(Math.floor(this.n.bitLength()/2)),d=e,h=this.n.clone(),p=new i(1),v=new i(0),g=new i(0),m=new i(1),b=0;0!==d.cmpn(0);){var y=h.div(d);c=h.sub(y.mul(d)),f=g.sub(y.mul(p));var w=m.sub(y.mul(v));if(!r&&c.cmp(l)<0)t=u.neg(),n=p,r=c.neg(),o=f;else if(r&&2==++b)break;u=c,h=d,d=c,g=p,p=f,m=v,v=w}s=c.neg(),a=f;var _=r.sqr().add(o.sqr());return s.sqr().add(a.sqr()).cmp(_)>=0&&(s=t,a=n),r.negative&&(r=r.neg(),o=o.neg()),s.negative&&(s=s.neg(),a=a.neg()),[{a:r,b:o},{a:s,b:a}]},u.prototype._endoSplit=function(e){var t=this.endo.basis,n=t[0],r=t[1],i=r.b.mul(e).divRound(this.n),o=n.b.neg().mul(e).divRound(this.n),s=i.mul(n.a),a=o.mul(r.a),u=i.mul(n.b),c=o.mul(r.b);return{k1:e.sub(s).sub(a),k2:u.add(c).neg()}},u.prototype.pointFromX=function(e,t){(e=new i(e,16)).red||(e=e.toRed(this.red));var n=e.redSqr().redMul(e).redIAdd(e.redMul(this.a)).redIAdd(this.b),r=n.redSqrt();if(0!==r.redSqr().redSub(n).cmp(this.zero))throw new Error("invalid point");var o=r.fromRed().isOdd();return(t&&!o||!t&&o)&&(r=r.redNeg()),this.point(e,r)},u.prototype.validate=function(e){if(e.inf)return!0;var t=e.x,n=e.y,r=this.a.redMul(t),i=t.redSqr().redMul(t).redIAdd(r).redIAdd(this.b);return 0===n.redSqr().redISub(i).cmpn(0)},u.prototype._endoWnafMulAdd=function(e,t,n){for(var r=this._endoWnafT1,i=this._endoWnafT2,o=0;o<e.length;o++){var s=this._endoSplit(t[o]),a=e[o],u=a._getBeta();s.k1.negative&&(s.k1.ineg(),a=a.neg(!0)),s.k2.negative&&(s.k2.ineg(),u=u.neg(!0)),r[2*o]=a,r[2*o+1]=u,i[2*o]=s.k1,i[2*o+1]=s.k2}for(var c=this._wnafMulAdd(1,r,i,2*o,n),f=0;f<2*o;f++)r[f]=null,i[f]=null;return c},o(c,s.BasePoint),u.prototype.point=function(e,t,n){return new c(this,e,t,n)},u.prototype.pointFromJSON=function(e,t){return c.fromJSON(this,e,t)},c.prototype._getBeta=function(){if(this.curve.endo){var e=this.precomputed;if(e&&e.beta)return e.beta;var t=this.curve.point(this.x.redMul(this.curve.endo.beta),this.y);if(e){var n=this.curve,r=function(e){return n.point(e.x.redMul(n.endo.beta),e.y)};e.beta=t,t.precomputed={beta:null,naf:e.naf&&{wnd:e.naf.wnd,points:e.naf.points.map(r)},doubles:e.doubles&&{step:e.doubles.step,points:e.doubles.points.map(r)}}}return t}},c.prototype.toJSON=function(){return this.precomputed?[this.x,this.y,this.precomputed&&{doubles:this.precomputed.doubles&&{step:this.precomputed.doubles.step,points:this.precomputed.doubles.points.slice(1)},naf:this.precomputed.naf&&{wnd:this.precomputed.naf.wnd,points:this.precomputed.naf.points.slice(1)}}]:[this.x,this.y]},c.fromJSON=function(e,t,n){"string"==typeof t&&(t=JSON.parse(t));var r=e.point(t[0],t[1],n);if(!t[2])return r;function i(t){return e.point(t[0],t[1],n)}var o=t[2];return r.precomputed={beta:null,doubles:o.doubles&&{step:o.doubles.step,points:[r].concat(o.doubles.points.map(i))},naf:o.naf&&{wnd:o.naf.wnd,points:[r].concat(o.naf.points.map(i))}},r},c.prototype.inspect=function(){return this.isInfinity()?"<EC Point Infinity>":"<EC Point x: "+this.x.fromRed().toString(16,2)+" y: "+this.y.fromRed().toString(16,2)+">"},c.prototype.isInfinity=function(){return this.inf},c.prototype.add=function(e){if(this.inf)return e;if(e.inf)return this;if(this.eq(e))return this.dbl();if(this.neg().eq(e))return this.curve.point(null,null);if(0===this.x.cmp(e.x))return this.curve.point(null,null);var t=this.y.redSub(e.y);0!==t.cmpn(0)&&(t=t.redMul(this.x.redSub(e.x).redInvm()));var n=t.redSqr().redISub(this.x).redISub(e.x),r=t.redMul(this.x.redSub(n)).redISub(this.y);return this.curve.point(n,r)},c.prototype.dbl=function(){if(this.inf)return this;var e=this.y.redAdd(this.y);if(0===e.cmpn(0))return this.curve.point(null,null);var t=this.curve.a,n=this.x.redSqr(),r=e.redInvm(),i=n.redAdd(n).redIAdd(n).redIAdd(t).redMul(r),o=i.redSqr().redISub(this.x.redAdd(this.x)),s=i.redMul(this.x.redSub(o)).redISub(this.y);return this.curve.point(o,s)},c.prototype.getX=function(){return this.x.fromRed()},c.prototype.getY=function(){return this.y.fromRed()},c.prototype.mul=function(e){return e=new i(e,16),this.isInfinity()?this:this._hasDoubles(e)?this.curve._fixedNafMul(this,e):this.curve.endo?this.curve._endoWnafMulAdd([this],[e]):this.curve._wnafMul(this,e)},c.prototype.mulAdd=function(e,t,n){var r=[this,t],i=[e,n];return this.curve.endo?this.curve._endoWnafMulAdd(r,i):this.curve._wnafMulAdd(1,r,i,2)},c.prototype.jmulAdd=function(e,t,n){var r=[this,t],i=[e,n];return this.curve.endo?this.curve._endoWnafMulAdd(r,i,!0):this.curve._wnafMulAdd(1,r,i,2,!0)},c.prototype.eq=function(e){return this===e||this.inf===e.inf&&(this.inf||0===this.x.cmp(e.x)&&0===this.y.cmp(e.y))},c.prototype.neg=function(e){if(this.inf)return this;var t=this.curve.point(this.x,this.y.redNeg());if(e&&this.precomputed){var n=this.precomputed,r=function(e){return e.neg()};t.precomputed={naf:n.naf&&{wnd:n.naf.wnd,points:n.naf.points.map(r)},doubles:n.doubles&&{step:n.doubles.step,points:n.doubles.points.map(r)}}}return t},c.prototype.toJ=function(){return this.inf?this.curve.jpoint(null,null,null):this.curve.jpoint(this.x,this.y,this.curve.one)},o(f,s.BasePoint),u.prototype.jpoint=function(e,t,n){return new f(this,e,t,n)},f.prototype.toP=function(){if(this.isInfinity())return this.curve.point(null,null);var e=this.z.redInvm(),t=e.redSqr(),n=this.x.redMul(t),r=this.y.redMul(t).redMul(e);return this.curve.point(n,r)},f.prototype.neg=function(){return this.curve.jpoint(this.x,this.y.redNeg(),this.z)},f.prototype.add=function(e){if(this.isInfinity())return e;if(e.isInfinity())return this;var t=e.z.redSqr(),n=this.z.redSqr(),r=this.x.redMul(t),i=e.x.redMul(n),o=this.y.redMul(t.redMul(e.z)),s=e.y.redMul(n.redMul(this.z)),a=r.redSub(i),u=o.redSub(s);if(0===a.cmpn(0))return 0!==u.cmpn(0)?this.curve.jpoint(null,null,null):this.dbl();var c=a.redSqr(),f=c.redMul(a),l=r.redMul(c),d=u.redSqr().redIAdd(f).redISub(l).redISub(l),h=u.redMul(l.redISub(d)).redISub(o.redMul(f)),p=this.z.redMul(e.z).redMul(a);return this.curve.jpoint(d,h,p)},f.prototype.mixedAdd=function(e){if(this.isInfinity())return e.toJ();if(e.isInfinity())return this;var t=this.z.redSqr(),n=this.x,r=e.x.redMul(t),i=this.y,o=e.y.redMul(t).redMul(this.z),s=n.redSub(r),a=i.redSub(o);if(0===s.cmpn(0))return 0!==a.cmpn(0)?this.curve.jpoint(null,null,null):this.dbl();var u=s.redSqr(),c=u.redMul(s),f=n.redMul(u),l=a.redSqr().redIAdd(c).redISub(f).redISub(f),d=a.redMul(f.redISub(l)).redISub(i.redMul(c)),h=this.z.redMul(s);return this.curve.jpoint(l,d,h)},f.prototype.dblp=function(e){if(0===e)return this;if(this.isInfinity())return this;if(!e)return this.dbl();var t;if(this.curve.zeroA||this.curve.threeA){var n=this;for(t=0;t<e;t++)n=n.dbl();return n}var r=this.curve.a,i=this.curve.tinv,o=this.x,s=this.y,a=this.z,u=a.redSqr().redSqr(),c=s.redAdd(s);for(t=0;t<e;t++){var f=o.redSqr(),l=c.redSqr(),d=l.redSqr(),h=f.redAdd(f).redIAdd(f).redIAdd(r.redMul(u)),p=o.redMul(l),v=h.redSqr().redISub(p.redAdd(p)),g=p.redISub(v),m=h.redMul(g);m=m.redIAdd(m).redISub(d);var b=c.redMul(a);t+1<e&&(u=u.redMul(d)),o=v,a=b,c=m}return this.curve.jpoint(o,c.redMul(i),a)},f.prototype.dbl=function(){return this.isInfinity()?this:this.curve.zeroA?this._zeroDbl():this.curve.threeA?this._threeDbl():this._dbl()},f.prototype._zeroDbl=function(){var e,t,n;if(this.zOne){var r=this.x.redSqr(),i=this.y.redSqr(),o=i.redSqr(),s=this.x.redAdd(i).redSqr().redISub(r).redISub(o);s=s.redIAdd(s);var a=r.redAdd(r).redIAdd(r),u=a.redSqr().redISub(s).redISub(s),c=o.redIAdd(o);c=(c=c.redIAdd(c)).redIAdd(c),e=u,t=a.redMul(s.redISub(u)).redISub(c),n=this.y.redAdd(this.y)}else{var f=this.x.redSqr(),l=this.y.redSqr(),d=l.redSqr(),h=this.x.redAdd(l).redSqr().redISub(f).redISub(d);h=h.redIAdd(h);var p=f.redAdd(f).redIAdd(f),v=p.redSqr(),g=d.redIAdd(d);g=(g=g.redIAdd(g)).redIAdd(g),e=v.redISub(h).redISub(h),t=p.redMul(h.redISub(e)).redISub(g),n=(n=this.y.redMul(this.z)).redIAdd(n)}return this.curve.jpoint(e,t,n)},f.prototype._threeDbl=function(){var e,t,n;if(this.zOne){var r=this.x.redSqr(),i=this.y.redSqr(),o=i.redSqr(),s=this.x.redAdd(i).redSqr().redISub(r).redISub(o);s=s.redIAdd(s);var a=r.redAdd(r).redIAdd(r).redIAdd(this.curve.a),u=a.redSqr().redISub(s).redISub(s);e=u;var c=o.redIAdd(o);c=(c=c.redIAdd(c)).redIAdd(c),t=a.redMul(s.redISub(u)).redISub(c),n=this.y.redAdd(this.y)}else{var f=this.z.redSqr(),l=this.y.redSqr(),d=this.x.redMul(l),h=this.x.redSub(f).redMul(this.x.redAdd(f));h=h.redAdd(h).redIAdd(h);var p=d.redIAdd(d),v=(p=p.redIAdd(p)).redAdd(p);e=h.redSqr().redISub(v),n=this.y.redAdd(this.z).redSqr().redISub(l).redISub(f);var g=l.redSqr();g=(g=(g=g.redIAdd(g)).redIAdd(g)).redIAdd(g),t=h.redMul(p.redISub(e)).redISub(g)}return this.curve.jpoint(e,t,n)},f.prototype._dbl=function(){var e=this.curve.a,t=this.x,n=this.y,r=this.z,i=r.redSqr().redSqr(),o=t.redSqr(),s=n.redSqr(),a=o.redAdd(o).redIAdd(o).redIAdd(e.redMul(i)),u=t.redAdd(t),c=(u=u.redIAdd(u)).redMul(s),f=a.redSqr().redISub(c.redAdd(c)),l=c.redISub(f),d=s.redSqr();d=(d=(d=d.redIAdd(d)).redIAdd(d)).redIAdd(d);var h=a.redMul(l).redISub(d),p=n.redAdd(n).redMul(r);return this.curve.jpoint(f,h,p)},f.prototype.trpl=function(){if(!this.curve.zeroA)return this.dbl().add(this);var e=this.x.redSqr(),t=this.y.redSqr(),n=this.z.redSqr(),r=t.redSqr(),i=e.redAdd(e).redIAdd(e),o=i.redSqr(),s=this.x.redAdd(t).redSqr().redISub(e).redISub(r),a=(s=(s=(s=s.redIAdd(s)).redAdd(s).redIAdd(s)).redISub(o)).redSqr(),u=r.redIAdd(r);u=(u=(u=u.redIAdd(u)).redIAdd(u)).redIAdd(u);var c=i.redIAdd(s).redSqr().redISub(o).redISub(a).redISub(u),f=t.redMul(c);f=(f=f.redIAdd(f)).redIAdd(f);var l=this.x.redMul(a).redISub(f);l=(l=l.redIAdd(l)).redIAdd(l);var d=this.y.redMul(c.redMul(u.redISub(c)).redISub(s.redMul(a)));d=(d=(d=d.redIAdd(d)).redIAdd(d)).redIAdd(d);var h=this.z.redAdd(s).redSqr().redISub(n).redISub(a);return this.curve.jpoint(l,d,h)},f.prototype.mul=function(e,t){return e=new i(e,t),this.curve._wnafMul(this,e)},f.prototype.eq=function(e){if("affine"===e.type)return this.eq(e.toJ());if(this===e)return!0;var t=this.z.redSqr(),n=e.z.redSqr();if(0!==this.x.redMul(n).redISub(e.x.redMul(t)).cmpn(0))return!1;var r=t.redMul(this.z),i=n.redMul(e.z);return 0===this.y.redMul(i).redISub(e.y.redMul(r)).cmpn(0)},f.prototype.eqXToP=function(e){var t=this.z.redSqr(),n=e.toRed(this.curve.red).redMul(t);if(0===this.x.cmp(n))return!0;for(var r=e.clone(),i=this.curve.redN.redMul(t);;){if(r.iadd(this.curve.n),r.cmp(this.curve.p)>=0)return!1;if(n.redIAdd(i),0===this.x.cmp(n))return!0}},f.prototype.inspect=function(){return this.isInfinity()?"<EC JPoint Infinity>":"<EC JPoint x: "+this.x.toString(16,2)+" y: "+this.y.toString(16,2)+" z: "+this.z.toString(16,2)+">"},f.prototype.isInfinity=function(){return 0===this.z.cmpn(0)}},function(e,t,n){"use strict";var r=n(29),i=n(7),o=n(95),s=n(47);function a(e){o.call(this,"mont",e),this.a=new r(e.a,16).toRed(this.red),this.b=new r(e.b,16).toRed(this.red),this.i4=new r(4).toRed(this.red).redInvm(),this.two=new r(2).toRed(this.red),this.a24=this.i4.redMul(this.a.redAdd(this.two))}function u(e,t,n){o.BasePoint.call(this,e,"projective"),null===t&&null===n?(this.x=this.curve.one,this.z=this.curve.zero):(this.x=new r(t,16),this.z=new r(n,16),this.x.red||(this.x=this.x.toRed(this.curve.red)),this.z.red||(this.z=this.z.toRed(this.curve.red)))}i(a,o),e.exports=a,a.prototype.validate=function(e){var t=e.normalize().x,n=t.redSqr(),r=n.redMul(t).redAdd(n.redMul(this.a)).redAdd(t);return 0===r.redSqrt().redSqr().cmp(r)},i(u,o.BasePoint),a.prototype.decodePoint=function(e,t){return this.point(s.toArray(e,t),1)},a.prototype.point=function(e,t){return new u(this,e,t)},a.prototype.pointFromJSON=function(e){return u.fromJSON(this,e)},u.prototype.precompute=function(){},u.prototype._encode=function(){return this.getX().toArray("be",this.curve.p.byteLength())},u.fromJSON=function(e,t){return new u(e,t[0],t[1]||e.one)},u.prototype.inspect=function(){return this.isInfinity()?"<EC Point Infinity>":"<EC Point x: "+this.x.fromRed().toString(16,2)+" z: "+this.z.fromRed().toString(16,2)+">"},u.prototype.isInfinity=function(){return 0===this.z.cmpn(0)},u.prototype.dbl=function(){var e=this.x.redAdd(this.z).redSqr(),t=this.x.redSub(this.z).redSqr(),n=e.redSub(t),r=e.redMul(t),i=n.redMul(t.redAdd(this.curve.a24.redMul(n)));return this.curve.point(r,i)},u.prototype.add=function(){throw new Error("Not supported on Montgomery curve")},u.prototype.diffAdd=function(e,t){var n=this.x.redAdd(this.z),r=this.x.redSub(this.z),i=e.x.redAdd(e.z),o=e.x.redSub(e.z).redMul(n),s=i.redMul(r),a=t.z.redMul(o.redAdd(s).redSqr()),u=t.x.redMul(o.redISub(s).redSqr());return this.curve.point(a,u)},u.prototype.mul=function(e){for(var t=e.clone(),n=this,r=this.curve.point(null,null),i=[];0!==t.cmpn(0);t.iushrn(1))i.push(t.andln(1));for(var o=i.length-1;o>=0;o--)0===i[o]?(n=n.diffAdd(r,this),r=r.dbl()):(r=n.diffAdd(r,this),n=n.dbl());return r},u.prototype.mulAdd=function(){throw new Error("Not supported on Montgomery curve")},u.prototype.jumlAdd=function(){throw new Error("Not supported on Montgomery curve")},u.prototype.eq=function(e){return 0===this.getX().cmp(e.getX())},u.prototype.normalize=function(){return this.x=this.x.redMul(this.z.redInvm()),this.z=this.curve.one,this},u.prototype.getX=function(){return this.normalize(),this.x.fromRed()}},function(e,t,n){"use strict";var r=n(47),i=n(29),o=n(7),s=n(95),a=r.assert;function u(e){this.twisted=1!=(0|e.a),this.mOneA=this.twisted&&-1==(0|e.a),this.extended=this.mOneA,s.call(this,"edwards",e),this.a=new i(e.a,16).umod(this.red.m),this.a=this.a.toRed(this.red),this.c=new i(e.c,16).toRed(this.red),this.c2=this.c.redSqr(),this.d=new i(e.d,16).toRed(this.red),this.dd=this.d.redAdd(this.d),a(!this.twisted||0===this.c.fromRed().cmpn(1)),this.oneC=1==(0|e.c)}function c(e,t,n,r,o){s.BasePoint.call(this,e,"projective"),null===t&&null===n&&null===r?(this.x=this.curve.zero,this.y=this.curve.one,this.z=this.curve.one,this.t=this.curve.zero,this.zOne=!0):(this.x=new i(t,16),this.y=new i(n,16),this.z=r?new i(r,16):this.curve.one,this.t=o&&new i(o,16),this.x.red||(this.x=this.x.toRed(this.curve.red)),this.y.red||(this.y=this.y.toRed(this.curve.red)),this.z.red||(this.z=this.z.toRed(this.curve.red)),this.t&&!this.t.red&&(this.t=this.t.toRed(this.curve.red)),this.zOne=this.z===this.curve.one,this.curve.extended&&!this.t&&(this.t=this.x.redMul(this.y),this.zOne||(this.t=this.t.redMul(this.z.redInvm()))))}o(u,s),e.exports=u,u.prototype._mulA=function(e){return this.mOneA?e.redNeg():this.a.redMul(e)},u.prototype._mulC=function(e){return this.oneC?e:this.c.redMul(e)},u.prototype.jpoint=function(e,t,n,r){return this.point(e,t,n,r)},u.prototype.pointFromX=function(e,t){(e=new i(e,16)).red||(e=e.toRed(this.red));var n=e.redSqr(),r=this.c2.redSub(this.a.redMul(n)),o=this.one.redSub(this.c2.redMul(this.d).redMul(n)),s=r.redMul(o.redInvm()),a=s.redSqrt();if(0!==a.redSqr().redSub(s).cmp(this.zero))throw new Error("invalid point");var u=a.fromRed().isOdd();return(t&&!u||!t&&u)&&(a=a.redNeg()),this.point(e,a)},u.prototype.pointFromY=function(e,t){(e=new i(e,16)).red||(e=e.toRed(this.red));var n=e.redSqr(),r=n.redSub(this.c2),o=n.redMul(this.d).redMul(this.c2).redSub(this.a),s=r.redMul(o.redInvm());if(0===s.cmp(this.zero)){if(t)throw new Error("invalid point");return this.point(this.zero,e)}var a=s.redSqrt();if(0!==a.redSqr().redSub(s).cmp(this.zero))throw new Error("invalid point");return a.fromRed().isOdd()!==t&&(a=a.redNeg()),this.point(a,e)},u.prototype.validate=function(e){if(e.isInfinity())return!0;e.normalize();var t=e.x.redSqr(),n=e.y.redSqr(),r=t.redMul(this.a).redAdd(n),i=this.c2.redMul(this.one.redAdd(this.d.redMul(t).redMul(n)));return 0===r.cmp(i)},o(c,s.BasePoint),u.prototype.pointFromJSON=function(e){return c.fromJSON(this,e)},u.prototype.point=function(e,t,n,r){return new c(this,e,t,n,r)},c.fromJSON=function(e,t){return new c(e,t[0],t[1],t[2])},c.prototype.inspect=function(){return this.isInfinity()?"<EC Point Infinity>":"<EC Point x: "+this.x.fromRed().toString(16,2)+" y: "+this.y.fromRed().toString(16,2)+" z: "+this.z.fromRed().toString(16,2)+">"},c.prototype.isInfinity=function(){return 0===this.x.cmpn(0)&&(0===this.y.cmp(this.z)||this.zOne&&0===this.y.cmp(this.curve.c))},c.prototype._extDbl=function(){var e=this.x.redSqr(),t=this.y.redSqr(),n=this.z.redSqr();n=n.redIAdd(n);var r=this.curve._mulA(e),i=this.x.redAdd(this.y).redSqr().redISub(e).redISub(t),o=r.redAdd(t),s=o.redSub(n),a=r.redSub(t),u=i.redMul(s),c=o.redMul(a),f=i.redMul(a),l=s.redMul(o);return this.curve.point(u,c,l,f)},c.prototype._projDbl=function(){var e,t,n,r,i,o,s=this.x.redAdd(this.y).redSqr(),a=this.x.redSqr(),u=this.y.redSqr();if(this.curve.twisted){var c=(r=this.curve._mulA(a)).redAdd(u);this.zOne?(e=s.redSub(a).redSub(u).redMul(c.redSub(this.curve.two)),t=c.redMul(r.redSub(u)),n=c.redSqr().redSub(c).redSub(c)):(i=this.z.redSqr(),o=c.redSub(i).redISub(i),e=s.redSub(a).redISub(u).redMul(o),t=c.redMul(r.redSub(u)),n=c.redMul(o))}else r=a.redAdd(u),i=this.curve._mulC(this.z).redSqr(),o=r.redSub(i).redSub(i),e=this.curve._mulC(s.redISub(r)).redMul(o),t=this.curve._mulC(r).redMul(a.redISub(u)),n=r.redMul(o);return this.curve.point(e,t,n)},c.prototype.dbl=function(){return this.isInfinity()?this:this.curve.extended?this._extDbl():this._projDbl()},c.prototype._extAdd=function(e){var t=this.y.redSub(this.x).redMul(e.y.redSub(e.x)),n=this.y.redAdd(this.x).redMul(e.y.redAdd(e.x)),r=this.t.redMul(this.curve.dd).redMul(e.t),i=this.z.redMul(e.z.redAdd(e.z)),o=n.redSub(t),s=i.redSub(r),a=i.redAdd(r),u=n.redAdd(t),c=o.redMul(s),f=a.redMul(u),l=o.redMul(u),d=s.redMul(a);return this.curve.point(c,f,d,l)},c.prototype._projAdd=function(e){var t,n,r=this.z.redMul(e.z),i=r.redSqr(),o=this.x.redMul(e.x),s=this.y.redMul(e.y),a=this.curve.d.redMul(o).redMul(s),u=i.redSub(a),c=i.redAdd(a),f=this.x.redAdd(this.y).redMul(e.x.redAdd(e.y)).redISub(o).redISub(s),l=r.redMul(u).redMul(f);return this.curve.twisted?(t=r.redMul(c).redMul(s.redSub(this.curve._mulA(o))),n=u.redMul(c)):(t=r.redMul(c).redMul(s.redSub(o)),n=this.curve._mulC(u).redMul(c)),this.curve.point(l,t,n)},c.prototype.add=function(e){return this.isInfinity()?e:e.isInfinity()?this:this.curve.extended?this._extAdd(e):this._projAdd(e)},c.prototype.mul=function(e){return this._hasDoubles(e)?this.curve._fixedNafMul(this,e):this.curve._wnafMul(this,e)},c.prototype.mulAdd=function(e,t,n){return this.curve._wnafMulAdd(1,[this,t],[e,n],2,!1)},c.prototype.jmulAdd=function(e,t,n){return this.curve._wnafMulAdd(1,[this,t],[e,n],2,!0)},c.prototype.normalize=function(){if(this.zOne)return this;var e=this.z.redInvm();return this.x=this.x.redMul(e),this.y=this.y.redMul(e),this.t&&(this.t=this.t.redMul(e)),this.z=this.curve.one,this.zOne=!0,this},c.prototype.neg=function(){return this.curve.point(this.x.redNeg(),this.y,this.z,this.t&&this.t.redNeg())},c.prototype.getX=function(){return this.normalize(),this.x.fromRed()},c.prototype.getY=function(){return this.normalize(),this.y.fromRed()},c.prototype.eq=function(e){return this===e||0===this.getX().cmp(e.getX())&&0===this.getY().cmp(e.getY())},c.prototype.eqXToP=function(e){var t=e.toRed(this.curve.red).redMul(this.z);if(0===this.x.cmp(t))return!0;for(var n=e.clone(),r=this.curve.redN.redMul(this.z);;){if(n.iadd(this.curve.n),n.cmp(this.curve.p)>=0)return!1;if(t.redIAdd(r),0===this.x.cmp(t))return!0}},c.prototype.toP=c.prototype.normalize,c.prototype.mixedAdd=c.prototype.add},function(e,t,n){"use strict";t.sha1=n(336),t.sha224=n(337),t.sha256=n(201),t.sha384=n(338),t.sha512=n(202)},function(e,t,n){"use strict";var r=n(51),i=n(82),o=n(200),s=r.rotl32,a=r.sum32,u=r.sum32_5,c=o.ft_1,f=i.BlockHash,l=[1518500249,1859775393,2400959708,3395469782];function d(){if(!(this instanceof d))return new d;f.call(this),this.h=[1732584193,4023233417,2562383102,271733878,3285377520],this.W=new Array(80)}r.inherits(d,f),e.exports=d,d.blockSize=512,d.outSize=160,d.hmacStrength=80,d.padLength=64,d.prototype._update=function(e,t){for(var n=this.W,r=0;r<16;r++)n[r]=e[t+r];for(;r<n.length;r++)n[r]=s(n[r-3]^n[r-8]^n[r-14]^n[r-16],1);var i=this.h[0],o=this.h[1],f=this.h[2],d=this.h[3],h=this.h[4];for(r=0;r<n.length;r++){var p=~~(r/20),v=u(s(i,5),c(p,o,f,d),h,n[r],l[p]);h=d,d=f,f=s(o,30),o=i,i=v}this.h[0]=a(this.h[0],i),this.h[1]=a(this.h[1],o),this.h[2]=a(this.h[2],f),this.h[3]=a(this.h[3],d),this.h[4]=a(this.h[4],h)},d.prototype._digest=function(e){return"hex"===e?r.toHex32(this.h,"big"):r.split32(this.h,"big")}},function(e,t,n){"use strict";var r=n(51),i=n(201);function o(){if(!(this instanceof o))return new o;i.call(this),this.h=[3238371032,914150663,812702999,4144912697,4290775857,1750603025,1694076839,3204075428]}r.inherits(o,i),e.exports=o,o.blockSize=512,o.outSize=224,o.hmacStrength=192,o.padLength=64,o.prototype._digest=function(e){return"hex"===e?r.toHex32(this.h.slice(0,7),"big"):r.split32(this.h.slice(0,7),"big")}},function(e,t,n){"use strict";var r=n(51),i=n(202);function o(){if(!(this instanceof o))return new o;i.call(this),this.h=[3418070365,3238371032,1654270250,914150663,2438529370,812702999,355462360,4144912697,1731405415,4290775857,2394180231,1750603025,3675008525,1694076839,1203062813,3204075428]}r.inherits(o,i),e.exports=o,o.blockSize=1024,o.outSize=384,o.hmacStrength=192,o.padLength=128,o.prototype._digest=function(e){return"hex"===e?r.toHex32(this.h.slice(0,12),"big"):r.split32(this.h.slice(0,12),"big")}},function(e,t,n){"use strict";var r=n(51),i=n(82),o=r.rotl32,s=r.sum32,a=r.sum32_3,u=r.sum32_4,c=i.BlockHash;function f(){if(!(this instanceof f))return new f;c.call(this),this.h=[1732584193,4023233417,2562383102,271733878,3285377520],this.endian="little"}function l(e,t,n,r){return e<=15?t^n^r:e<=31?t&n|~t&r:e<=47?(t|~n)^r:e<=63?t&r|n&~r:t^(n|~r)}function d(e){return e<=15?0:e<=31?1518500249:e<=47?1859775393:e<=63?2400959708:2840853838}function h(e){return e<=15?1352829926:e<=31?1548603684:e<=47?1836072691:e<=63?2053994217:0}r.inherits(f,c),t.ripemd160=f,f.blockSize=512,f.outSize=160,f.hmacStrength=192,f.padLength=64,f.prototype._update=function(e,t){for(var n=this.h[0],r=this.h[1],i=this.h[2],c=this.h[3],f=this.h[4],b=n,y=r,w=i,_=c,S=f,E=0;E<80;E++){var M=s(o(u(n,l(E,r,i,c),e[p[E]+t],d(E)),g[E]),f);n=f,f=c,c=o(i,10),i=r,r=M,M=s(o(u(b,l(79-E,y,w,_),e[v[E]+t],h(E)),m[E]),S),b=S,S=_,_=o(w,10),w=y,y=M}M=a(this.h[1],i,_),this.h[1]=a(this.h[2],c,S),this.h[2]=a(this.h[3],f,b),this.h[3]=a(this.h[4],n,y),this.h[4]=a(this.h[0],r,w),this.h[0]=M},f.prototype._digest=function(e){return"hex"===e?r.toHex32(this.h,"little"):r.split32(this.h,"little")};var p=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13],v=[5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11],g=[11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6],m=[8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]},function(e,t,n){"use strict";var r=n(51),i=n(46);function o(e,t,n){if(!(this instanceof o))return new o(e,t,n);this.Hash=e,this.blockSize=e.blockSize/8,this.outSize=e.outSize/8,this.inner=null,this.outer=null,this._init(r.toArray(t,n))}e.exports=o,o.prototype._init=function(e){e.length>this.blockSize&&(e=(new this.Hash).update(e).digest()),i(e.length<=this.blockSize);for(var t=e.length;t<this.blockSize;t++)e.push(0);for(t=0;t<e.length;t++)e[t]^=54;for(this.inner=(new this.Hash).update(e),t=0;t<e.length;t++)e[t]^=106;this.outer=(new this.Hash).update(e)},o.prototype.update=function(e,t){return this.inner.update(e,t),this},o.prototype.digest=function(e){return this.outer.update(this.inner.digest()),this.outer.digest(e)}},function(e,t){e.exports={doubles:{step:4,points:[["e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0a","f7e3507399e595929db99f34f57937101296891e44d23f0be1f32cce69616821"],["8282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508","11f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf"],["175e159f728b865a72f99cc6c6fc846de0b93833fd2222ed73fce5b551e5b739","d3506e0d9e3c79eba4ef97a51ff71f5eacb5955add24345c6efa6ffee9fed695"],["363d90d447b00c9c99ceac05b6262ee053441c7e55552ffe526bad8f83ff4640","4e273adfc732221953b445397f3363145b9a89008199ecb62003c7f3bee9de9"],["8b4b5f165df3c2be8c6244b5b745638843e4a781a15bcd1b69f79a55dffdf80c","4aad0a6f68d308b4b3fbd7813ab0da04f9e336546162ee56b3eff0c65fd4fd36"],["723cbaa6e5db996d6bf771c00bd548c7b700dbffa6c0e77bcb6115925232fcda","96e867b5595cc498a921137488824d6e2660a0653779494801dc069d9eb39f5f"],["eebfa4d493bebf98ba5feec812c2d3b50947961237a919839a533eca0e7dd7fa","5d9a8ca3970ef0f269ee7edaf178089d9ae4cdc3a711f712ddfd4fdae1de8999"],["100f44da696e71672791d0a09b7bde459f1215a29b3c03bfefd7835b39a48db0","cdd9e13192a00b772ec8f3300c090666b7ff4a18ff5195ac0fbd5cd62bc65a09"],["e1031be262c7ed1b1dc9227a4a04c017a77f8d4464f3b3852c8acde6e534fd2d","9d7061928940405e6bb6a4176597535af292dd419e1ced79a44f18f29456a00d"],["feea6cae46d55b530ac2839f143bd7ec5cf8b266a41d6af52d5e688d9094696d","e57c6b6c97dce1bab06e4e12bf3ecd5c981c8957cc41442d3155debf18090088"],["da67a91d91049cdcb367be4be6ffca3cfeed657d808583de33fa978bc1ec6cb1","9bacaa35481642bc41f463f7ec9780e5dec7adc508f740a17e9ea8e27a68be1d"],["53904faa0b334cdda6e000935ef22151ec08d0f7bb11069f57545ccc1a37b7c0","5bc087d0bc80106d88c9eccac20d3c1c13999981e14434699dcb096b022771c8"],["8e7bcd0bd35983a7719cca7764ca906779b53a043a9b8bcaeff959f43ad86047","10b7770b2a3da4b3940310420ca9514579e88e2e47fd68b3ea10047e8460372a"],["385eed34c1cdff21e6d0818689b81bde71a7f4f18397e6690a841e1599c43862","283bebc3e8ea23f56701de19e9ebf4576b304eec2086dc8cc0458fe5542e5453"],["6f9d9b803ecf191637c73a4413dfa180fddf84a5947fbc9c606ed86c3fac3a7","7c80c68e603059ba69b8e2a30e45c4d47ea4dd2f5c281002d86890603a842160"],["3322d401243c4e2582a2147c104d6ecbf774d163db0f5e5313b7e0e742d0e6bd","56e70797e9664ef5bfb019bc4ddaf9b72805f63ea2873af624f3a2e96c28b2a0"],["85672c7d2de0b7da2bd1770d89665868741b3f9af7643397721d74d28134ab83","7c481b9b5b43b2eb6374049bfa62c2e5e77f17fcc5298f44c8e3094f790313a6"],["948bf809b1988a46b06c9f1919413b10f9226c60f668832ffd959af60c82a0a","53a562856dcb6646dc6b74c5d1c3418c6d4dff08c97cd2bed4cb7f88d8c8e589"],["6260ce7f461801c34f067ce0f02873a8f1b0e44dfc69752accecd819f38fd8e8","bc2da82b6fa5b571a7f09049776a1ef7ecd292238051c198c1a84e95b2b4ae17"],["e5037de0afc1d8d43d8348414bbf4103043ec8f575bfdc432953cc8d2037fa2d","4571534baa94d3b5f9f98d09fb990bddbd5f5b03ec481f10e0e5dc841d755bda"],["e06372b0f4a207adf5ea905e8f1771b4e7e8dbd1c6a6c5b725866a0ae4fce725","7a908974bce18cfe12a27bb2ad5a488cd7484a7787104870b27034f94eee31dd"],["213c7a715cd5d45358d0bbf9dc0ce02204b10bdde2a3f58540ad6908d0559754","4b6dad0b5ae462507013ad06245ba190bb4850f5f36a7eeddff2c27534b458f2"],["4e7c272a7af4b34e8dbb9352a5419a87e2838c70adc62cddf0cc3a3b08fbd53c","17749c766c9d0b18e16fd09f6def681b530b9614bff7dd33e0b3941817dcaae6"],["fea74e3dbe778b1b10f238ad61686aa5c76e3db2be43057632427e2840fb27b6","6e0568db9b0b13297cf674deccb6af93126b596b973f7b77701d3db7f23cb96f"],["76e64113f677cf0e10a2570d599968d31544e179b760432952c02a4417bdde39","c90ddf8dee4e95cf577066d70681f0d35e2a33d2b56d2032b4b1752d1901ac01"],["c738c56b03b2abe1e8281baa743f8f9a8f7cc643df26cbee3ab150242bcbb891","893fb578951ad2537f718f2eacbfbbbb82314eef7880cfe917e735d9699a84c3"],["d895626548b65b81e264c7637c972877d1d72e5f3a925014372e9f6588f6c14b","febfaa38f2bc7eae728ec60818c340eb03428d632bb067e179363ed75d7d991f"],["b8da94032a957518eb0f6433571e8761ceffc73693e84edd49150a564f676e03","2804dfa44805a1e4d7c99cc9762808b092cc584d95ff3b511488e4e74efdf6e7"],["e80fea14441fb33a7d8adab9475d7fab2019effb5156a792f1a11778e3c0df5d","eed1de7f638e00771e89768ca3ca94472d155e80af322ea9fcb4291b6ac9ec78"],["a301697bdfcd704313ba48e51d567543f2a182031efd6915ddc07bbcc4e16070","7370f91cfb67e4f5081809fa25d40f9b1735dbf7c0a11a130c0d1a041e177ea1"],["90ad85b389d6b936463f9d0512678de208cc330b11307fffab7ac63e3fb04ed4","e507a3620a38261affdcbd9427222b839aefabe1582894d991d4d48cb6ef150"],["8f68b9d2f63b5f339239c1ad981f162ee88c5678723ea3351b7b444c9ec4c0da","662a9f2dba063986de1d90c2b6be215dbbea2cfe95510bfdf23cbf79501fff82"],["e4f3fb0176af85d65ff99ff9198c36091f48e86503681e3e6686fd5053231e11","1e63633ad0ef4f1c1661a6d0ea02b7286cc7e74ec951d1c9822c38576feb73bc"],["8c00fa9b18ebf331eb961537a45a4266c7034f2f0d4e1d0716fb6eae20eae29e","efa47267fea521a1a9dc343a3736c974c2fadafa81e36c54e7d2a4c66702414b"],["e7a26ce69dd4829f3e10cec0a9e98ed3143d084f308b92c0997fddfc60cb3e41","2a758e300fa7984b471b006a1aafbb18d0a6b2c0420e83e20e8a9421cf2cfd51"],["b6459e0ee3662ec8d23540c223bcbdc571cbcb967d79424f3cf29eb3de6b80ef","67c876d06f3e06de1dadf16e5661db3c4b3ae6d48e35b2ff30bf0b61a71ba45"],["d68a80c8280bb840793234aa118f06231d6f1fc67e73c5a5deda0f5b496943e8","db8ba9fff4b586d00c4b1f9177b0e28b5b0e7b8f7845295a294c84266b133120"],["324aed7df65c804252dc0270907a30b09612aeb973449cea4095980fc28d3d5d","648a365774b61f2ff130c0c35aec1f4f19213b0c7e332843967224af96ab7c84"],["4df9c14919cde61f6d51dfdbe5fee5dceec4143ba8d1ca888e8bd373fd054c96","35ec51092d8728050974c23a1d85d4b5d506cdc288490192ebac06cad10d5d"],["9c3919a84a474870faed8a9c1cc66021523489054d7f0308cbfc99c8ac1f98cd","ddb84f0f4a4ddd57584f044bf260e641905326f76c64c8e6be7e5e03d4fc599d"],["6057170b1dd12fdf8de05f281d8e06bb91e1493a8b91d4cc5a21382120a959e5","9a1af0b26a6a4807add9a2daf71df262465152bc3ee24c65e899be932385a2a8"],["a576df8e23a08411421439a4518da31880cef0fba7d4df12b1a6973eecb94266","40a6bf20e76640b2c92b97afe58cd82c432e10a7f514d9f3ee8be11ae1b28ec8"],["7778a78c28dec3e30a05fe9629de8c38bb30d1f5cf9a3a208f763889be58ad71","34626d9ab5a5b22ff7098e12f2ff580087b38411ff24ac563b513fc1fd9f43ac"],["928955ee637a84463729fd30e7afd2ed5f96274e5ad7e5cb09eda9c06d903ac","c25621003d3f42a827b78a13093a95eeac3d26efa8a8d83fc5180e935bcd091f"],["85d0fef3ec6db109399064f3a0e3b2855645b4a907ad354527aae75163d82751","1f03648413a38c0be29d496e582cf5663e8751e96877331582c237a24eb1f962"],["ff2b0dce97eece97c1c9b6041798b85dfdfb6d8882da20308f5404824526087e","493d13fef524ba188af4c4dc54d07936c7b7ed6fb90e2ceb2c951e01f0c29907"],["827fbbe4b1e880ea9ed2b2e6301b212b57f1ee148cd6dd28780e5e2cf856e241","c60f9c923c727b0b71bef2c67d1d12687ff7a63186903166d605b68baec293ec"],["eaa649f21f51bdbae7be4ae34ce6e5217a58fdce7f47f9aa7f3b58fa2120e2b3","be3279ed5bbbb03ac69a80f89879aa5a01a6b965f13f7e59d47a5305ba5ad93d"],["e4a42d43c5cf169d9391df6decf42ee541b6d8f0c9a137401e23632dda34d24f","4d9f92e716d1c73526fc99ccfb8ad34ce886eedfa8d8e4f13a7f7131deba9414"],["1ec80fef360cbdd954160fadab352b6b92b53576a88fea4947173b9d4300bf19","aeefe93756b5340d2f3a4958a7abbf5e0146e77f6295a07b671cdc1cc107cefd"],["146a778c04670c2f91b00af4680dfa8bce3490717d58ba889ddb5928366642be","b318e0ec3354028add669827f9d4b2870aaa971d2f7e5ed1d0b297483d83efd0"],["fa50c0f61d22e5f07e3acebb1aa07b128d0012209a28b9776d76a8793180eef9","6b84c6922397eba9b72cd2872281a68a5e683293a57a213b38cd8d7d3f4f2811"],["da1d61d0ca721a11b1a5bf6b7d88e8421a288ab5d5bba5220e53d32b5f067ec2","8157f55a7c99306c79c0766161c91e2966a73899d279b48a655fba0f1ad836f1"],["a8e282ff0c9706907215ff98e8fd416615311de0446f1e062a73b0610d064e13","7f97355b8db81c09abfb7f3c5b2515888b679a3e50dd6bd6cef7c73111f4cc0c"],["174a53b9c9a285872d39e56e6913cab15d59b1fa512508c022f382de8319497c","ccc9dc37abfc9c1657b4155f2c47f9e6646b3a1d8cb9854383da13ac079afa73"],["959396981943785c3d3e57edf5018cdbe039e730e4918b3d884fdff09475b7ba","2e7e552888c331dd8ba0386a4b9cd6849c653f64c8709385e9b8abf87524f2fd"],["d2a63a50ae401e56d645a1153b109a8fcca0a43d561fba2dbb51340c9d82b151","e82d86fb6443fcb7565aee58b2948220a70f750af484ca52d4142174dcf89405"],["64587e2335471eb890ee7896d7cfdc866bacbdbd3839317b3436f9b45617e073","d99fcdd5bf6902e2ae96dd6447c299a185b90a39133aeab358299e5e9faf6589"],["8481bde0e4e4d885b3a546d3e549de042f0aa6cea250e7fd358d6c86dd45e458","38ee7b8cba5404dd84a25bf39cecb2ca900a79c42b262e556d64b1b59779057e"],["13464a57a78102aa62b6979ae817f4637ffcfed3c4b1ce30bcd6303f6caf666b","69be159004614580ef7e433453ccb0ca48f300a81d0942e13f495a907f6ecc27"],["bc4a9df5b713fe2e9aef430bcc1dc97a0cd9ccede2f28588cada3a0d2d83f366","d3a81ca6e785c06383937adf4b798caa6e8a9fbfa547b16d758d666581f33c1"],["8c28a97bf8298bc0d23d8c749452a32e694b65e30a9472a3954ab30fe5324caa","40a30463a3305193378fedf31f7cc0eb7ae784f0451cb9459e71dc73cbef9482"],["8ea9666139527a8c1dd94ce4f071fd23c8b350c5a4bb33748c4ba111faccae0","620efabbc8ee2782e24e7c0cfb95c5d735b783be9cf0f8e955af34a30e62b945"],["dd3625faef5ba06074669716bbd3788d89bdde815959968092f76cc4eb9a9787","7a188fa3520e30d461da2501045731ca941461982883395937f68d00c644a573"],["f710d79d9eb962297e4f6232b40e8f7feb2bc63814614d692c12de752408221e","ea98e67232d3b3295d3b535532115ccac8612c721851617526ae47a9c77bfc82"]]},naf:{wnd:7,points:[["f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9","388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672"],["2f8bde4d1a07209355b4a7250a5c5128e88b84bddc619ab7cba8d569b240efe4","d8ac222636e5e3d6d4dba9dda6c9c426f788271bab0d6840dca87d3aa6ac62d6"],["5cbdf0646e5db4eaa398f365f2ea7a0e3d419b7e0330e39ce92bddedcac4f9bc","6aebca40ba255960a3178d6d861a54dba813d0b813fde7b5a5082628087264da"],["acd484e2f0c7f65309ad178a9f559abde09796974c57e714c35f110dfc27ccbe","cc338921b0a7d9fd64380971763b61e9add888a4375f8e0f05cc262ac64f9c37"],["774ae7f858a9411e5ef4246b70c65aac5649980be5c17891bbec17895da008cb","d984a032eb6b5e190243dd56d7b7b365372db1e2dff9d6a8301d74c9c953c61b"],["f28773c2d975288bc7d1d205c3748651b075fbc6610e58cddeeddf8f19405aa8","ab0902e8d880a89758212eb65cdaf473a1a06da521fa91f29b5cb52db03ed81"],["d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e","581e2872a86c72a683842ec228cc6defea40af2bd896d3a5c504dc9ff6a26b58"],["defdea4cdb677750a420fee807eacf21eb9898ae79b9768766e4faa04a2d4a34","4211ab0694635168e997b0ead2a93daeced1f4a04a95c0f6cfb199f69e56eb77"],["2b4ea0a797a443d293ef5cff444f4979f06acfebd7e86d277475656138385b6c","85e89bc037945d93b343083b5a1c86131a01f60c50269763b570c854e5c09b7a"],["352bbf4a4cdd12564f93fa332ce333301d9ad40271f8107181340aef25be59d5","321eb4075348f534d59c18259dda3e1f4a1b3b2e71b1039c67bd3d8bcf81998c"],["2fa2104d6b38d11b0230010559879124e42ab8dfeff5ff29dc9cdadd4ecacc3f","2de1068295dd865b64569335bd5dd80181d70ecfc882648423ba76b532b7d67"],["9248279b09b4d68dab21a9b066edda83263c3d84e09572e269ca0cd7f5453714","73016f7bf234aade5d1aa71bdea2b1ff3fc0de2a887912ffe54a32ce97cb3402"],["daed4f2be3a8bf278e70132fb0beb7522f570e144bf615c07e996d443dee8729","a69dce4a7d6c98e8d4a1aca87ef8d7003f83c230f3afa726ab40e52290be1c55"],["c44d12c7065d812e8acf28d7cbb19f9011ecd9e9fdf281b0e6a3b5e87d22e7db","2119a460ce326cdc76c45926c982fdac0e106e861edf61c5a039063f0e0e6482"],["6a245bf6dc698504c89a20cfded60853152b695336c28063b61c65cbd269e6b4","e022cf42c2bd4a708b3f5126f16a24ad8b33ba48d0423b6efd5e6348100d8a82"],["1697ffa6fd9de627c077e3d2fe541084ce13300b0bec1146f95ae57f0d0bd6a5","b9c398f186806f5d27561506e4557433a2cf15009e498ae7adee9d63d01b2396"],["605bdb019981718b986d0f07e834cb0d9deb8360ffb7f61df982345ef27a7479","2972d2de4f8d20681a78d93ec96fe23c26bfae84fb14db43b01e1e9056b8c49"],["62d14dab4150bf497402fdc45a215e10dcb01c354959b10cfe31c7e9d87ff33d","80fc06bd8cc5b01098088a1950eed0db01aa132967ab472235f5642483b25eaf"],["80c60ad0040f27dade5b4b06c408e56b2c50e9f56b9b8b425e555c2f86308b6f","1c38303f1cc5c30f26e66bad7fe72f70a65eed4cbe7024eb1aa01f56430bd57a"],["7a9375ad6167ad54aa74c6348cc54d344cc5dc9487d847049d5eabb0fa03c8fb","d0e3fa9eca8726909559e0d79269046bdc59ea10c70ce2b02d499ec224dc7f7"],["d528ecd9b696b54c907a9ed045447a79bb408ec39b68df504bb51f459bc3ffc9","eecf41253136e5f99966f21881fd656ebc4345405c520dbc063465b521409933"],["49370a4b5f43412ea25f514e8ecdad05266115e4a7ecb1387231808f8b45963","758f3f41afd6ed428b3081b0512fd62a54c3f3afbb5b6764b653052a12949c9a"],["77f230936ee88cbbd73df930d64702ef881d811e0e1498e2f1c13eb1fc345d74","958ef42a7886b6400a08266e9ba1b37896c95330d97077cbbe8eb3c7671c60d6"],["f2dac991cc4ce4b9ea44887e5c7c0bce58c80074ab9d4dbaeb28531b7739f530","e0dedc9b3b2f8dad4da1f32dec2531df9eb5fbeb0598e4fd1a117dba703a3c37"],["463b3d9f662621fb1b4be8fbbe2520125a216cdfc9dae3debcba4850c690d45b","5ed430d78c296c3543114306dd8622d7c622e27c970a1de31cb377b01af7307e"],["f16f804244e46e2a09232d4aff3b59976b98fac14328a2d1a32496b49998f247","cedabd9b82203f7e13d206fcdf4e33d92a6c53c26e5cce26d6579962c4e31df6"],["caf754272dc84563b0352b7a14311af55d245315ace27c65369e15f7151d41d1","cb474660ef35f5f2a41b643fa5e460575f4fa9b7962232a5c32f908318a04476"],["2600ca4b282cb986f85d0f1709979d8b44a09c07cb86d7c124497bc86f082120","4119b88753c15bd6a693b03fcddbb45d5ac6be74ab5f0ef44b0be9475a7e4b40"],["7635ca72d7e8432c338ec53cd12220bc01c48685e24f7dc8c602a7746998e435","91b649609489d613d1d5e590f78e6d74ecfc061d57048bad9e76f302c5b9c61"],["754e3239f325570cdbbf4a87deee8a66b7f2b33479d468fbc1a50743bf56cc18","673fb86e5bda30fb3cd0ed304ea49a023ee33d0197a695d0c5d98093c536683"],["e3e6bd1071a1e96aff57859c82d570f0330800661d1c952f9fe2694691d9b9e8","59c9e0bba394e76f40c0aa58379a3cb6a5a2283993e90c4167002af4920e37f5"],["186b483d056a033826ae73d88f732985c4ccb1f32ba35f4b4cc47fdcf04aa6eb","3b952d32c67cf77e2e17446e204180ab21fb8090895138b4a4a797f86e80888b"],["df9d70a6b9876ce544c98561f4be4f725442e6d2b737d9c91a8321724ce0963f","55eb2dafd84d6ccd5f862b785dc39d4ab157222720ef9da217b8c45cf2ba2417"],["5edd5cc23c51e87a497ca815d5dce0f8ab52554f849ed8995de64c5f34ce7143","efae9c8dbc14130661e8cec030c89ad0c13c66c0d17a2905cdc706ab7399a868"],["290798c2b6476830da12fe02287e9e777aa3fba1c355b17a722d362f84614fba","e38da76dcd440621988d00bcf79af25d5b29c094db2a23146d003afd41943e7a"],["af3c423a95d9f5b3054754efa150ac39cd29552fe360257362dfdecef4053b45","f98a3fd831eb2b749a93b0e6f35cfb40c8cd5aa667a15581bc2feded498fd9c6"],["766dbb24d134e745cccaa28c99bf274906bb66b26dcf98df8d2fed50d884249a","744b1152eacbe5e38dcc887980da38b897584a65fa06cedd2c924f97cbac5996"],["59dbf46f8c94759ba21277c33784f41645f7b44f6c596a58ce92e666191abe3e","c534ad44175fbc300f4ea6ce648309a042ce739a7919798cd85e216c4a307f6e"],["f13ada95103c4537305e691e74e9a4a8dd647e711a95e73cb62dc6018cfd87b8","e13817b44ee14de663bf4bc808341f326949e21a6a75c2570778419bdaf5733d"],["7754b4fa0e8aced06d4167a2c59cca4cda1869c06ebadfb6488550015a88522c","30e93e864e669d82224b967c3020b8fa8d1e4e350b6cbcc537a48b57841163a2"],["948dcadf5990e048aa3874d46abef9d701858f95de8041d2a6828c99e2262519","e491a42537f6e597d5d28a3224b1bc25df9154efbd2ef1d2cbba2cae5347d57e"],["7962414450c76c1689c7b48f8202ec37fb224cf5ac0bfa1570328a8a3d7c77ab","100b610ec4ffb4760d5c1fc133ef6f6b12507a051f04ac5760afa5b29db83437"],["3514087834964b54b15b160644d915485a16977225b8847bb0dd085137ec47ca","ef0afbb2056205448e1652c48e8127fc6039e77c15c2378b7e7d15a0de293311"],["d3cc30ad6b483e4bc79ce2c9dd8bc54993e947eb8df787b442943d3f7b527eaf","8b378a22d827278d89c5e9be8f9508ae3c2ad46290358630afb34db04eede0a4"],["1624d84780732860ce1c78fcbfefe08b2b29823db913f6493975ba0ff4847610","68651cf9b6da903e0914448c6cd9d4ca896878f5282be4c8cc06e2a404078575"],["733ce80da955a8a26902c95633e62a985192474b5af207da6df7b4fd5fc61cd4","f5435a2bd2badf7d485a4d8b8db9fcce3e1ef8e0201e4578c54673bc1dc5ea1d"],["15d9441254945064cf1a1c33bbd3b49f8966c5092171e699ef258dfab81c045c","d56eb30b69463e7234f5137b73b84177434800bacebfc685fc37bbe9efe4070d"],["a1d0fcf2ec9de675b612136e5ce70d271c21417c9d2b8aaaac138599d0717940","edd77f50bcb5a3cab2e90737309667f2641462a54070f3d519212d39c197a629"],["e22fbe15c0af8ccc5780c0735f84dbe9a790badee8245c06c7ca37331cb36980","a855babad5cd60c88b430a69f53a1a7a38289154964799be43d06d77d31da06"],["311091dd9860e8e20ee13473c1155f5f69635e394704eaa74009452246cfa9b3","66db656f87d1f04fffd1f04788c06830871ec5a64feee685bd80f0b1286d8374"],["34c1fd04d301be89b31c0442d3e6ac24883928b45a9340781867d4232ec2dbdf","9414685e97b1b5954bd46f730174136d57f1ceeb487443dc5321857ba73abee"],["f219ea5d6b54701c1c14de5b557eb42a8d13f3abbcd08affcc2a5e6b049b8d63","4cb95957e83d40b0f73af4544cccf6b1f4b08d3c07b27fb8d8c2962a400766d1"],["d7b8740f74a8fbaab1f683db8f45de26543a5490bca627087236912469a0b448","fa77968128d9c92ee1010f337ad4717eff15db5ed3c049b3411e0315eaa4593b"],["32d31c222f8f6f0ef86f7c98d3a3335ead5bcd32abdd94289fe4d3091aa824bf","5f3032f5892156e39ccd3d7915b9e1da2e6dac9e6f26e961118d14b8462e1661"],["7461f371914ab32671045a155d9831ea8793d77cd59592c4340f86cbc18347b5","8ec0ba238b96bec0cbdddcae0aa442542eee1ff50c986ea6b39847b3cc092ff6"],["ee079adb1df1860074356a25aa38206a6d716b2c3e67453d287698bad7b2b2d6","8dc2412aafe3be5c4c5f37e0ecc5f9f6a446989af04c4e25ebaac479ec1c8c1e"],["16ec93e447ec83f0467b18302ee620f7e65de331874c9dc72bfd8616ba9da6b5","5e4631150e62fb40d0e8c2a7ca5804a39d58186a50e497139626778e25b0674d"],["eaa5f980c245f6f038978290afa70b6bd8855897f98b6aa485b96065d537bd99","f65f5d3e292c2e0819a528391c994624d784869d7e6ea67fb18041024edc07dc"],["78c9407544ac132692ee1910a02439958ae04877151342ea96c4b6b35a49f51","f3e0319169eb9b85d5404795539a5e68fa1fbd583c064d2462b675f194a3ddb4"],["494f4be219a1a77016dcd838431aea0001cdc8ae7a6fc688726578d9702857a5","42242a969283a5f339ba7f075e36ba2af925ce30d767ed6e55f4b031880d562c"],["a598a8030da6d86c6bc7f2f5144ea549d28211ea58faa70ebf4c1e665c1fe9b5","204b5d6f84822c307e4b4a7140737aec23fc63b65b35f86a10026dbd2d864e6b"],["c41916365abb2b5d09192f5f2dbeafec208f020f12570a184dbadc3e58595997","4f14351d0087efa49d245b328984989d5caf9450f34bfc0ed16e96b58fa9913"],["841d6063a586fa475a724604da03bc5b92a2e0d2e0a36acfe4c73a5514742881","73867f59c0659e81904f9a1c7543698e62562d6744c169ce7a36de01a8d6154"],["5e95bb399a6971d376026947f89bde2f282b33810928be4ded112ac4d70e20d5","39f23f366809085beebfc71181313775a99c9aed7d8ba38b161384c746012865"],["36e4641a53948fd476c39f8a99fd974e5ec07564b5315d8bf99471bca0ef2f66","d2424b1b1abe4eb8164227b085c9aa9456ea13493fd563e06fd51cf5694c78fc"],["336581ea7bfbbb290c191a2f507a41cf5643842170e914faeab27c2c579f726","ead12168595fe1be99252129b6e56b3391f7ab1410cd1e0ef3dcdcabd2fda224"],["8ab89816dadfd6b6a1f2634fcf00ec8403781025ed6890c4849742706bd43ede","6fdcef09f2f6d0a044e654aef624136f503d459c3e89845858a47a9129cdd24e"],["1e33f1a746c9c5778133344d9299fcaa20b0938e8acff2544bb40284b8c5fb94","60660257dd11b3aa9c8ed618d24edff2306d320f1d03010e33a7d2057f3b3b6"],["85b7c1dcb3cec1b7ee7f30ded79dd20a0ed1f4cc18cbcfcfa410361fd8f08f31","3d98a9cdd026dd43f39048f25a8847f4fcafad1895d7a633c6fed3c35e999511"],["29df9fbd8d9e46509275f4b125d6d45d7fbe9a3b878a7af872a2800661ac5f51","b4c4fe99c775a606e2d8862179139ffda61dc861c019e55cd2876eb2a27d84b"],["a0b1cae06b0a847a3fea6e671aaf8adfdfe58ca2f768105c8082b2e449fce252","ae434102edde0958ec4b19d917a6a28e6b72da1834aff0e650f049503a296cf2"],["4e8ceafb9b3e9a136dc7ff67e840295b499dfb3b2133e4ba113f2e4c0e121e5","cf2174118c8b6d7a4b48f6d534ce5c79422c086a63460502b827ce62a326683c"],["d24a44e047e19b6f5afb81c7ca2f69080a5076689a010919f42725c2b789a33b","6fb8d5591b466f8fc63db50f1c0f1c69013f996887b8244d2cdec417afea8fa3"],["ea01606a7a6c9cdd249fdfcfacb99584001edd28abbab77b5104e98e8e3b35d4","322af4908c7312b0cfbfe369f7a7b3cdb7d4494bc2823700cfd652188a3ea98d"],["af8addbf2b661c8a6c6328655eb96651252007d8c5ea31be4ad196de8ce2131f","6749e67c029b85f52a034eafd096836b2520818680e26ac8f3dfbcdb71749700"],["e3ae1974566ca06cc516d47e0fb165a674a3dabcfca15e722f0e3450f45889","2aeabe7e4531510116217f07bf4d07300de97e4874f81f533420a72eeb0bd6a4"],["591ee355313d99721cf6993ffed1e3e301993ff3ed258802075ea8ced397e246","b0ea558a113c30bea60fc4775460c7901ff0b053d25ca2bdeee98f1a4be5d196"],["11396d55fda54c49f19aa97318d8da61fa8584e47b084945077cf03255b52984","998c74a8cd45ac01289d5833a7beb4744ff536b01b257be4c5767bea93ea57a4"],["3c5d2a1ba39c5a1790000738c9e0c40b8dcdfd5468754b6405540157e017aa7a","b2284279995a34e2f9d4de7396fc18b80f9b8b9fdd270f6661f79ca4c81bd257"],["cc8704b8a60a0defa3a99a7299f2e9c3fbc395afb04ac078425ef8a1793cc030","bdd46039feed17881d1e0862db347f8cf395b74fc4bcdc4e940b74e3ac1f1b13"],["c533e4f7ea8555aacd9777ac5cad29b97dd4defccc53ee7ea204119b2889b197","6f0a256bc5efdf429a2fb6242f1a43a2d9b925bb4a4b3a26bb8e0f45eb596096"],["c14f8f2ccb27d6f109f6d08d03cc96a69ba8c34eec07bbcf566d48e33da6593","c359d6923bb398f7fd4473e16fe1c28475b740dd098075e6c0e8649113dc3a38"],["a6cbc3046bc6a450bac24789fa17115a4c9739ed75f8f21ce441f72e0b90e6ef","21ae7f4680e889bb130619e2c0f95a360ceb573c70603139862afd617fa9b9f"],["347d6d9a02c48927ebfb86c1359b1caf130a3c0267d11ce6344b39f99d43cc38","60ea7f61a353524d1c987f6ecec92f086d565ab687870cb12689ff1e31c74448"],["da6545d2181db8d983f7dcb375ef5866d47c67b1bf31c8cf855ef7437b72656a","49b96715ab6878a79e78f07ce5680c5d6673051b4935bd897fea824b77dc208a"],["c40747cc9d012cb1a13b8148309c6de7ec25d6945d657146b9d5994b8feb1111","5ca560753be2a12fc6de6caf2cb489565db936156b9514e1bb5e83037e0fa2d4"],["4e42c8ec82c99798ccf3a610be870e78338c7f713348bd34c8203ef4037f3502","7571d74ee5e0fb92a7a8b33a07783341a5492144cc54bcc40a94473693606437"],["3775ab7089bc6af823aba2e1af70b236d251cadb0c86743287522a1b3b0dedea","be52d107bcfa09d8bcb9736a828cfa7fac8db17bf7a76a2c42ad961409018cf7"],["cee31cbf7e34ec379d94fb814d3d775ad954595d1314ba8846959e3e82f74e26","8fd64a14c06b589c26b947ae2bcf6bfa0149ef0be14ed4d80f448a01c43b1c6d"],["b4f9eaea09b6917619f6ea6a4eb5464efddb58fd45b1ebefcdc1a01d08b47986","39e5c9925b5a54b07433a4f18c61726f8bb131c012ca542eb24a8ac07200682a"],["d4263dfc3d2df923a0179a48966d30ce84e2515afc3dccc1b77907792ebcc60e","62dfaf07a0f78feb30e30d6295853ce189e127760ad6cf7fae164e122a208d54"],["48457524820fa65a4f8d35eb6930857c0032acc0a4a2de422233eeda897612c4","25a748ab367979d98733c38a1fa1c2e7dc6cc07db2d60a9ae7a76aaa49bd0f77"],["dfeeef1881101f2cb11644f3a2afdfc2045e19919152923f367a1767c11cceda","ecfb7056cf1de042f9420bab396793c0c390bde74b4bbdff16a83ae09a9a7517"],["6d7ef6b17543f8373c573f44e1f389835d89bcbc6062ced36c82df83b8fae859","cd450ec335438986dfefa10c57fea9bcc521a0959b2d80bbf74b190dca712d10"],["e75605d59102a5a2684500d3b991f2e3f3c88b93225547035af25af66e04541f","f5c54754a8f71ee540b9b48728473e314f729ac5308b06938360990e2bfad125"],["eb98660f4c4dfaa06a2be453d5020bc99a0c2e60abe388457dd43fefb1ed620c","6cb9a8876d9cb8520609af3add26cd20a0a7cd8a9411131ce85f44100099223e"],["13e87b027d8514d35939f2e6892b19922154596941888336dc3563e3b8dba942","fef5a3c68059a6dec5d624114bf1e91aac2b9da568d6abeb2570d55646b8adf1"],["ee163026e9fd6fe017c38f06a5be6fc125424b371ce2708e7bf4491691e5764a","1acb250f255dd61c43d94ccc670d0f58f49ae3fa15b96623e5430da0ad6c62b2"],["b268f5ef9ad51e4d78de3a750c2dc89b1e626d43505867999932e5db33af3d80","5f310d4b3c99b9ebb19f77d41c1dee018cf0d34fd4191614003e945a1216e423"],["ff07f3118a9df035e9fad85eb6c7bfe42b02f01ca99ceea3bf7ffdba93c4750d","438136d603e858a3a5c440c38eccbaddc1d2942114e2eddd4740d098ced1f0d8"],["8d8b9855c7c052a34146fd20ffb658bea4b9f69e0d825ebec16e8c3ce2b526a1","cdb559eedc2d79f926baf44fb84ea4d44bcf50fee51d7ceb30e2e7f463036758"],["52db0b5384dfbf05bfa9d472d7ae26dfe4b851ceca91b1eba54263180da32b63","c3b997d050ee5d423ebaf66a6db9f57b3180c902875679de924b69d84a7b375"],["e62f9490d3d51da6395efd24e80919cc7d0f29c3f3fa48c6fff543becbd43352","6d89ad7ba4876b0b22c2ca280c682862f342c8591f1daf5170e07bfd9ccafa7d"],["7f30ea2476b399b4957509c88f77d0191afa2ff5cb7b14fd6d8e7d65aaab1193","ca5ef7d4b231c94c3b15389a5f6311e9daff7bb67b103e9880ef4bff637acaec"],["5098ff1e1d9f14fb46a210fada6c903fef0fb7b4a1dd1d9ac60a0361800b7a00","9731141d81fc8f8084d37c6e7542006b3ee1b40d60dfe5362a5b132fd17ddc0"],["32b78c7de9ee512a72895be6b9cbefa6e2f3c4ccce445c96b9f2c81e2778ad58","ee1849f513df71e32efc3896ee28260c73bb80547ae2275ba497237794c8753c"],["e2cb74fddc8e9fbcd076eef2a7c72b0ce37d50f08269dfc074b581550547a4f7","d3aa2ed71c9dd2247a62df062736eb0baddea9e36122d2be8641abcb005cc4a4"],["8438447566d4d7bedadc299496ab357426009a35f235cb141be0d99cd10ae3a8","c4e1020916980a4da5d01ac5e6ad330734ef0d7906631c4f2390426b2edd791f"],["4162d488b89402039b584c6fc6c308870587d9c46f660b878ab65c82c711d67e","67163e903236289f776f22c25fb8a3afc1732f2b84b4e95dbda47ae5a0852649"],["3fad3fa84caf0f34f0f89bfd2dcf54fc175d767aec3e50684f3ba4a4bf5f683d","cd1bc7cb6cc407bb2f0ca647c718a730cf71872e7d0d2a53fa20efcdfe61826"],["674f2600a3007a00568c1a7ce05d0816c1fb84bf1370798f1c69532faeb1a86b","299d21f9413f33b3edf43b257004580b70db57da0b182259e09eecc69e0d38a5"],["d32f4da54ade74abb81b815ad1fb3b263d82d6c692714bcff87d29bd5ee9f08f","f9429e738b8e53b968e99016c059707782e14f4535359d582fc416910b3eea87"],["30e4e670435385556e593657135845d36fbb6931f72b08cb1ed954f1e3ce3ff6","462f9bce619898638499350113bbc9b10a878d35da70740dc695a559eb88db7b"],["be2062003c51cc3004682904330e4dee7f3dcd10b01e580bf1971b04d4cad297","62188bc49d61e5428573d48a74e1c655b1c61090905682a0d5558ed72dccb9bc"],["93144423ace3451ed29e0fb9ac2af211cb6e84a601df5993c419859fff5df04a","7c10dfb164c3425f5c71a3f9d7992038f1065224f72bb9d1d902a6d13037b47c"],["b015f8044f5fcbdcf21ca26d6c34fb8197829205c7b7d2a7cb66418c157b112c","ab8c1e086d04e813744a655b2df8d5f83b3cdc6faa3088c1d3aea1454e3a1d5f"],["d5e9e1da649d97d89e4868117a465a3a4f8a18de57a140d36b3f2af341a21b52","4cb04437f391ed73111a13cc1d4dd0db1693465c2240480d8955e8592f27447a"],["d3ae41047dd7ca065dbf8ed77b992439983005cd72e16d6f996a5316d36966bb","bd1aeb21ad22ebb22a10f0303417c6d964f8cdd7df0aca614b10dc14d125ac46"],["463e2763d885f958fc66cdd22800f0a487197d0a82e377b49f80af87c897b065","bfefacdb0e5d0fd7df3a311a94de062b26b80c61fbc97508b79992671ef7ca7f"],["7985fdfd127c0567c6f53ec1bb63ec3158e597c40bfe747c83cddfc910641917","603c12daf3d9862ef2b25fe1de289aed24ed291e0ec6708703a5bd567f32ed03"],["74a1ad6b5f76e39db2dd249410eac7f99e74c59cb83d2d0ed5ff1543da7703e9","cc6157ef18c9c63cd6193d83631bbea0093e0968942e8c33d5737fd790e0db08"],["30682a50703375f602d416664ba19b7fc9bab42c72747463a71d0896b22f6da3","553e04f6b018b4fa6c8f39e7f311d3176290d0e0f19ca73f17714d9977a22ff8"],["9e2158f0d7c0d5f26c3791efefa79597654e7a2b2464f52b1ee6c1347769ef57","712fcdd1b9053f09003a3481fa7762e9ffd7c8ef35a38509e2fbf2629008373"],["176e26989a43c9cfeba4029c202538c28172e566e3c4fce7322857f3be327d66","ed8cc9d04b29eb877d270b4878dc43c19aefd31f4eee09ee7b47834c1fa4b1c3"],["75d46efea3771e6e68abb89a13ad747ecf1892393dfc4f1b7004788c50374da8","9852390a99507679fd0b86fd2b39a868d7efc22151346e1a3ca4726586a6bed8"],["809a20c67d64900ffb698c4c825f6d5f2310fb0451c869345b7319f645605721","9e994980d9917e22b76b061927fa04143d096ccc54963e6a5ebfa5f3f8e286c1"],["1b38903a43f7f114ed4500b4eac7083fdefece1cf29c63528d563446f972c180","4036edc931a60ae889353f77fd53de4a2708b26b6f5da72ad3394119daf408f9"]]}}},function(e,t,n){"use strict";var r=n(29),i=n(343),o=n(47),s=n(128),a=n(124),u=o.assert,c=n(344),f=n(345);function l(e){if(!(this instanceof l))return new l(e);"string"==typeof e&&(u(Object.prototype.hasOwnProperty.call(s,e),"Unknown curve "+e),e=s[e]),e instanceof s.PresetCurve&&(e={curve:e}),this.curve=e.curve.curve,this.n=this.curve.n,this.nh=this.n.ushrn(1),this.g=this.curve.g,this.g=e.curve.g,this.g.precompute(e.curve.n.bitLength()+1),this.hash=e.hash||e.curve.hash}e.exports=l,l.prototype.keyPair=function(e){return new c(this,e)},l.prototype.keyFromPrivate=function(e,t){return c.fromPrivate(this,e,t)},l.prototype.keyFromPublic=function(e,t){return c.fromPublic(this,e,t)},l.prototype.genKeyPair=function(e){e||(e={});for(var t=new i({hash:this.hash,pers:e.pers,persEnc:e.persEnc||"utf8",entropy:e.entropy||a(this.hash.hmacStrength),entropyEnc:e.entropy&&e.entropyEnc||"utf8",nonce:this.n.toArray()}),n=this.n.byteLength(),o=this.n.sub(new r(2));;){var s=new r(t.generate(n));if(!(s.cmp(o)>0))return s.iaddn(1),this.keyFromPrivate(s)}},l.prototype._truncateToN=function(e,t){var n=8*e.byteLength()-this.n.bitLength();return n>0&&(e=e.ushrn(n)),!t&&e.cmp(this.n)>=0?e.sub(this.n):e},l.prototype.sign=function(e,t,n,o){"object"==typeof n&&(o=n,n=null),o||(o={}),t=this.keyFromPrivate(t,n),e=this._truncateToN(new r(e,16));for(var s=this.n.byteLength(),a=t.getPrivate().toArray("be",s),u=e.toArray("be",s),c=new i({hash:this.hash,entropy:a,nonce:u,pers:o.pers,persEnc:o.persEnc||"utf8"}),l=this.n.sub(new r(1)),d=0;;d++){var h=o.k?o.k(d):new r(c.generate(this.n.byteLength()));if(!((h=this._truncateToN(h,!0)).cmpn(1)<=0||h.cmp(l)>=0)){var p=this.g.mul(h);if(!p.isInfinity()){var v=p.getX(),g=v.umod(this.n);if(0!==g.cmpn(0)){var m=h.invm(this.n).mul(g.mul(t.getPrivate()).iadd(e));if(0!==(m=m.umod(this.n)).cmpn(0)){var b=(p.getY().isOdd()?1:0)|(0!==v.cmp(g)?2:0);return o.canonical&&m.cmp(this.nh)>0&&(m=this.n.sub(m),b^=1),new f({r:g,s:m,recoveryParam:b})}}}}}},l.prototype.verify=function(e,t,n,i){e=this._truncateToN(new r(e,16)),n=this.keyFromPublic(n,i);var o=(t=new f(t,"hex")).r,s=t.s;if(o.cmpn(1)<0||o.cmp(this.n)>=0)return!1;if(s.cmpn(1)<0||s.cmp(this.n)>=0)return!1;var a,u=s.invm(this.n),c=u.mul(e).umod(this.n),l=u.mul(o).umod(this.n);return this.curve._maxwellTrick?!(a=this.g.jmulAdd(c,n.getPublic(),l)).isInfinity()&&a.eqXToP(o):!(a=this.g.mulAdd(c,n.getPublic(),l)).isInfinity()&&0===a.getX().umod(this.n).cmp(o)},l.prototype.recoverPubKey=function(e,t,n,i){u((3&n)===n,"The recovery param is more than two bits"),t=new f(t,i);var o=this.n,s=new r(e),a=t.r,c=t.s,l=1&n,d=n>>1;if(a.cmp(this.curve.p.umod(this.curve.n))>=0&&d)throw new Error("Unable to find sencond key candinate");a=d?this.curve.pointFromX(a.add(this.curve.n),l):this.curve.pointFromX(a,l);var h=t.r.invm(o),p=o.sub(s).mul(h).umod(o),v=c.mul(h).umod(o);return this.g.mulAdd(p,a,v)},l.prototype.getKeyRecoveryParam=function(e,t,n,r){if(null!==(t=new f(t,r)).recoveryParam)return t.recoveryParam;for(var i=0;i<4;i++){var o;try{o=this.recoverPubKey(e,t,i)}catch(e){continue}if(o.eq(n))return i}throw new Error("Unable to find valid recovery factor")}},function(e,t,n){"use strict";var r=n(129),i=n(198),o=n(46);function s(e){if(!(this instanceof s))return new s(e);this.hash=e.hash,this.predResist=!!e.predResist,this.outLen=this.hash.outSize,this.minEntropy=e.minEntropy||this.hash.hmacStrength,this._reseed=null,this.reseedInterval=null,this.K=null,this.V=null;var t=i.toArray(e.entropy,e.entropyEnc||"hex"),n=i.toArray(e.nonce,e.nonceEnc||"hex"),r=i.toArray(e.pers,e.persEnc||"hex");o(t.length>=this.minEntropy/8,"Not enough entropy. Minimum is: "+this.minEntropy+" bits"),this._init(t,n,r)}e.exports=s,s.prototype._init=function(e,t,n){var r=e.concat(t).concat(n);this.K=new Array(this.outLen/8),this.V=new Array(this.outLen/8);for(var i=0;i<this.V.length;i++)this.K[i]=0,this.V[i]=1;this._update(r),this._reseed=1,this.reseedInterval=281474976710656},s.prototype._hmac=function(){return new r.hmac(this.hash,this.K)},s.prototype._update=function(e){var t=this._hmac().update(this.V).update([0]);e&&(t=t.update(e)),this.K=t.digest(),this.V=this._hmac().update(this.V).digest(),e&&(this.K=this._hmac().update(this.V).update([1]).update(e).digest(),this.V=this._hmac().update(this.V).digest())},s.prototype.reseed=function(e,t,n,r){"string"!=typeof t&&(r=n,n=t,t=null),e=i.toArray(e,t),n=i.toArray(n,r),o(e.length>=this.minEntropy/8,"Not enough entropy. Minimum is: "+this.minEntropy+" bits"),this._update(e.concat(n||[])),this._reseed=1},s.prototype.generate=function(e,t,n,r){if(this._reseed>this.reseedInterval)throw new Error("Reseed is required");"string"!=typeof t&&(r=n,n=t,t=null),n&&(n=i.toArray(n,r||"hex"),this._update(n));for(var o=[];o.length<e;)this.V=this._hmac().update(this.V).digest(),o=o.concat(this.V);var s=o.slice(0,e);return this._update(n),this._reseed++,i.encode(s,t)}},function(e,t,n){"use strict";var r=n(29),i=n(47).assert;function o(e,t){this.ec=e,this.priv=null,this.pub=null,t.priv&&this._importPrivate(t.priv,t.privEnc),t.pub&&this._importPublic(t.pub,t.pubEnc)}e.exports=o,o.fromPublic=function(e,t,n){return t instanceof o?t:new o(e,{pub:t,pubEnc:n})},o.fromPrivate=function(e,t,n){return t instanceof o?t:new o(e,{priv:t,privEnc:n})},o.prototype.validate=function(){var e=this.getPublic();return e.isInfinity()?{result:!1,reason:"Invalid public key"}:e.validate()?e.mul(this.ec.curve.n).isInfinity()?{result:!0,reason:null}:{result:!1,reason:"Public key * N != O"}:{result:!1,reason:"Public key is not a point"}},o.prototype.getPublic=function(e,t){return"string"==typeof e&&(t=e,e=null),this.pub||(this.pub=this.ec.g.mul(this.priv)),t?this.pub.encode(t,e):this.pub},o.prototype.getPrivate=function(e){return"hex"===e?this.priv.toString(16,2):this.priv},o.prototype._importPrivate=function(e,t){this.priv=new r(e,t||16),this.priv=this.priv.umod(this.ec.curve.n)},o.prototype._importPublic=function(e,t){if(e.x||e.y)return"mont"===this.ec.curve.type?i(e.x,"Need x coordinate"):"short"!==this.ec.curve.type&&"edwards"!==this.ec.curve.type||i(e.x&&e.y,"Need both x and y coordinate"),void(this.pub=this.ec.curve.point(e.x,e.y));this.pub=this.ec.curve.decodePoint(e,t)},o.prototype.derive=function(e){return e.validate()||i(e.validate(),"public point not validated"),e.mul(this.priv).getX()},o.prototype.sign=function(e,t,n){return this.ec.sign(e,this,t,n)},o.prototype.verify=function(e,t){return this.ec.verify(e,t,this)},o.prototype.inspect=function(){return"<Key priv: "+(this.priv&&this.priv.toString(16,2))+" pub: "+(this.pub&&this.pub.inspect())+" >"}},function(e,t,n){"use strict";var r=n(29),i=n(47),o=i.assert;function s(e,t){if(e instanceof s)return e;this._importDER(e,t)||(o(e.r&&e.s,"Signature without r or s"),this.r=new r(e.r,16),this.s=new r(e.s,16),void 0===e.recoveryParam?this.recoveryParam=null:this.recoveryParam=e.recoveryParam)}function a(){this.place=0}function u(e,t){var n=e[t.place++];if(!(128&n))return n;var r=15&n;if(0===r||r>4)return!1;for(var i=0,o=0,s=t.place;o<r;o++,s++)i<<=8,i|=e[s],i>>>=0;return!(i<=127)&&(t.place=s,i)}function c(e){for(var t=0,n=e.length-1;!e[t]&&!(128&e[t+1])&&t<n;)t++;return 0===t?e:e.slice(t)}function f(e,t){if(t<128)e.push(t);else{var n=1+(Math.log(t)/Math.LN2>>>3);for(e.push(128|n);--n;)e.push(t>>>(n<<3)&255);e.push(t)}}e.exports=s,s.prototype._importDER=function(e,t){e=i.toArray(e,t);var n=new a;if(48!==e[n.place++])return!1;var o=u(e,n);if(!1===o)return!1;if(o+n.place!==e.length)return!1;if(2!==e[n.place++])return!1;var s=u(e,n);if(!1===s)return!1;var c=e.slice(n.place,s+n.place);if(n.place+=s,2!==e[n.place++])return!1;var f=u(e,n);if(!1===f)return!1;if(e.length!==f+n.place)return!1;var l=e.slice(n.place,f+n.place);if(0===c[0]){if(!(128&c[1]))return!1;c=c.slice(1)}if(0===l[0]){if(!(128&l[1]))return!1;l=l.slice(1)}return this.r=new r(c),this.s=new r(l),this.recoveryParam=null,!0},s.prototype.toDER=function(e){var t=this.r.toArray(),n=this.s.toArray();for(128&t[0]&&(t=[0].concat(t)),128&n[0]&&(n=[0].concat(n)),t=c(t),n=c(n);!(n[0]||128&n[1]);)n=n.slice(1);var r=[2];f(r,t.length),(r=r.concat(t)).push(2),f(r,n.length);var o=r.concat(n),s=[48];return f(s,o.length),s=s.concat(o),i.encode(s,e)}},function(e,t,n){"use strict";var r=n(129),i=n(128),o=n(47),s=o.assert,a=o.parseBytes,u=n(347),c=n(348);function f(e){if(s("ed25519"===e,"only tested with ed25519 so far"),!(this instanceof f))return new f(e);e=i[e].curve,this.curve=e,this.g=e.g,this.g.precompute(e.n.bitLength()+1),this.pointClass=e.point().constructor,this.encodingLength=Math.ceil(e.n.bitLength()/8),this.hash=r.sha512}e.exports=f,f.prototype.sign=function(e,t){e=a(e);var n=this.keyFromSecret(t),r=this.hashInt(n.messagePrefix(),e),i=this.g.mul(r),o=this.encodePoint(i),s=this.hashInt(o,n.pubBytes(),e).mul(n.priv()),u=r.add(s).umod(this.curve.n);return this.makeSignature({R:i,S:u,Rencoded:o})},f.prototype.verify=function(e,t,n){e=a(e),t=this.makeSignature(t);var r=this.keyFromPublic(n),i=this.hashInt(t.Rencoded(),r.pubBytes(),e),o=this.g.mul(t.S());return t.R().add(r.pub().mul(i)).eq(o)},f.prototype.hashInt=function(){for(var e=this.hash(),t=0;t<arguments.length;t++)e.update(arguments[t]);return o.intFromLE(e.digest()).umod(this.curve.n)},f.prototype.keyFromPublic=function(e){return u.fromPublic(this,e)},f.prototype.keyFromSecret=function(e){return u.fromSecret(this,e)},f.prototype.makeSignature=function(e){return e instanceof c?e:new c(this,e)},f.prototype.encodePoint=function(e){var t=e.getY().toArray("le",this.encodingLength);return t[this.encodingLength-1]|=e.getX().isOdd()?128:0,t},f.prototype.decodePoint=function(e){var t=(e=o.parseBytes(e)).length-1,n=e.slice(0,t).concat(-129&e[t]),r=0!=(128&e[t]),i=o.intFromLE(n);return this.curve.pointFromY(i,r)},f.prototype.encodeInt=function(e){return e.toArray("le",this.encodingLength)},f.prototype.decodeInt=function(e){return o.intFromLE(e)},f.prototype.isPoint=function(e){return e instanceof this.pointClass}},function(e,t,n){"use strict";var r=n(47),i=r.assert,o=r.parseBytes,s=r.cachedProperty;function a(e,t){this.eddsa=e,this._secret=o(t.secret),e.isPoint(t.pub)?this._pub=t.pub:this._pubBytes=o(t.pub)}a.fromPublic=function(e,t){return t instanceof a?t:new a(e,{pub:t})},a.fromSecret=function(e,t){return t instanceof a?t:new a(e,{secret:t})},a.prototype.secret=function(){return this._secret},s(a,"pubBytes",(function(){return this.eddsa.encodePoint(this.pub())})),s(a,"pub",(function(){return this._pubBytes?this.eddsa.decodePoint(this._pubBytes):this.eddsa.g.mul(this.priv())})),s(a,"privBytes",(function(){var e=this.eddsa,t=this.hash(),n=e.encodingLength-1,r=t.slice(0,e.encodingLength);return r[0]&=248,r[n]&=127,r[n]|=64,r})),s(a,"priv",(function(){return this.eddsa.decodeInt(this.privBytes())})),s(a,"hash",(function(){return this.eddsa.hash().update(this.secret()).digest()})),s(a,"messagePrefix",(function(){return this.hash().slice(this.eddsa.encodingLength)})),a.prototype.sign=function(e){return i(this._secret,"KeyPair can only verify"),this.eddsa.sign(e,this)},a.prototype.verify=function(e,t){return this.eddsa.verify(e,t,this)},a.prototype.getSecret=function(e){return i(this._secret,"KeyPair is public only"),r.encode(this.secret(),e)},a.prototype.getPublic=function(e){return r.encode(this.pubBytes(),e)},e.exports=a},function(e,t,n){"use strict";var r=n(29),i=n(47),o=i.assert,s=i.cachedProperty,a=i.parseBytes;function u(e,t){this.eddsa=e,"object"!=typeof t&&(t=a(t)),Array.isArray(t)&&(t={R:t.slice(0,e.encodingLength),S:t.slice(e.encodingLength)}),o(t.R&&t.S,"Signature without R or S"),e.isPoint(t.R)&&(this._R=t.R),t.S instanceof r&&(this._S=t.S),this._Rencoded=Array.isArray(t.R)?t.R:t.Rencoded,this._Sencoded=Array.isArray(t.S)?t.S:t.Sencoded}s(u,"S",(function(){return this.eddsa.decodeInt(this.Sencoded())})),s(u,"R",(function(){return this.eddsa.decodePoint(this.Rencoded())})),s(u,"Rencoded",(function(){return this.eddsa.encodePoint(this.R())})),s(u,"Sencoded",(function(){return this.eddsa.encodeInt(this.S())})),u.prototype.toBytes=function(){return this.Rencoded().concat(this.Sencoded())},u.prototype.toHex=function(){return i.encode(this.toBytes(),"hex").toUpperCase()},e.exports=u},function(e,t){},function(e,t,n){"use strict";var r=n(204);t.certificate=n(356);var i=r.define("RSAPrivateKey",(function(){this.seq().obj(this.key("version").int(),this.key("modulus").int(),this.key("publicExponent").int(),this.key("privateExponent").int(),this.key("prime1").int(),this.key("prime2").int(),this.key("exponent1").int(),this.key("exponent2").int(),this.key("coefficient").int())}));t.RSAPrivateKey=i;var o=r.define("RSAPublicKey",(function(){this.seq().obj(this.key("modulus").int(),this.key("publicExponent").int())}));t.RSAPublicKey=o;var s=r.define("SubjectPublicKeyInfo",(function(){this.seq().obj(this.key("algorithm").use(a),this.key("subjectPublicKey").bitstr())}));t.PublicKey=s;var a=r.define("AlgorithmIdentifier",(function(){this.seq().obj(this.key("algorithm").objid(),this.key("none").null_().optional(),this.key("curve").objid().optional(),this.key("params").seq().obj(this.key("p").int(),this.key("q").int(),this.key("g").int()).optional())})),u=r.define("PrivateKeyInfo",(function(){this.seq().obj(this.key("version").int(),this.key("algorithm").use(a),this.key("subjectPrivateKey").octstr())}));t.PrivateKey=u;var c=r.define("EncryptedPrivateKeyInfo",(function(){this.seq().obj(this.key("algorithm").seq().obj(this.key("id").objid(),this.key("decrypt").seq().obj(this.key("kde").seq().obj(this.key("id").objid(),this.key("kdeparams").seq().obj(this.key("salt").octstr(),this.key("iters").int())),this.key("cipher").seq().obj(this.key("algo").objid(),this.key("iv").octstr()))),this.key("subjectPrivateKey").octstr())}));t.EncryptedPrivateKey=c;var f=r.define("DSAPrivateKey",(function(){this.seq().obj(this.key("version").int(),this.key("p").int(),this.key("q").int(),this.key("g").int(),this.key("pub_key").int(),this.key("priv_key").int())}));t.DSAPrivateKey=f,t.DSAparam=r.define("DSAparam",(function(){this.int()}));var l=r.define("ECPrivateKey",(function(){this.seq().obj(this.key("version").int(),this.key("privateKey").octstr(),this.key("parameters").optional().explicit(0).use(d),this.key("publicKey").optional().explicit(1).bitstr())}));t.ECPrivateKey=l;var d=r.define("ECParameters",(function(){this.choice({namedCurve:this.objid()})}));t.signature=r.define("signature",(function(){this.seq().obj(this.key("r").int(),this.key("s").int())}))},function(e,t,n){"use strict";const r=n(205),i=n(207),o=n(7);function s(e,t){this.name=e,this.body=t,this.decoders={},this.encoders={}}t.define=function(e,t){return new s(e,t)},s.prototype._createNamed=function(e){const t=this.name;function n(e){this._initNamed(e,t)}return o(n,e),n.prototype._initNamed=function(t,n){e.call(this,t,n)},new n(this)},s.prototype._getDecoder=function(e){return e=e||"der",this.decoders.hasOwnProperty(e)||(this.decoders[e]=this._createNamed(i[e])),this.decoders[e]},s.prototype.decode=function(e,t,n){return this._getDecoder(t).decode(e,n)},s.prototype._getEncoder=function(e){return e=e||"der",this.encoders.hasOwnProperty(e)||(this.encoders[e]=this._createNamed(r[e])),this.encoders[e]},s.prototype.encode=function(e,t,n){return this._getEncoder(t).encode(e,n)}},function(e,t,n){"use strict";const r=n(7),i=n(206);function o(e){i.call(this,e),this.enc="pem"}r(o,i),e.exports=o,o.prototype.encode=function(e,t){const n=i.prototype.encode.call(this,e).toString("base64"),r=["-----BEGIN "+t.label+"-----"];for(let e=0;e<n.length;e+=64)r.push(n.slice(e,e+64));return r.push("-----END "+t.label+"-----"),r.join("\n")}},function(e,t,n){"use strict";const r=n(7),i=n(130).Buffer,o=n(208);function s(e){o.call(this,e),this.enc="pem"}r(s,o),e.exports=s,s.prototype.decode=function(e,t){const n=e.toString().split(/[\r\n]+/g),r=t.label.toUpperCase(),s=/^-----(BEGIN|END) ([^-]+)-----$/;let a=-1,u=-1;for(let e=0;e<n.length;e++){const t=n[e].match(s);if(null!==t&&t[2]===r){if(-1!==a){if("END"!==t[1])break;u=e;break}if("BEGIN"!==t[1])break;a=e}}if(-1===a||-1===u)throw new Error("PEM section not found for: "+r);const c=n.slice(a+1,u).join("");c.replace(/[^a-z0-9+/=]+/gi,"");const f=i.from(c,"base64");return o.prototype.decode.call(this,f,t)}},function(e,t,n){"use strict";const r=t;r.Reporter=n(132).Reporter,r.DecoderBuffer=n(83).DecoderBuffer,r.EncoderBuffer=n(83).EncoderBuffer,r.Node=n(131)},function(e,t,n){"use strict";const r=t;r._reverse=function(e){const t={};return Object.keys(e).forEach((function(n){(0|n)==n&&(n|=0);const r=e[n];t[r]=n})),t},r.der=n(133)},function(e,t,n){"use strict";var r=n(204),i=r.define("Time",(function(){this.choice({utcTime:this.utctime(),generalTime:this.gentime()})})),o=r.define("AttributeTypeValue",(function(){this.seq().obj(this.key("type").objid(),this.key("value").any())})),s=r.define("AlgorithmIdentifier",(function(){this.seq().obj(this.key("algorithm").objid(),this.key("parameters").optional(),this.key("curve").objid().optional())})),a=r.define("SubjectPublicKeyInfo",(function(){this.seq().obj(this.key("algorithm").use(s),this.key("subjectPublicKey").bitstr())})),u=r.define("RelativeDistinguishedName",(function(){this.setof(o)})),c=r.define("RDNSequence",(function(){this.seqof(u)})),f=r.define("Name",(function(){this.choice({rdnSequence:this.use(c)})})),l=r.define("Validity",(function(){this.seq().obj(this.key("notBefore").use(i),this.key("notAfter").use(i))})),d=r.define("Extension",(function(){this.seq().obj(this.key("extnID").objid(),this.key("critical").bool().def(!1),this.key("extnValue").octstr())})),h=r.define("TBSCertificate",(function(){this.seq().obj(this.key("version").explicit(0).int().optional(),this.key("serialNumber").int(),this.key("signature").use(s),this.key("issuer").use(f),this.key("validity").use(l),this.key("subject").use(f),this.key("subjectPublicKeyInfo").use(a),this.key("issuerUniqueID").implicit(1).bitstr().optional(),this.key("subjectUniqueID").implicit(2).bitstr().optional(),this.key("extensions").explicit(3).seqof(d).optional())})),p=r.define("X509Certificate",(function(){this.seq().obj(this.key("tbsCertificate").use(h),this.key("signatureAlgorithm").use(s),this.key("signatureValue").bitstr())}));e.exports=p},function(e){e.exports=JSON.parse('{"2.16.840.1.101.3.4.1.1":"aes-128-ecb","2.16.840.1.101.3.4.1.2":"aes-128-cbc","2.16.840.1.101.3.4.1.3":"aes-128-ofb","2.16.840.1.101.3.4.1.4":"aes-128-cfb","2.16.840.1.101.3.4.1.21":"aes-192-ecb","2.16.840.1.101.3.4.1.22":"aes-192-cbc","2.16.840.1.101.3.4.1.23":"aes-192-ofb","2.16.840.1.101.3.4.1.24":"aes-192-cfb","2.16.840.1.101.3.4.1.41":"aes-256-ecb","2.16.840.1.101.3.4.1.42":"aes-256-cbc","2.16.840.1.101.3.4.1.43":"aes-256-ofb","2.16.840.1.101.3.4.1.44":"aes-256-cfb"}')},function(e,t,n){var r=/Proc-Type: 4,ENCRYPTED[\n\r]+DEK-Info: AES-((?:128)|(?:192)|(?:256))-CBC,([0-9A-H]+)[\n\r]+([0-9A-z\n\r+/=]+)[\n\r]+/m,i=/^-----BEGIN ((?:.*? KEY)|CERTIFICATE)-----/m,o=/^-----BEGIN ((?:.*? KEY)|CERTIFICATE)-----([0-9A-z\n\r+/=]+)-----END \1-----$/m,s=n(94),a=n(122),u=n(8).Buffer;e.exports=function(e,t){var n,c=e.toString(),f=c.match(r);if(f){var l="aes"+f[1],d=u.from(f[2],"hex"),h=u.from(f[3].replace(/[\r\n]/g,""),"base64"),p=s(t,d.slice(0,8),parseInt(f[1],10)).key,v=[],g=a.createDecipheriv(l,p,d);v.push(g.update(h)),v.push(g.final()),n=u.concat(v)}else{var m=c.match(o);n=u.from(m[2].replace(/[\r\n]/g,""),"base64")}return{tag:c.match(i)[1],data:n}}},function(e,t,n){var r=n(8).Buffer,i=n(203),o=n(127).ec,s=n(96),a=n(209);function u(e,t){if(e.cmpn(0)<=0)throw new Error("invalid sig");if(e.cmp(t)>=t)throw new Error("invalid sig")}e.exports=function(e,t,n,c,f){var l=s(n);if("ec"===l.type){if("ecdsa"!==c&&"ecdsa/rsa"!==c)throw new Error("wrong public key type");return function(e,t,n){var r=a[n.data.algorithm.curve.join(".")];if(!r)throw new Error("unknown curve "+n.data.algorithm.curve.join("."));var i=new o(r),s=n.data.subjectPrivateKey.data;return i.verify(t,e,s)}(e,t,l)}if("dsa"===l.type){if("dsa"!==c)throw new Error("wrong public key type");return function(e,t,n){var r=n.data.p,o=n.data.q,a=n.data.g,c=n.data.pub_key,f=s.signature.decode(e,"der"),l=f.s,d=f.r;u(l,o),u(d,o);var h=i.mont(r),p=l.invm(o);return 0===a.toRed(h).redPow(new i(t).mul(p).mod(o)).fromRed().mul(c.toRed(h).redPow(d.mul(p).mod(o)).fromRed()).mod(r).mod(o).cmp(d)}(e,t,l)}if("rsa"!==c&&"ecdsa/rsa"!==c)throw new Error("wrong public key type");t=r.concat([f,t]);for(var d=l.modulus.byteLength(),h=[1],p=0;t.length+h.length+2<d;)h.push(255),p++;h.push(0);for(var v=-1;++v<t.length;)h.push(t[v]);h=r.from(h);var g=i.mont(l.modulus);e=(e=new i(e).toRed(g)).redPow(new i(l.publicExponent)),e=r.from(e.fromRed().toArray());var m=p<8?1:0;for(d=Math.min(e.length,h.length),e.length!==h.length&&(m=1),v=-1;++v<d;)m|=e[v]^h[v];return 0===m}},function(e,t,n){(function(t){var r=n(127),i=n(29);e.exports=function(e){return new s(e)};var o={secp256k1:{name:"secp256k1",byteLength:32},secp224r1:{name:"p224",byteLength:28},prime256v1:{name:"p256",byteLength:32},prime192v1:{name:"p192",byteLength:24},ed25519:{name:"ed25519",byteLength:32},secp384r1:{name:"p384",byteLength:48},secp521r1:{name:"p521",byteLength:66}};function s(e){this.curveType=o[e],this.curveType||(this.curveType={name:e}),this.curve=new r.ec(this.curveType.name),this.keys=void 0}function a(e,n,r){Array.isArray(e)||(e=e.toArray());var i=new t(e);if(r&&i.length<r){var o=new t(r-i.length);o.fill(0),i=t.concat([o,i])}return n?i.toString(n):i}o.p224=o.secp224r1,o.p256=o.secp256r1=o.prime256v1,o.p192=o.secp192r1=o.prime192v1,o.p384=o.secp384r1,o.p521=o.secp521r1,s.prototype.generateKeys=function(e,t){return this.keys=this.curve.genKeyPair(),this.getPublicKey(e,t)},s.prototype.computeSecret=function(e,n,r){return n=n||"utf8",t.isBuffer(e)||(e=new t(e,n)),a(this.curve.keyFromPublic(e).getPublic().mul(this.keys.getPrivate()).getX(),r,this.curveType.byteLength)},s.prototype.getPublicKey=function(e,t){var n=this.keys.getPublic("compressed"===t,!0);return"hybrid"===t&&(n[n.length-1]%2?n[0]=7:n[0]=6),a(n,e)},s.prototype.getPrivateKey=function(e){return a(this.keys.getPrivate(),e)},s.prototype.setPublicKey=function(e,n){return n=n||"utf8",t.isBuffer(e)||(e=new t(e,n)),this.keys._importPublic(e),this},s.prototype.setPrivateKey=function(e,n){n=n||"utf8",t.isBuffer(e)||(e=new t(e,n));var r=new i(e);return r=r.toString(16),this.keys=this.curve.genKeyPair(),this.keys._importPrivate(r),this}}).call(this,n(6).Buffer)},function(e,t,n){t.publicEncrypt=n(362),t.privateDecrypt=n(363),t.privateEncrypt=function(e,n){return t.publicEncrypt(e,n,!0)},t.publicDecrypt=function(e,n){return t.privateDecrypt(e,n,!0)}},function(e,t,n){var r=n(96),i=n(66),o=n(79),s=n(210),a=n(211),u=n(29),c=n(212),f=n(126),l=n(8).Buffer;e.exports=function(e,t,n){var d;d=e.padding?e.padding:n?1:4;var h,p=r(e);if(4===d)h=function(e,t){var n=e.modulus.byteLength(),r=t.length,c=o("sha1").update(l.alloc(0)).digest(),f=c.length,d=2*f;if(r>n-d-2)throw new Error("message too long");var h=l.alloc(n-r-d-2),p=n-f-1,v=i(f),g=a(l.concat([c,h,l.alloc(1,1),t],p),s(v,p)),m=a(v,s(g,f));return new u(l.concat([l.alloc(1),m,g],n))}(p,t);else if(1===d)h=function(e,t,n){var r,o=t.length,s=e.modulus.byteLength();if(o>s-11)throw new Error("message too long");r=n?l.alloc(s-o-3,255):function(e){var t,n=l.allocUnsafe(e),r=0,o=i(2*e),s=0;for(;r<e;)s===o.length&&(o=i(2*e),s=0),(t=o[s++])&&(n[r++]=t);return n}(s-o-3);return new u(l.concat([l.from([0,n?1:2]),r,l.alloc(1),t],s))}(p,t,n);else{if(3!==d)throw new Error("unknown padding");if((h=new u(t)).cmp(p.modulus)>=0)throw new Error("data too long for modulus")}return n?f(h,p):c(h,p)}},function(e,t,n){var r=n(96),i=n(210),o=n(211),s=n(29),a=n(126),u=n(79),c=n(212),f=n(8).Buffer;e.exports=function(e,t,n){var l;l=e.padding?e.padding:n?1:4;var d,h=r(e),p=h.modulus.byteLength();if(t.length>p||new s(t).cmp(h.modulus)>=0)throw new Error("decryption error");d=n?c(new s(t),h):a(t,h);var v=f.alloc(p-d.length);if(d=f.concat([v,d],p),4===l)return function(e,t){var n=e.modulus.byteLength(),r=u("sha1").update(f.alloc(0)).digest(),s=r.length;if(0!==t[0])throw new Error("decryption error");var a=t.slice(1,s+1),c=t.slice(s+1),l=o(a,i(c,s)),d=o(c,i(l,n-s-1));if(function(e,t){e=f.from(e),t=f.from(t);var n=0,r=e.length;e.length!==t.length&&(n++,r=Math.min(e.length,t.length));var i=-1;for(;++i<r;)n+=e[i]^t[i];return n}(r,d.slice(0,s)))throw new Error("decryption error");var h=s;for(;0===d[h];)h++;if(1!==d[h++])throw new Error("decryption error");return d.slice(h)}(h,d);if(1===l)return function(e,t,n){var r=t.slice(0,2),i=2,o=0;for(;0!==t[i++];)if(i>=t.length){o++;break}var s=t.slice(2,i-1);("0002"!==r.toString("hex")&&!n||"0001"!==r.toString("hex")&&n)&&o++;s.length<8&&o++;if(o)throw new Error("decryption error");return t.slice(i)}(0,d,n);if(3===l)return d;throw new Error("unknown padding")}},function(e,t,n){"use strict";(function(e,r){function i(){throw new Error("secure random number generation not supported by this browser\nuse chrome, FireFox or Internet Explorer 11")}var o=n(8),s=n(66),a=o.Buffer,u=o.kMaxLength,c=e.crypto||e.msCrypto,f=Math.pow(2,32)-1;function l(e,t){if("number"!=typeof e||e!=e)throw new TypeError("offset must be a number");if(e>f||e<0)throw new TypeError("offset must be a uint32");if(e>u||e>t)throw new RangeError("offset out of range")}function d(e,t,n){if("number"!=typeof e||e!=e)throw new TypeError("size must be a number");if(e>f||e<0)throw new TypeError("size must be a uint32");if(e+t>n||e>u)throw new RangeError("buffer too small")}function h(e,t,n,i){if(r.browser){var o=e.buffer,a=new Uint8Array(o,t,n);return c.getRandomValues(a),i?void r.nextTick((function(){i(null,e)})):e}if(!i)return s(n).copy(e,t),e;s(n,(function(n,r){if(n)return i(n);r.copy(e,t),i(null,e)}))}c&&c.getRandomValues||!r.browser?(t.randomFill=function(t,n,r,i){if(!(a.isBuffer(t)||t instanceof e.Uint8Array))throw new TypeError('"buf" argument must be a Buffer or Uint8Array');if("function"==typeof n)i=n,n=0,r=t.length;else if("function"==typeof r)i=r,r=t.length-n;else if("function"!=typeof i)throw new TypeError('"cb" argument must be a function');return l(n,t.length),d(r,n,t.length),h(t,n,r,i)},t.randomFillSync=function(t,n,r){void 0===n&&(n=0);if(!(a.isBuffer(t)||t instanceof e.Uint8Array))throw new TypeError('"buf" argument must be a Buffer or Uint8Array');l(n,t.length),void 0===r&&(r=t.length-n);return d(r,n,t.length),h(t,n,r)}):(t.randomFill=i,t.randomFillSync=i)}).call(this,n(31),n(20))},function(e,t,n){e.exports=self.fetch||(self.fetch=n(213).default||n(213))},function(e,t,n){(function(e,r){var i;/*! https://mths.be/punycode v1.4.1 by @mathias */!function(o){t&&t.nodeType,e&&e.nodeType;var s="object"==typeof r&&r;s.global!==s&&s.window!==s&&s.self;var a,u=2147483647,c=/^xn--/,f=/[^\x20-\x7E]/,l=/[\x2E\u3002\uFF0E\uFF61]/g,d={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},h=Math.floor,p=String.fromCharCode;function v(e){throw new RangeError(d[e])}function g(e,t){for(var n=e.length,r=[];n--;)r[n]=t(e[n]);return r}function m(e,t){var n=e.split("@"),r="";return n.length>1&&(r=n[0]+"@",e=n[1]),r+g((e=e.replace(l,".")).split("."),t).join(".")}function b(e){for(var t,n,r=[],i=0,o=e.length;i<o;)(t=e.charCodeAt(i++))>=55296&&t<=56319&&i<o?56320==(64512&(n=e.charCodeAt(i++)))?r.push(((1023&t)<<10)+(1023&n)+65536):(r.push(t),i--):r.push(t);return r}function y(e){return g(e,(function(e){var t="";return e>65535&&(t+=p((e-=65536)>>>10&1023|55296),e=56320|1023&e),t+=p(e)})).join("")}function w(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function _(e,t,n){var r=0;for(e=n?h(e/700):e>>1,e+=h(e/t);e>455;r+=36)e=h(e/35);return h(r+36*e/(e+38))}function S(e){var t,n,r,i,o,s,a,c,f,l,d,p=[],g=e.length,m=0,b=128,w=72;for((n=e.lastIndexOf("-"))<0&&(n=0),r=0;r<n;++r)e.charCodeAt(r)>=128&&v("not-basic"),p.push(e.charCodeAt(r));for(i=n>0?n+1:0;i<g;){for(o=m,s=1,a=36;i>=g&&v("invalid-input"),((c=(d=e.charCodeAt(i++))-48<10?d-22:d-65<26?d-65:d-97<26?d-97:36)>=36||c>h((u-m)/s))&&v("overflow"),m+=c*s,!(c<(f=a<=w?1:a>=w+26?26:a-w));a+=36)s>h(u/(l=36-f))&&v("overflow"),s*=l;w=_(m-o,t=p.length+1,0==o),h(m/t)>u-b&&v("overflow"),b+=h(m/t),m%=t,p.splice(m++,0,b)}return y(p)}function E(e){var t,n,r,i,o,s,a,c,f,l,d,g,m,y,S,E=[];for(g=(e=b(e)).length,t=128,n=0,o=72,s=0;s<g;++s)(d=e[s])<128&&E.push(p(d));for(r=i=E.length,i&&E.push("-");r<g;){for(a=u,s=0;s<g;++s)(d=e[s])>=t&&d<a&&(a=d);for(a-t>h((u-n)/(m=r+1))&&v("overflow"),n+=(a-t)*m,t=a,s=0;s<g;++s)if((d=e[s])<t&&++n>u&&v("overflow"),d==t){for(c=n,f=36;!(c<(l=f<=o?1:f>=o+26?26:f-o));f+=36)S=c-l,y=36-l,E.push(p(w(l+S%y,0))),c=h(S/y);E.push(p(w(c,0))),o=_(n,m,r==i),n=0,++r}++n,++t}return E.join("")}a={version:"1.4.1",ucs2:{decode:b,encode:y},decode:S,encode:E,toASCII:function(e){return m(e,(function(e){return f.test(e)?"xn--"+E(e):e}))},toUnicode:function(e){return m(e,(function(e){return c.test(e)?S(e.slice(4).toLowerCase()):e}))}},void 0===(i=function(){return a}.call(t,n,t,e))||(e.exports=i)}()}).call(this,n(57)(e),n(31))},function(e,t,n){"use strict";e.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},function(e,t,n){"use strict";t.decode=t.parse=n(369),t.encode=t.stringify=n(370)},function(e,t,n){"use strict";function r(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=function(e,t,n,o){t=t||"&",n=n||"=";var s={};if("string"!=typeof e||0===e.length)return s;var a=/\+/g;e=e.split(t);var u=1e3;o&&"number"==typeof o.maxKeys&&(u=o.maxKeys);var c=e.length;u>0&&c>u&&(c=u);for(var f=0;f<c;++f){var l,d,h,p,v=e[f].replace(a,"%20"),g=v.indexOf(n);g>=0?(l=v.substr(0,g),d=v.substr(g+1)):(l=v,d=""),h=decodeURIComponent(l),p=decodeURIComponent(d),r(s,h)?i(s[h])?s[h].push(p):s[h]=[s[h],p]:s[h]=p}return s};var i=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},function(e,t,n){"use strict";var r=function(e){switch(typeof e){case"string":return e;case"boolean":return e?"true":"false";case"number":return isFinite(e)?e:"";default:return""}};e.exports=function(e,t,n,a){return t=t||"&",n=n||"=",null===e&&(e=void 0),"object"==typeof e?o(s(e),(function(s){var a=encodeURIComponent(r(s))+n;return i(e[s])?o(e[s],(function(e){return a+encodeURIComponent(r(e))})).join(t):a+encodeURIComponent(r(e[s]))})).join(t):a?encodeURIComponent(r(a))+n+encodeURIComponent(r(e)):""};var i=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)};function o(e,t){if(e.map)return e.map(t);for(var n=[],r=0;r<e.length;r++)n.push(t(e[r],r));return n}var s=Object.keys||function(e){var t=[];for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.push(n);return t}},function(e,t,n){var r,i,o=n(214),s=n(215),a=0,u=0;e.exports=function(e,t,n){var c=t&&n||0,f=t||[],l=(e=e||{}).node||r,d=void 0!==e.clockseq?e.clockseq:i;if(null==l||null==d){var h=o();null==l&&(l=r=[1|h[0],h[1],h[2],h[3],h[4],h[5]]),null==d&&(d=i=16383&(h[6]<<8|h[7]))}var p=void 0!==e.msecs?e.msecs:(new Date).getTime(),v=void 0!==e.nsecs?e.nsecs:u+1,g=p-a+(v-u)/1e4;if(g<0&&void 0===e.clockseq&&(d=d+1&16383),(g<0||p>a)&&void 0===e.nsecs&&(v=0),v>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");a=p,u=v,i=d;var m=(1e4*(268435455&(p+=122192928e5))+v)%4294967296;f[c++]=m>>>24&255,f[c++]=m>>>16&255,f[c++]=m>>>8&255,f[c++]=255&m;var b=p/4294967296*1e4&268435455;f[c++]=b>>>8&255,f[c++]=255&b,f[c++]=b>>>24&15|16,f[c++]=b>>>16&255,f[c++]=d>>>8|128,f[c++]=255&d;for(var y=0;y<6;++y)f[c+y]=l[y];return t||s(f)}},function(e,t,n){var r=n(214),i=n(215);e.exports=function(e,t,n){var o=t&&n||0;"string"==typeof e&&(t="binary"===e?new Array(16):null,e=null);var s=(e=e||{}).random||(e.rng||r)();if(s[6]=15&s[6]|64,s[8]=63&s[8]|128,t)for(var a=0;a<16;++a)t[o+a]=s[a];return t||i(s)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Sha256=void 0;var r=n(216),i=n(219),o=n(374),s=n(377),a=n(379),u=n(134),c=function(){function e(e){s.supportsWebCrypto(u.locateWindow())?this.hash=new i.Sha256(e):a.isMsWindow(u.locateWindow())?this.hash=new r.Sha256(e):this.hash=new o.Sha256(e)}return e.prototype.update=function(e,t){this.hash.update(e,t)},e.prototype.digest=function(){return this.hash.digest()},e}();t.Sha256=c},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(1).__exportStar(n(375),t)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.Sha256=void 0;var r=n(1),i=n(220),o=n(376),s=n(497),a=function(){function e(e){if(this.hash=new o.RawSha256,e){this.outer=new o.RawSha256;var t=function(e){var t=u(e);if(t.byteLength>i.BLOCK_SIZE){var n=new o.RawSha256;n.update(t),t=n.digest()}var r=new Uint8Array(i.BLOCK_SIZE);return r.set(t),r}(e),n=new Uint8Array(i.BLOCK_SIZE);n.set(t);for(var r=0;r<i.BLOCK_SIZE;r++)t[r]^=54,n[r]^=92;this.hash.update(t),this.outer.update(n);for(r=0;r<t.byteLength;r++)t[r]=0}}return e.prototype.update=function(e){if(!function(e){if("string"==typeof e)return 0===e.length;return 0===e.byteLength}(e)&&!this.error)try{this.hash.update(u(e))}catch(e){this.error=e}},e.prototype.digestSync=function(){if(this.error)throw this.error;return this.outer?(this.outer.finished||this.outer.update(this.hash.digest()),this.outer.digest()):this.hash.digest()},e.prototype.digest=function(){return r.__awaiter(this,void 0,void 0,(function(){return r.__generator(this,(function(e){return[2,this.digestSync()]}))}))},e}();function u(e){return"string"==typeof e?s.fromUtf8(e):ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength/Uint8Array.BYTES_PER_ELEMENT):new Uint8Array(e)}t.Sha256=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.RawSha256=void 0;var r=n(220),i=function(){function e(){this.state=Int32Array.from(r.INIT),this.temp=new Int32Array(64),this.buffer=new Uint8Array(64),this.bufferLength=0,this.bytesHashed=0,this.finished=!1}return e.prototype.update=function(e){if(this.finished)throw new Error("Attempted to update an already finished hash.");var t=0,n=e.byteLength;if(this.bytesHashed+=n,8*this.bytesHashed>r.MAX_HASHABLE_LENGTH)throw new Error("Cannot hash more than 2^53 - 1 bits");for(;n>0;)this.buffer[this.bufferLength++]=e[t++],n--,this.bufferLength===r.BLOCK_SIZE&&(this.hashBuffer(),this.bufferLength=0)},e.prototype.digest=function(){if(!this.finished){var e=8*this.bytesHashed,t=new DataView(this.buffer.buffer,this.buffer.byteOffset,this.buffer.byteLength),n=this.bufferLength;if(t.setUint8(this.bufferLength++,128),n%r.BLOCK_SIZE>=r.BLOCK_SIZE-8){for(var i=this.bufferLength;i<r.BLOCK_SIZE;i++)t.setUint8(i,0);this.hashBuffer(),this.bufferLength=0}for(i=this.bufferLength;i<r.BLOCK_SIZE-8;i++)t.setUint8(i,0);t.setUint32(r.BLOCK_SIZE-8,Math.floor(e/4294967296),!0),t.setUint32(r.BLOCK_SIZE-4,e),this.hashBuffer(),this.finished=!0}var o=new Uint8Array(r.DIGEST_LENGTH);for(i=0;i<8;i++)o[4*i]=this.state[i]>>>24&255,o[4*i+1]=this.state[i]>>>16&255,o[4*i+2]=this.state[i]>>>8&255,o[4*i+3]=this.state[i]>>>0&255;return o},e.prototype.hashBuffer=function(){for(var e=this.buffer,t=this.state,n=t[0],i=t[1],o=t[2],s=t[3],a=t[4],u=t[5],c=t[6],f=t[7],l=0;l<r.BLOCK_SIZE;l++){if(l<16)this.temp[l]=(255&e[4*l])<<24|(255&e[4*l+1])<<16|(255&e[4*l+2])<<8|255&e[4*l+3];else{var d=this.temp[l-2],h=(d>>>17|d<<15)^(d>>>19|d<<13)^d>>>10,p=((d=this.temp[l-15])>>>7|d<<25)^(d>>>18|d<<14)^d>>>3;this.temp[l]=(h+this.temp[l-7]|0)+(p+this.temp[l-16]|0)}var v=(((a>>>6|a<<26)^(a>>>11|a<<21)^(a>>>25|a<<7))+(a&u^~a&c)|0)+(f+(r.KEY[l]+this.temp[l]|0)|0)|0,g=((n>>>2|n<<30)^(n>>>13|n<<19)^(n>>>22|n<<10))+(n&i^n&o^i&o)|0;f=c,c=u,u=a,a=s+v|0,s=o,o=i,i=n,n=v+g|0}t[0]+=n,t[1]+=i,t[2]+=o,t[3]+=s,t[4]+=a,t[5]+=u,t[6]+=c,t[7]+=f},e}();t.RawSha256=i},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),n(1).__exportStar(n(378),t)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.supportsZeroByteGCM=t.supportsSubtleCrypto=t.supportsSecureRandom=t.supportsWebCrypto=void 0;var r=n(1),i=["decrypt","digest","encrypt","exportKey","generateKey","importKey","sign","verify"];function o(e){return"object"==typeof e&&"object"==typeof e.crypto&&"function"==typeof e.crypto.getRandomValues}function s(e){return e&&i.every((function(t){return"function"==typeof e[t]}))}t.supportsWebCrypto=function(e){return!(!o(e)||"object"!=typeof e.crypto.subtle)&&s(e.crypto.subtle)},t.supportsSecureRandom=o,t.supportsSubtleCrypto=s,t.supportsZeroByteGCM=function(e){return r.__awaiter(this,void 0,void 0,(function(){var t;return r.__generator(this,(function(n){switch(n.label){case 0:if(!s(e))return[2,!1];n.label=1;case 1:return n.trys.push([1,4,,5]),[4,e.generateKey({name:"AES-GCM",length:128},!1,["encrypt"])];case 2:return t=n.sent(),[4,e.encrypt({name:"AES-GCM",iv:new Uint8Array(Array(12)),additionalData:new Uint8Array(Array(16)),tagLength:128},t,new Uint8Array(0))];case 3:return[2,16===n.sent().byteLength];case 4:return n.sent(),[2,!1];case 5:return[2]}}))}))}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(1);r.__exportStar(n(380),t),r.__exportStar(n(381),t),r.__exportStar(n(382),t),r.__exportStar(n(383),t),r.__exportStar(n(384),t)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0})},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.isMsWindow=void 0;var r=["decrypt","digest","encrypt","exportKey","generateKey","importKey","sign","verify"];t.isMsWindow=function(e){if(function(e){return"MSInputMethodContext"in e&&"msCrypto"in e}(e)&&void 0!==e.msCrypto.subtle){var t=e.msCrypto,n=t.getRandomValues,i=t.subtle;return r.map((function(e){return i[e]})).concat(n).every((function(e){return"function"==typeof e}))}return!1}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(1),i=n(222),o=n(386),s=n(494),a=function(){function e(e){if(this.hash=new o.RawSha256,e){this.outer=new o.RawSha256;var t=function(e){var t=u(e);if(t.byteLength>i.BLOCK_SIZE){var n=new o.RawSha256;n.update(t),t=n.digest()}var r=new Uint8Array(i.BLOCK_SIZE);return r.set(t),r}(e),n=new Uint8Array(i.BLOCK_SIZE);n.set(t);for(var r=0;r<i.BLOCK_SIZE;r++)t[r]^=54,n[r]^=92;this.hash.update(t),this.outer.update(n);for(r=0;r<t.byteLength;r++)t[r]=0}}return e.prototype.update=function(e){if(!function(e){if("string"==typeof e)return 0===e.length;return 0===e.byteLength}(e)&&!this.error)try{this.hash.update(u(e))}catch(e){this.error=e}},e.prototype.digestSync=function(){if(this.error)throw this.error;return this.outer?(this.outer.finished||this.outer.update(this.hash.digest()),this.outer.digest()):this.hash.digest()},e.prototype.digest=function(){return r.__awaiter(this,void 0,void 0,(function(){return r.__generator(this,(function(e){return[2,this.digestSync()]}))}))},e}();function u(e){return"string"==typeof e?s.fromUtf8(e):ArrayBuffer.isView(e)?new Uint8Array(e.buffer,e.byteOffset,e.byteLength/Uint8Array.BYTES_PER_ELEMENT):new Uint8Array(e)}t.Sha256=a},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(222),i=function(){function e(){this.state=Int32Array.from(r.INIT),this.temp=new Int32Array(64),this.buffer=new Uint8Array(64),this.bufferLength=0,this.bytesHashed=0,this.finished=!1}return e.prototype.update=function(e){if(this.finished)throw new Error("Attempted to update an already finished hash.");var t=0,n=e.byteLength;if(this.bytesHashed+=n,8*this.bytesHashed>r.MAX_HASHABLE_LENGTH)throw new Error("Cannot hash more than 2^53 - 1 bits");for(;n>0;)this.buffer[this.bufferLength++]=e[t++],n--,this.bufferLength===r.BLOCK_SIZE&&(this.hashBuffer(),this.bufferLength=0)},e.prototype.digest=function(){if(!this.finished){var e=8*this.bytesHashed,t=new DataView(this.buffer.buffer,this.buffer.byteOffset,this.buffer.byteLength),n=this.bufferLength;if(t.setUint8(this.bufferLength++,128),n%r.BLOCK_SIZE>=r.BLOCK_SIZE-8){for(var i=this.bufferLength;i<r.BLOCK_SIZE;i++)t.setUint8(i,0);this.hashBuffer(),this.bufferLength=0}for(i=this.bufferLength;i<r.BLOCK_SIZE-8;i++)t.setUint8(i,0);t.setUint32(r.BLOCK_SIZE-8,Math.floor(e/4294967296),!0),t.setUint32(r.BLOCK_SIZE-4,e),this.hashBuffer(),this.finished=!0}var o=new Uint8Array(r.DIGEST_LENGTH);for(i=0;i<8;i++)o[4*i]=this.state[i]>>>24&255,o[4*i+1]=this.state[i]>>>16&255,o[4*i+2]=this.state[i]>>>8&255,o[4*i+3]=this.state[i]>>>0&255;return o},e.prototype.hashBuffer=function(){for(var e=this.buffer,t=this.state,n=t[0],i=t[1],o=t[2],s=t[3],a=t[4],u=t[5],c=t[6],f=t[7],l=0;l<r.BLOCK_SIZE;l++){if(l<16)this.temp[l]=(255&e[4*l])<<24|(255&e[4*l+1])<<16|(255&e[4*l+2])<<8|255&e[4*l+3];else{var d=this.temp[l-2],h=(d>>>17|d<<15)^(d>>>19|d<<13)^d>>>10,p=((d=this.temp[l-15])>>>7|d<<25)^(d>>>18|d<<14)^d>>>3;this.temp[l]=(h+this.temp[l-7]|0)+(p+this.temp[l-16]|0)}var v=(((a>>>6|a<<26)^(a>>>11|a<<21)^(a>>>25|a<<7))+(a&u^~a&c)|0)+(f+(r.KEY[l]+this.temp[l]|0)|0)|0,g=((n>>>2|n<<30)^(n>>>13|n<<19)^(n>>>22|n<<10))+(n&i^n&o^i&o)|0;f=c,c=u,u=a,a=s+v|0,s=o,o=i,i=n,n=v+g|0}t[0]+=n,t[1]+=i,t[2]+=o,t[3]+=s,t[4]+=a,t[5]+=u,t[6]+=c,t[7]+=f},e}();t.RawSha256=i},function(e,t,n){var r=n(388),i=n(419);e.exports=function(e,t){for(var n=0,o=(t=r(t,e)).length;null!=e&&n<o;)e=e[i(t[n++])];return n&&n==o?e:void 0}},function(e,t,n){var r=n(61),i=n(389),o=n(392),s=n(416);e.exports=function(e,t){return r(e)?e:i(e,t)?[e]:o(s(e))}},function(e,t,n){var r=n(61),i=n(135),o=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,s=/^\w*$/;e.exports=function(e,t){if(r(e))return!1;var n=typeof e;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=e&&!i(e))||(s.test(e)||!o.test(e)||null!=t&&e in Object(t))}},function(e,t,n){var r=n(97),i=Object.prototype,o=i.hasOwnProperty,s=i.toString,a=r?r.toStringTag:void 0;e.exports=function(e){var t=o.call(e,a),n=e[a];try{e[a]=void 0;var r=!0}catch(e){}var i=s.call(e);return r&&(t?e[a]=n:delete e[a]),i}},function(e,t){var n=Object.prototype.toString;e.exports=function(e){return n.call(e)}},function(e,t,n){var r=n(393),i=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,o=/\\(\\)?/g,s=r((function(e){var t=[];return 46===e.charCodeAt(0)&&t.push(""),e.replace(i,(function(e,n,r,i){t.push(r?i.replace(o,"$1"):n||e)})),t}));e.exports=s},function(e,t,n){var r=n(394);e.exports=function(e){var t=r(e,(function(e){return 500===n.size&&n.clear(),e})),n=t.cache;return t}},function(e,t,n){var r=n(136);function i(e,t){if("function"!=typeof e||null!=t&&"function"!=typeof t)throw new TypeError("Expected a function");var n=function(){var r=arguments,i=t?t.apply(this,r):r[0],o=n.cache;if(o.has(i))return o.get(i);var s=e.apply(this,r);return n.cache=o.set(i,s)||o,s};return n.cache=new(i.Cache||r),n}i.Cache=r,e.exports=i},function(e,t,n){var r=n(396),i=n(99),o=n(137);e.exports=function(){this.size=0,this.__data__={hash:new r,map:new(o||i),string:new r}}},function(e,t,n){var r=n(397),i=n(402),o=n(403),s=n(404),a=n(405);function u(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t<n;){var r=e[t];this.set(r[0],r[1])}}u.prototype.clear=r,u.prototype.delete=i,u.prototype.get=o,u.prototype.has=s,u.prototype.set=a,e.exports=u},function(e,t,n){var r=n(98);e.exports=function(){this.__data__=r?r(null):{},this.size=0}},function(e,t,n){var r=n(224),i=n(399),o=n(225),s=n(226),a=/^\[object .+?Constructor\]$/,u=Function.prototype,c=Object.prototype,f=u.toString,l=c.hasOwnProperty,d=RegExp("^"+f.call(l).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");e.exports=function(e){return!(!o(e)||i(e))&&(r(e)?d:a).test(s(e))}},function(e,t,n){var r,i=n(400),o=(r=/[^.]+$/.exec(i&&i.keys&&i.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";e.exports=function(e){return!!o&&o in e}},function(e,t,n){var r=n(53)["__core-js_shared__"];e.exports=r},function(e,t){e.exports=function(e,t){return null==e?void 0:e[t]}},function(e,t){e.exports=function(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t}},function(e,t,n){var r=n(98),i=Object.prototype.hasOwnProperty;e.exports=function(e){var t=this.__data__;if(r){var n=t[e];return"__lodash_hash_undefined__"===n?void 0:n}return i.call(t,e)?t[e]:void 0}},function(e,t,n){var r=n(98),i=Object.prototype.hasOwnProperty;e.exports=function(e){var t=this.__data__;return r?void 0!==t[e]:i.call(t,e)}},function(e,t,n){var r=n(98);e.exports=function(e,t){var n=this.__data__;return this.size+=this.has(e)?0:1,n[e]=r&&void 0===t?"__lodash_hash_undefined__":t,this}},function(e,t){e.exports=function(){this.__data__=[],this.size=0}},function(e,t,n){var r=n(100),i=Array.prototype.splice;e.exports=function(e){var t=this.__data__,n=r(t,e);return!(n<0)&&(n==t.length-1?t.pop():i.call(t,n,1),--this.size,!0)}},function(e,t,n){var r=n(100);e.exports=function(e){var t=this.__data__,n=r(t,e);return n<0?void 0:t[n][1]}},function(e,t,n){var r=n(100);e.exports=function(e){return r(this.__data__,e)>-1}},function(e,t,n){var r=n(100);e.exports=function(e,t){var n=this.__data__,i=r(n,e);return i<0?(++this.size,n.push([e,t])):n[i][1]=t,this}},function(e,t,n){var r=n(101);e.exports=function(e){var t=r(this,e).delete(e);return this.size-=t?1:0,t}},function(e,t){e.exports=function(e){var t=typeof e;return"string"==t||"number"==t||"symbol"==t||"boolean"==t?"__proto__"!==e:null===e}},function(e,t,n){var r=n(101);e.exports=function(e){return r(this,e).get(e)}},function(e,t,n){var r=n(101);e.exports=function(e){return r(this,e).has(e)}},function(e,t,n){var r=n(101);e.exports=function(e,t){var n=r(this,e),i=n.size;return n.set(e,t),this.size+=n.size==i?0:1,this}},function(e,t,n){var r=n(417);e.exports=function(e){return null==e?"":r(e)}},function(e,t,n){var r=n(97),i=n(418),o=n(61),s=n(135),a=r?r.prototype:void 0,u=a?a.toString:void 0;e.exports=function e(t){if("string"==typeof t)return t;if(o(t))return i(t,e)+"";if(s(t))return u?u.call(t):"";var n=t+"";return"0"==n&&1/t==-1/0?"-0":n}},function(e,t){e.exports=function(e,t){for(var n=-1,r=null==e?0:e.length,i=Array(r);++n<r;)i[n]=t(e[n],n,e);return i}},function(e,t,n){var r=n(135);e.exports=function(e){if("string"==typeof e||r(e))return e;var t=e+"";return"0"==t&&1/e==-1/0?"-0":t}},function(e,t,n){var r=n(421)(Object.keys,Object);e.exports=r},function(e,t){e.exports=function(e,t){return function(n){return e(t(n))}}},function(e,t,n){var r=n(72)(n(53),"DataView");e.exports=r},function(e,t,n){var r=n(72)(n(53),"Promise");e.exports=r},function(e,t,n){var r=n(72)(n(53),"Set");e.exports=r},function(e,t,n){var r=n(72)(n(53),"WeakMap");e.exports=r},function(e,t,n){var r=n(84),i=n(85);e.exports=function(e){return i(e)&&"[object Arguments]"==r(e)}},function(e,t){e.exports=function(){return!1}},function(e,t,n){var r=n(84),i=n(233),o=n(85),s={};s["[object Float32Array]"]=s["[object Float64Array]"]=s["[object Int8Array]"]=s["[object Int16Array]"]=s["[object Int32Array]"]=s["[object Uint8Array]"]=s["[object Uint8ClampedArray]"]=s["[object Uint16Array]"]=s["[object Uint32Array]"]=!0,s["[object Arguments]"]=s["[object Array]"]=s["[object ArrayBuffer]"]=s["[object Boolean]"]=s["[object DataView]"]=s["[object Date]"]=s["[object Error]"]=s["[object Function]"]=s["[object Map]"]=s["[object Number]"]=s["[object Object]"]=s["[object RegExp]"]=s["[object Set]"]=s["[object String]"]=s["[object WeakMap]"]=!1,e.exports=function(e){return o(e)&&i(e.length)&&!!s[r(e)]}},function(e,t){e.exports=function(e){return function(t){return e(t)}}},function(e,t,n){(function(e){var r=n(223),i=t&&!t.nodeType&&t,o=i&&"object"==typeof e&&e&&!e.nodeType&&e,s=o&&o.exports===i&&r.process,a=function(){try{var e=o&&o.require&&o.require("util").types;return e||s&&s.binding&&s.binding("util")}catch(e){}}();e.exports=a}).call(this,n(57)(e))},function(e,t,n){var r=n(432),i=n(85);e.exports=function e(t,n,o,s,a){return t===n||(null==t||null==n||!i(t)&&!i(n)?t!=t&&n!=n:r(t,n,o,s,e,a))}},function(e,t,n){var r=n(433),i=n(234),o=n(444),s=n(448),a=n(230),u=n(61),c=n(138),f=n(139),l="[object Object]",d=Object.prototype.hasOwnProperty;e.exports=function(e,t,n,h,p,v){var g=u(e),m=u(t),b=g?"[object Array]":a(e),y=m?"[object Array]":a(t),w=(b="[object Arguments]"==b?l:b)==l,_=(y="[object Arguments]"==y?l:y)==l,S=b==y;if(S&&c(e)){if(!c(t))return!1;g=!0,w=!1}if(S&&!w)return v||(v=new r),g||f(e)?i(e,t,n,h,p,v):o(e,t,b,n,h,p,v);if(!(1&n)){var E=w&&d.call(e,"__wrapped__"),M=_&&d.call(t,"__wrapped__");if(E||M){var A=E?e.value():e,I=M?t.value():t;return v||(v=new r),p(A,I,n,h,v)}}return!!S&&(v||(v=new r),s(e,t,n,h,p,v))}},function(e,t,n){var r=n(99),i=n(434),o=n(435),s=n(436),a=n(437),u=n(438);function c(e){var t=this.__data__=new r(e);this.size=t.size}c.prototype.clear=i,c.prototype.delete=o,c.prototype.get=s,c.prototype.has=a,c.prototype.set=u,e.exports=c},function(e,t,n){var r=n(99);e.exports=function(){this.__data__=new r,this.size=0}},function(e,t){e.exports=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n}},function(e,t){e.exports=function(e){return this.__data__.get(e)}},function(e,t){e.exports=function(e){return this.__data__.has(e)}},function(e,t,n){var r=n(99),i=n(137),o=n(136);e.exports=function(e,t){var n=this.__data__;if(n instanceof r){var s=n.__data__;if(!i||s.length<199)return s.push([e,t]),this.size=++n.size,this;n=this.__data__=new o(s)}return n.set(e,t),this.size=n.size,this}},function(e,t,n){var r=n(136),i=n(440),o=n(441);function s(e){var t=-1,n=null==e?0:e.length;for(this.__data__=new r;++t<n;)this.add(e[t])}s.prototype.add=s.prototype.push=i,s.prototype.has=o,e.exports=s},function(e,t){e.exports=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this}},function(e,t){e.exports=function(e){return this.__data__.has(e)}},function(e,t){e.exports=function(e,t){for(var n=-1,r=null==e?0:e.length;++n<r;)if(t(e[n],n,e))return!0;return!1}},function(e,t){e.exports=function(e,t){return e.has(t)}},function(e,t,n){var r=n(97),i=n(445),o=n(227),s=n(234),a=n(446),u=n(447),c=r?r.prototype:void 0,f=c?c.valueOf:void 0;e.exports=function(e,t,n,r,c,l,d){switch(n){case"[object DataView]":if(e.byteLength!=t.byteLength||e.byteOffset!=t.byteOffset)return!1;e=e.buffer,t=t.buffer;case"[object ArrayBuffer]":return!(e.byteLength!=t.byteLength||!l(new i(e),new i(t)));case"[object Boolean]":case"[object Date]":case"[object Number]":return o(+e,+t);case"[object Error]":return e.name==t.name&&e.message==t.message;case"[object RegExp]":case"[object String]":return e==t+"";case"[object Map]":var h=a;case"[object Set]":var p=1&r;if(h||(h=u),e.size!=t.size&&!p)return!1;var v=d.get(e);if(v)return v==t;r|=2,d.set(e,t);var g=s(h(e),h(t),r,c,l,d);return d.delete(e),g;case"[object Symbol]":if(f)return f.call(e)==f.call(t)}return!1}},function(e,t,n){var r=n(53).Uint8Array;e.exports=r},function(e,t){e.exports=function(e){var t=-1,n=Array(e.size);return e.forEach((function(e,r){n[++t]=[r,e]})),n}},function(e,t){e.exports=function(e){var t=-1,n=Array(e.size);return e.forEach((function(e){n[++t]=e})),n}},function(e,t,n){var r=n(449),i=Object.prototype.hasOwnProperty;e.exports=function(e,t,n,o,s,a){var u=1&n,c=r(e),f=c.length;if(f!=r(t).length&&!u)return!1;for(var l=f;l--;){var d=c[l];if(!(u?d in t:i.call(t,d)))return!1}var h=a.get(e),p=a.get(t);if(h&&p)return h==t&&p==e;var v=!0;a.set(e,t),a.set(t,e);for(var g=u;++l<f;){var m=e[d=c[l]],b=t[d];if(o)var y=u?o(b,m,d,t,e,a):o(m,b,d,e,t,a);if(!(void 0===y?m===b||s(m,b,n,o,a):y)){v=!1;break}g||(g="constructor"==d)}if(v&&!g){var w=e.constructor,_=t.constructor;w==_||!("constructor"in e)||!("constructor"in t)||"function"==typeof w&&w instanceof w&&"function"==typeof _&&_ instanceof _||(v=!1)}return a.delete(e),a.delete(t),v}},function(e,t,n){var r=n(450),i=n(452),o=n(455);e.exports=function(e){return r(e,o,i)}},function(e,t,n){var r=n(451),i=n(61);e.exports=function(e,t,n){var o=t(e);return i(e)?o:r(o,n(e))}},function(e,t){e.exports=function(e,t){for(var n=-1,r=t.length,i=e.length;++n<r;)e[i+n]=t[n];return e}},function(e,t,n){var r=n(453),i=n(454),o=Object.prototype.propertyIsEnumerable,s=Object.getOwnPropertySymbols,a=s?function(e){return null==e?[]:(e=Object(e),r(s(e),(function(t){return o.call(e,t)})))}:i;e.exports=a},function(e,t){e.exports=function(e,t){for(var n=-1,r=null==e?0:e.length,i=0,o=[];++n<r;){var s=e[n];t(s,n,e)&&(o[i++]=s)}return o}},function(e,t){e.exports=function(){return[]}},function(e,t,n){var r=n(456),i=n(228),o=n(232);e.exports=function(e){return o(e)?r(e):i(e)}},function(e,t,n){var r=n(457),i=n(231),o=n(61),s=n(138),a=n(458),u=n(139),c=Object.prototype.hasOwnProperty;e.exports=function(e,t){var n=o(e),f=!n&&i(e),l=!n&&!f&&s(e),d=!n&&!f&&!l&&u(e),h=n||f||l||d,p=h?r(e.length,String):[],v=p.length;for(var g in e)!t&&!c.call(e,g)||h&&("length"==g||l&&("offset"==g||"parent"==g)||d&&("buffer"==g||"byteLength"==g||"byteOffset"==g)||a(g,v))||p.push(g);return p}},function(e,t){e.exports=function(e,t){for(var n=-1,r=Array(e);++n<e;)r[n]=t(n);return r}},function(e,t){var n=/^(?:0|[1-9]\d*)$/;e.exports=function(e,t){var r=typeof e;return!!(t=null==t?9007199254740991:t)&&("number"==r||"symbol"!=r&&n.test(e))&&e>-1&&e%1==0&&e<t}},function(e,t,n){"use strict";const r=n(54),i=function(e,t,n){const o={};if((!e.child||r.isEmptyObject(e.child))&&(!e.attrsMap||r.isEmptyObject(e.attrsMap)))return r.isExist(e.val)?e.val:"";if(r.isExist(e.val)&&("string"!=typeof e.val||""!==e.val&&e.val!==t.cdataPositionChar)){const i=r.isTagNameInArrayMode(e.tagname,t.arrayMode,n);o[t.textNodeName]=i?[e.val]:e.val}r.merge(o,e.attrsMap,t.arrayMode);const s=Object.keys(e.child);for(let a=0;a<s.length;a++){const u=s[a];if(e.child[u]&&e.child[u].length>1){o[u]=[];for(let n in e.child[u])e.child[u].hasOwnProperty(n)&&o[u].push(i(e.child[u][n],t,u))}else{const s=i(e.child[u][0],t,u),a=!0===t.arrayMode&&"object"==typeof s||r.isTagNameInArrayMode(u,t.arrayMode,n);o[u]=a?[s]:s}}return o};t.convertToJson=i},function(e,t,n){"use strict";e.exports=function(e,t,n){this.tagname=e,this.parent=t,this.child={},this.attrsMap={},this.val=n,this.addChild=function(e){Array.isArray(this.child[e.tagname])?this.child[e.tagname].push(e):this.child[e.tagname]=[e]}}},function(e,t,n){"use strict";const r=n(54),i={allowBooleanAttributes:!1},o=["allowBooleanAttributes"];function s(e,t){for(var n=t;t<e.length;t++)if("?"!=e[t]&&" "!=e[t]);else{var r=e.substr(n,t-n);if(t>5&&"xml"===r)return d("InvalidXml","XML declaration allowed only at the start of the document.",p(e,t));if("?"==e[t]&&">"==e[t+1]){t++;break}}return t}function a(e,t){if(e.length>t+5&&"-"===e[t+1]&&"-"===e[t+2]){for(t+=3;t<e.length;t++)if("-"===e[t]&&"-"===e[t+1]&&">"===e[t+2]){t+=2;break}}else if(e.length>t+8&&"D"===e[t+1]&&"O"===e[t+2]&&"C"===e[t+3]&&"T"===e[t+4]&&"Y"===e[t+5]&&"P"===e[t+6]&&"E"===e[t+7]){let n=1;for(t+=8;t<e.length;t++)if("<"===e[t])n++;else if(">"===e[t]&&(n--,0===n))break}else if(e.length>t+9&&"["===e[t+1]&&"C"===e[t+2]&&"D"===e[t+3]&&"A"===e[t+4]&&"T"===e[t+5]&&"A"===e[t+6]&&"["===e[t+7])for(t+=8;t<e.length;t++)if("]"===e[t]&&"]"===e[t+1]&&">"===e[t+2]){t+=2;break}return t}t.validate=function(e,t){t=r.buildOptions(t,i,o);const n=[];let c=!1,h=!1;"\ufeff"===e[0]&&(e=e.substr(1));for(let i=0;i<e.length;i++)if("<"===e[i]&&"?"===e[i+1]){if(i+=2,i=s(e,i),i.err)return i}else{if("<"!==e[i]){if(" "===e[i]||"\t"===e[i]||"\n"===e[i]||"\r"===e[i])continue;return d("InvalidChar","char '"+e[i]+"' is not expected.",p(e,i))}if(i++,"!"===e[i]){i=a(e,i);continue}{let o=!1;"/"===e[i]&&(o=!0,i++);let g="";for(;i<e.length&&">"!==e[i]&&" "!==e[i]&&"\t"!==e[i]&&"\n"!==e[i]&&"\r"!==e[i];i++)g+=e[i];if(g=g.trim(),"/"===g[g.length-1]&&(g=g.substring(0,g.length-1),i--),v=g,!r.isName(v)){let t;return t=0===g.trim().length?"There is an unnecessary space between tag name and backward slash '</ ..'.":"Tag '"+g+"' is an invalid name.",d("InvalidTag",t,p(e,i))}const m=u(e,i);if(!1===m)return d("InvalidAttr","Attributes for '"+g+"' have open quote.",p(e,i));let b=m.value;if(i=m.index,"/"===b[b.length-1]){b=b.substring(0,b.length-1);const n=f(b,t);if(!0!==n)return d(n.err.code,n.err.msg,p(e,i-b.length+n.err.line));c=!0}else if(o){if(!m.tagClosed)return d("InvalidTag","Closing tag '"+g+"' doesn't have proper closing.",p(e,i));if(b.trim().length>0)return d("InvalidTag","Closing tag '"+g+"' can't have attributes or invalid starting.",p(e,i));{const t=n.pop();if(g!==t)return d("InvalidTag","Closing tag '"+t+"' is expected inplace of '"+g+"'.",p(e,i));0==n.length&&(h=!0)}}else{const r=f(b,t);if(!0!==r)return d(r.err.code,r.err.msg,p(e,i-b.length+r.err.line));if(!0===h)return d("InvalidXml","Multiple possible root nodes found.",p(e,i));n.push(g),c=!0}for(i++;i<e.length;i++)if("<"===e[i]){if("!"===e[i+1]){i++,i=a(e,i);continue}if("?"!==e[i+1])break;if(i=s(e,++i),i.err)return i}else if("&"===e[i]){const t=l(e,i);if(-1==t)return d("InvalidChar","char '&' is not expected.",p(e,i));i=t}"<"===e[i]&&i--}}var v;return c?!(n.length>0)||d("InvalidXml","Invalid '"+JSON.stringify(n,null,4).replace(/\r?\n/g,"")+"' found.",1):d("InvalidXml","Start tag expected.",1)};function u(e,t){let n="",r="",i=!1;for(;t<e.length;t++){if('"'===e[t]||"'"===e[t])if(""===r)r=e[t];else{if(r!==e[t])continue;r=""}else if(">"===e[t]&&""===r){i=!0;break}n+=e[t]}return""===r&&{value:n,index:t,tagClosed:i}}const c=new RegExp("(\\s*)([^\\s=]+)(\\s*=)?(\\s*(['\"])(([\\s\\S])*?)\\5)?","g");function f(e,t){const n=r.getAllMatches(e,c),i={};for(let r=0;r<n.length;r++){if(0===n[r][1].length)return d("InvalidAttr","Attribute '"+n[r][2]+"' has no space in starting.",v(e,n[r][0]));if(void 0===n[r][3]&&!t.allowBooleanAttributes)return d("InvalidAttr","boolean attribute '"+n[r][2]+"' is not allowed.",v(e,n[r][0]));const o=n[r][2];if(!h(o))return d("InvalidAttr","Attribute '"+o+"' is an invalid name.",v(e,n[r][0]));if(i.hasOwnProperty(o))return d("InvalidAttr","Attribute '"+o+"' is repeated.",v(e,n[r][0]));i[o]=1}return!0}function l(e,t){if(";"===e[++t])return-1;if("#"===e[t])return function(e,t){let n=/\d/;for("x"===e[t]&&(t++,n=/[\da-fA-F]/);t<e.length;t++){if(";"===e[t])return t;if(!e[t].match(n))break}return-1}(e,++t);let n=0;for(;t<e.length;t++,n++)if(!(e[t].match(/\w/)&&n<20)){if(";"===e[t])break;return-1}return t}function d(e,t,n){return{err:{code:e,msg:t,line:n}}}function h(e){return r.isName(e)}function p(e,t){return e.substring(0,t).split(/\r?\n/).length}function v(e,t){return e.indexOf(t)+t.length}},function(e,t,n){"use strict";const r=function(e){return String.fromCharCode(e)},i={nilChar:r(176),missingChar:r(201),nilPremitive:r(175),missingPremitive:r(200),emptyChar:r(178),emptyValue:r(177),boundryChar:r(179),objStart:r(198),arrStart:r(204),arrayEnd:r(185)},o=[i.nilChar,i.nilPremitive,i.missingChar,i.missingPremitive,i.boundryChar,i.emptyChar,i.emptyValue,i.arrayEnd,i.objStart,i.arrStart],s=function(e,t,n){if("string"==typeof t)return e&&e[0]&&void 0!==e[0].val?a(e[0].val,t):a(e,t);{const o=void 0===(r=e)?i.missingChar:null===r?i.nilChar:!(r.child&&0===Object.keys(r.child).length&&(!r.attrsMap||0===Object.keys(r.attrsMap).length))||i.emptyChar;if(!0===o){let r="";if(Array.isArray(t)){r+=i.arrStart;const o=t[0],c=e.length;if("string"==typeof o)for(let t=0;t<c;t++){const n=a(e[t].val,o);r=u(r,n)}else for(let t=0;t<c;t++){const i=s(e[t],o,n);r=u(r,i)}r+=i.arrayEnd}else{r+=i.objStart;const o=Object.keys(t);Array.isArray(e)&&(e=e[0]);for(let i in o){const a=o[i];let c;c=!n.ignoreAttributes&&e.attrsMap&&e.attrsMap[a]?s(e.attrsMap[a],t[a],n):a===n.textNodeName?s(e.val,t[a],n):s(e.child[a],t[a],n),r=u(r,c)}}return r}return o}var r},a=function(e){switch(e){case void 0:return i.missingPremitive;case null:return i.nilPremitive;case"":return i.emptyValue;default:return e}},u=function(e,t){return c(t[0])||c(e[e.length-1])||(e+=i.boundryChar),e+t},c=function(e){return-1!==o.indexOf(e)};const f=n(102),l=n(54).buildOptions;t.convert2nimn=function(e,t,n){return n=l(n,f.defaultOptions,f.props),s(e,t,n)}},function(e,t,n){"use strict";const r=n(54),i=n(54).buildOptions,o=n(102),s=function(e,t,n){let i="{";const o=Object.keys(e.child);for(let n=0;n<o.length;n++){var a=o[n];if(e.child[a]&&e.child[a].length>1){for(var u in i+='"'+a+'" : [ ',e.child[a])i+=s(e.child[a][u],t)+" , ";i=i.substr(0,i.length-1)+" ] "}else i+='"'+a+'" : '+s(e.child[a][0],t)+" ,"}return r.merge(i,e.attrsMap),r.isEmptyObject(i)?r.isExist(e.val)?e.val:"":(r.isExist(e.val)&&("string"!=typeof e.val||""!==e.val&&e.val!==t.cdataPositionChar)&&(i+='"'+t.textNodeName+'" : '+(!0!==(c=e.val)&&!1!==c&&isNaN(c)?'"'+c+'"':c)),","===i[i.length-1]&&(i=i.substr(0,i.length-2)),i+"}");var c};t.convertToJsonString=function(e,t){return(t=i(t,o.defaultOptions,o.props)).indentBy=t.indentBy||"",s(e,t,0)}},function(e,t,n){"use strict";const r=n(54).buildOptions,i={attributeNamePrefix:"@_",attrNodeName:!1,textNodeName:"#text",ignoreAttributes:!0,cdataTagName:!1,cdataPositionChar:"\\c",format:!1,indentBy:" ",supressEmptyNode:!1,tagValueProcessor:function(e){return e},attrValueProcessor:function(e){return e}},o=["attributeNamePrefix","attrNodeName","textNodeName","ignoreAttributes","cdataTagName","cdataPositionChar","format","indentBy","supressEmptyNode","tagValueProcessor","attrValueProcessor"];function s(e){this.options=r(e,i,o),this.options.ignoreAttributes||this.options.attrNodeName?this.isAttribute=function(){return!1}:(this.attrPrefixLen=this.options.attributeNamePrefix.length,this.isAttribute=p),this.options.cdataTagName?this.isCDATA=v:this.isCDATA=function(){return!1},this.replaceCDATAstr=a,this.replaceCDATAarr=u,this.options.format?(this.indentate=h,this.tagEndChar=">\n",this.newLine="\n"):(this.indentate=function(){return""},this.tagEndChar=">",this.newLine=""),this.options.supressEmptyNode?(this.buildTextNode=d,this.buildObjNode=f):(this.buildTextNode=l,this.buildObjNode=c),this.buildTextValNode=l,this.buildObjectNode=c}function a(e,t){return e=this.options.tagValueProcessor(""+e),""===this.options.cdataPositionChar||""===e?e+"<![CDATA["+t+"]]"+this.tagEndChar:e.replace(this.options.cdataPositionChar,"<![CDATA["+t+"]]"+this.tagEndChar)}function u(e,t){if(e=this.options.tagValueProcessor(""+e),""===this.options.cdataPositionChar||""===e)return e+"<![CDATA["+t.join("]]><![CDATA[")+"]]"+this.tagEndChar;for(let n in t)e=e.replace(this.options.cdataPositionChar,"<![CDATA["+t[n]+"]]>");return e+this.newLine}function c(e,t,n,r){return n&&!e.includes("<")?this.indentate(r)+"<"+t+n+">"+e+"</"+t+this.tagEndChar:this.indentate(r)+"<"+t+n+this.tagEndChar+e+this.indentate(r)+"</"+t+this.tagEndChar}function f(e,t,n,r){return""!==e?this.buildObjectNode(e,t,n,r):this.indentate(r)+"<"+t+n+"/"+this.tagEndChar}function l(e,t,n,r){return this.indentate(r)+"<"+t+n+">"+this.options.tagValueProcessor(e)+"</"+t+this.tagEndChar}function d(e,t,n,r){return""!==e?this.buildTextValNode(e,t,n,r):this.indentate(r)+"<"+t+n+"/"+this.tagEndChar}function h(e){return this.options.indentBy.repeat(e)}function p(e){return!!e.startsWith(this.options.attributeNamePrefix)&&e.substr(this.attrPrefixLen)}function v(e){return e===this.options.cdataTagName}s.prototype.parse=function(e){return this.j2x(e,0).val},s.prototype.j2x=function(e,t){let n="",r="";const i=Object.keys(e),o=i.length;for(let s=0;s<o;s++){const o=i[s];if(void 0===e[o]);else if(null===e[o])r+=this.indentate(t)+"<"+o+"/"+this.tagEndChar;else if(e[o]instanceof Date)r+=this.buildTextNode(e[o],o,"",t);else if("object"!=typeof e[o]){const i=this.isAttribute(o);i?n+=" "+i+'="'+this.options.attrValueProcessor(""+e[o])+'"':this.isCDATA(o)?e[this.options.textNodeName]?r+=this.replaceCDATAstr(e[this.options.textNodeName],e[o]):r+=this.replaceCDATAstr("",e[o]):o===this.options.textNodeName?e[this.options.cdataTagName]||(r+=this.options.tagValueProcessor(""+e[o])):r+=this.buildTextNode(e[o],o,"",t)}else if(Array.isArray(e[o]))if(this.isCDATA(o))r+=this.indentate(t),e[this.options.textNodeName]?r+=this.replaceCDATAarr(e[this.options.textNodeName],e[o]):r+=this.replaceCDATAarr("",e[o]);else{const n=e[o].length;for(let i=0;i<n;i++){const n=e[o][i];if(void 0===n);else if(null===n)r+=this.indentate(t)+"<"+o+"/"+this.tagEndChar;else if("object"==typeof n){const e=this.j2x(n,t+1);r+=this.buildObjNode(e.val,o,e.attrStr,t)}else r+=this.buildTextNode(n,o,"",t)}}else if(this.options.attrNodeName&&o===this.options.attrNodeName){const t=Object.keys(e[o]),r=t.length;for(let i=0;i<r;i++)n+=" "+t[i]+'="'+this.options.attrValueProcessor(""+e[o][t[i]])+'"'}else{const n=this.j2x(e[o],t+1);r+=this.buildObjNode(n.val,o,n.attrStr,t)}}return{attrStr:n,val:r}},e.exports=s},function(e,t,n){"use strict";var r=n(45),i=n(235),o=n(466),s=n(241);function a(e){var t=new o(e),n=i(o.prototype.request,t);return r.extend(n,o.prototype,t),r.extend(n,t),n}var u=a(n(238));u.Axios=o,u.create=function(e){return a(s(u.defaults,e))},u.Cancel=n(242),u.CancelToken=n(479),u.isCancel=n(237),u.all=function(e){return Promise.all(e)},u.spread=n(480),u.isAxiosError=n(481),e.exports=u,e.exports.default=u},function(e,t,n){"use strict";var r=n(45),i=n(236),o=n(467),s=n(468),a=n(241);function u(e){this.defaults=e,this.interceptors={request:new o,response:new o}}u.prototype.request=function(e){"string"==typeof e?(e=arguments[1]||{}).url=arguments[0]:e=e||{},(e=a(this.defaults,e)).method?e.method=e.method.toLowerCase():this.defaults.method?e.method=this.defaults.method.toLowerCase():e.method="get";var t=[s,void 0],n=Promise.resolve(e);for(this.interceptors.request.forEach((function(e){t.unshift(e.fulfilled,e.rejected)})),this.interceptors.response.forEach((function(e){t.push(e.fulfilled,e.rejected)}));t.length;)n=n.then(t.shift(),t.shift());return n},u.prototype.getUri=function(e){return e=a(this.defaults,e),i(e.url,e.params,e.paramsSerializer).replace(/^\?/,"")},r.forEach(["delete","get","head","options"],(function(e){u.prototype[e]=function(t,n){return this.request(a(n||{},{method:e,url:t,data:(n||{}).data}))}})),r.forEach(["post","put","patch"],(function(e){u.prototype[e]=function(t,n,r){return this.request(a(r||{},{method:e,url:t,data:n}))}})),e.exports=u},function(e,t,n){"use strict";var r=n(45);function i(){this.handlers=[]}i.prototype.use=function(e,t){return this.handlers.push({fulfilled:e,rejected:t}),this.handlers.length-1},i.prototype.eject=function(e){this.handlers[e]&&(this.handlers[e]=null)},i.prototype.forEach=function(e){r.forEach(this.handlers,(function(t){null!==t&&e(t)}))},e.exports=i},function(e,t,n){"use strict";var r=n(45),i=n(469),o=n(237),s=n(238);function a(e){e.cancelToken&&e.cancelToken.throwIfRequested()}e.exports=function(e){return a(e),e.headers=e.headers||{},e.data=i(e.data,e.headers,e.transformRequest),e.headers=r.merge(e.headers.common||{},e.headers[e.method]||{},e.headers),r.forEach(["delete","get","head","post","put","patch","common"],(function(t){delete e.headers[t]})),(e.adapter||s.adapter)(e).then((function(t){return a(e),t.data=i(t.data,t.headers,e.transformResponse),t}),(function(t){return o(t)||(a(e),t&&t.response&&(t.response.data=i(t.response.data,t.response.headers,e.transformResponse))),Promise.reject(t)}))}},function(e,t,n){"use strict";var r=n(45);e.exports=function(e,t,n){return r.forEach(n,(function(n){e=n(e,t)})),e}},function(e,t,n){"use strict";var r=n(45);e.exports=function(e,t){r.forEach(e,(function(n,r){r!==t&&r.toUpperCase()===t.toUpperCase()&&(e[t]=n,delete e[r])}))}},function(e,t,n){"use strict";var r=n(240);e.exports=function(e,t,n){var i=n.config.validateStatus;n.status&&i&&!i(n.status)?t(r("Request failed with status code "+n.status,n.config,null,n.request,n)):e(n)}},function(e,t,n){"use strict";e.exports=function(e,t,n,r,i){return e.config=t,n&&(e.code=n),e.request=r,e.response=i,e.isAxiosError=!0,e.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code}},e}},function(e,t,n){"use strict";var r=n(45);e.exports=r.isStandardBrowserEnv()?{write:function(e,t,n,i,o,s){var a=[];a.push(e+"="+encodeURIComponent(t)),r.isNumber(n)&&a.push("expires="+new Date(n).toGMTString()),r.isString(i)&&a.push("path="+i),r.isString(o)&&a.push("domain="+o),!0===s&&a.push("secure"),document.cookie=a.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}}},function(e,t,n){"use strict";var r=n(475),i=n(476);e.exports=function(e,t){return e&&!r(t)?i(e,t):t}},function(e,t,n){"use strict";e.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},function(e,t,n){"use strict";e.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},function(e,t,n){"use strict";var r=n(45),i=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];e.exports=function(e){var t,n,o,s={};return e?(r.forEach(e.split("\n"),(function(e){if(o=e.indexOf(":"),t=r.trim(e.substr(0,o)).toLowerCase(),n=r.trim(e.substr(o+1)),t){if(s[t]&&i.indexOf(t)>=0)return;s[t]="set-cookie"===t?(s[t]?s[t]:[]).concat([n]):s[t]?s[t]+", "+n:n}})),s):s}},function(e,t,n){"use strict";var r=n(45);e.exports=r.isStandardBrowserEnv()?function(){var e,t=/(msie|trident)/i.test(navigator.userAgent),n=document.createElement("a");function i(e){var r=e;return t&&(n.setAttribute("href",r),r=n.href),n.setAttribute("href",r),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,""):"",host:n.host,search:n.search?n.search.replace(/^\?/,""):"",hash:n.hash?n.hash.replace(/^#/,""):"",hostname:n.hostname,port:n.port,pathname:"/"===n.pathname.charAt(0)?n.pathname:"/"+n.pathname}}return e=i(window.location.href),function(t){var n=r.isString(t)?i(t):t;return n.protocol===e.protocol&&n.host===e.host}}():function(){return!0}},function(e,t,n){"use strict";var r=n(242);function i(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise((function(e){t=e}));var n=this;e((function(e){n.reason||(n.reason=new r(e),t(n.reason))}))}i.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},i.source=function(){var e;return{token:new i((function(t){e=t})),cancel:e}},e.exports=i},function(e,t,n){"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}},function(e,t,n){"use strict";e.exports=function(e){return"object"==typeof e&&!0===e.isAxiosError}},function(e,t,n){"use strict";function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function o(e,t,n){return t&&i(e.prototype,t),n&&i(e,n),e}Object.defineProperty(t,"__esModule",{value:!0}),t.Observable=void 0;var s=function(){return"function"==typeof Symbol},a=function(e){return s()&&Boolean(Symbol[e])},u=function(e){return a(e)?Symbol[e]:"@@"+e};s()&&!a("observable")&&(Symbol.observable=Symbol("observable"));var c=u("iterator"),f=u("observable"),l=u("species");function d(e,t){var n=e[t];if(null!=n){if("function"!=typeof n)throw new TypeError(n+" is not a function");return n}}function h(e){var t=e.constructor;return void 0!==t&&null===(t=t[l])&&(t=void 0),void 0!==t?t:E}function p(e){return e instanceof E}function v(e){v.log?v.log(e):setTimeout((function(){throw e}))}function g(e){Promise.resolve().then((function(){try{e()}catch(e){v(e)}}))}function m(e){var t=e._cleanup;if(void 0!==t&&(e._cleanup=void 0,t))try{if("function"==typeof t)t();else{var n=d(t,"unsubscribe");n&&n.call(t)}}catch(e){v(e)}}function b(e){e._observer=void 0,e._queue=void 0,e._state="closed"}function y(e,t,n){e._state="running";var r=e._observer;try{var i=d(r,t);switch(t){case"next":i&&i.call(r,n);break;case"error":if(b(e),!i)throw n;i.call(r,n);break;case"complete":b(e),i&&i.call(r)}}catch(e){v(e)}"closed"===e._state?m(e):"running"===e._state&&(e._state="ready")}function w(e,t,n){if("closed"!==e._state){if("buffering"!==e._state)return"ready"!==e._state?(e._state="buffering",e._queue=[{type:t,value:n}],void g((function(){return function(e){var t=e._queue;if(t){e._queue=void 0,e._state="ready";for(var n=0;n<t.length&&(y(e,t[n].type,t[n].value),"closed"!==e._state);++n);}}(e)}))):void y(e,t,n);e._queue.push({type:t,value:n})}}var _=function(){function e(t,n){r(this,e),this._cleanup=void 0,this._observer=t,this._queue=void 0,this._state="initializing";var i=new S(this);try{this._cleanup=n.call(void 0,i)}catch(e){i.error(e)}"initializing"===this._state&&(this._state="ready")}return o(e,[{key:"unsubscribe",value:function(){"closed"!==this._state&&(b(this),m(this))}},{key:"closed",get:function(){return"closed"===this._state}}]),e}(),S=function(){function e(t){r(this,e),this._subscription=t}return o(e,[{key:"next",value:function(e){w(this._subscription,"next",e)}},{key:"error",value:function(e){w(this._subscription,"error",e)}},{key:"complete",value:function(){w(this._subscription,"complete")}},{key:"closed",get:function(){return"closed"===this._subscription._state}}]),e}(),E=function(){function e(t){if(r(this,e),!(this instanceof e))throw new TypeError("Observable cannot be called as a function");if("function"!=typeof t)throw new TypeError("Observable initializer must be a function");this._subscriber=t}return o(e,[{key:"subscribe",value:function(e){return"object"==typeof e&&null!==e||(e={next:e,error:arguments[1],complete:arguments[2]}),new _(e,this._subscriber)}},{key:"forEach",value:function(e){var t=this;return new Promise((function(n,r){if("function"==typeof e)var i=t.subscribe({next:function(t){try{e(t,o)}catch(e){r(e),i.unsubscribe()}},error:r,complete:n});else r(new TypeError(e+" is not a function"));function o(){i.unsubscribe(),n()}}))}},{key:"map",value:function(e){var t=this;if("function"!=typeof e)throw new TypeError(e+" is not a function");return new(h(this))((function(n){return t.subscribe({next:function(t){try{t=e(t)}catch(e){return n.error(e)}n.next(t)},error:function(e){n.error(e)},complete:function(){n.complete()}})}))}},{key:"filter",value:function(e){var t=this;if("function"!=typeof e)throw new TypeError(e+" is not a function");return new(h(this))((function(n){return t.subscribe({next:function(t){try{if(!e(t))return}catch(e){return n.error(e)}n.next(t)},error:function(e){n.error(e)},complete:function(){n.complete()}})}))}},{key:"reduce",value:function(e){var t=this;if("function"!=typeof e)throw new TypeError(e+" is not a function");var n=h(this),r=arguments.length>1,i=!1,o=arguments[1],s=o;return new n((function(n){return t.subscribe({next:function(t){var o=!i;if(i=!0,!o||r)try{s=e(s,t)}catch(e){return n.error(e)}else s=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(new TypeError("Cannot reduce an empty sequence"));n.next(s),n.complete()}})}))}},{key:"concat",value:function(){for(var e=this,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];var i=h(this);return new i((function(t){var r,o=0;return function e(s){r=s.subscribe({next:function(e){t.next(e)},error:function(e){t.error(e)},complete:function(){o===n.length?(r=void 0,t.complete()):e(i.from(n[o++]))}})}(e),function(){r&&(r.unsubscribe(),r=void 0)}}))}},{key:"flatMap",value:function(e){var t=this;if("function"!=typeof e)throw new TypeError(e+" is not a function");var n=h(this);return new n((function(r){var i=[],o=t.subscribe({next:function(t){if(e)try{t=e(t)}catch(e){return r.error(e)}var o=n.from(t).subscribe({next:function(e){r.next(e)},error:function(e){r.error(e)},complete:function(){var e=i.indexOf(o);e>=0&&i.splice(e,1),s()}});i.push(o)},error:function(e){r.error(e)},complete:function(){s()}});function s(){o.closed&&0===i.length&&r.complete()}return function(){i.forEach((function(e){return e.unsubscribe()})),o.unsubscribe()}}))}},{key:f,value:function(){return this}}],[{key:"from",value:function(t){var n="function"==typeof this?this:e;if(null==t)throw new TypeError(t+" is not an object");var r=d(t,f);if(r){var i=r.call(t);if(Object(i)!==i)throw new TypeError(i+" is not an object");return p(i)&&i.constructor===n?i:new n((function(e){return i.subscribe(e)}))}if(a("iterator")&&(r=d(t,c)))return new n((function(e){g((function(){if(!e.closed){var n=!0,i=!1,o=void 0;try{for(var s,a=r.call(t)[Symbol.iterator]();!(n=(s=a.next()).done);n=!0){var u=s.value;if(e.next(u),e.closed)return}}catch(e){i=!0,o=e}finally{try{n||null==a.return||a.return()}finally{if(i)throw o}}e.complete()}}))}));if(Array.isArray(t))return new n((function(e){g((function(){if(!e.closed){for(var n=0;n<t.length;++n)if(e.next(t[n]),e.closed)return;e.complete()}}))}));throw new TypeError(t+" is not observable")}},{key:"of",value:function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];var i="function"==typeof this?this:e;return new i((function(e){g((function(){if(!e.closed){for(var t=0;t<n.length;++t)if(e.next(n[t]),e.closed)return;e.complete()}}))}))}},{key:l,get:function(){return this}}]),e}();t.Observable=E,s()&&Object.defineProperty(E,Symbol("extensions"),{value:{symbol:f,hostReportError:v},configurable:!0})},function(e,t,n){var r,i,o=n(243),s=n(244),a=0,u=0;e.exports=function(e,t,n){var c=t&&n||0,f=t||[],l=(e=e||{}).node||r,d=void 0!==e.clockseq?e.clockseq:i;if(null==l||null==d){var h=o();null==l&&(l=r=[1|h[0],h[1],h[2],h[3],h[4],h[5]]),null==d&&(d=i=16383&(h[6]<<8|h[7]))}var p=void 0!==e.msecs?e.msecs:(new Date).getTime(),v=void 0!==e.nsecs?e.nsecs:u+1,g=p-a+(v-u)/1e4;if(g<0&&void 0===e.clockseq&&(d=d+1&16383),(g<0||p>a)&&void 0===e.nsecs&&(v=0),v>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");a=p,u=v,i=d;var m=(1e4*(268435455&(p+=122192928e5))+v)%4294967296;f[c++]=m>>>24&255,f[c++]=m>>>16&255,f[c++]=m>>>8&255,f[c++]=255&m;var b=p/4294967296*1e4&268435455;f[c++]=b>>>8&255,f[c++]=255&b,f[c++]=b>>>24&15|16,f[c++]=b>>>16&255,f[c++]=d>>>8|128,f[c++]=255&d;for(var y=0;y<6;++y)f[c+y]=l[y];return t||s(f)}},function(e,t,n){var r=n(243),i=n(244);e.exports=function(e,t,n){var o=t&&n||0;"string"==typeof e&&(t="binary"===e?new Array(16):null,e=null);var s=(e=e||{}).random||(e.rng||r)();if(s[6]=15&s[6]|64,s[8]=63&s[8]|128,t)for(var a=0;a<16;++a)t[o+a]=s[a];return t||i(s)}},function(e,t){},function(e,t,n){e.exports=n(487).Observable},function(e,t,n){"use strict";(function(e){!function(e,t){function n(e){return"function"==typeof Symbol&&Boolean(Symbol[e])}function r(e){return n(e)?Symbol[e]:"@@"+e}function i(e){setTimeout((function(){throw e}))}function o(e,t){var n=e[t];if(null!=n){if("function"!=typeof n)throw new TypeError(n+" is not a function");return n}}function s(e){var t=e.constructor;return void 0!==t&&null===(t=t[r("species")])&&(t=void 0),void 0!==t?t:d}function a(e,t){Object.keys(t).forEach((function(n){var r=Object.getOwnPropertyDescriptor(t,n);r.enumerable=!1,Object.defineProperty(e,n,r)}))}function u(e){var t=e._cleanup;if(t){e._cleanup=void 0;try{t()}catch(e){i(e)}}}function c(e){return void 0===e._observer}function f(e,t){if(Object(e)!==e)throw new TypeError("Observer must be an object");this._cleanup=void 0,this._observer=e;try{var n=o(e,"start");n&&n.call(e,this)}catch(e){i(e)}if(!c(this)){e=new l(this);try{var r=t.call(void 0,e);if(null!=r){if("function"==typeof r.unsubscribe)s=r,r=function(){s.unsubscribe()};else if("function"!=typeof r)throw new TypeError(r+" is not a function");this._cleanup=r}}catch(t){return void e.error(t)}var s;c(this)&&u(this)}}function l(e){this._subscription=e}function d(e){if(!(this instanceof d))throw new TypeError("Observable cannot be called as a function");if("function"!=typeof e)throw new TypeError("Observable initializer must be a function");this._subscriber=e}"function"!=typeof Symbol||Symbol.observable||(Symbol.observable=Symbol("observable")),a(f.prototype={},{get closed(){return c(this)},unsubscribe:function(){var e;c(e=this)||(e._observer=void 0,u(e))}}),a(l.prototype={},{get closed(){return c(this._subscription)},next:function(e){var t=this._subscription;if(!c(t)){var n=t._observer;try{var r=o(n,"next");r&&r.call(n,e)}catch(e){i(e)}}},error:function(e){var t=this._subscription;if(c(t))i(e);else{var n=t._observer;t._observer=void 0;try{var r=o(n,"error");if(!r)throw e;r.call(n,e)}catch(e){i(e)}u(t)}},complete:function(){var e=this._subscription;if(!c(e)){var t=e._observer;e._observer=void 0;try{var n=o(t,"complete");n&&n.call(t)}catch(e){i(e)}u(e)}}}),a(d.prototype,{subscribe:function(e){for(var t=[],n=1;n<arguments.length;++n)t.push(arguments[n]);return"function"==typeof e?e={next:e,error:t[0],complete:t[1]}:"object"==typeof e&&null!==e||(e={}),new f(e,this._subscriber)},forEach:function(e){var t=this;return new Promise((function(n,r){if("function"!=typeof e)return Promise.reject(new TypeError(e+" is not a function"));t.subscribe({_subscription:null,start:function(e){if(Object(e)!==e)throw new TypeError(e+" is not an object");this._subscription=e},next:function(t){var n=this._subscription;if(!n.closed)try{e(t)}catch(e){r(e),n.unsubscribe()}},error:r,complete:n})}))},map:function(e){var t=this;if("function"!=typeof e)throw new TypeError(e+" is not a function");return new(s(this))((function(n){return t.subscribe({next:function(t){if(!n.closed){try{t=e(t)}catch(e){return n.error(e)}n.next(t)}},error:function(e){n.error(e)},complete:function(){n.complete()}})}))},filter:function(e){var t=this;if("function"!=typeof e)throw new TypeError(e+" is not a function");return new(s(this))((function(n){return t.subscribe({next:function(t){if(!n.closed){try{if(!e(t))return}catch(e){return n.error(e)}n.next(t)}},error:function(e){n.error(e)},complete:function(){n.complete()}})}))},reduce:function(e){var t=this;if("function"!=typeof e)throw new TypeError(e+" is not a function");var n=s(this),r=arguments.length>1,i=!1,o=arguments[1],a=o;return new n((function(n){return t.subscribe({next:function(t){if(!n.closed){var o=!i;if(i=!0,!o||r)try{a=e(a,t)}catch(e){return n.error(e)}else a=t}},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(new TypeError("Cannot reduce an empty sequence"));n.next(a),n.complete()}})}))}}),Object.defineProperty(d.prototype,r("observable"),{value:function(){return this},writable:!0,configurable:!0}),a(d,{from:function(e){var t="function"==typeof this?this:d;if(null==e)throw new TypeError(e+" is not an object");var i=o(e,r("observable"));if(i){var s=i.call(e);if(Object(s)!==s)throw new TypeError(s+" is not an object");return s.constructor===t?s:new t((function(e){return s.subscribe(e)}))}if(n("iterator")&&(i=o(e,r("iterator"))))return new t((function(t){for(var n,r=i.call(e)[Symbol.iterator]();!(n=r.next()).done;){var o=n.value;if(t.next(o),t.closed)return}t.complete()}));if(Array.isArray(e))return new t((function(t){for(var n=0;n<e.length;++n)if(t.next(e[n]),t.closed)return;t.complete()}));throw new TypeError(e+" is not observable")},of:function(){for(var e=[],t=0;t<arguments.length;++t)e.push(arguments[t]);var n="function"==typeof this?this:d;return new n((function(t){for(var n=0;n<e.length;++n)if(t.next(e[n]),t.closed)return;t.complete()}))}}),Object.defineProperty(d,r("species"),{get:function(){return this},configurable:!0}),Object.defineProperty(d,"extensions",{value:{observableSymbol:r("observable"),setHostReportError:function(e){i=e}}}),e.Observable=d}(t)}).call(this,n(57)(e))},function(e,t,n){"use strict";n.d(t,"a",(function(){return c}));var r=n(44),i=n(19),o=function(){return(o=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},s=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},a=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(s(arguments[t]));return e},u=new r.a("Predictions"),c=new(function(){function e(e){this._options=e,this._convertPluggables=[],this._identifyPluggables=[],this._interpretPluggables=[]}return e.prototype.getModuleName=function(){return"Predictions"},e.prototype.addPluggable=function(e){if(this.getPluggable(e.getProviderName()))throw new Error("Pluggable with name "+e.getProviderName()+" has already been added.");var t=!1;this.implementsConvertPluggable(e)&&(this._convertPluggables.push(e),t=!0),this.implementsIdentifyPluggable(e)&&(this._identifyPluggables.push(e),t=!0),this.implementsInterpretPluggable(e)&&(this._interpretPluggables.push(e),t=!0),t&&this.configurePluggable(e)},e.prototype.getPluggable=function(e){var t=this.getAllProviders().find((function(t){return t.getProviderName()===e}));return void 0===t?(u.debug("No plugin found with providerName=>",e),null):t},e.prototype.removePluggable=function(e){this._convertPluggables=this._convertPluggables.filter((function(t){return t.getProviderName()!==e})),this._identifyPluggables=this._identifyPluggables.filter((function(t){return t.getProviderName()!==e})),this._interpretPluggables=this._interpretPluggables.filter((function(t){return t.getProviderName()!==e}))},e.prototype.configure=function(e){var t=this,n=e?e.predictions||e:{};n=o(o({},n),e),this._options=Object.assign({},this._options,n),u.debug("configure Predictions",this._options),this.getAllProviders().forEach((function(e){return t.configurePluggable(e)}))},e.prototype.interpret=function(e,t){return this.getPluggableToExecute(this._interpretPluggables,t).interpret(e)},e.prototype.convert=function(e,t){return this.getPluggableToExecute(this._convertPluggables,t).convert(e)},e.prototype.identify=function(e,t){return this.getPluggableToExecute(this._identifyPluggables,t).identify(e)},e.prototype.getPluggableToExecute=function(e,t){if(t&&t.providerName)return a(e).find((function(e){return e.getProviderName()===t.providerName}));if(1===e.length)return e[0];throw new Error("More than one or no providers are configured, Either specify a provider name or configure exactly one provider")},e.prototype.getAllProviders=function(){return a(this._convertPluggables,this._identifyPluggables,this._interpretPluggables)},e.prototype.configurePluggable=function(e){var t=Object.assign({},this._options.predictions,this._options[e.getCategory().toLowerCase()]);e.configure(t)},e.prototype.implementsConvertPluggable=function(e){return e&&"function"==typeof e.convert},e.prototype.implementsIdentifyPluggable=function(e){return e&&"function"==typeof e.identify},e.prototype.implementsInterpretPluggable=function(e){return e&&"function"==typeof e.interpret},e}())({});i.a.register(c)},function(e,t,n){"use strict";n.d(t,"a",(function(){return ft}));var r=n(44),i=n(19),o=function(){return(o=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},s=new r.a("AbstractInteractionsProvider"),a=function(){function e(e){void 0===e&&(e={}),this._config=e}return e.prototype.configure=function(e){return void 0===e&&(e={}),this._config=o(o({},this._config),e),s.debug("configure "+this.getProviderName(),this._config),this.options},e.prototype.getCategory=function(){return"Interactions"},Object.defineProperty(e.prototype,"options",{get:function(){return o({},this._config)},enumerable:!0,configurable:!0}),e}(),u=function(e,t){return(u=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function c(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}u(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var f=function(){return(f=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function l(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))}function d(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}}Object.create;function h(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s}Object.create;var p,v,g,m,b,y,w,_,S,E,M,A,I,k,O,x,C,T,P,N,R,L,j,D,U,B,F,z,q,K,H,V,G,W,$,Y=n(155),J=n(38),Z=n(18),X=n(24),Q=n(11),ee=n(39),te=n(17),ne=n(40),re=n(41),ie=n(15),oe=new Set(["ap-east-1","ap-northeast-1","ap-northeast-2","ap-south-1","ap-southeast-1","ap-southeast-2","ca-central-1","eu-central-1","eu-north-1","eu-west-1","eu-west-2","eu-west-3","me-south-1","sa-east-1","us-east-1","us-east-2","us-west-1","us-west-2"]),se=new Set(["cn-north-1","cn-northwest-1"]),ae=new Set(["us-iso-east-1"]),ue=new Set(["us-isob-east-1"]),ce=new Set(["us-gov-east-1","us-gov-west-1"]),fe=f(f({},{apiVersion:"2016-11-28",disableHostPrefix:!1,logger:{},regionInfoProvider:function(e,t){var n=void 0;switch(e){case"eu-west-1":n={hostname:"runtime.lex.eu-west-1.amazonaws.com",partition:"aws",signingService:"lex"};break;case"us-east-1":n={hostname:"runtime.lex.us-east-1.amazonaws.com",partition:"aws",signingService:"lex"};break;case"us-west-2":n={hostname:"runtime.lex.us-west-2.amazonaws.com",partition:"aws",signingService:"lex"};break;default:oe.has(e)&&(n={hostname:"runtime.lex.{region}.amazonaws.com".replace("{region}",e),partition:"aws",signingService:"lex"}),se.has(e)&&(n={hostname:"runtime.lex.{region}.amazonaws.com.cn".replace("{region}",e),partition:"aws-cn"}),ae.has(e)&&(n={hostname:"runtime.lex.{region}.c2s.ic.gov".replace("{region}",e),partition:"aws-iso"}),ue.has(e)&&(n={hostname:"runtime.lex.{region}.sc2s.sgov.gov".replace("{region}",e),partition:"aws-iso-b"}),ce.has(e)&&(n={hostname:"runtime.lex.{region}.amazonaws.com".replace("{region}",e),partition:"aws-us-gov"}),void 0===n&&(n={hostname:"runtime.lex.{region}.amazonaws.com".replace("{region}",e),partition:"aws",signingService:"lex"})}return Promise.resolve(n)},signingName:"lex"}),{runtime:"browser",base64Decoder:te.a,base64Encoder:te.b,bodyLengthChecker:ne.a,credentialDefaultProvider:Object(X.a)("Credential is missing"),defaultUserAgent:Object(re.a)(Y.name,Y.version),maxAttempts:Q.a,region:Object(X.a)("Region is missing"),requestHandler:new Z.a,sha256:J.Sha256,streamCollector:Z.b,urlParser:ee.a,utf8Decoder:ie.a,utf8Encoder:ie.b}),le=n(22),de=n(37),he=n(21),pe=n(43),ve=n(25),ge=n(23),me=n(0),be=function(e){function t(t){var n=this,r=f(f({},fe),t),i=Object(le.b)(r),o=Object(le.a)(i),s=Object(ve.b)(o),a=Object(Q.c)(s),u=Object(ge.b)(a),c=Object(he.b)(u);return(n=e.call(this,c)||this).config=c,n.middlewareStack.use(Object(ve.a)(n.config)),n.middlewareStack.use(Object(Q.b)(n.config)),n.middlewareStack.use(Object(ge.a)(n.config)),n.middlewareStack.use(Object(de.a)(n.config)),n.middlewareStack.use(Object(he.a)(n.config)),n.middlewareStack.use(Object(pe.a)(n.config)),n}return c(t,e),t.prototype.destroy=function(){e.prototype.destroy.call(this)},t}(me.a);(p||(p={})).filterSensitiveLog=function(e){return f({},e)},(v||(v={})).filterSensitiveLog=function(e){return f({},e)},(g||(g={})).filterSensitiveLog=function(e){return f({},e)},(m||(m={})).filterSensitiveLog=function(e){return f({},e)},(b||(b={})).filterSensitiveLog=function(e){return f({},e)},(y||(y={})).filterSensitiveLog=function(e){return f({},e)},(w||(w={})).filterSensitiveLog=function(e){return f({},e)},(_||(_={})).filterSensitiveLog=function(e){return f({},e)},function(e){e.FAILED="Failed",e.FULFILLED="Fulfilled",e.READY_FOR_FULFILLMENT="ReadyForFulfillment"}(S||(S={})),function(e){e.COMPOSITE="Composite",e.CUSTOM_PAYLOAD="CustomPayload",e.PLAIN_TEXT="PlainText",e.SSML="SSML"}(E||(E={})),function(e){e.CLOSE="Close",e.CONFIRM_INTENT="ConfirmIntent",e.DELEGATE="Delegate",e.ELICIT_INTENT="ElicitIntent",e.ELICIT_SLOT="ElicitSlot"}(M||(M={})),(A||(A={})).filterSensitiveLog=function(e){return f(f(f({},e),e.slots&&{slots:me.d}),e.message&&{message:me.d})},function(e){e.CONFIRMED="Confirmed",e.DENIED="Denied",e.NONE="None"}(I||(I={})),(k||(k={})).filterSensitiveLog=function(e){return f(f({},e),e.slots&&{slots:me.d})},(O||(O={})).filterSensitiveLog=function(e){return f(f(f(f({},e),e.dialogAction&&{dialogAction:A.filterSensitiveLog(e.dialogAction)}),e.recentIntentSummaryView&&{recentIntentSummaryView:e.recentIntentSummaryView.map((function(e){return k.filterSensitiveLog(e)}))}),e.sessionAttributes&&{sessionAttributes:me.d})},(x||(x={})).filterSensitiveLog=function(e){return f({},e)},(C||(C={})).filterSensitiveLog=function(e){return f({},e)},(T||(T={})).filterSensitiveLog=function(e){return f({},e)},(P||(P={})).filterSensitiveLog=function(e){return f({},e)},(N||(N={})).filterSensitiveLog=function(e){return f(f(f({},e),e.requestAttributes&&{requestAttributes:me.d}),e.sessionAttributes&&{sessionAttributes:me.d})},function(e){e.CONFIRM_INTENT="ConfirmIntent",e.ELICIT_INTENT="ElicitIntent",e.ELICIT_SLOT="ElicitSlot",e.FAILED="Failed",e.FULFILLED="Fulfilled",e.READY_FOR_FULFILLMENT="ReadyForFulfillment"}(R||(R={})),(L||(L={})).filterSensitiveLog=function(e){return f(f({},e),e.message&&{message:me.d})},(j||(j={})).filterSensitiveLog=function(e){return f({},e)},(D||(D={})).filterSensitiveLog=function(e){return f({},e)},(U||(U={})).filterSensitiveLog=function(e){return f(f(f(f({},e),e.requestAttributes&&{requestAttributes:me.d}),e.inputText&&{inputText:me.d}),e.sessionAttributes&&{sessionAttributes:me.d})},(B||(B={})).filterSensitiveLog=function(e){return f({},e)},(F||(F={})).filterSensitiveLog=function(e){return f(f({},e),e.slots&&{slots:me.d})},function(e){e.GENERIC="application/vnd.amazonaws.card.generic"}(z||(z={})),(q||(q={})).filterSensitiveLog=function(e){return f({},e)},(K||(K={})).filterSensitiveLog=function(e){return f({},e)},(H||(H={})).filterSensitiveLog=function(e){return f({},e)},(V||(V={})).filterSensitiveLog=function(e){return f({},e)},(G||(G={})).filterSensitiveLog=function(e){return f(f(f(f(f({},e),e.alternativeIntents&&{alternativeIntents:e.alternativeIntents.map((function(e){return F.filterSensitiveLog(e)}))}),e.message&&{message:me.d}),e.sessionAttributes&&{sessionAttributes:me.d}),e.slots&&{slots:me.d})},(W||(W={})).filterSensitiveLog=function(e){return f(f(f(f({},e),e.dialogAction&&{dialogAction:A.filterSensitiveLog(e.dialogAction)}),e.recentIntentSummaryView&&{recentIntentSummaryView:e.recentIntentSummaryView.map((function(e){return k.filterSensitiveLog(e)}))}),e.sessionAttributes&&{sessionAttributes:me.d})},($||($={})).filterSensitiveLog=function(e){return f(f({},e),e.message&&{message:me.d})};var ye,we=n(2),_e=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l,h,p,v,g,m,b,y,w,_;return d(this,(function(d){switch(d.label){case 0:return r=[f({},e)],_={},[4,Ge(e.body,t)];case 1:switch(n=f.apply(void 0,r.concat([(_.body=d.sent(),_)])),o="UnknownError",o=We(e,n.body),o){case"BadGatewayException":case"com.amazonaws.lexruntimeservice#BadGatewayException":return[3,2];case"BadRequestException":case"com.amazonaws.lexruntimeservice#BadRequestException":return[3,4];case"ConflictException":case"com.amazonaws.lexruntimeservice#ConflictException":return[3,6];case"DependencyFailedException":case"com.amazonaws.lexruntimeservice#DependencyFailedException":return[3,8];case"InternalFailureException":case"com.amazonaws.lexruntimeservice#InternalFailureException":return[3,10];case"LimitExceededException":case"com.amazonaws.lexruntimeservice#LimitExceededException":return[3,12];case"LoopDetectedException":case"com.amazonaws.lexruntimeservice#LoopDetectedException":return[3,14];case"NotAcceptableException":case"com.amazonaws.lexruntimeservice#NotAcceptableException":return[3,16];case"NotFoundException":case"com.amazonaws.lexruntimeservice#NotFoundException":return[3,18];case"RequestTimeoutException":case"com.amazonaws.lexruntimeservice#RequestTimeoutException":return[3,20];case"UnsupportedMediaTypeException":case"com.amazonaws.lexruntimeservice#UnsupportedMediaTypeException":return[3,22]}return[3,24];case 2:return s=[{}],[4,Ee(n,t)];case 3:return i=f.apply(void 0,[f.apply(void 0,s.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 4:return a=[{}],[4,Me(n,t)];case 5:return i=f.apply(void 0,[f.apply(void 0,a.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 6:return u=[{}],[4,Ae(n,t)];case 7:return i=f.apply(void 0,[f.apply(void 0,u.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 8:return c=[{}],[4,Ie(n,t)];case 9:return i=f.apply(void 0,[f.apply(void 0,c.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 10:return l=[{}],[4,ke(n,t)];case 11:return i=f.apply(void 0,[f.apply(void 0,l.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 12:return h=[{}],[4,Oe(n,t)];case 13:return i=f.apply(void 0,[f.apply(void 0,h.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 14:return p=[{}],[4,xe(n,t)];case 15:return i=f.apply(void 0,[f.apply(void 0,p.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 16:return v=[{}],[4,Ce(n,t)];case 17:return i=f.apply(void 0,[f.apply(void 0,v.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 18:return g=[{}],[4,Te(n,t)];case 19:return i=f.apply(void 0,[f.apply(void 0,g.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 20:return m=[{}],[4,Pe(n,t)];case 21:return i=f.apply(void 0,[f.apply(void 0,m.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 22:return b=[{}],[4,Ne(n,t)];case 23:return i=f.apply(void 0,[f.apply(void 0,b.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,25];case 24:y=n.body,o=y.code||y.Code||o,i=f(f({},y),{name:""+o,message:y.message||y.Message||o,$fault:"client",$metadata:Ke(e)}),d.label=25;case 25:return w=i.message||i.Message||o,i.message=w,delete i.Message,[2,Promise.reject(Object.assign(new Error(w),i))]}}))}))},Se=function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l,h,p,v,g,m,b;return d(this,(function(d){switch(d.label){case 0:return r=[f({},e)],b={},[4,Ge(e.body,t)];case 1:switch(n=f.apply(void 0,r.concat([(b.body=d.sent(),b)])),o="UnknownError",o=We(e,n.body),o){case"BadGatewayException":case"com.amazonaws.lexruntimeservice#BadGatewayException":return[3,2];case"BadRequestException":case"com.amazonaws.lexruntimeservice#BadRequestException":return[3,4];case"ConflictException":case"com.amazonaws.lexruntimeservice#ConflictException":return[3,6];case"DependencyFailedException":case"com.amazonaws.lexruntimeservice#DependencyFailedException":return[3,8];case"InternalFailureException":case"com.amazonaws.lexruntimeservice#InternalFailureException":return[3,10];case"LimitExceededException":case"com.amazonaws.lexruntimeservice#LimitExceededException":return[3,12];case"LoopDetectedException":case"com.amazonaws.lexruntimeservice#LoopDetectedException":return[3,14];case"NotFoundException":case"com.amazonaws.lexruntimeservice#NotFoundException":return[3,16]}return[3,18];case 2:return s=[{}],[4,Ee(n,t)];case 3:return i=f.apply(void 0,[f.apply(void 0,s.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,19];case 4:return a=[{}],[4,Me(n,t)];case 5:return i=f.apply(void 0,[f.apply(void 0,a.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,19];case 6:return u=[{}],[4,Ae(n,t)];case 7:return i=f.apply(void 0,[f.apply(void 0,u.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,19];case 8:return c=[{}],[4,Ie(n,t)];case 9:return i=f.apply(void 0,[f.apply(void 0,c.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,19];case 10:return l=[{}],[4,ke(n,t)];case 11:return i=f.apply(void 0,[f.apply(void 0,l.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,19];case 12:return h=[{}],[4,Oe(n,t)];case 13:return i=f.apply(void 0,[f.apply(void 0,h.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,19];case 14:return p=[{}],[4,xe(n,t)];case 15:return i=f.apply(void 0,[f.apply(void 0,p.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,19];case 16:return v=[{}],[4,Te(n,t)];case 17:return i=f.apply(void 0,[f.apply(void 0,v.concat([d.sent()])),{name:o,$metadata:Ke(e)}]),[3,19];case 18:g=n.body,o=g.code||g.Code||o,i=f(f({},g),{name:""+o,message:g.message||g.Message||o,$fault:"client",$metadata:Ke(e)}),d.label=19;case 19:return m=i.message||i.Message||o,i.message=m,delete i.Message,[2,Promise.reject(Object.assign(new Error(m),i))]}}))}))},Ee=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"BadGatewayException",$fault:"server",$metadata:Ke(e),Message:void 0},void 0!==(n=e.body).Message&&null!==n.Message&&(t.Message=n.Message),[2,t]}))}))},Me=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"BadRequestException",$fault:"client",$metadata:Ke(e),message:void 0},void 0!==(n=e.body).message&&null!==n.message&&(t.message=n.message),[2,t]}))}))},Ae=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"ConflictException",$fault:"client",$metadata:Ke(e),message:void 0},void 0!==(n=e.body).message&&null!==n.message&&(t.message=n.message),[2,t]}))}))},Ie=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"DependencyFailedException",$fault:"client",$metadata:Ke(e),Message:void 0},void 0!==(n=e.body).Message&&null!==n.Message&&(t.Message=n.Message),[2,t]}))}))},ke=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"InternalFailureException",$fault:"server",$metadata:Ke(e),message:void 0},void 0!==(n=e.body).message&&null!==n.message&&(t.message=n.message),[2,t]}))}))},Oe=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"LimitExceededException",$fault:"client",$metadata:Ke(e),message:void 0,retryAfterSeconds:void 0},void 0!==e.headers["retry-after"]&&(t.retryAfterSeconds=e.headers["retry-after"]),void 0!==(n=e.body).message&&null!==n.message&&(t.message=n.message),[2,t]}))}))},xe=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"LoopDetectedException",$fault:"server",$metadata:Ke(e),Message:void 0},void 0!==(n=e.body).Message&&null!==n.Message&&(t.Message=n.Message),[2,t]}))}))},Ce=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"NotAcceptableException",$fault:"client",$metadata:Ke(e),message:void 0},void 0!==(n=e.body).message&&null!==n.message&&(t.message=n.message),[2,t]}))}))},Te=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"NotFoundException",$fault:"client",$metadata:Ke(e),message:void 0},void 0!==(n=e.body).message&&null!==n.message&&(t.message=n.message),[2,t]}))}))},Pe=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"RequestTimeoutException",$fault:"client",$metadata:Ke(e),message:void 0},void 0!==(n=e.body).message&&null!==n.message&&(t.message=n.message),[2,t]}))}))},Ne=function(e,t){return l(void 0,void 0,void 0,(function(){var t,n;return d(this,(function(r){return t={name:"UnsupportedMediaTypeException",$fault:"client",$metadata:Ke(e),message:void 0},void 0!==(n=e.body).message&&null!==n.message&&(t.message=n.message),[2,t]}))}))},Re=function(e,t){return Object.entries(e).reduce((function(e,t){var n,r=h(t,2),i=r[0],o=r[1];return f(f({},e),((n={})[i]=o,n))}),{})},Le=function(e,t){return(e||[]).map((function(e){return function(e,t){return{attachmentLinkUrl:void 0!==e.attachmentLinkUrl&&null!==e.attachmentLinkUrl?e.attachmentLinkUrl:void 0,buttons:void 0!==e.buttons&&null!==e.buttons?Ue(e.buttons,t):void 0,imageUrl:void 0!==e.imageUrl&&null!==e.imageUrl?e.imageUrl:void 0,subTitle:void 0!==e.subTitle&&null!==e.subTitle?e.subTitle:void 0,title:void 0!==e.title&&null!==e.title?e.title:void 0}}(e,t)}))},je=function(e,t){return{score:void 0!==e.score&&null!==e.score?e.score:void 0}},De=function(e,t){return(e||[]).map((function(e){return Be(e,t)}))},Ue=function(e,t){return(e||[]).map((function(e){return function(e,t){return{text:void 0!==e.text&&null!==e.text?e.text:void 0,value:void 0!==e.value&&null!==e.value?e.value:void 0}}(e)}))},Be=function(e,t){return{intentName:void 0!==e.intentName&&null!==e.intentName?e.intentName:void 0,nluIntentConfidence:void 0!==e.nluIntentConfidence&&null!==e.nluIntentConfidence?je(e.nluIntentConfidence,t):void 0,slots:void 0!==e.slots&&null!==e.slots?qe(e.slots,t):void 0}},Fe=function(e,t){return{contentType:void 0!==e.contentType&&null!==e.contentType?e.contentType:void 0,genericAttachments:void 0!==e.genericAttachments&&null!==e.genericAttachments?Le(e.genericAttachments,t):void 0,version:void 0!==e.version&&null!==e.version?e.version:void 0}},ze=function(e,t){return{sentimentLabel:void 0!==e.sentimentLabel&&null!==e.sentimentLabel?e.sentimentLabel:void 0,sentimentScore:void 0!==e.sentimentScore&&null!==e.sentimentScore?e.sentimentScore:void 0}},qe=function(e,t){return Object.entries(e).reduce((function(e,t){var n,r=h(t,2),i=r[0],o=r[1];return f(f({},e),((n={})[i]=o,n))}),{})},Ke=function(e){return{httpStatusCode:e.statusCode,httpHeaders:e.headers,requestId:e.headers["x-amzn-requestid"]}},He=function(e,t){return function(e,t){return void 0===e&&(e=new Uint8Array),e instanceof Uint8Array?Promise.resolve(e):t.streamCollector(e)||Promise.resolve(new Uint8Array)}(e,t).then((function(e){return t.utf8Encoder(e)}))},Ve=function(e){return!(void 0===e||""===e||Object.getOwnPropertyNames(e).includes("length")&&0==e.length||Object.getOwnPropertyNames(e).includes("size")&&0==e.size)},Ge=function(e,t){return He(e,t).then((function(e){return e.length?JSON.parse(e):{}}))},We=function(e,t){var n,r,i=function(e){var t=e;return t.indexOf(":")>=0&&(t=t.split(":")[0]),t.indexOf("#")>=0&&(t=t.split("#")[1]),t},o=(n=e.headers,r="x-amzn-errortype",Object.keys(n).find((function(e){return e.toLowerCase()===r.toLowerCase()})));return void 0!==o?i(e.headers[o]):void 0!==t.code?i(t.code):void 0!==t.__type?i(t.__type):""},$e=n(10),Ye=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object($e.a)(t,this.serialize,this.deserialize));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"LexRuntimeServiceClient",commandName:"PostTextCommand",inputFilterSensitiveLog:U.filterSensitiveLog,outputFilterSensitiveLog:G.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"LexRuntimeServiceClient",commandName:"PostTextCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l;return d(this,(function(d){switch(d.label){case 0:if(n={"Content-Type":"application/json"},r="/bot/{botName}/alias/{botAlias}/user/{userId}/text",void 0===e.userId)throw new Error("No value provided for input HTTP label: userId.");if((i=e.userId).length<=0)throw new Error("Empty value provided for input HTTP label: userId.");if(r=r.replace("{userId}",Object(me.f)(i)),void 0===e.botAlias)throw new Error("No value provided for input HTTP label: botAlias.");if((i=e.botAlias).length<=0)throw new Error("Empty value provided for input HTTP label: botAlias.");if(r=r.replace("{botAlias}",Object(me.f)(i)),void 0===e.botName)throw new Error("No value provided for input HTTP label: botName.");if((i=e.botName).length<=0)throw new Error("Empty value provided for input HTTP label: botName.");return r=r.replace("{botName}",Object(me.f)(i)),o=JSON.stringify(f(f(f({},void 0!==e.inputText&&{inputText:e.inputText}),void 0!==e.requestAttributes&&{requestAttributes:Re(e.requestAttributes,t)}),void 0!==e.sessionAttributes&&{sessionAttributes:Re(e.sessionAttributes,t)})),[4,t.endpoint()];case 1:return s=d.sent(),a=s.hostname,u=s.protocol,c=void 0===u?"https":u,l=s.port,[2,new we.a({protocol:c,hostname:a,port:l,method:"POST",headers:n,path:r,body:o})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r;return d(this,(function(i){switch(i.label){case 0:return 200!==e.statusCode&&e.statusCode>=300?[2,Se(e,t)]:(n={$metadata:Ke(e),alternativeIntents:void 0,botVersion:void 0,dialogState:void 0,intentName:void 0,message:void 0,messageFormat:void 0,nluIntentConfidence:void 0,responseCard:void 0,sentimentResponse:void 0,sessionAttributes:void 0,sessionId:void 0,slotToElicit:void 0,slots:void 0},[4,Ge(e.body,t)]);case 1:return void 0!==(r=i.sent()).alternativeIntents&&null!==r.alternativeIntents&&(n.alternativeIntents=De(r.alternativeIntents,t)),void 0!==r.botVersion&&null!==r.botVersion&&(n.botVersion=r.botVersion),void 0!==r.dialogState&&null!==r.dialogState&&(n.dialogState=r.dialogState),void 0!==r.intentName&&null!==r.intentName&&(n.intentName=r.intentName),void 0!==r.message&&null!==r.message&&(n.message=r.message),void 0!==r.messageFormat&&null!==r.messageFormat&&(n.messageFormat=r.messageFormat),void 0!==r.nluIntentConfidence&&null!==r.nluIntentConfidence&&(n.nluIntentConfidence=je(r.nluIntentConfidence,t)),void 0!==r.responseCard&&null!==r.responseCard&&(n.responseCard=Fe(r.responseCard,t)),void 0!==r.sentimentResponse&&null!==r.sentimentResponse&&(n.sentimentResponse=ze(r.sentimentResponse,t)),void 0!==r.sessionAttributes&&null!==r.sessionAttributes&&(n.sessionAttributes=qe(r.sessionAttributes,t)),void 0!==r.sessionId&&null!==r.sessionId&&(n.sessionId=r.sessionId),void 0!==r.slotToElicit&&null!==r.slotToElicit&&(n.slotToElicit=r.slotToElicit),void 0!==r.slots&&null!==r.slots&&(n.slots=qe(r.slots,t)),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(me.b),Je=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return c(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object($e.a)(t,this.serialize,this.deserialize));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"LexRuntimeServiceClient",commandName:"PostContentCommand",inputFilterSensitiveLog:N.filterSensitiveLog,outputFilterSensitiveLog:L.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"LexRuntimeServiceClient",commandName:"PostContentCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,l;return d(this,(function(d){switch(d.label){case 0:if(n=f(f(f(f({"Content-Type":"application/octet-stream","x-amz-content-sha256":"UNSIGNED-PAYLOAD"},Ve(e.requestAttributes)&&{"x-amz-lex-request-attributes":me.c.fromObject(e.requestAttributes)}),Ve(e.sessionAttributes)&&{"x-amz-lex-session-attributes":me.c.fromObject(e.sessionAttributes)}),Ve(e.contentType)&&{"Content-Type":e.contentType}),Ve(e.accept)&&{Accept:e.accept}),r="/bot/{botName}/alias/{botAlias}/user/{userId}/content",void 0===e.botAlias)throw new Error("No value provided for input HTTP label: botAlias.");if((i=e.botAlias).length<=0)throw new Error("Empty value provided for input HTTP label: botAlias.");if(r=r.replace("{botAlias}",Object(me.f)(i)),void 0===e.botName)throw new Error("No value provided for input HTTP label: botName.");if((i=e.botName).length<=0)throw new Error("Empty value provided for input HTTP label: botName.");if(r=r.replace("{botName}",Object(me.f)(i)),void 0===e.userId)throw new Error("No value provided for input HTTP label: userId.");if((i=e.userId).length<=0)throw new Error("Empty value provided for input HTTP label: userId.");return r=r.replace("{userId}",Object(me.f)(i)),void 0!==e.inputStream&&(o=e.inputStream),[4,t.endpoint()];case 1:return s=d.sent(),a=s.hostname,u=s.protocol,c=void 0===u?"https":u,l=s.port,[2,new we.a({protocol:c,hostname:a,port:l,method:"POST",headers:n,path:r,body:o})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return l(void 0,void 0,void 0,(function(){var n,r;return d(this,(function(i){return 200!==e.statusCode&&e.statusCode>=300?[2,_e(e,t)]:(n={$metadata:Ke(e),alternativeIntents:void 0,audioStream:void 0,botVersion:void 0,contentType:void 0,dialogState:void 0,inputTranscript:void 0,intentName:void 0,message:void 0,messageFormat:void 0,nluIntentConfidence:void 0,sentimentResponse:void 0,sessionAttributes:void 0,sessionId:void 0,slotToElicit:void 0,slots:void 0},void 0!==e.headers["x-amz-lex-alternative-intents"]&&(n.alternativeIntents=new me.c(e.headers["x-amz-lex-alternative-intents"])),void 0!==e.headers["x-amz-lex-message-format"]&&(n.messageFormat=e.headers["x-amz-lex-message-format"]),void 0!==e.headers["content-type"]&&(n.contentType=e.headers["content-type"]),void 0!==e.headers["x-amz-lex-message"]&&(n.message=e.headers["x-amz-lex-message"]),void 0!==e.headers["x-amz-lex-bot-version"]&&(n.botVersion=e.headers["x-amz-lex-bot-version"]),void 0!==e.headers["x-amz-lex-sentiment"]&&(n.sentimentResponse=e.headers["x-amz-lex-sentiment"]),void 0!==e.headers["x-amz-lex-slots"]&&(n.slots=new me.c(e.headers["x-amz-lex-slots"])),void 0!==e.headers["x-amz-lex-input-transcript"]&&(n.inputTranscript=e.headers["x-amz-lex-input-transcript"]),void 0!==e.headers["x-amz-lex-slot-to-elicit"]&&(n.slotToElicit=e.headers["x-amz-lex-slot-to-elicit"]),void 0!==e.headers["x-amz-lex-session-attributes"]&&(n.sessionAttributes=new me.c(e.headers["x-amz-lex-session-attributes"])),void 0!==e.headers["x-amz-lex-session-id"]&&(n.sessionId=e.headers["x-amz-lex-session-id"]),void 0!==e.headers["x-amz-lex-dialog-state"]&&(n.dialogState=e.headers["x-amz-lex-dialog-state"]),void 0!==e.headers["x-amz-lex-intent-name"]&&(n.intentName=e.headers["x-amz-lex-intent-name"]),void 0!==e.headers["x-amz-lex-nlu-intent-confidence"]&&(n.nluIntentConfidence=new me.c(e.headers["x-amz-lex-nlu-intent-confidence"])),r=e.body,n.audioStream=r,[2,Promise.resolve(n)])}))}))}(e,t)},t}(me.b),Ze=n(89),Xe=n(50),Qe=function(e){if(e instanceof Blob||e instanceof ReadableStream)return new Response(e).arrayBuffer().then((function(e){return new Uint8Array(e)}));throw new Error("Readable is not supported.")},et=(ye=function(e,t){return(ye=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}ye(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),tt=function(){return(tt=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},nt=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},rt=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},it=new r.a("AWSLexProvider"),ot=function(e){function t(t){void 0===t&&(t={});var n=e.call(this,t)||this;return n._botsCompleteCallback={},n}return et(t,e),t.prototype.getProviderName=function(){return"AWSLexProvider"},t.prototype.reportBotStatus=function(e,t){var n=this;it.debug("postContent state",e.dialogState),"ReadyForFulfillment"!==e.dialogState&&"Fulfilled"!==e.dialogState||("function"==typeof this._botsCompleteCallback[t]&&setTimeout((function(){return n._botsCompleteCallback[t](null,{slots:e.slots})}),0),this._config&&"function"==typeof this._config[t].onComplete&&setTimeout((function(){return n._config[t].onComplete(null,{slots:e.slots})}),0)),"Failed"===e.dialogState&&("function"==typeof this._botsCompleteCallback[t]&&setTimeout((function(){return n._botsCompleteCallback[t]("Bot conversation failed")}),0),this._config&&"function"==typeof this._config[t].onComplete&&setTimeout((function(){return n._config[t].onComplete("Bot conversation failed")}),0))},t.prototype.sendMessage=function(e,t){return nt(this,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l;return rt(this,(function(d){switch(d.label){case 0:return this._config[e]?[4,Ze.a.get()]:[2,Promise.reject("Bot "+e+" does not exist")];case 1:if(!(n=d.sent()))return[2,Promise.reject("No credentials")];if(this.lexRuntimeServiceClient=new be({region:this._config[e].region,credentials:n,customUserAgent:Object(Xe.b)()}),"string"!=typeof t)return[3,6];r={botAlias:this._config[e].alias,botName:e,inputText:t,userId:n.identityId},it.debug("postText to lex",t),d.label=2;case 2:return d.trys.push([2,4,,5]),i=new Ye(r),[4,this.lexRuntimeServiceClient.send(i)];case 3:return c=d.sent(),this.reportBotStatus(c,e),[2,c];case 4:return o=d.sent(),[2,Promise.reject(o)];case 5:return[3,11];case 6:s=t.content,a=t.options.messageType,r="voice"===a?{botAlias:this._config[e].alias,botName:e,contentType:"audio/x-l16; sample-rate=16000",inputStream:s,userId:n.identityId,accept:"audio/mpeg"}:{botAlias:this._config[e].alias,botName:e,contentType:"text/plain; charset=utf-8",inputStream:s,userId:n.identityId,accept:"audio/mpeg"},it.debug("postContent to lex",t),d.label=7;case 7:return d.trys.push([7,10,,11]),u=new Je(r),[4,this.lexRuntimeServiceClient.send(u)];case 8:return c=d.sent(),[4,Qe(c.audioStream)];case 9:return f=d.sent(),this.reportBotStatus(c,e),[2,tt(tt({},c),{audioStream:f})];case 10:return l=d.sent(),[2,Promise.reject(l)];case 11:return[2]}}))}))},t.prototype.onComplete=function(e,t){if(!this._config[e])throw new ErrorEvent("Bot "+e+" does not exist");this._botsCompleteCallback[e]=t},t}(a),st=function(){return(st=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},at=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},ut=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},ct=new r.a("Interactions"),ft=new(function(){function e(e){this._options=e,ct.debug("Interactions Options",this._options),this._pluggables={}}return e.prototype.getModuleName=function(){return"Interactions"},e.prototype.configure=function(e){var t=this,n=e?e.Interactions||e:{};ct.debug("configure Interactions",{opt:n}),this._options=st(st({bots:{}},n),n.Interactions);var r=this._options.aws_bots_config,i=this._options.bots;return!Object.keys(i).length&&r&&Array.isArray(r)&&r.forEach((function(e){t._options.bots[e.name]=e})),!this._pluggables.AWSLexProvider&&i&&Object.keys(i).map((function(e){return i[e]})).find((function(e){return!e.providerName||"AWSLexProvider"===e.providerName}))&&(this._pluggables.AWSLexProvider=new ot),Object.keys(this._pluggables).map((function(e){t._pluggables[e].configure(t._options.bots)})),this._options},e.prototype.addPluggable=function(e){if(e&&"Interactions"===e.getCategory()){if(this._pluggables[e.getProviderName()])throw new Error("Bot "+e.getProviderName()+" already plugged");return e.configure(this._options.bots),void(this._pluggables[e.getProviderName()]=e)}},e.prototype.send=function(e,t){return at(this,void 0,void 0,(function(){var n;return ut(this,(function(r){switch(r.label){case 0:if(!this._options.bots||!this._options.bots[e])throw new Error("Bot "+e+" does not exist");if(n=this._options.bots[e].providerName||"AWSLexProvider",!this._pluggables[n])throw new Error("Bot "+n+" does not have valid pluggin did you try addPluggable first?");return[4,this._pluggables[n].sendMessage(e,t)];case 1:return[2,r.sent()]}}))}))},e.prototype.onComplete=function(e,t){if(!this._options.bots||!this._options.bots[e])throw new Error("Bot "+e+" does not exist");var n=this._options.bots[e].providerName||"AWSLexProvider";if(!this._pluggables[n])throw new Error("Bot "+n+" does not have valid pluggin did you try addPluggable first?");this._pluggables[n].onComplete(e,t)},e}())(null);i.a.register(ft)},function(e,t,n){"use strict";n.d(t,"a",(function(){return be}));var r=n(44),i=n(33),o=n(50),s=n(89),a=function(e,t){return(a=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function u(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}a(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var c=function(){return(c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function f(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))}function l(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}}Object.create;var d,h,p,v,g,m,b,y;Object.create;(d||(d={})).filterSensitiveLog=function(e){return c({},e)},(h||(h={})).filterSensitiveLog=function(e){return c({},e)},(p||(p={})).filterSensitiveLog=function(e){return c({},e)},(v||(v={})).filterSensitiveLog=function(e){return c({},e)},(g||(g={})).filterSensitiveLog=function(e){return c({},e)},(m||(m={})).filterSensitiveLog=function(e){return c({},e)},(b||(b={})).filterSensitiveLog=function(e){return c({},e)},(y||(y={})).filterSensitiveLog=function(e){return c({},e)};var w,_,S,E=n(2),M=n(0),A=function(e,t){return f(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,f;return l(this,(function(l){switch(l.label){case 0:return r=[c({},e)],f={},[4,T(e.body,t)];case 1:switch(n=c.apply(void 0,r.concat([(f.body=l.sent(),f)])),o="UnknownError",o=P(e,n.body),o){case"InvalidInputException":case"com.amazonaws.personalizeevents#InvalidInputException":return[3,2]}return[3,4];case 2:return s=[{}],[4,I(n,t)];case 3:return i=c.apply(void 0,[c.apply(void 0,s.concat([l.sent()])),{name:o,$metadata:x(e)}]),[3,5];case 4:a=n.body,o=a.code||a.Code||o,i=c(c({},a),{name:""+o,message:a.message||a.Message||o,$fault:"client",$metadata:x(e)}),l.label=5;case 5:return u=i.message||i.Message||o,i.message=u,delete i.Message,[2,Promise.reject(Object.assign(new Error(u),i))]}}))}))},I=function(e,t){return f(void 0,void 0,void 0,(function(){var t,n;return l(this,(function(r){return t={name:"InvalidInputException",$fault:"client",$metadata:x(e),message:void 0},void 0!==(n=e.body).message&&null!==n.message&&(t.message=n.message),[2,t]}))}))},k=function(e,t){return e.map((function(e){return function(e,t){return c(c(c(c(c(c(c(c({},void 0!==e.eventId&&{eventId:e.eventId}),void 0!==e.eventType&&{eventType:e.eventType}),void 0!==e.eventValue&&{eventValue:e.eventValue}),void 0!==e.impression&&{impression:O(e.impression,t)}),void 0!==e.itemId&&{itemId:e.itemId}),void 0!==e.properties&&{properties:M.c.fromObject(e.properties)}),void 0!==e.recommendationId&&{recommendationId:e.recommendationId}),void 0!==e.sentAt&&{sentAt:Math.round(e.sentAt.getTime()/1e3)})}(e,t)}))},O=function(e,t){return e.map((function(e){return e}))},x=function(e){return{httpStatusCode:e.statusCode,httpHeaders:e.headers,requestId:e.headers["x-amzn-requestid"]}},C=function(e,t){return void 0===e&&(e=new Uint8Array),e instanceof Uint8Array?Promise.resolve(e):t.streamCollector(e)||Promise.resolve(new Uint8Array)},T=function(e,t){return function(e,t){return C(e,t).then((function(e){return t.utf8Encoder(e)}))}(e,t).then((function(e){return e.length?JSON.parse(e):{}}))},P=function(e,t){var n,r,i=function(e){var t=e;return t.indexOf(":")>=0&&(t=t.split(":")[0]),t.indexOf("#")>=0&&(t=t.split("#")[1]),t},o=(n=e.headers,r="x-amzn-errortype",Object.keys(n).find((function(e){return e.toLowerCase()===r.toLowerCase()})));return void 0!==o?i(e.headers[o]):void 0!==t.code?i(t.code):void 0!==t.__type?i(t.__type):""},N=n(10),R=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return u(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(N.a)(t,this.serialize,this.deserialize));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"PersonalizeEventsClient",commandName:"PutEventsCommand",inputFilterSensitiveLog:p.filterSensitiveLog,outputFilterSensitiveLog:function(e){return e}};"function"==typeof i.info&&i.info({clientName:"PersonalizeEventsClient",commandName:"PutEventsCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return f(void 0,void 0,void 0,(function(){var n,r,i,o,s,a,u,f;return l(this,(function(l){switch(l.label){case 0:return n={"Content-Type":"application/json"},r="/events",i=JSON.stringify(c(c(c(c({},void 0!==e.eventList&&{eventList:k(e.eventList,t)}),void 0!==e.sessionId&&{sessionId:e.sessionId}),void 0!==e.trackingId&&{trackingId:e.trackingId}),void 0!==e.userId&&{userId:e.userId})),[4,t.endpoint()];case 1:return o=l.sent(),s=o.hostname,a=o.protocol,u=void 0===a?"https":a,f=o.port,[2,new E.a({protocol:u,hostname:s,port:f,method:"POST",headers:n,path:r,body:i})]}}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return f(void 0,void 0,void 0,(function(){var n;return l(this,(function(r){switch(r.label){case 0:return 200!==e.statusCode&&e.statusCode>=300?[2,A(e,t)]:(n={$metadata:x(e)},[4,C(e.body,t)]);case 1:return r.sent(),[2,Promise.resolve(n)]}}))}))}(e,t)},t}(M.b),L=n(152),j=n(38),D=n(18),U=n(24),B=n(11),F=n(39),z=n(17),q=n(40),K=n(41),H=n(15),V="personalize-events.{region}.amazonaws.com",G=new Set(["ap-east-1","ap-northeast-1","ap-northeast-2","ap-south-1","ap-southeast-1","ap-southeast-2","ca-central-1","eu-central-1","eu-north-1","eu-west-1","eu-west-2","eu-west-3","me-south-1","sa-east-1","us-east-1","us-east-2","us-west-1","us-west-2"]),W=new Set(["cn-north-1","cn-northwest-1"]),$=new Set(["us-iso-east-1"]),Y=new Set(["us-isob-east-1"]),J=new Set(["us-gov-east-1","us-gov-west-1"]),Z=c(c({},{apiVersion:"2018-03-22",disableHostPrefix:!1,logger:{},regionInfoProvider:function(e,t){var n=void 0;return G.has(e)&&(n={hostname:V.replace("{region}",e),partition:"aws"}),W.has(e)&&(n={hostname:"personalize-events.{region}.amazonaws.com.cn".replace("{region}",e),partition:"aws-cn"}),$.has(e)&&(n={hostname:"personalize-events.{region}.c2s.ic.gov".replace("{region}",e),partition:"aws-iso"}),Y.has(e)&&(n={hostname:"personalize-events.{region}.sc2s.sgov.gov".replace("{region}",e),partition:"aws-iso-b"}),J.has(e)&&(n={hostname:"personalize-events.{region}.amazonaws.com".replace("{region}",e),partition:"aws-us-gov"}),void 0===n&&(n={hostname:V.replace("{region}",e),partition:"aws"}),Promise.resolve(n)},signingName:"personalize"}),{runtime:"browser",base64Decoder:z.a,base64Encoder:z.b,bodyLengthChecker:q.a,credentialDefaultProvider:Object(U.a)("Credential is missing"),defaultUserAgent:Object(K.a)(L.name,L.version),maxAttempts:B.a,region:Object(U.a)("Region is missing"),requestHandler:new D.a,sha256:j.Sha256,streamCollector:D.b,urlParser:F.a,utf8Decoder:H.a,utf8Encoder:H.b}),X=n(22),Q=n(37),ee=n(21),te=n(43),ne=n(25),re=n(23),ie=function(e){function t(t){var n=this,r=c(c({},Z),t),i=Object(X.b)(r),o=Object(X.a)(i),s=Object(ne.b)(o),a=Object(B.c)(s),u=Object(re.b)(a),f=Object(ee.b)(u);return(n=e.call(this,f)||this).config=f,n.middlewareStack.use(Object(ne.a)(n.config)),n.middlewareStack.use(Object(B.b)(n.config)),n.middlewareStack.use(Object(re.a)(n.config)),n.middlewareStack.use(Object(Q.a)(n.config)),n.middlewareStack.use(Object(ee.a)(n.config)),n.middlewareStack.use(Object(te.a)(n.config)),n}return u(t,e),t.prototype.destroy=function(){e.prototype.destroy.call(this)},t}(M.a),oe=n(36),se=n.n(oe),ae=n(108),ue=n.n(ae),ce=n(27),fe=n(26),le=(new r.a("AmazonPersonalizeProvider"),function(){function e(e){void 0===e&&(e=""),this._isBrowser=i.a.browserOrNode().isBrowser,this._timerKey=Object(ce.v1)().substr(0,15),this._refreshTimer()}return e.prototype._refreshTimer=function(){this._timer&&clearInterval(this._timer);var e=this;this._timer=setInterval((function(){e._timerKey=Object(ce.v1)().substr(0,15)}),3e4)},e.prototype.storeValue=function(e,t){var n=new Date,r=new Date;r.setTime(n.getTime()+6048e5),fe.a.setItem(this._getCachePrefix(e),t,{expires:r.getTime()})},e.prototype.retrieveValue=function(e){return fe.a.getItem(this._getCachePrefix(e))},e.prototype._getCachePrefix=function(e){return this._isBrowser?e+"."+window.location.host:"peronslize"},e.prototype.getTimerKey=function(){return this._timerKey},e.prototype.updateSessionInfo=function(e,t){var n=t.userId,r=t.sessionId;if(this._isRequireNewSession(e,n,r)){var i=Object(ce.v1)();this.storeValue("_awsct_uid",e),this.storeValue("_awsct_sid",i),t.sessionId=i}else this._isRequireUpdateSessionInfo(e,n,r)&&this.storeValue("_awsct_uid",e);t.userId=e},e.prototype._isRequireUpdateSessionInfo=function(e,t,n){return!se()(n)&&se()(t)&&!se()(e)},e.prototype.retrieveSessionInfo=function(e){var t={};return t.trackingId=e,t.sessionId=this.retrieveValue("_awsct_sid"),t.userId=this.retrieveValue("_awsct_uid"),se()(t.sessionId)&&(t.sessionId=Object(ce.v1)(),this.storeValue("_awsct_sid",t.sessionId)),this.storeValue("_awsct",e),t},e.prototype._isRequireNewSession=function(e,t,n){var r=se()(n),i=se()(e)&&!se()(t),o=!se()(e)&&!se()(t)&&!ue()(e,t);return r||i||o},e}());!function(e){e.PLAY="play",e.PAUSE="pause",e.ENDED="Ended"}(w||(w={})),function(e){e.IFRAME="IFRAME",e.VIDEO="VIDEO",e.AUDIO="AUDIO"}(_||(_={})),function(e){e.PLAY="Play",e.ENDED="Ended",e.PAUSE="Pause",e.TIME_WATCHED="TimeWatched"}(S||(S={}));var de=function(){function e(e,t){var n;this.eventActionMapping=((n={})[S.ENDED]=this.endedEventAction.bind(this),n[S.PLAY]=this.playEventAction.bind(this),n[S.PAUSE]=this.pauseEventAction.bind(this),n);var r=e.eventData;this._params=e,this._mediaElement=document.getElementById(r.properties.domElementId),this._started=!1,this._provider=t,{IFRAME:this._iframeMediaTracker,VIDEO:this._html5MediaTracker,AUDIO:this._html5MediaTracker}[this._mediaElement.tagName].bind(this)(),this._initYoutubeFrame()}return e.prototype._initYoutubeFrame=function(){this._youTubeIframeLoader={src:"https://www.youtube.com/iframe_api",loading:!1,loaded:!1,listeners:[],load:function(e){var t=this;if(this.listeners.push(e),this.loaded)setTimeout((function(){t.done()}));else if(!this.loading){this.loading=!0,window.onYouTubeIframeAPIReady=function(){t.loaded=!0,t.done()};var n=document.createElement("script");n.type="text/javascript",n.src=this.src,document.body.appendChild(n)}},done:function(){for(delete window.onYouTubeIframeAPIReady;this.listeners.length;)this.listeners.pop()(window.YT)}}},e.prototype._iframeMediaTracker=function(){var e=this;setInterval((function(){e._started&&e.recordEvent(_.IFRAME,S.TIME_WATCHED)}),3e3),this._youTubeIframeLoader.load((function(t){e._iframePlayer=new t.Player(e._mediaElement.id,{events:{onStateChange:e._onPlayerStateChange.bind(e)}})}))},e.prototype._onPlayerStateChange=function(e){var t={0:S.ENDED,1:S.PLAY,2:S.PAUSE}[e.data];t&&this.eventActionMapping[t](_.IFRAME)},e.prototype._html5MediaTracker=function(){var e=this;setInterval((function(){e._started&&e.recordEvent(_.VIDEO,S.TIME_WATCHED)}),3e3),this._mediaElement.addEventListener(w.PLAY,(function(){e.eventActionMapping[S.PLAY](_.VIDEO)}),!1),this._mediaElement.addEventListener(w.PAUSE,(function(){e.eventActionMapping[S.PAUSE](_.VIDEO)}),!1),this._mediaElement.addEventListener(w.ENDED,(function(){e.eventActionMapping[S.ENDED](_.VIDEO)}),!1)},e.prototype.playEventAction=function(e){this._started=!0,this.recordEvent(e,S.PLAY)},e.prototype.pauseEventAction=function(e){this._started=!1,this.recordEvent(e,S.PAUSE)},e.prototype.endedEventAction=function(e){this._started=!1,this.recordEvent(e,S.ENDED)},e.prototype.recordEvent=function(e,t){var n=Object.assign({},this._params),r=n.eventData;r.eventType=t,e===_.VIDEO?(r.properties.timestamp=this._mediaElement.currentTime,r.properties.duration=this._mediaElement.duration):(r.properties.timestamp=this._financial(this._iframePlayer.getCurrentTime()),r.properties.duration=this._financial(this._iframePlayer.getDuration()));var i=parseFloat(r.properties.timestamp)/parseFloat(r.properties.duration);r.properties.eventValue=Number(i.toFixed(4)),delete r.properties.domElementId,this._provider.putToBuffer(n)},e.prototype._financial=function(e){return Number.parseFloat(e).toFixed(4)},e}(),he=n(252),pe=n.n(he),ve=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},ge=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},me=new r.a("AmazonPersonalizeProvider"),be=function(){function e(e){this._buffer=[],this._config=e||{},this._config.flushSize=this._config.flushSize>0&&this._config.flushSize<=10?this._config.flushSize:5,this._config.flushInterval=this._config.flushInterval||5e3,this._sessionManager=new le,se()(this._config.trackingId)||(this._sessionInfo=this._sessionManager.retrieveSessionInfo(this._config.trackingId)),this._isBrowser=i.a.browserOrNode().isBrowser,this._setupTimer()}return e.prototype._setupTimer=function(){this._timer&&clearInterval(this._timer);var e=this._config.flushInterval,t=this;this._timer=setInterval((function(){t._sendFromBuffer()}),e)},e.prototype.record=function(e){return ve(this,void 0,void 0,(function(){var t,n,r,i,o;return ge(this,(function(s){switch(s.label){case 0:return[4,this._getCredentials()];case 1:return(t=s.sent())?(Object.assign(e,{config:this._config,credentials:t,sentAt:new Date}),n=e.event,r=n.eventType,i=n.properties,"Identify"===r?(this._sessionManager.updateSessionInfo(i&&i.userId?i.userId:"",this._sessionInfo),[2]):(se()(e.event.userId)||this._sessionManager.updateSessionInfo(e.event.userId,this._sessionInfo),o=this.generateRequestParams(e,this._sessionInfo),"MediaAutoTrack"!==r?[3,7]:this._isBrowser?se()(pe()(o,"eventData.properties.domElementId",null))?[3,3]:[4,this.isElementFullyLoaded(this.loadElement,o.eventData.properties.domElementId,500,5)]:[3,5])):[2,Promise.resolve(!1)];case 2:return s.sent()?new de(o,this):me.debug("Cannot find the media element."),[3,4];case 3:me.debug("Missing domElementId field in 'properties' for MediaAutoTrack event type."),s.label=4;case 4:return[3,6];case 5:me.debug("MediaAutoTrack only for browser"),s.label=6;case 6:return[2];case 7:return[2,this.putToBuffer(o)]}}))}))},e.prototype.loadElement=function(e){return new Promise((function(t,n){return document.getElementById(e)&&document.getElementById(e).clientHeight?t(!0):n(!0)}))},e.prototype.isElementFullyLoaded=function(e,t,n,r){var i=this;return new Promise((function(o,s){return e(t).then(o).catch((function(a){return r-1>0?(u=n,new Promise((function(e){return setTimeout(e,u)}))).then(i.isElementFullyLoaded.bind(null,e,t,n,r-1)).then(o).catch(s):s(a);var u}))}))},e.prototype.getCategory=function(){return"Analytics"},e.prototype.getProviderName=function(){return"AmazonPersonalize"},e.prototype.configure=function(e){me.debug("configure Analytics",e);var t=e||{};return this._config=Object.assign({},this._config,t),se()(this._config.trackingId)||(this._sessionInfo=this._sessionManager.retrieveSessionInfo(this._config.trackingId)),this._setupTimer(),this._config},e.prototype.generateRequestParams=function(e,t){var n={},r=e.event,i=r.eventType,o=r.properties;return n.eventData={eventType:i,properties:o},n.sessionInfo=t,n.sentAt=e.sentAt,n.credentials=e.credentials,n.config=e.config,n},e.prototype._sendEvents=function(e){var t=e.length;if(0!==t){var n=e[0],r=n.config,i=n.credentials,o=n.sessionInfo;if(!this._init(r,i))return!1;if(t>0){for(var s=[],a=0;a<t;a+=1){var u=e.shift(),c=this._generateSingleRecordPayload(u,o);s.push(c)}var f={};f.trackingId=o.trackingId,f.sessionId=o.sessionId,f.userId=o.userId,f.eventList=[],s.forEach((function(e){f.eventList.push(e)}));var l=new R(f);this._personalize.send(l,(function(e){e?me.debug("Failed to call putEvents in Personalize",e):me.debug("Put events")}))}}else me.debug("events array is empty, directly return")},e.prototype.putToBuffer=function(e){return this._buffer.length<this._config.flushSize?this._buffer.push(e):(this._buffer.push(e),this._sendFromBuffer()),Promise.resolve(!0)},e.prototype._sendFromBuffer=function(){var e=this,t=this._buffer.length;if(!(t<=0)){for(var n=[],r=null,i=[],o=0;o<t;o+=1){var s=this._buffer.shift(),a=s.credentials,u=s.sessionInfo;0===o?(i.push(s),r=a):ue()(u,this._sessionInfo)&&a.sessionToken===r.sessionToken&&a.identityId===r.identityId?(me.debug("no change for cred, put event in the same group"),i.push(s)):(n.push(i),(i=[]).push(s),r=a,this._sessionInfo=u)}n.push(i),n.map((function(t){e._sendEvents(t)}))}},e.prototype._generateSingleRecordPayload=function(e,t){var n=e.eventData,r=e.sentAt,i={};return i.sentAt=r,i.properties=n.properties&&JSON.stringify(n.properties),i.eventId=this._sessionManager.getTimerKey()+t.sessionId,i.eventType=n.eventType,i},e.prototype._init=function(e,t){if(me.debug("init clients"),this._personalize&&this._config.credentials&&this._config.credentials.sessionToken===t.sessionToken&&this._config.credentials.identityId===t.identityId)return me.debug("no change for analytics config, directly return from init"),!0;this._config.credentials=t;var n=e.region;return me.debug("initialize personalize with credentials",t),this._personalize=new ie({region:n,credentials:t,customUserAgent:Object(o.b)()}),!0},e.prototype._getCredentials=function(){var e=this;return s.a.get().then((function(t){return t?(me.debug("set credentials for analytics",e._config.credentials),s.a.shear(t)):null})).catch((function(e){return me.debug("ensure credentials error",e),null}))},e}()},function(e,t,n){"use strict";n.d(t,"a",(function(){return X}));var r=n(44),i=n(88),o=n(221),s=n(19),a=n(144),u=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},c=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(u(arguments[t]));return e},f=[],l=function(){function e(e,t){this.context=e,this.methodName=t,this._originalMethod=e[t].bind(e)}return e.add=function(e,t,n){d(e,t).set(n)},e.remove=function(e,t){d(e,t).remove()},e.prototype.set=function(e){var t=this;this.context[this.methodName]=function(){for(var n=[],r=0;r<arguments.length;r++)n[r]=arguments[r];return e(t._originalMethod.apply(t,c(n)))}},e.prototype.remove=function(){this.context[this.methodName]=this._originalMethod},e}();function d(e,t){var n=f.filter((function(n){return n.context===e&&n.methodName===t}))[0];return n||(n=new l(e,t),f.push(n)),n}var h=n(33),p=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},v=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},g=new r.a("PageViewTracker"),m="aws-amplify-analytics-prevUrl",b={enable:!1,provider:"AWSPinpoint",getUrl:function(){return h.a.browserOrNode().isBrowser?window.location.origin+window.location.pathname:""}},y=function(){function e(e,t){g.debug("initialize pageview tracker with opts",t),this._config=Object.assign({},b,t),this._tracker=e,this._hasEnabled=!1,this._trackFunc=this._trackFunc.bind(this),"SPA"===this._config.type?this._pageViewTrackSPA():this._pageViewTrackDefault()}return e.prototype.configure=function(e){return Object.assign(this._config,e),"SPA"===this._config.type&&this._pageViewTrackSPA(),this._config},e.prototype._isSameUrl=function(){return sessionStorage.getItem(m)===this._config.getUrl()&&(g.debug("the url is same"),!0)},e.prototype._pageViewTrackDefault=function(){return p(this,void 0,void 0,(function(){var e,t,n,r;return v(this,(function(i){switch(i.label){case 0:return h.a.browserOrNode().isBrowser&&window.addEventListener&&window.sessionStorage?(e=this._config.getUrl(),"function"!=typeof this._config.attributes?[3,2]:[4,this._config.attributes()]):(g.debug("not in the supported web enviroment"),[2]);case 1:return n=i.sent(),[3,3];case 2:n=this._config.attributes,i.label=3;case 3:return t=n,r=Object.assign({url:e},t),this._config.enable&&!this._isSameUrl()&&(this._tracker({name:this._config.eventName||"pageView",attributes:r},this._config.provider).catch((function(e){g.debug("Failed to record the page view event",e)})),sessionStorage.setItem(m,e)),[2]}}))}))},e.prototype._trackFunc=function(){return p(this,void 0,void 0,(function(){var e,t,n,r;return v(this,(function(i){switch(i.label){case 0:return h.a.browserOrNode().isBrowser&&window.addEventListener&&history.pushState&&window.sessionStorage?(e=this._config.getUrl(),"function"!=typeof this._config.attributes?[3,2]:[4,this._config.attributes()]):(g.debug("not in the supported web enviroment"),[2]);case 1:return n=i.sent(),[3,3];case 2:n=this._config.attributes,i.label=3;case 3:return t=n,r=Object.assign({url:e},t),this._isSameUrl()||(this._tracker({name:this._config.eventName||"pageView",attributes:r},this._config.provider).catch((function(e){g.debug("Failed to record the page view event",e)})),sessionStorage.setItem(m,e)),[2]}}))}))},e.prototype._pageViewTrackSPA=function(){h.a.browserOrNode().isBrowser&&window.addEventListener&&history.pushState?this._config.enable&&!this._hasEnabled?(l.add(history,"pushState",this._trackFunc),l.add(history,"replaceState",this._trackFunc),window.addEventListener("popstate",this._trackFunc),this._trackFunc(),this._hasEnabled=!0):(l.remove(history,"pushState"),l.remove(history,"replaceState"),window.removeEventListener("popstate",this._trackFunc),this._hasEnabled=!1):g.debug("not in the supported web enviroment")},e}(),w=h.a.browserOrNode().isBrowser&&window.Element?window.Element.prototype:null,_=w?w.matches||w.matchesSelector||w.webkitMatchesSelector||w.mozMatchesSelector||w.msMatchesSelector||w.oMatchesSelector:null;function S(e,t){if(e&&1===e.nodeType&&t){if("string"==typeof t||1===t.nodeType)return e===t||E(e,t);if("length"in t)for(var n=0,r=void 0;r=t[n];n++)if(e===r||E(e,r))return!0}return!1}function E(e,t){if("string"!=typeof t)return!1;if(_)return _.call(e,t);for(var n=e.parentNode.querySelectorAll(t),r=0,i=void 0;i=n[r];r++)if(i===e)return!0;return!1}function M(e,t,n,r,i){void 0===i&&(i={});var o=function(e){var t;if(i.composed&&"function"==typeof e.composedPath)for(var o=e.composedPath(),s=0,a=void 0;a=o[s];s++)1===a.nodeType&&S(a,n)&&(t=a);else t=function(e,t,n){if(void 0===n&&(n=!1),e&&1===e.nodeType&&t)for(var r,i=(n?[e]:[]).concat(function(e){for(var t=[],n=e;n&&n.parentNode&&1===n.parentNode.nodeType;)n=n.parentNode,t.push(n);return t}(e)),o=0;r=i[o];o++)if(S(r,t))return r}(e.target,n,!0);t&&r.call(t,e,t)};return e.addEventListener(t,o,i.useCapture),{destroy:function(){e.removeEventListener(t,o,i.useCapture)}}}var A=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},I=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},k=new r.a("EventTracker"),O={enable:!1,events:["click"],selectorPrefix:"data-amplify-analytics-",provider:"AWSPinpoint"},x=function(){function e(e,t){h.a.browserOrNode().isBrowser&&window.addEventListener?(this._config=Object.assign({},O,t),this._tracker=e,this._delegates={},this._trackFunc=this._trackFunc.bind(this),k.debug("initialize pageview tracker with opts",this._config),this.configure(this._config)):k.debug("not in the supported web environment")}return e.prototype.configure=function(e){var t=this;if(Object.assign(this._config,e),this._config.enable){if(this._config.enable&&0===Object.keys(this._delegates).length){var n="["+this._config.selectorPrefix+"on]";this._config.events.forEach((function(e){t._delegates[e]=M(document,e,n,t._trackFunc,{composed:!0,useCapture:!0})}))}}else Object.keys(this._delegates).forEach((function(e){"function"==typeof t._delegates[e].destroy&&t._delegates[e].destroy()})),this._delegates={};return this._config},e.prototype._trackFunc=function(e,t){return A(this,void 0,void 0,(function(){var n,r,i,o,s,a,u;return I(this,(function(c){switch(c.label){case 0:return n={},r=t.getAttribute(this._config.selectorPrefix+"on").split(/\s*,\s*/),i=t.getAttribute(this._config.selectorPrefix+"name"),(o=t.getAttribute(this._config.selectorPrefix+"attrs"))&&o.split(/\s*,\s*/).forEach((function(e){var t=e.trim().split(/\s*:\s*/);n[t[0]]=t[1]})),"function"!=typeof this._config.attributes?[3,2]:[4,this._config.attributes()];case 1:return a=c.sent(),[3,3];case 2:a=this._config.attributes,c.label=3;case 3:return s=a,u=Object.assign({type:e.type,target:e.target.localName+" with id "+e.target.id},s,n),k.debug("events needed to be recorded",r),k.debug("attributes needed to be attached",n),r.indexOf(e.type)<0?(k.debug("event "+e.type+" is not selected to be recorded"),[2]):(this._tracker({name:i||"event",attributes:u},this._config.provider).catch((function(t){k.debug("Failed to record the "+e.type+" event', "+t)})),[2])}}))}))},e}(),C=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},T=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},P=new r.a("SessionTracker"),N={enable:!1,provider:"AWSPinpoint"},R=!1,L=function(){function e(e,t){this._config=Object.assign({},N,t),this._tracker=e,this._hasEnabled=!1,this._trackFunc=this._trackFunc.bind(this),this._trackBeforeUnload=this._trackBeforeUnload.bind(this),this.configure(this._config)}return e.prototype._envCheck=function(){if(!h.a.browserOrNode().isBrowser)return!1;if(!document||!document.addEventListener)return P.debug("not in the supported web environment"),!1;if(void 0!==document.hidden)this._hidden="hidden",this._visibilityChange="visibilitychange";else if(void 0!==document.msHidden)this._hidden="msHidden",this._visibilityChange="msvisibilitychange";else{if(void 0===document.webkitHidden)return P.debug("not in the supported web environment"),!1;this._hidden="webkitHidden",this._visibilityChange="webkitvisibilitychange"}return!0},e.prototype._trackFunc=function(){return C(this,void 0,void 0,(function(){var e,t,n;return T(this,(function(r){switch(r.label){case 0:return"function"!=typeof this._config.attributes?[3,2]:[4,this._config.attributes()];case 1:return t=r.sent(),[3,3];case 2:t=this._config.attributes,r.label=3;case 3:return e=t,n=Object.assign({},e),document.visibilityState===this._hidden?this._tracker({name:"_session.stop",attributes:n},this._config.provider).catch((function(e){P.debug("record session stop event failed.",e)})):this._tracker({name:"_session.start",attributes:n},this._config.provider).catch((function(e){P.debug("record session start event failed.",e)})),[2]}}))}))},e.prototype._trackBeforeUnload=function(e){var t=this;("function"==typeof this._config.attributes?Promise.resolve(this._config.attributes()):Promise.resolve(this._config.attributes)).then((function(e){var n=Object.assign({},e);t._tracker({name:"_session.stop",attributes:n,immediate:!0},t._config.provider).catch((function(e){P.debug("record session stop event failed.",e)}))}))},e.prototype._sendInitialEvent=function(){return C(this,void 0,void 0,(function(){var e,t,n;return T(this,(function(r){switch(r.label){case 0:return R?(P.debug("the start session has been sent when the page is loaded"),[2]):(R=!0,"function"!=typeof this._config.attributes?[3,2]:[4,this._config.attributes()]);case 1:return t=r.sent(),[3,3];case 2:t=this._config.attributes,r.label=3;case 3:return e=t,n=Object.assign({},e),this._tracker({name:"_session.start",attributes:n},this._config.provider).catch((function(e){P.debug("record session start event failed.",e)})),[2]}}))}))},e.prototype.configure=function(e){return this._envCheck()?(Object.assign(this._config,e),this._config.enable&&!this._hasEnabled?(this._sendInitialEvent(),document.addEventListener(this._visibilityChange,this._trackFunc,!1),window.addEventListener("beforeunload",this._trackBeforeUnload,!1),this._hasEnabled=!0):!this._config.enable&&this._hasEnabled&&(document.removeEventListener(this._visibilityChange,this._trackFunc,!1),window.removeEventListener("beforeunload",this._trackBeforeUnload,!1),this._hasEnabled=!1),this._config):this._config},e}(),j=function(){return(j=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},D=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},U=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},B=new r.a("AnalyticsClass"),F="undefined"!=typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("amplify_default"):"@@amplify_default",z={pageView:y,event:x,session:L},q=null,K=function(){function e(){this._config={},this._pluggables=[],this._disabled=!1,this._trackers={},q=this,this.record=this.record.bind(this),i.a.listen("auth",W),i.a.listen("storage",W),i.a.listen("analytics",W)}return e.prototype.getModuleName=function(){return"Analytics"},e.prototype.configure=function(e){var t=this;if(!e)return this._config;B.debug("configure Analytics",e);var n,r,s,u=o.a.parseMobilehubConfig(e);return this._config=Object.assign({},this._config,u.Analytics,e),this._config.disabled&&(this._disabled=!0),void 0===this._config.autoSessionRecord&&(this._config.autoSessionRecord=!0),this._pluggables.forEach((function(e){var n="AWSPinpoint"!==e.getProviderName()||t._config.AWSPinpoint?t._config[e.getProviderName()]:t._config;e.configure(j({disabled:t._config.disabled,autoSessionRecord:t._config.autoSessionRecord},n))})),0===this._pluggables.length&&this.addPluggable(new a.a),n="configured",r=null,s="The Analytics category has been configured successfully",i.a.dispatch("analytics",{event:n,data:r,message:s},"Analytics",F),B.debug("current configuration",this._config),this._config},e.prototype.addPluggable=function(e){if(e&&"Analytics"===e.getCategory()){this._pluggables.push(e);var t="AWSPinpoint"!==e.getProviderName()||this._config.AWSPinpoint?this._config[e.getProviderName()]:this._config,n=j({disabled:this._config.disabled},t);return e.configure(n),n}},e.prototype.getPluggable=function(e){for(var t=0;t<this._pluggables.length;t+=1){var n=this._pluggables[t];if(n.getProviderName()===e)return n}return B.debug("No plugin found with providerName",e),null},e.prototype.removePluggable=function(e){for(var t=0;t<this._pluggables.length&&this._pluggables[t].getProviderName()!==e;)t+=1;return t===this._pluggables.length?void B.debug("No plugin found with providerName",e):void this._pluggables.splice(t,t+1)},e.prototype.disable=function(){this._disabled=!0},e.prototype.enable=function(){this._disabled=!1},e.prototype.startSession=function(e){return D(this,void 0,void 0,(function(){var t;return U(this,(function(n){return t={event:{name:"_session.start"},provider:e},[2,this._sendEvent(t)]}))}))},e.prototype.stopSession=function(e){return D(this,void 0,void 0,(function(){var t;return U(this,(function(n){return t={event:{name:"_session.stop"},provider:e},[2,this._sendEvent(t)]}))}))},e.prototype.record=function(e,t,n){return D(this,void 0,void 0,(function(){var r;return U(this,(function(i){return r=null,r="string"==typeof e?{event:{name:e,attributes:t,metrics:n},provider:"AWSPinpoint"}:{event:e,provider:t},[2,this._sendEvent(r)]}))}))},e.prototype.updateEndpoint=function(e,t){return D(this,void 0,void 0,(function(){var n;return U(this,(function(r){return n=j(j({},e),{name:"_update_endpoint"}),[2,this.record(n,t)]}))}))},e.prototype._sendEvent=function(e){var t=this;if(this._disabled)return B.debug("Analytics has been disabled"),Promise.resolve();var n=e.provider?e.provider:"AWSPinpoint";return new Promise((function(r,i){t._pluggables.forEach((function(t){t.getProviderName()===n&&t.record(e,{resolve:r,reject:i})}))}))},e.prototype.autoTrack=function(e,t){if(z[e]){"session"===e&&(this._config.autoSessionRecord=t.enable);var n=this._trackers[e];n?n.configure(t):this._trackers[e]=new z[e](this.record,t)}else B.debug("invalid tracker type")},e}(),H=!1,V=!1,G=!1,W=function(e){var t=e.channel,n=e.payload;switch(B.debug("on hub capsule "+t,n),t){case"auth":Y(n);break;case"storage":$(n);break;case"analytics":J(n)}},$=function(e){var t=e.data,n=t.attrs,r=t.metrics;n&&G&&q.record({name:"Storage",attributes:n,metrics:r}).catch((function(e){B.debug("Failed to send the storage event automatically",e)}))},Y=function(e){var t=e.event;if(t){var n=function(e){return D(void 0,void 0,void 0,(function(){var t;return U(this,(function(n){switch(n.label){case 0:if(!V||!G)return[3,4];n.label=1;case 1:return n.trys.push([1,3,,4]),[4,q.record({name:"_userauth."+e})];case 2:return[2,n.sent()];case 3:return t=n.sent(),B.debug("Failed to send the "+e+" event automatically",t),[3,4];case 4:return[2]}}))}))};switch(t){case"signIn":return n("sign_in");case"signUp":return n("sign_up");case"signOut":return n("sign_out");case"signIn_failure":return n("auth_fail");case"configured":(V=!0)&&G&&Z()}}},J=function(e){var t=e.event;if(t)switch(t){case"pinpointProvider_configured":G=!0,V&&G&&Z()}},Z=function(){var e=q.configure();!H&&e.autoSessionRecord&&(q.updateEndpoint({immediate:!0}).catch((function(e){B.debug("Failed to update the endpoint",e)})),H=!0),q.autoTrack("session",{enable:e.autoSessionRecord})},X=new K;s.a.register(X)},function(e,t,n){"use strict";n.d(t,"a",(function(){return Zt}));var r=n(44),i=n(145),o=function(e,t){return(o=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function s(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}o(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)};function u(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))}function c(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}}Object.create;Object.create;var f,l,d,h,p,v,g,m,b,y,w,_,S,E,M,A,I,k,O,x,C,T,P,N,R,L,j,D,U,B,F,z,q,K,H,V,G,W,$,Y,J,Z,X,Q,ee,te,ne,re,ie,oe,se,ae,ue,ce,fe,le,de,he,pe,ve,ge,me,be,ye,we,_e,Se,Ee,Me,Ae,Ie,ke,Oe,xe,Ce,Te,Pe,Ne,Re,Le,je,De,Ue,Be,Fe,ze,qe,Ke,He,Ve,Ge,We,$e,Ye,Je,Ze,Xe,Qe,et,tt,nt,rt=n(0);(f||(f={})).filterSensitiveLog=function(e){return a({},e)},(l||(l={})).filterSensitiveLog=function(e){return a({},e)},function(e){e.GZIP="GZIP",e.HADOOP_SNAPPY="HADOOP_SNAPPY",e.SNAPPY="Snappy",e.UNCOMPRESSED="UNCOMPRESSED",e.ZIP="ZIP"}(d||(d={})),(h||(h={})).filterSensitiveLog=function(e){return a({},e)},function(e){e.GZIP="GZIP",e.NONE="NONE"}(p||(p={})),(v||(v={})).filterSensitiveLog=function(e){return a({},e)},function(e){e.AWS_OWNED_CMK="AWS_OWNED_CMK",e.CUSTOMER_MANAGED_CMK="CUSTOMER_MANAGED_CMK"}(g||(g={})),(m||(m={})).filterSensitiveLog=function(e){return a({},e)},(b||(b={})).filterSensitiveLog=function(e){return a({},e)},function(e){e.BUFFER_INTERVAL_IN_SECONDS="BufferIntervalInSeconds",e.BUFFER_SIZE_IN_MB="BufferSizeInMBs",e.LAMBDA_ARN="LambdaArn",e.LAMBDA_NUMBER_OF_RETRIES="NumberOfRetries",e.ROLE_ARN="RoleArn"}(y||(y={})),(w||(w={})).filterSensitiveLog=function(e){return a({},e)},(_||(_={})).filterSensitiveLog=function(e){return a({},e)},(S||(S={})).filterSensitiveLog=function(e){return a({},e)},(E||(E={})).filterSensitiveLog=function(e){return a({},e)},(M||(M={})).filterSensitiveLog=function(e){return a({},e)},(A||(A={})).filterSensitiveLog=function(e){return a({},e)},(I||(I={})).filterSensitiveLog=function(e){return a({},e)},(k||(k={})).filterSensitiveLog=function(e){return a({},e)},(O||(O={})).filterSensitiveLog=function(e){return a({},e)},(x||(x={})).filterSensitiveLog=function(e){return a({},e)},(C||(C={})).filterSensitiveLog=function(e){return a({},e)},(T||(T={})).filterSensitiveLog=function(e){return a({},e)},(P||(P={})).filterSensitiveLog=function(e){return a({},e)},function(e){e.NONE="NONE",e.SNAPPY="SNAPPY",e.ZLIB="ZLIB"}(N||(N={})),function(e){e.V0_11="V0_11",e.V0_12="V0_12"}(R||(R={})),(L||(L={})).filterSensitiveLog=function(e){return a({},e)},function(e){e.GZIP="GZIP",e.SNAPPY="SNAPPY",e.UNCOMPRESSED="UNCOMPRESSED"}(j||(j={})),function(e){e.V1="V1",e.V2="V2"}(D||(D={})),(U||(U={})).filterSensitiveLog=function(e){return a({},e)},(B||(B={})).filterSensitiveLog=function(e){return a({},e)},(F||(F={})).filterSensitiveLog=function(e){return a({},e)},(z||(z={})).filterSensitiveLog=function(e){return a({},e)},(q||(q={})).filterSensitiveLog=function(e){return a({},e)},(K||(K={})).filterSensitiveLog=function(e){return a({},e)},(H||(H={})).filterSensitiveLog=function(e){return a({},e)},(V||(V={})).filterSensitiveLog=function(e){return a(a(a({},e),e.Url&&{Url:rt.d}),e.AccessKey&&{AccessKey:rt.d})},(G||(G={})).filterSensitiveLog=function(e){return a(a(a({},e),e.AttributeName&&{AttributeName:rt.d}),e.AttributeValue&&{AttributeValue:rt.d})},(W||(W={})).filterSensitiveLog=function(e){return a(a({},e),e.CommonAttributes&&{CommonAttributes:e.CommonAttributes.map((function(e){return G.filterSensitiveLog(e)}))})},($||($={})).filterSensitiveLog=function(e){return a({},e)},(Y||(Y={})).filterSensitiveLog=function(e){return a(a(a({},e),e.RequestConfiguration&&{RequestConfiguration:W.filterSensitiveLog(e.RequestConfiguration)}),e.EndpointConfiguration&&{EndpointConfiguration:V.filterSensitiveLog(e.EndpointConfiguration)})},(J||(J={})).filterSensitiveLog=function(e){return a({},e)},(Z||(Z={})).filterSensitiveLog=function(e){return a({},e)},(X||(X={})).filterSensitiveLog=function(e){return a(a(a({},e),e.Password&&{Password:rt.d}),e.Username&&{Username:rt.d})},(Q||(Q={})).filterSensitiveLog=function(e){return a({},e)},(ee||(ee={})).filterSensitiveLog=function(e){return a({},e)},(te||(te={})).filterSensitiveLog=function(e){return a({},e)},(ne||(ne={})).filterSensitiveLog=function(e){return a(a(a({},e),e.HttpEndpointDestinationConfiguration&&{HttpEndpointDestinationConfiguration:Y.filterSensitiveLog(e.HttpEndpointDestinationConfiguration)}),e.RedshiftDestinationConfiguration&&{RedshiftDestinationConfiguration:X.filterSensitiveLog(e.RedshiftDestinationConfiguration)})},(re||(re={})).filterSensitiveLog=function(e){return a({},e)},(ie||(ie={})).filterSensitiveLog=function(e){return a({},e)},(oe||(oe={})).filterSensitiveLog=function(e){return a({},e)},(se||(se={})).filterSensitiveLog=function(e){return a({},e)},(ae||(ae={})).filterSensitiveLog=function(e){return a({},e)},(ue||(ue={})).filterSensitiveLog=function(e){return a({},e)},(ce||(ce={})).filterSensitiveLog=function(e){return a({},e)},(fe||(fe={})).filterSensitiveLog=function(e){return a({},e)},function(e){e.CREATE_ENI_FAILED="CREATE_ENI_FAILED",e.CREATE_KMS_GRANT_FAILED="CREATE_KMS_GRANT_FAILED",e.DELETE_ENI_FAILED="DELETE_ENI_FAILED",e.DISABLED_KMS_KEY="DISABLED_KMS_KEY",e.ENI_ACCESS_DENIED="ENI_ACCESS_DENIED",e.INVALID_KMS_KEY="INVALID_KMS_KEY",e.KMS_ACCESS_DENIED="KMS_ACCESS_DENIED",e.KMS_KEY_NOT_FOUND="KMS_KEY_NOT_FOUND",e.KMS_OPT_IN_REQUIRED="KMS_OPT_IN_REQUIRED",e.RETIRE_KMS_GRANT_FAILED="RETIRE_KMS_GRANT_FAILED",e.SECURITY_GROUP_ACCESS_DENIED="SECURITY_GROUP_ACCESS_DENIED",e.SECURITY_GROUP_NOT_FOUND="SECURITY_GROUP_NOT_FOUND",e.SUBNET_ACCESS_DENIED="SUBNET_ACCESS_DENIED",e.SUBNET_NOT_FOUND="SUBNET_NOT_FOUND",e.UNKNOWN_ERROR="UNKNOWN_ERROR"}(le||(le={})),(de||(de={})).filterSensitiveLog=function(e){return a({},e)},function(e){e.DISABLED="DISABLED",e.DISABLING="DISABLING",e.DISABLING_FAILED="DISABLING_FAILED",e.ENABLED="ENABLED",e.ENABLING="ENABLING",e.ENABLING_FAILED="ENABLING_FAILED"}(he||(he={})),(pe||(pe={})).filterSensitiveLog=function(e){return a({},e)},function(e){e.ACTIVE="ACTIVE",e.CREATING="CREATING",e.CREATING_FAILED="CREATING_FAILED",e.DELETING="DELETING",e.DELETING_FAILED="DELETING_FAILED"}(ve||(ve={})),(ge||(ge={})).filterSensitiveLog=function(e){return a({},e)},(me||(me={})).filterSensitiveLog=function(e){return a({},e)},(be||(be={})).filterSensitiveLog=function(e){return a({},e)},(ye||(ye={})).filterSensitiveLog=function(e){return a({},e)},(we||(we={})).filterSensitiveLog=function(e){return a(a({},e),e.Url&&{Url:rt.d})},(_e||(_e={})).filterSensitiveLog=function(e){return a(a(a({},e),e.EndpointConfiguration&&{EndpointConfiguration:we.filterSensitiveLog(e.EndpointConfiguration)}),e.RequestConfiguration&&{RequestConfiguration:W.filterSensitiveLog(e.RequestConfiguration)})},(Se||(Se={})).filterSensitiveLog=function(e){return a(a({},e),e.Username&&{Username:rt.d})},(Ee||(Ee={})).filterSensitiveLog=function(e){return a({},e)},(Me||(Me={})).filterSensitiveLog=function(e){return a(a(a({},e),e.HttpEndpointDestinationDescription&&{HttpEndpointDestinationDescription:_e.filterSensitiveLog(e.HttpEndpointDestinationDescription)}),e.RedshiftDestinationDescription&&{RedshiftDestinationDescription:Se.filterSensitiveLog(e.RedshiftDestinationDescription)})},(Ae||(Ae={})).filterSensitiveLog=function(e){return a({},e)},(Ie||(Ie={})).filterSensitiveLog=function(e){return a({},e)},(ke||(ke={})).filterSensitiveLog=function(e){return a(a({},e),e.Destinations&&{Destinations:e.Destinations.map((function(e){return Me.filterSensitiveLog(e)}))})},(Oe||(Oe={})).filterSensitiveLog=function(e){return a({},e)},(xe||(xe={})).filterSensitiveLog=function(e){return a(a({},e),e.DeliveryStreamDescription&&{DeliveryStreamDescription:ke.filterSensitiveLog(e.DeliveryStreamDescription)})},(Ce||(Ce={})).filterSensitiveLog=function(e){return a({},e)},(Te||(Te={})).filterSensitiveLog=function(e){return a({},e)},(Pe||(Pe={})).filterSensitiveLog=function(e){return a({},e)},(Ne||(Ne={})).filterSensitiveLog=function(e){return a({},e)},(Re||(Re={})).filterSensitiveLog=function(e){return a({},e)},(Le||(Le={})).filterSensitiveLog=function(e){return a({},e)},(je||(je={})).filterSensitiveLog=function(e){return a({},e)},(De||(De={})).filterSensitiveLog=function(e){return a({},e)},(Ue||(Ue={})).filterSensitiveLog=function(e){return a({},e)},(Be||(Be={})).filterSensitiveLog=function(e){return a({},e)},(Fe||(Fe={})).filterSensitiveLog=function(e){return a({},e)},(ze||(ze={})).filterSensitiveLog=function(e){return a({},e)},(qe||(qe={})).filterSensitiveLog=function(e){return a({},e)},(Ke||(Ke={})).filterSensitiveLog=function(e){return a({},e)},(He||(He={})).filterSensitiveLog=function(e){return a({},e)},(Ve||(Ve={})).filterSensitiveLog=function(e){return a({},e)},(Ge||(Ge={})).filterSensitiveLog=function(e){return a({},e)},(We||(We={})).filterSensitiveLog=function(e){return a({},e)},($e||($e={})).filterSensitiveLog=function(e){return a({},e)},(Ye||(Ye={})).filterSensitiveLog=function(e){return a({},e)},(Je||(Je={})).filterSensitiveLog=function(e){return a({},e)},(Ze||(Ze={})).filterSensitiveLog=function(e){return a({},e)},(Xe||(Xe={})).filterSensitiveLog=function(e){return a(a(a({},e),e.EndpointConfiguration&&{EndpointConfiguration:V.filterSensitiveLog(e.EndpointConfiguration)}),e.RequestConfiguration&&{RequestConfiguration:W.filterSensitiveLog(e.RequestConfiguration)})},(Qe||(Qe={})).filterSensitiveLog=function(e){return a(a(a({},e),e.Username&&{Username:rt.d}),e.Password&&{Password:rt.d})},(et||(et={})).filterSensitiveLog=function(e){return a({},e)},(tt||(tt={})).filterSensitiveLog=function(e){return a(a(a({},e),e.HttpEndpointDestinationUpdate&&{HttpEndpointDestinationUpdate:Xe.filterSensitiveLog(e.HttpEndpointDestinationUpdate)}),e.RedshiftDestinationUpdate&&{RedshiftDestinationUpdate:Qe.filterSensitiveLog(e.RedshiftDestinationUpdate)})},(nt||(nt={})).filterSensitiveLog=function(e){return a({},e)};var it,ot=n(2),st=function(e,t){return u(void 0,void 0,void 0,(function(){var n,r,i,o,s,u,f,l,d,h,p,v;return c(this,(function(c){switch(c.label){case 0:return r=[a({},e)],v={},[4,Et(e.body,t)];case 1:switch(n=a.apply(void 0,r.concat([(v.body=c.sent(),v)])),o="UnknownError",s=n.body.__type.split("#"),o=void 0===s[1]?s[0]:s[1],o){case"InvalidArgumentException":case"com.amazonaws.firehose#InvalidArgumentException":return[3,2];case"InvalidKMSResourceException":case"com.amazonaws.firehose#InvalidKMSResourceException":return[3,4];case"ResourceNotFoundException":case"com.amazonaws.firehose#ResourceNotFoundException":return[3,6];case"ServiceUnavailableException":case"com.amazonaws.firehose#ServiceUnavailableException":return[3,8]}return[3,10];case 2:return u=[{}],[4,at(n,t)];case 3:return i=a.apply(void 0,[a.apply(void 0,u.concat([c.sent()])),{name:o,$metadata:wt(e)}]),[3,11];case 4:return f=[{}],[4,ut(n,t)];case 5:return i=a.apply(void 0,[a.apply(void 0,f.concat([c.sent()])),{name:o,$metadata:wt(e)}]),[3,11];case 6:return l=[{}],[4,ct(n,t)];case 7:return i=a.apply(void 0,[a.apply(void 0,l.concat([c.sent()])),{name:o,$metadata:wt(e)}]),[3,11];case 8:return d=[{}],[4,ft(n,t)];case 9:return i=a.apply(void 0,[a.apply(void 0,d.concat([c.sent()])),{name:o,$metadata:wt(e)}]),[3,11];case 10:h=n.body,o=h.code||h.Code||o,i=a(a({},h),{name:""+o,message:h.message||h.Message||o,$fault:"client",$metadata:wt(e)}),c.label=11;case 11:return p=i.message||i.Message||o,i.message=p,delete i.Message,[2,Promise.reject(Object.assign(new Error(p),i))]}}))}))},at=function(e,t){return u(void 0,void 0,void 0,(function(){var n,r;return c(this,(function(i){return n=e.body,r=pt(n,t),[2,a({name:"InvalidArgumentException",$fault:"client",$metadata:wt(e)},r)]}))}))},ut=function(e,t){return u(void 0,void 0,void 0,(function(){var n,r;return c(this,(function(i){return n=e.body,r=vt(n,t),[2,a({name:"InvalidKMSResourceException",$fault:"client",$metadata:wt(e)},r)]}))}))},ct=function(e,t){return u(void 0,void 0,void 0,(function(){var n,r;return c(this,(function(i){return n=e.body,r=bt(n,t),[2,a({name:"ResourceNotFoundException",$fault:"client",$metadata:wt(e)},r)]}))}))},ft=function(e,t){return u(void 0,void 0,void 0,(function(){var n,r;return c(this,(function(i){return n=e.body,r=yt(n,t),[2,a({name:"ServiceUnavailableException",$fault:"server",$metadata:wt(e)},r)]}))}))},lt=function(e,t){return a(a({},void 0!==e.DeliveryStreamName&&{DeliveryStreamName:e.DeliveryStreamName}),void 0!==e.Records&&{Records:dt(e.Records,t)})},dt=function(e,t){return e.map((function(e){return ht(e,t)}))},ht=function(e,t){return a({},void 0!==e.Data&&{Data:t.base64Encoder(e.Data)})},pt=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},vt=function(e,t){return{code:void 0!==e.code&&null!==e.code?e.code:void 0,message:void 0!==e.message&&null!==e.message?e.message:void 0}},gt=function(e,t){return{Encrypted:void 0!==e.Encrypted&&null!==e.Encrypted?e.Encrypted:void 0,FailedPutCount:void 0!==e.FailedPutCount&&null!==e.FailedPutCount?e.FailedPutCount:void 0,RequestResponses:void 0!==e.RequestResponses&&null!==e.RequestResponses?mt(e.RequestResponses,t):void 0}},mt=function(e,t){return(e||[]).map((function(e){return function(e,t){return{ErrorCode:void 0!==e.ErrorCode&&null!==e.ErrorCode?e.ErrorCode:void 0,ErrorMessage:void 0!==e.ErrorMessage&&null!==e.ErrorMessage?e.ErrorMessage:void 0,RecordId:void 0!==e.RecordId&&null!==e.RecordId?e.RecordId:void 0}}(e)}))},bt=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},yt=function(e,t){return{message:void 0!==e.message&&null!==e.message?e.message:void 0}},wt=function(e){return{httpStatusCode:e.statusCode,httpHeaders:e.headers,requestId:e.headers["x-amzn-requestid"]}},_t=function(e,t){return function(e,t){return void 0===e&&(e=new Uint8Array),e instanceof Uint8Array?Promise.resolve(e):t.streamCollector(e)||Promise.resolve(new Uint8Array)}(e,t).then((function(e){return t.utf8Encoder(e)}))},St=function(e,t,n,r,i){return u(void 0,void 0,void 0,(function(){var o,s,a,u,f,l;return c(this,(function(c){switch(c.label){case 0:return[4,e.endpoint()];case 1:return o=c.sent(),s=o.hostname,a=o.protocol,u=void 0===a?"https":a,f=o.port,l={protocol:u,hostname:s,port:f,method:"POST",path:n,headers:t},void 0!==r&&(l.hostname=r),void 0!==i&&(l.body=i),[2,new ot.a(l)]}}))}))},Et=function(e,t){return _t(e,t).then((function(e){return e.length?JSON.parse(e):{}}))},Mt=n(10),At=function(e){function t(t){var n=e.call(this)||this;return n.input=t,n}return s(t,e),t.prototype.resolveMiddleware=function(e,t,n){this.middlewareStack.use(Object(Mt.a)(t,this.serialize,this.deserialize));var r=e.concat(this.middlewareStack),i=t.logger,o={logger:i,clientName:"FirehoseClient",commandName:"PutRecordBatchCommand",inputFilterSensitiveLog:ze.filterSensitiveLog,outputFilterSensitiveLog:Ke.filterSensitiveLog};"function"==typeof i.info&&i.info({clientName:"FirehoseClient",commandName:"PutRecordBatchCommand"});var s=t.requestHandler;return r.resolve((function(e){return s.handle(e.request,n||{})}),o)},t.prototype.serialize=function(e,t){return function(e,t){return u(void 0,void 0,void 0,(function(){var n,r;return c(this,(function(i){return n={"Content-Type":"application/x-amz-json-1.1","X-Amz-Target":"Firehose_20150804.PutRecordBatch"},r=JSON.stringify(lt(e,t)),[2,St(t,n,"/",void 0,r)]}))}))}(e,t)},t.prototype.deserialize=function(e,t){return function(e,t){return u(void 0,void 0,void 0,(function(){var n,r,i;return c(this,(function(o){switch(o.label){case 0:return e.statusCode>=300?[2,st(e,t)]:[4,Et(e.body,t)];case 1:return n=o.sent(),{},r=gt(n,t),i=a({$metadata:wt(e)},r),[2,Promise.resolve(i)]}}))}))}(e,t)},t}(rt.b),It=n(151),kt=n(38),Ot=n(18),xt=n(24),Ct=n(11),Tt=n(39),Pt=n(17),Nt=n(40),Rt=n(41),Lt=n(15),jt=new Set(["ap-east-1","ap-northeast-1","ap-northeast-2","ap-south-1","ap-southeast-1","ap-southeast-2","ca-central-1","eu-central-1","eu-north-1","eu-west-1","eu-west-2","eu-west-3","me-south-1","sa-east-1","us-east-1","us-east-2","us-west-1","us-west-2"]),Dt=new Set(["cn-north-1","cn-northwest-1"]),Ut=new Set(["us-iso-east-1"]),Bt=new Set(["us-isob-east-1"]),Ft=new Set(["us-gov-east-1","us-gov-west-1"]),zt=a(a({},{apiVersion:"2015-08-04",disableHostPrefix:!1,logger:{},regionInfoProvider:function(e,t){var n=void 0;switch(e){case"ap-east-1":n={hostname:"firehose.ap-east-1.amazonaws.com",partition:"aws"};break;case"ap-northeast-1":n={hostname:"firehose.ap-northeast-1.amazonaws.com",partition:"aws"};break;case"ap-northeast-2":n={hostname:"firehose.ap-northeast-2.amazonaws.com",partition:"aws"};break;case"ap-south-1":n={hostname:"firehose.ap-south-1.amazonaws.com",partition:"aws"};break;case"ap-southeast-1":n={hostname:"firehose.ap-southeast-1.amazonaws.com",partition:"aws"};break;case"ap-southeast-2":n={hostname:"firehose.ap-southeast-2.amazonaws.com",partition:"aws"};break;case"ca-central-1":n={hostname:"firehose.ca-central-1.amazonaws.com",partition:"aws"};break;case"cn-north-1":n={hostname:"firehose.cn-north-1.amazonaws.com.cn",partition:"aws-cn"};break;case"cn-northwest-1":n={hostname:"firehose.cn-northwest-1.amazonaws.com.cn",partition:"aws-cn"};break;case"eu-central-1":n={hostname:"firehose.eu-central-1.amazonaws.com",partition:"aws"};break;case"eu-north-1":n={hostname:"firehose.eu-north-1.amazonaws.com",partition:"aws"};break;case"eu-west-1":n={hostname:"firehose.eu-west-1.amazonaws.com",partition:"aws"};break;case"eu-west-2":n={hostname:"firehose.eu-west-2.amazonaws.com",partition:"aws"};break;case"eu-west-3":n={hostname:"firehose.eu-west-3.amazonaws.com",partition:"aws"};break;case"me-south-1":n={hostname:"firehose.me-south-1.amazonaws.com",partition:"aws"};break;case"sa-east-1":n={hostname:"firehose.sa-east-1.amazonaws.com",partition:"aws"};break;case"us-east-1":n={hostname:"firehose.us-east-1.amazonaws.com",partition:"aws"};break;case"us-east-2":n={hostname:"firehose.us-east-2.amazonaws.com",partition:"aws"};break;case"us-gov-east-1":n={hostname:"firehose.us-gov-east-1.amazonaws.com",partition:"aws-us-gov"};break;case"us-gov-west-1":n={hostname:"firehose.us-gov-west-1.amazonaws.com",partition:"aws-us-gov"};break;case"us-west-1":n={hostname:"firehose.us-west-1.amazonaws.com",partition:"aws"};break;case"us-west-2":n={hostname:"firehose.us-west-2.amazonaws.com",partition:"aws"};break;default:jt.has(e)&&(n={hostname:"firehose.{region}.amazonaws.com".replace("{region}",e),partition:"aws"}),Dt.has(e)&&(n={hostname:"firehose.{region}.amazonaws.com.cn".replace("{region}",e),partition:"aws-cn"}),Ut.has(e)&&(n={hostname:"firehose.{region}.c2s.ic.gov".replace("{region}",e),partition:"aws-iso"}),Bt.has(e)&&(n={hostname:"firehose.{region}.sc2s.sgov.gov".replace("{region}",e),partition:"aws-iso-b"}),Ft.has(e)&&(n={hostname:"firehose.{region}.amazonaws.com".replace("{region}",e),partition:"aws-us-gov"}),void 0===n&&(n={hostname:"firehose.{region}.amazonaws.com".replace("{region}",e),partition:"aws"})}return Promise.resolve(n)},signingName:"firehose"}),{runtime:"browser",base64Decoder:Pt.a,base64Encoder:Pt.b,bodyLengthChecker:Nt.a,credentialDefaultProvider:Object(xt.a)("Credential is missing"),defaultUserAgent:Object(Rt.a)(It.name,It.version),maxAttempts:Ct.a,region:Object(xt.a)("Region is missing"),requestHandler:new Ot.a,sha256:kt.Sha256,streamCollector:Ot.b,urlParser:Tt.a,utf8Decoder:Lt.a,utf8Encoder:Lt.b}),qt=n(22),Kt=n(37),Ht=n(21),Vt=n(43),Gt=n(25),Wt=n(23),$t=function(e){function t(t){var n=this,r=a(a({},zt),t),i=Object(qt.b)(r),o=Object(qt.a)(i),s=Object(Gt.b)(o),u=Object(Ct.c)(s),c=Object(Wt.b)(u),f=Object(Ht.b)(c);return(n=e.call(this,f)||this).config=f,n.middlewareStack.use(Object(Gt.a)(n.config)),n.middlewareStack.use(Object(Ct.b)(n.config)),n.middlewareStack.use(Object(Wt.a)(n.config)),n.middlewareStack.use(Object(Kt.a)(n.config)),n.middlewareStack.use(Object(Ht.a)(n.config)),n.middlewareStack.use(Object(Vt.a)(n.config)),n}return s(t,e),t.prototype.destroy=function(){e.prototype.destroy.call(this)},t}(rt.a),Yt=(it=function(e,t){return(it=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}it(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),Jt=new r.a("AWSKineisFirehoseProvider"),Zt=function(e){function t(t){return e.call(this,t)||this}return Yt(t,e),t.prototype.getProviderName=function(){return"AWSKinesisFirehose"},t.prototype._sendEvents=function(e){var t=this;if(0!==e.length){var n=e[0],r=n.config,i=n.credentials;if(!this._init(r,i))return!1;var o={};e.map((function(e){var t=e.event,n=t.streamName,r=t.data;void 0===o[n]&&(o[n]=[]);var i=r&&"string"!=typeof r?JSON.stringify(r):r,s={Data:Object(Lt.a)(i)};o[n].push(s)})),Object.keys(o).map((function(e){Jt.debug("putting records to kinesis",e,"with records",o[e]),t._kinesisFirehose.send(new At({Records:o[e],DeliveryStreamName:e})).then((function(t){return Jt.debug("Upload records to stream",e)})).catch((function(e){return Jt.debug("Failed to upload records to Kinesis",e)}))}))}},t.prototype._init=function(e,t){if(Jt.debug("init clients"),this._kinesisFirehose&&this._config.credentials&&this._config.credentials.sessionToken===t.sessionToken&&this._config.credentials.identityId===t.identityId)return Jt.debug("no change for analytics config, directly return from init"),!0;this._config.credentials=t;var n=e.region;return this._initFirehose(n,t)},t.prototype._initFirehose=function(e,t){return Jt.debug("initialize kinesis firehose with credentials",t),this._kinesisFirehose=new $t({apiVersion:"2015-08-04",region:e,credentials:t}),!0},t}(i.a)},function(e,t,n){"use strict";n.d(t,"a",(function(){return T}));var r,i=n(44),o=n(19),s=n(5),a=n(89),u=n(104),c=function(){return(c=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},f=new i.a("AbstractXRProvider"),l=function(){function e(e){void 0===e&&(e={}),this._config=e}return e.prototype.configure=function(e){return void 0===e&&(e={}),this._config=c(c({},e),this._config),f.debug("configure "+this.getProviderName(),this._config),this.options},e.prototype.getCategory=function(){return"XR"},Object.defineProperty(e.prototype,"options",{get:function(){return c({},this._config)},enumerable:!0,configurable:!0}),e}(),d=(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),h=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return d(t,e),t}(Error),p=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return d(t,e),t}(h),v=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return d(t,e),t}(h),g=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return d(t,e),t}(h),m=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return d(t,e),t}(h),b=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return d(t,e),t}(h),y=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return d(t,e),t}(h),w=function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),_=function(){return(_=Object.assign||function(e){for(var t,n=1,r=arguments.length;n<r;n++)for(var i in t=arguments[n])Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i]);return e}).apply(this,arguments)},S=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},E=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},M=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},A=new i.a("SumerianProvider"),I=function(e){function t(t){return void 0===t&&(t={}),e.call(this,t)||this}return w(t,e),t.prototype.getProviderName=function(){return"SumerianProvider"},t.prototype.loadScript=function(e){return S(this,void 0,void 0,(function(){return E(this,(function(t){return[2,new Promise((function(t,n){var r=document.createElement("script");r.src=e,r.addEventListener("load",(function(e){t()})),r.addEventListener("error",(function(t){n(new Error("Failed to load script: "+e))})),document.head.appendChild(r)}))]}))}))},t.prototype.loadScene=function(e,t,n){return S(this,void 0,void 0,(function(){var r,i,o,c,f,l,d,h,p,v,g,y,w,S,I,k,O,x,C,T,P,N,R,L,j,D,U;return E(this,(function(E){switch(E.label){case 0:if(!e)throw l="No scene name passed into loadScene",A.error(l),new b(l);if(!t)throw l="No dom element id passed into loadScene",A.error(l),new m(l);if(!(r=document.getElementById(t)))throw l="DOM element id, "+t+" not found",A.error(l),new m(l);if(!(i=this.getScene(e)).sceneConfig)throw l="No scene config configured for scene: "+e,A.error(l),new b(l);if(o=i.sceneConfig.url,c=i.sceneConfig.sceneId,i.sceneConfig.hasOwnProperty("region"))f=i.sceneConfig.region;else{if(!this.options.hasOwnProperty("region"))throw l="No region configured for scene: "+e,A.error(l),new b(l);f=this.options.region}d={region:f,customUserAgent:s.a.userAgent+"-SumerianScene"},h={headers:{"X-Amz-User-Agent":s.a.userAgent}},p=o,E.label=1;case 1:return E.trys.push([1,3,,4]),[4,a.a.get()];case 2:return v=E.sent(),d.credentials=v,g={secret_key:v.secretAccessKey,access_key:v.accessKeyId,session_token:v.sessionToken},y={region:f,service:"sumerian"},w=u.a.sign({method:"GET",url:o},g,y),h.headers=_(_({},h.headers),w.headers),p=w.url,[3,4];case 3:return E.sent(),A.debug("No credentials available, the request will be unsigned"),[3,4];case 4:return[4,fetch(p,h)];case 5:return[4,(S=E.sent()).json()];case 6:if(I=E.sent(),403===S.status)throw I.message?(A.error("Failure to authenticate user: "+I.message),new b("Failure to authenticate user: "+I.message)):(A.error("Failure to authenticate user"),new b("Failure to authenticate user"));return k=I.bundleData[c],[4,fetch(k.url,{headers:k.headers})];case 7:return[4,E.sent().json()];case 8:O=E.sent(),E.label=9;case 9:return E.trys.push([9,11,,12]),[4,this.loadScript(O[c].bootstrapperUrl)];case 10:return E.sent(),[3,12];case 11:throw x=E.sent(),A.error(x),new b(x);case 12:return C=n.progressCallback?n.progressCallback:void 0,T=i.publishParamOverrides?i.publishParamOverrides:void 0,P={element:r,sceneId:c,sceneBundle:O,apiResponse:I,progressCallback:C,publishParamOverrides:T,awsSDKConfigOverride:d},[4,window.SumerianBootstrapper.loadScene(P)];case 13:N=E.sent(),i.sceneController=N,i.isLoaded=!0;try{for(R=M(N.sceneLoadWarnings),L=R.next();!L.done;L=R.next())j=L.value,A.warn("loadScene warning: "+j)}catch(e){D={error:e}}finally{try{L&&!L.done&&(U=R.return)&&U.call(R)}finally{if(D)throw D.error}}return[2]}}))}))},t.prototype.isSceneLoaded=function(e){return this.getScene(e).isLoaded||!1},t.prototype.getScene=function(e){if(!this.options.scenes){var t="No scenes were defined in the configuration";throw A.error(t),new p(t)}if(!e){t="No scene name was passed";throw A.error(t),new v(t)}if(!this.options.scenes[e]){t="Scene '"+e+"' is not configured";throw A.error(t),new v(t)}return this.options.scenes[e]},t.prototype.getSceneController=function(e){if(!this.options.scenes){var t="No scenes were defined in the configuration";throw A.error(t),new p(t)}var n=this.options.scenes[e];if(!n){t="Scene '"+e+"' is not configured";throw A.error(t),new v(t)}var r=n.sceneController;if(!r){t="Scene controller for '"+e+"' has not been loaded";throw A.error(t),new g(t)}return r},t.prototype.isVRCapable=function(e){return this.getSceneController(e).vrCapable},t.prototype.isVRPresentationActive=function(e){return this.getSceneController(e).vrPresentationActive},t.prototype.start=function(e){this.getSceneController(e).start()},t.prototype.enterVR=function(e){this.getSceneController(e).enterVR()},t.prototype.exitVR=function(e){this.getSceneController(e).exitVR()},t.prototype.isMuted=function(e){return this.getSceneController(e).muted},t.prototype.setMuted=function(e,t){this.getSceneController(e).muted=t},t.prototype.onSceneEvent=function(e,t,n){this.getSceneController(e).on(t,n)},t.prototype.enableAudio=function(e){this.getSceneController(e).enableAudio()},t}(l),k=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},O=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},x=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},C=new i.a("XR"),T=new(function(){function e(e){this._options=e,C.debug("XR Options",this._options),this._defaultProvider="SumerianProvider",this._pluggables={},this.addPluggable(new I)}return e.prototype.configure=function(e){var t=this,n=e?e.XR||e:{};return C.debug("configure XR",{opt:n}),this._options=Object.assign({},this._options,n),Object.entries(this._pluggables).map((function(e){var r=x(e,2),i=r[0],o=r[1];i!==t._defaultProvider||n[t._defaultProvider]?o.configure(t._options[i]):o.configure(t._options)})),this._options},e.prototype.addPluggable=function(e){return k(this,void 0,void 0,(function(){return O(this,(function(t){return e&&"XR"===e.getCategory()?(this._pluggables[e.getProviderName()]=e,[2,e.configure(this._options)]):[2]}))}))},e.prototype.loadScene=function(e,t,n,r){return void 0===n&&(n={}),void 0===r&&(r=this._defaultProvider),k(this,void 0,void 0,(function(){return O(this,(function(i){switch(i.label){case 0:if(!this._pluggables[r])throw new y("Provider '"+r+"' not configured");return[4,this._pluggables[r].loadScene(e,t,n)];case 1:return[2,i.sent()]}}))}))},e.prototype.isSceneLoaded=function(e,t){if(void 0===t&&(t=this._defaultProvider),!this._pluggables[t])throw new y("Provider '"+t+"' not configured");return this._pluggables[t].isSceneLoaded(e)},e.prototype.getSceneController=function(e,t){if(void 0===t&&(t=this._defaultProvider),!this._pluggables[t])throw new y("Provider '"+t+"' not configured");return this._pluggables[t].getSceneController(e)},e.prototype.isVRCapable=function(e,t){if(void 0===t&&(t=this._defaultProvider),!this._pluggables[t])throw new y("Provider '"+t+"' not configured");return this._pluggables[t].isVRCapable(e)},e.prototype.isVRPresentationActive=function(e,t){if(void 0===t&&(t=this._defaultProvider),!this._pluggables[t])throw new y("Provider '"+t+"' not configured");return this._pluggables[t].isVRPresentationActive(e)},e.prototype.start=function(e,t){if(void 0===t&&(t=this._defaultProvider),!this._pluggables[t])throw new y("Provider '"+t+"' not configured");return this._pluggables[t].start(e)},e.prototype.enterVR=function(e,t){if(void 0===t&&(t=this._defaultProvider),!this._pluggables[t])throw new y("Provider '"+t+"' not configured");return this._pluggables[t].enterVR(e)},e.prototype.exitVR=function(e,t){if(void 0===t&&(t=this._defaultProvider),!this._pluggables[t])throw new y("Provider '"+t+"' not configured");return this._pluggables[t].exitVR(e)},e.prototype.isMuted=function(e,t){if(void 0===t&&(t=this._defaultProvider),!this._pluggables[t])throw new y("Provider '"+t+"' not configured");return this._pluggables[t].isMuted(e)},e.prototype.setMuted=function(e,t,n){if(void 0===n&&(n=this._defaultProvider),!this._pluggables[n])throw new y("Provider '"+n+"' not configured");return this._pluggables[n].setMuted(e,t)},e.prototype.onSceneEvent=function(e,t,n,r){if(void 0===r&&(r=this._defaultProvider),!this._pluggables[r])throw new y("Provider '"+r+"' not configured");return this._pluggables[r].onSceneEvent(e,t,n)},e.prototype.enableAudio=function(e,t){if(void 0===t&&(t=this._defaultProvider),!this._pluggables[t])throw new y("Provider '"+t+"' not configured");return this._pluggables[t].enableAudio(e)},e}())(null);o.a.register(T)},function(e,t,n){"use strict";n.r(t),n.d(t,"fromUtf8",(function(){return r})),n.d(t,"toUtf8",(function(){return i}));var r=function(e){return"function"==typeof TextEncoder?function(e){return(new TextEncoder).encode(e)}(e):function(e){for(var t=[],n=0,r=e.length;n<r;n++){var i=e.charCodeAt(n);if(i<128)t.push(i);else if(i<2048)t.push(i>>6|192,63&i|128);else if(n+1<e.length&&55296==(64512&i)&&56320==(64512&e.charCodeAt(n+1))){var o=65536+((1023&i)<<10)+(1023&e.charCodeAt(++n));t.push(o>>18|240,o>>12&63|128,o>>6&63|128,63&o|128)}else t.push(i>>12|224,i>>6&63|128,63&i|128)}return Uint8Array.from(t)}(e)},i=function(e){return"function"==typeof TextDecoder?function(e){return new TextDecoder("utf-8").decode(e)}(e):function(e){for(var t="",n=0,r=e.length;n<r;n++){var i=e[n];if(i<128)t+=String.fromCharCode(i);else if(192<=i&&i<224){var o=e[++n];t+=String.fromCharCode((31&i)<<6|63&o)}else if(240<=i&&i<365){var s="%"+[i,e[++n],e[++n],e[++n]].map((function(e){return e.toString(16)})).join("%");t+=decodeURIComponent(s)}else t+=String.fromCharCode((15&i)<<12|(63&e[++n])<<6|63&e[++n])}return t}(e)}},function(e,t,n){"use strict";n.r(t);var r=n(44);let i,o;const s=new WeakMap,a=new WeakMap,u=new WeakMap,c=new WeakMap,f=new WeakMap;let l={get(e,t,n){if(e instanceof IDBTransaction){if("done"===t)return a.get(e);if("objectStoreNames"===t)return e.objectStoreNames||u.get(e);if("store"===t)return n.objectStoreNames[1]?void 0:n.objectStore(n.objectStoreNames[0])}return p(e[t])},set:(e,t,n)=>(e[t]=n,!0),has:(e,t)=>e instanceof IDBTransaction&&("done"===t||"store"===t)||t in e};function d(e){return e!==IDBDatabase.prototype.transaction||"objectStoreNames"in IDBTransaction.prototype?(o||(o=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])).includes(e)?function(...t){return e.apply(v(this),t),p(s.get(this))}:function(...t){return p(e.apply(v(this),t))}:function(t,...n){const r=e.call(v(this),t,...n);return u.set(r,t.sort?t.sort():[t]),p(r)}}function h(e){return"function"==typeof e?d(e):(e instanceof IDBTransaction&&function(e){if(a.has(e))return;const t=new Promise((t,n)=>{const r=()=>{e.removeEventListener("complete",i),e.removeEventListener("error",o),e.removeEventListener("abort",o)},i=()=>{t(),r()},o=()=>{n(e.error||new DOMException("AbortError","AbortError")),r()};e.addEventListener("complete",i),e.addEventListener("error",o),e.addEventListener("abort",o)});a.set(e,t)}(e),t=e,(i||(i=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])).some(e=>t instanceof e)?new Proxy(e,l):e);var t}function p(e){if(e instanceof IDBRequest)return function(e){const t=new Promise((t,n)=>{const r=()=>{e.removeEventListener("success",i),e.removeEventListener("error",o)},i=()=>{t(p(e.result)),r()},o=()=>{n(e.error),r()};e.addEventListener("success",i),e.addEventListener("error",o)});return t.then(t=>{t instanceof IDBCursor&&s.set(t,e)}).catch(()=>{}),f.set(t,e),t}(e);if(c.has(e))return c.get(e);const t=h(e);return t!==e&&(c.set(e,t),f.set(t,e)),t}const v=e=>f.get(e);function g(e,t,{blocked:n,upgrade:r,blocking:i,terminated:o}={}){const s=indexedDB.open(e,t),a=p(s);return r&&s.addEventListener("upgradeneeded",e=>{r(p(s.result),e.oldVersion,e.newVersion,p(s.transaction))}),n&&s.addEventListener("blocked",()=>n()),a.then(e=>{o&&e.addEventListener("close",()=>o()),i&&e.addEventListener("versionchange",()=>i())}).catch(()=>{}),a}function m(e,{blocked:t}={}){const n=indexedDB.deleteDatabase(e);return t&&n.addEventListener("blocked",()=>t()),p(n).then(()=>{})}const b=["get","getKey","getAll","getAllKeys","count"],y=["put","add","delete","clear"],w=new Map;function _(e,t){if(!(e instanceof IDBDatabase)||t in e||"string"!=typeof t)return;if(w.get(t))return w.get(t);const n=t.replace(/FromIndex$/,""),r=t!==n,i=y.includes(n);if(!(n in(r?IDBIndex:IDBObjectStore).prototype)||!i&&!b.includes(n))return;const o=async function(e,...t){const o=this.transaction(e,i?"readwrite":"readonly");let s=o.store;r&&(s=s.index(t.shift()));const a=await s[n](...t);return i&&await o.done,a};return w.set(t,o),o}l=(e=>({...e,get:(t,n,r)=>_(t,n)||e.get(t,n,r),has:(t,n)=>!!_(t,n)||e.has(t,n)}))(l);var S=n(9),E=n(245),M=n(4),A=n(3);function I(e){return(I="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var k=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},O=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},x=function(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e="function"==typeof C?C(e):e[Symbol.iterator](),t={},r("next"),r("throw"),r("return"),t[Symbol.asyncIterator]=function(){return this},t);function r(n){t[n]=e[n]&&function(t){return new Promise((function(r,i){(function(e,t,n,r){Promise.resolve(r).then((function(t){e({value:t,done:n})}),t)})(r,i,(t=e[n](t)).done,t.value)}))}}},C=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},T=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},P=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(T(arguments[t]));return e},N=new r.a("DataStore"),R=function(){function e(){this.dbName="amplify-datastore"}return e.prototype.checkPrivate=function(){return k(this,void 0,void 0,(function(){return O(this,(function(e){switch(e.label){case 0:return[4,Object(A.u)().then((function(e){return e}))];case 1:return e.sent()?(N.error("IndexedDB not supported in this browser's private mode"),[2,Promise.reject("IndexedDB not supported in this browser's private mode")]):[2,Promise.resolve()]}}))}))},e.prototype.getStorenameForModel=function(e){var t=this.namespaceResolver(e),n=e.name;return this.getStorename(t,n)},e.prototype.getStorename=function(e,t){return e+"_"+t},e.prototype.setUp=function(e,t,n,r,i){return k(this,void 0,void 0,(function(){var o,s,a=this;return O(this,(function(u){switch(u.label){case 0:return[4,this.checkPrivate()];case 1:return u.sent(),this.initPromise?[3,2]:(this.initPromise=new Promise((function(e,t){a.resolve=e,a.reject=t})),[3,4]);case 2:return[4,this.initPromise];case 3:u.sent(),u.label=4;case 4:i&&(this.dbName="amplify-datastore-"+i),this.schema=e,this.namespaceResolver=t,this.modelInstanceCreator=n,this.getModelConstructorByModelName=r,u.label=5;case 5:return u.trys.push([5,8,,9]),this.db?[3,7]:(2,o=this,[4,g(this.dbName,2,{upgrade:function(t,n,r,i){return k(a,void 0,void 0,(function(){var o,s,a,u,c,f,l,d,h,p,v,g,m=this;return O(this,(function(b){switch(b.label){case 0:if(0===n)return Object.keys(e.namespaces).forEach((function(n){var r=e.namespaces[n];Object.keys(r.models).forEach((function(e){var r=m.getStorename(n,e),i=t.createObjectStore(r,{autoIncrement:!0});m.schema.namespaces[n].relationships[e].indexes.forEach((function(e){return i.createIndex(e,e)})),i.createIndex("byId","id",{unique:!0})}))})),[2];if(1!==n||2!==r)return[3,16];b.label=1;case 1:b.trys.push([1,14,,15]),b.label=2;case 2:b.trys.push([2,11,12,13]),o=C(i.objectStoreNames),s=o.next(),b.label=3;case 3:return s.done?[3,10]:(a=s.value,u=i.objectStore(a),c="tmp_"+a,u.name=c,(f=t.createObjectStore(a,{keyPath:void 0,autoIncrement:!0})).createIndex("byId","id",{unique:!0}),[4,u.openCursor()]);case 4:l=b.sent(),d=0,b.label=5;case 5:return l&&l.value?[4,f.put(l.value)]:[3,8];case 6:return b.sent(),[4,l.continue()];case 7:return l=b.sent(),d++,[3,5];case 8:t.deleteObjectStore(c),N.debug(d+" "+a+" records migrated"),b.label=9;case 9:return s=o.next(),[3,3];case 10:return[3,13];case 11:return h=b.sent(),v={error:h},[3,13];case 12:try{s&&!s.done&&(g=o.return)&&g.call(o)}finally{if(v)throw v.error}return[7];case 13:return[3,15];case 14:throw p=b.sent(),N.error("Error migrating IndexedDB data",p),i.abort(),p;case 15:case 16:return[2]}}))}))}})]);case 6:o.db=u.sent(),this.resolve(),u.label=7;case 7:return[3,9];case 8:return s=u.sent(),this.reject(s),[3,9];case 9:return[2]}}))}))},e.prototype._get=function(e,t){return k(this,void 0,void 0,(function(){var n,r;return O(this,(function(i){switch(i.label){case 0:return"string"==typeof e?(r=e,n=this.db.transaction(r,"readonly").store.index("byId")):n=e.index("byId"),[4,n.get(t)];case 1:return[2,i.sent()]}}))}))},e.prototype.save=function(e,t){var n,r;return k(this,void 0,void 0,(function(){var i,o,s,a,u,c,f,l,d,h,p,v,g,m,b,y,w,_,E,I,k,C,T,R,L,j=this;return O(this,(function(O){switch(O.label){case 0:return[4,this.checkPrivate()];case 1:return O.sent(),i=Object.getPrototypeOf(e).constructor,o=this.getStorenameForModel(i),s=Object(A.x)(i.name,e,this.schema.namespaces[this.namespaceResolver(i)],this.modelInstanceCreator,this.getModelConstructorByModelName),a=this.namespaceResolver(i),u=new Set,c=Object.values(s).map((function(e){var t=e.modelName,n=e.item,r=e.instance,i=j.getStorename(a,t);return u.add(i),{storeName:i,item:n,instance:r}})),f=this.db.transaction(P([o],Array.from(u.values())),"readwrite"),l=f.objectStore(o),[4,this._get(l,e.id)];case 2:if(d=O.sent(),t&&d&&(h=S.a.getPredicates(t),p=h.predicates,v=h.type,!Object(A.y)(d,v,p)))throw g="Conditional update failed",N.error(g,{model:d,condition:p}),new Error(g);m=[],O.label=3;case 3:O.trys.push([3,14,15,20]),b=x(c),O.label=4;case 4:return[4,b.next()];case 5:return(y=O.sent()).done?[3,13]:(w=y.value,_=w.storeName,E=w.item,I=w.instance,k=f.objectStore(_),C=E.id,[4,this._get(k,C)]);case 6:return T=void 0===O.sent()?M.c.INSERT:M.c.UPDATE,C!==e.id?[3,9]:[4,k.index("byId").getKey(E.id)];case 7:return R=O.sent(),[4,k.put(E,R)];case 8:return O.sent(),m.push([I,T]),[3,12];case 9:return T!==M.c.INSERT?[3,12]:[4,k.index("byId").getKey(E.id)];case 10:return R=O.sent(),[4,k.put(E,R)];case 11:O.sent(),m.push([I,T]),O.label=12;case 12:return[3,4];case 13:return[3,20];case 14:return L=O.sent(),n={error:L},[3,20];case 15:return O.trys.push([15,,18,19]),y&&!y.done&&(r=b.return)?[4,r.call(b)]:[3,17];case 16:O.sent(),O.label=17;case 17:return[3,19];case 18:if(n)throw n.error;return[7];case 19:return[7];case 20:return[4,f.done];case 21:return O.sent(),[2,m]}}))}))},e.prototype.load=function(e,t,n){var r,i,o,s,a,u,c,f,l,d;return k(this,void 0,void 0,(function(){var h,p,v,g,m,b,y,w,_,S,E,M,I,k,C,T,N,R,L,j=this;return O(this,(function(O){switch(O.label){case 0:if(h=this.schema.namespaces[e],p=h.relationships[t].relationTypes,v=p.map((function(t){var n=t.modelName;return j.getStorename(e,n)})),g=this.getModelConstructorByModelName(e,t),0===v.length)return[2,n.map((function(e){return j.modelInstanceCreator(g,e)}))];m=this.db.transaction(P(v),"readonly"),O.label=1;case 1:O.trys.push([1,34,35,40]),b=x(p),O.label=2;case 2:return[4,b.next()];case 3:if((y=O.sent()).done)return[3,33];switch(w=y.value,_=w.fieldName,S=w.modelName,E=w.targetName,M=this.getStorename(e,S),I=m.objectStore(M),k=this.getModelConstructorByModelName(e,S),w.relationType){case"HAS_ONE":return[3,4];case"BELONGS_TO":return[3,17];case"HAS_MANY":return[3,30]}return[3,31];case 4:O.trys.push([4,10,11,16]),r=x(n),O.label=5;case 5:return[4,r.next()];case 6:return(i=O.sent()).done?[3,9]:(T=i.value)[_]?[4,this._get(I,T[_])]:[3,8];case 7:N=O.sent(),T[_]=N&&this.modelInstanceCreator(k,N),O.label=8;case 8:return[3,5];case 9:return[3,16];case 10:return C=O.sent(),c={error:C},[3,16];case 11:return O.trys.push([11,,14,15]),i&&!i.done&&(f=r.return)?[4,f.call(r)]:[3,13];case 12:O.sent(),O.label=13;case 13:return[3,15];case 14:if(c)throw c.error;return[7];case 15:return[7];case 16:return[3,32];case 17:O.trys.push([17,23,24,29]),o=x(n),O.label=18;case 18:return[4,o.next()];case 19:return(s=O.sent()).done?[3,22]:(T=s.value)[E]?[4,this._get(I,T[E])]:[3,21];case 20:N=O.sent(),T[_]=N&&this.modelInstanceCreator(k,N),delete T[E],O.label=21;case 21:return[3,18];case 22:return[3,29];case 23:return R=O.sent(),l={error:R},[3,29];case 24:return O.trys.push([24,,27,28]),s&&!s.done&&(d=o.return)?[4,d.call(o)]:[3,26];case 25:O.sent(),O.label=26;case 26:return[3,28];case 27:if(l)throw l.error;return[7];case 28:return[7];case 29:case 30:return[3,32];case 31:return Object(A.f)(w.relationType),[3,32];case 32:return[3,2];case 33:return[3,40];case 34:return L=O.sent(),a={error:L},[3,40];case 35:return O.trys.push([35,,38,39]),y&&!y.done&&(u=b.return)?[4,u.call(b)]:[3,37];case 36:O.sent(),O.label=37;case 37:return[3,39];case 38:if(a)throw a.error;return[7];case 39:return[7];case 40:return[2,n.map((function(e){return j.modelInstanceCreator(g,e)}))]}}))}))},e.prototype.query=function(e,t,n){return k(this,void 0,void 0,(function(){var r,i,o,s,a,u,c,f,l,d,h,p,v,g;return O(this,(function(m){switch(m.label){case 0:return[4,this.checkPrivate()];case 1:return m.sent(),r=this.getStorenameForModel(e),i=this.namespaceResolver(e),o=n&&n.sort,t?(s=S.a.getPredicates(t))?(a=s.predicates,u=s.type,(c=1===a.length&&a.find((function(e){return Object(M.k)(e)&&"id"===e.field&&"eq"===e.operator})))?(f=c.operand,[4,this._get(r,f)]):[3,5]):[3,8]:[3,8];case 2:return(l=m.sent())?[4,this.load(i,e.name,[l])]:[3,4];case 3:return d=T.apply(void 0,[m.sent(),1]),[2,[d[0]]];case 4:return[2,[]];case 5:return[4,this.db.getAll(r)];case 6:return p=m.sent(),h=a?p.filter((function(e){return Object(A.y)(e,u,a)})):p,[4,this.load(i,e.name,this.inMemoryPagination(h,n))];case 7:return[2,m.sent()];case 8:return o?[4,this.db.getAll(r)]:[3,11];case 9:return p=m.sent(),[4,this.load(i,e.name,this.inMemoryPagination(p,n))];case 10:return[2,m.sent()];case 11:return v=this.load,g=[i,e.name],[4,this.enginePagination(r,n)];case 12:return[4,v.apply(this,g.concat([m.sent()]))];case 13:return[2,m.sent()]}}))}))},e.prototype.inMemoryPagination=function(e,t){if(t){if(t.sort){var n=E.a.getPredicates(t.sort);if(n.length){var r=Object(A.w)(n);e.sort(r)}}var i=t.page,o=void 0===i?0:i,s=t.limit,a=void 0===s?0:s,u=Math.max(0,o*a)||0,c=a>0?u+a:e.length;return e.slice(u,c)}return e},e.prototype.enginePagination=function(e,t){return k(this,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,d;return O(this,(function(h){switch(h.label){case 0:return t?(r=t.page,i=void 0===r?0:r,o=t.limit,s=void 0===o?0:o,a=Math.max(0,i*s)||0,[4,this.db.transaction(e).objectStore(e).openCursor()]):[3,7];case 1:return(u=h.sent())&&a>0?[4,u.advance(a)]:[3,3];case 2:h.sent(),h.label=3;case 3:c=[],f="number"==typeof s&&s>0,l=!0,d=s,h.label=4;case 4:return l&&u&&u.value?(c.push(u.value),[4,u.continue()]):[3,6];case 5:return u=h.sent(),f?(d--,l=d>0&&null!==u):l=null!==u,[3,4];case 6:return n=c,[3,9];case 7:return[4,this.db.getAll(e)];case 8:n=h.sent(),h.label=9;case 9:return[2,n]}}))}))},e.prototype.queryOne=function(e,t){return void 0===t&&(t=M.d.FIRST),k(this,void 0,void 0,(function(){var n,r,i;return O(this,(function(o){switch(o.label){case 0:return[4,this.checkPrivate()];case 1:return o.sent(),n=this.getStorenameForModel(e),[4,this.db.transaction([n],"readonly").objectStore(n).openCursor(void 0,t===M.d.FIRST?"next":"prev")];case 2:return r=o.sent(),[2,(i=r?r.value:void 0)&&this.modelInstanceCreator(e,i)]}}))}))},e.prototype.delete=function(e,t){return k(this,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,d,h,p,v,g;return O(this,(function(m){switch(m.label){case 0:return[4,this.checkPrivate()];case 1:return m.sent(),n=[],Object(A.s)(e)?(o=e,s=this.namespaceResolver(o),a=this.getStorenameForModel(o),[4,this.query(o,t)]):[3,9];case 2:return r=m.sent(),v=this.schema.namespaces[s].relationships[o.name].relationTypes,void 0===t?[3,5]:[4,this.deleteTraverse(v,r,o.name,s,n)];case 3:return m.sent(),[4,this.deleteItem(n)];case 4:return m.sent(),g=n.reduce((function(e,t){var n=t.items;return e.concat(n)}),[]),[2,[r,g]];case 5:return[4,this.deleteTraverse(v,r,o.name,s,n)];case 6:return m.sent(),[4,this.db.transaction([a],"readwrite").objectStore(a).clear()];case 7:return m.sent(),g=n.reduce((function(e,t){var n=t.items;return e.concat(n)}),[]),[2,[r,g]];case 8:return[3,17];case 9:return i=e,o=Object.getPrototypeOf(i).constructor,s=this.namespaceResolver(o),a=this.getStorenameForModel(o),t?(u=this.db.transaction([a],"readwrite"),c=u.objectStore(a),[4,this._get(c,i.id)]):[3,13];case 10:if(void 0===(f=m.sent()))return p="Model instance not found in storage",N.warn(p,{model:i}),[2,[[i],[]]];if(l=S.a.getPredicates(t),d=l.predicates,h=l.type,!Object(A.y)(f,h,d))throw p="Conditional update failed",N.error(p,{model:f,condition:d}),new Error(p);return[4,u.done];case 11:return m.sent(),v=this.schema.namespaces[s].relationships[o.name].relationTypes,[4,this.deleteTraverse(v,[i],o.name,s,n)];case 12:return m.sent(),[3,15];case 13:return v=this.schema.namespaces[s].relationships[o.name].relationTypes,[4,this.deleteTraverse(v,[i],o.name,s,n)];case 14:m.sent(),m.label=15;case 15:return[4,this.deleteItem(n)];case 16:return m.sent(),g=n.reduce((function(e,t){var n=t.items;return e.concat(n)}),[]),[2,[[i],g]];case 17:return[2]}}))}))},e.prototype.deleteItem=function(e){var t,n,r,i,o,s;return k(this,void 0,void 0,(function(){var a,u,c,f,l,d,h,p,v,g,m,b;return O(this,(function(y){switch(y.label){case 0:a=e.map((function(e){return e.storeName})),u=this.db.transaction(P(a),"readwrite"),y.label=1;case 1:y.trys.push([1,22,23,28]),t=x(e),y.label=2;case 2:return[4,t.next()];case 3:if((n=y.sent()).done)return[3,21];c=n.value,f=c.storeName,l=c.items,d=u.objectStore(f),y.label=4;case 4:y.trys.push([4,14,15,20]),h=x(l),y.label=5;case 5:return[4,h.next()];case 6:return(p=y.sent()).done?[3,13]:(v=p.value)?(g=void 0,"object"!==I(v)?[3,8]:[4,d.index("byId").getKey(v.id)]):[3,12];case 7:return g=y.sent(),[3,10];case 8:return[4,d.index("byId").getKey(v.toString())];case 9:g=y.sent(),y.label=10;case 10:return void 0===g?[3,12]:[4,d.delete(g)];case 11:y.sent(),y.label=12;case 12:return[3,5];case 13:return[3,20];case 14:return m=y.sent(),o={error:m},[3,20];case 15:return y.trys.push([15,,18,19]),p&&!p.done&&(s=h.return)?[4,s.call(h)]:[3,17];case 16:y.sent(),y.label=17;case 17:return[3,19];case 18:if(o)throw o.error;return[7];case 19:return[7];case 20:return[3,2];case 21:return[3,28];case 22:return b=y.sent(),r={error:b},[3,28];case 23:return y.trys.push([23,,26,27]),n&&!n.done&&(i=t.return)?[4,i.call(t)]:[3,25];case 24:y.sent(),y.label=25;case 25:return[3,27];case 26:if(r)throw r.error;return[7];case 27:return[7];case 28:return[2]}}))}))},e.prototype.deleteTraverse=function(e,t,n,r,i){var o,s,a,u,c,f,l,d,h,p,v,g;return k(this,void 0,void 0,(function(){var m,b,y,w,_,S,E,M,I,k,C,T=this;return O(this,(function(O){switch(O.label){case 0:O.trys.push([0,35,36,41]),o=x(e),O.label=1;case 1:return[4,o.next()];case 2:if((s=O.sent()).done)return[3,34];switch(m=s.value,b=m.relationType,m.fieldName,y=m.modelName,w=this.getStorename(r,y),_=Object(A.g)(this.schema.namespaces[r].relationships[y].relationTypes,n)||Object(A.h)(this.schema.namespaces[r].relationships[y].indexes,m.associatedWith),b){case"HAS_ONE":return[3,3];case"HAS_MANY":return[3,17];case"BELONGS_TO":return[3,31]}return[3,32];case 3:O.trys.push([3,10,11,16]),a=x(t),O.label=4;case 4:return[4,a.next()];case 5:return(u=O.sent()).done?[3,9]:(M=u.value,[4,this.db.transaction(w,"readwrite").objectStore(w).index(_).get(M.id)]);case 6:return S=O.sent(),[4,this.deleteTraverse(this.schema.namespaces[r].relationships[y].relationTypes,S?[S]:[],y,r,i)];case 7:O.sent(),O.label=8;case 8:return[3,4];case 9:return[3,16];case 10:return E=O.sent(),h={error:E},[3,16];case 11:return O.trys.push([11,,14,15]),u&&!u.done&&(p=a.return)?[4,p.call(a)]:[3,13];case 12:O.sent(),O.label=13;case 13:return[3,15];case 14:if(h)throw h.error;return[7];case 15:return[7];case 16:return[3,33];case 17:O.trys.push([17,24,25,30]),c=x(t),O.label=18;case 18:return[4,c.next()];case 19:return(f=O.sent()).done?[3,23]:(M=f.value,[4,this.db.transaction(w,"readwrite").objectStore(w).index(_).getAll(M.id)]);case 20:return I=O.sent(),[4,this.deleteTraverse(this.schema.namespaces[r].relationships[y].relationTypes,I,y,r,i)];case 21:O.sent(),O.label=22;case 22:return[3,18];case 23:return[3,30];case 24:return k=O.sent(),v={error:k},[3,30];case 25:return O.trys.push([25,,28,29]),f&&!f.done&&(g=c.return)?[4,g.call(c)]:[3,27];case 26:O.sent(),O.label=27;case 27:return[3,29];case 28:if(v)throw v.error;return[7];case 29:return[7];case 30:case 31:return[3,33];case 32:return Object(A.f)(b),[3,33];case 33:return[3,1];case 34:return[3,41];case 35:return C=O.sent(),l={error:C},[3,41];case 36:return O.trys.push([36,,39,40]),s&&!s.done&&(d=o.return)?[4,d.call(o)]:[3,38];case 37:O.sent(),O.label=38;case 38:return[3,40];case 39:if(l)throw l.error;return[7];case 40:return[7];case 41:return i.push({storeName:this.getStorename(r,n),items:t.map((function(e){return T.modelInstanceCreator(T.getModelConstructorByModelName(r,n),e)}))}),[2]}}))}))},e.prototype.clear=function(){return k(this,void 0,void 0,(function(){return O(this,(function(e){switch(e.label){case 0:return[4,this.checkPrivate()];case 1:return e.sent(),this.db.close(),[4,m(this.dbName)];case 2:return e.sent(),this.db=void 0,this.initPromise=void 0,[2]}}))}))},e.prototype.batchSave=function(e,t){return k(this,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,l,d,h;return O(this,(function(p){switch(p.label){case 0:return 0===t.length?[2,[]]:[4,this.checkPrivate()];case 1:p.sent(),n=[],r=this.getStorenameForModel(e),i=this.db.transaction(r,"readwrite"),o=i.store,s=function(t){var r,i,s,u,c;return O(this,(function(f){switch(f.label){case 0:return r=Object(A.x)(e.name,a.modelInstanceCreator(e,t),a.schema.namespaces[a.namespaceResolver(e)],a.modelInstanceCreator,a.getModelConstructorByModelName),i=t.id,s=t._deleted,[4,o.index("byId").getKey(i)];case 1:return u=f.sent(),s?[3,3]:(c=r.find((function(e){return e.instance.id===i})).instance,n.push([c,u?M.c.UPDATE:M.c.INSERT]),[4,o.put(c,u)]);case 2:return f.sent(),[3,5];case 3:return n.push([t,M.c.DELETE]),u?[4,o.delete(u)]:[3,5];case 4:f.sent(),f.label=5;case 5:return[2]}}))},a=this,p.label=2;case 2:p.trys.push([2,7,8,9]),u=C(t),c=u.next(),p.label=3;case 3:return c.done?[3,6]:(f=c.value,[5,s(f)]);case 4:p.sent(),p.label=5;case 5:return c=u.next(),[3,3];case 6:return[3,9];case 7:return l=p.sent(),d={error:l},[3,9];case 8:try{c&&!c.done&&(h=u.return)&&h.call(u)}finally{if(d)throw d.error}return[7];case 9:return[4,i.done];case 10:return p.sent(),[2,n]}}))}))},e}();t.default=new R},function(e,t,n){"use strict";n.r(t),n.d(t,"AsyncStorageAdapter",(function(){return I}));var r=n(44),i=n(4),o=n(3),s=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},a=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},u=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},c=function(){var e=this;this.db=new Map,this.getAllKeys=function(){return s(e,void 0,void 0,(function(){return a(this,(function(e){return[2,Array.from(this.db.keys())]}))}))},this.multiGet=function(t){return s(e,void 0,void 0,(function(){var e=this;return a(this,(function(n){return[2,t.reduce((function(t,n){return t.push([n,e.db.get(n)]),t}),[])]}))}))},this.multiRemove=function(t,n){return s(e,void 0,void 0,(function(){var e=this;return a(this,(function(r){return t.forEach((function(t){return e.db.delete(t)})),n(),[2]}))}))},this.multiSet=function(t,n){return s(e,void 0,void 0,(function(){var e=this;return a(this,(function(r){return t.forEach((function(t){var n=u(t,2),r=n[0],i=n[1];e.setItem(r,i)})),n(),[2]}))}))},this.setItem=function(t,n){return s(e,void 0,void 0,(function(){return a(this,(function(e){return[2,this.db.set(t,n)]}))}))},this.removeItem=function(t){return s(e,void 0,void 0,(function(){return a(this,(function(e){return[2,this.db.delete(t)]}))}))},this.getItem=function(t){return s(e,void 0,void 0,(function(){return a(this,(function(e){return[2,this.db.get(t)]}))}))}};var f=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},l=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},d=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},h=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},p="@AmplifyDatastore",v=new Map,g=function(){function e(){this._collectionInMemoryIndex=new Map,this.storage=new c}return e.prototype.getCollectionIndex=function(e){return this._collectionInMemoryIndex.has(e)||this._collectionInMemoryIndex.set(e,new Map),this._collectionInMemoryIndex.get(e)},e.prototype.getMonotonicFactory=function(e){return v.has(e)||v.set(e,Object(o.v)()),v.get(e)},e.prototype.init=function(){return f(this,void 0,void 0,(function(){var e,t,n,r,i,o,s,a,u,c,f,v,g,m,b,y,w,_,S,E;return l(this,(function(l){switch(l.label){case 0:return this._collectionInMemoryIndex.clear(),[4,this.storage.getAllKeys()];case 1:e=l.sent(),t=[],l.label=2;case 2:l.trys.push([2,12,13,14]),n=d(e),r=n.next(),l.label=3;case 3:return r.done?[3,11]:(i=r.value,o=h(i.split("::"),5),s=o[0],a=o[1],u=o[2],c=o[3],f=o[4],s!==p?[3,10]:"Data"!==u?[3,9]:(v=void 0,void 0!==f?[3,7]:(g=c,m=this.getMonotonicFactory(a)(),b=this.getLegacyKeyForItem(a,g),y=this.getKeyForItem(a,g,m),[4,this.storage.getItem(b)])));case 4:return w=l.sent(),[4,this.storage.setItem(y,w)];case 5:return l.sent(),[4,this.storage.removeItem(b)];case 6:return l.sent(),v=m,[3,8];case 7:v=c,l.label=8;case 8:return this.getCollectionIndex(a).set(f,v),[3,10];case 9:"Collection"===u&&t.push(i),l.label=10;case 10:return r=n.next(),[3,3];case 11:return[3,14];case 12:return _=l.sent(),S={error:_},[3,14];case 13:try{r&&!r.done&&(E=n.return)&&E.call(n)}finally{if(S)throw S.error}return[7];case 14:return t.length>0?[4,this.storage.multiRemove(t)]:[3,16];case 15:l.sent(),l.label=16;case 16:return[2]}}))}))},e.prototype.save=function(e,t){return f(this,void 0,void 0,(function(){var n,r;return l(this,(function(i){switch(i.label){case 0:return n=this.getCollectionIndex(t).get(e.id)||this.getMonotonicFactory(t)(),r=this.getKeyForItem(t,e.id,n),this.getCollectionIndex(t).set(e.id,n),[4,this.storage.setItem(r,JSON.stringify(e))];case 1:return i.sent(),[2]}}))}))},e.prototype.batchSave=function(e,t){return f(this,void 0,void 0,(function(){var n,r,o,s,a,u,c,f,p,v,g,m,b,y,w,_,S,E,M,A,I,k=this;return l(this,(function(l){switch(l.label){case 0:if(0===t.length)return[2,[]];n=[],r=this.getCollectionIndex(e),o=new Set,s=new Set,a=[],u={};try{for(c=d(t),f=c.next();!f.done;f=c.next())p=f.value,v=p.id,g=p._deleted,m=r.get(v)||this.getMonotonicFactory(e)(),S=this.getKeyForItem(e,v,m),a.push(S),u[S]={ulid:m,model:p},g?o.add(S):s.add(S)}catch(e){E={error:e}}finally{try{f&&!f.done&&(M=c.return)&&M.call(c)}finally{if(E)throw E.error}}return[4,this.storage.multiGet(a)];case 1:return b=l.sent(),y=b.filter((function(e){return!!h(e,2)[1]})).reduce((function(e,t){var n=h(t,1)[0];return e.add(n)}),new Set),[4,new Promise((function(e,t){if(0!==o.size){var n=Array.from(o);n.forEach((function(e){return r.delete(u[e].model.id)})),k.storage.multiRemove(n,(function(n){n&&n.length>0?t(n):e()}))}else e()}))];case 2:return l.sent(),[4,new Promise((function(e,t){if(0!==s.size){var n=Array.from(s).map((function(e){return[e,JSON.stringify(u[e].model)]}));s.forEach((function(e){var t=u[e],n=t.model.id,i=t.ulid;r.set(n,i)})),k.storage.multiSet(n,(function(n){n&&n.length>0?t(n):e()}))}else e()}))];case 3:l.sent();try{for(w=d(a),_=w.next();!_.done;_=w.next())S=_.value,o.has(S)&&y.has(S)?n.push([u[S].model,i.c.DELETE]):s.has(S)&&n.push([u[S].model,y.has(S)?i.c.UPDATE:i.c.INSERT])}catch(e){A={error:e}}finally{try{_&&!_.done&&(I=w.return)&&I.call(w)}finally{if(A)throw A.error}}return[2,n]}}))}))},e.prototype.get=function(e,t){return f(this,void 0,void 0,(function(){var n,r,i;return l(this,(function(o){switch(o.label){case 0:return n=this.getCollectionIndex(t).get(e),r=this.getKeyForItem(t,e,n),[4,this.storage.getItem(r)];case 1:return i=o.sent(),[2,i&&JSON.parse(i)]}}))}))},e.prototype.getOne=function(e,t){return f(this,void 0,void 0,(function(){var n,r,o,s,a,u,c;return l(this,(function(f){switch(f.label){case 0:return n=this.getCollectionIndex(t),r=h(e===i.d.FIRST?function(){var e,t,r,i,o;try{for(var s=d(n),a=s.next();!a.done;a=s.next()){i=(r=h(a.value,2))[0],o=r[1];break}}catch(t){e={error:t}}finally{try{a&&!a.done&&(t=s.return)&&t.call(s)}finally{if(e)throw e.error}}return[i,o]}():function(){var e,t,r,i,o;try{for(var s=d(n),a=s.next();!a.done;a=s.next())i=(r=h(a.value,2))[0],o=r[1]}catch(t){e={error:t}}finally{try{a&&!a.done&&(t=s.return)&&t.call(s)}finally{if(e)throw e.error}}return[i,o]}(),2),o=r[0],s=r[1],a=this.getKeyForItem(t,o,s),(c=a)?[4,this.storage.getItem(a)]:[3,2];case 1:c=f.sent(),f.label=2;case 2:return[2,(u=c)&&JSON.parse(u)||void 0]}}))}))},e.prototype.getAll=function(e,t){return f(this,void 0,void 0,(function(){var n,r,i,o,s,a,u,c,f,p,v,g,m,b,y,w,_,S;return l(this,(function(l){switch(l.label){case 0:n=this.getCollectionIndex(e),i=(r=t||{}).page,o=void 0===i?0:i,s=r.limit,a=void 0===s?0:s,u=Math.max(0,o*a)||0,c=a>0?u+a:void 0,f=[],p=0;try{for(v=d(n),g=v.next();!g.done&&(m=h(g.value,2),b=m[0],y=m[1],++p<=u||(f.push(this.getKeyForItem(e,b,y)),p!==c));g=v.next());}catch(e){_={error:e}}finally{try{g&&!g.done&&(S=v.return)&&S.call(v)}finally{if(_)throw _.error}}return[4,this.storage.multiGet(f)];case 1:return w=l.sent(),[2,w.filter((function(e){return h(e,2)[1]})).map((function(e){var t=h(e,2)[1];return JSON.parse(t)}))]}}))}))},e.prototype.delete=function(e,t){return f(this,void 0,void 0,(function(){var n,r;return l(this,(function(i){switch(i.label){case 0:return n=this.getCollectionIndex(t).get(e),r=this.getKeyForItem(t,e,n),this.getCollectionIndex(t).delete(e),[4,this.storage.removeItem(r)];case 1:return i.sent(),[2]}}))}))},e.prototype.clear=function(){return f(this,void 0,void 0,(function(){var e,t;return l(this,(function(n){switch(n.label){case 0:return[4,this.storage.getAllKeys()];case 1:return e=n.sent(),t=e.filter((function(e){return e.startsWith(p)})),[4,this.storage.multiRemove(t)];case 2:return n.sent(),this._collectionInMemoryIndex.clear(),[2]}}))}))},e.prototype.getKeyForItem=function(e,t,n){return this.getKeyPrefixForStoreItems(e)+"::"+n+"::"+t},e.prototype.getLegacyKeyForItem=function(e,t){return this.getKeyPrefixForStoreItems(e)+"::"+t},e.prototype.getKeyPrefixForStoreItems=function(e){return p+"::"+e+"::Data"},e}(),m=n(9),b=n(245);function y(e){return(y="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var w=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},_=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},S=function(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t,n=e[Symbol.asyncIterator];return n?n.call(e):(e="function"==typeof M?M(e):e[Symbol.iterator](),t={},r("next"),r("throw"),r("return"),t[Symbol.asyncIterator]=function(){return this},t);function r(n){t[n]=e[n]&&function(t){return new Promise((function(r,i){(function(e,t,n,r){Promise.resolve(r).then((function(t){e({value:t,done:n})}),t)})(r,i,(t=e[n](t)).done,t.value)}))}}},E=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},M=function(e){var t="function"==typeof Symbol&&Symbol.iterator,n=t&&e[t],r=0;if(n)return n.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&r>=e.length&&(e=void 0),{value:e&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},A=new r.a("DataStore"),I=function(){function e(){}return e.prototype.getStorenameForModel=function(e){var t=this.namespaceResolver(e),n=e.name;return this.getStorename(t,n)},e.prototype.getStorename=function(e,t){return e+"_"+t},e.prototype.setUp=function(e,t,n,r){return w(this,void 0,void 0,(function(){var i,o=this;return _(this,(function(s){switch(s.label){case 0:return this.initPromise?[3,1]:(this.initPromise=new Promise((function(e,t){o.resolve=e,o.reject=t})),[3,3]);case 1:return[4,this.initPromise];case 2:return s.sent(),[2];case 3:this.schema=e,this.namespaceResolver=t,this.modelInstanceCreator=n,this.getModelConstructorByModelName=r,s.label=4;case 4:return s.trys.push([4,7,,8]),this.db?[3,6]:(this.db=new g,[4,this.db.init()]);case 5:s.sent(),this.resolve(),s.label=6;case 6:return[3,8];case 7:return i=s.sent(),this.reject(i),[3,8];case 8:return[2]}}))}))},e.prototype.save=function(e,t){var n,r;return w(this,void 0,void 0,(function(){var s,a,u,c,f,l,d,h,p,v,g,b,y,w,E,M,I,k,O,x,C,T=this;return _(this,(function(_){switch(_.label){case 0:return s=Object.getPrototypeOf(e).constructor,a=this.getStorenameForModel(s),u=Object(o.x)(s.name,e,this.schema.namespaces[this.namespaceResolver(s)],this.modelInstanceCreator,this.getModelConstructorByModelName),c=this.namespaceResolver(s),f=new Set,l=Object.values(u).map((function(e){var t=e.modelName,n=e.item,r=e.instance,i=T.getStorename(c,t);return f.add(i),{storeName:i,item:n,instance:r}})),[4,this.db.get(e.id,a)];case 1:if(d=_.sent(),t&&d&&(h=m.a.getPredicates(t),p=h.predicates,v=h.type,!Object(o.y)(d,v,p)))throw g="Conditional update failed",A.error(g,{model:d,condition:p}),new Error(g);b=[],_.label=2;case 2:_.trys.push([2,11,12,17]),y=S(l),_.label=3;case 3:return[4,y.next()];case 4:return(w=_.sent()).done?[3,10]:(E=w.value,M=E.storeName,I=E.item,k=E.instance,O=I.id,[4,this.db.get(O,M)]);case 5:return x=_.sent()?i.c.UPDATE:i.c.INSERT,O!==e.id?[3,7]:[4,this.db.save(I,M)];case 6:return _.sent(),b.push([k,x]),[3,9];case 7:return x!==i.c.INSERT?[3,9]:[4,this.db.save(I,M)];case 8:_.sent(),b.push([k,x]),_.label=9;case 9:return[3,3];case 10:return[3,17];case 11:return C=_.sent(),n={error:C},[3,17];case 12:return _.trys.push([12,,15,16]),w&&!w.done&&(r=y.return)?[4,r.call(y)]:[3,14];case 13:_.sent(),_.label=14;case 14:return[3,16];case 15:if(n)throw n.error;return[7];case 16:return[7];case 17:return[2,b]}}))}))},e.prototype.load=function(e,t,n){var r,i,s,a,u,c,f,l,d,h;return w(this,void 0,void 0,(function(){var p,v,g,m,b,y,w,E,M,A,I,k,O,x,C,T,P,N,R=this;return _(this,(function(_){switch(_.label){case 0:if(p=this.schema.namespaces[e],v=p.relationships[t].relationTypes,g=v.map((function(t){var n=t.modelName;return R.getStorename(e,n)})),m=this.getModelConstructorByModelName(e,t),0===g.length)return[2,n.map((function(e){return R.modelInstanceCreator(m,e)}))];_.label=1;case 1:_.trys.push([1,34,35,40]),b=S(v),_.label=2;case 2:return[4,b.next()];case 3:if((y=_.sent()).done)return[3,33];switch(w=y.value,E=w.fieldName,M=w.modelName,A=w.targetName,I=w.relationType,k=this.getStorename(e,M),O=this.getModelConstructorByModelName(e,M),I){case"HAS_ONE":return[3,4];case"BELONGS_TO":return[3,17];case"HAS_MANY":return[3,30]}return[3,31];case 4:_.trys.push([4,10,11,16]),r=S(n),_.label=5;case 5:return[4,r.next()];case 6:return(i=_.sent()).done?[3,9]:(C=i.value)[E]?[4,this.db.get(C[E],k)]:[3,8];case 7:T=_.sent(),C[E]=T&&this.modelInstanceCreator(O,T),_.label=8;case 8:return[3,5];case 9:return[3,16];case 10:return x=_.sent(),f={error:x},[3,16];case 11:return _.trys.push([11,,14,15]),i&&!i.done&&(l=r.return)?[4,l.call(r)]:[3,13];case 12:_.sent(),_.label=13;case 13:return[3,15];case 14:if(f)throw f.error;return[7];case 15:return[7];case 16:return[3,32];case 17:_.trys.push([17,23,24,29]),s=S(n),_.label=18;case 18:return[4,s.next()];case 19:return(a=_.sent()).done?[3,22]:(C=a.value)[A]?[4,this.db.get(C[A],k)]:[3,21];case 20:T=_.sent(),C[E]=T&&this.modelInstanceCreator(O,T),delete C[A],_.label=21;case 21:return[3,18];case 22:return[3,29];case 23:return P=_.sent(),d={error:P},[3,29];case 24:return _.trys.push([24,,27,28]),a&&!a.done&&(h=s.return)?[4,h.call(s)]:[3,26];case 25:_.sent(),_.label=26;case 26:return[3,28];case 27:if(d)throw d.error;return[7];case 28:return[7];case 29:case 30:return[3,32];case 31:return Object(o.f)(I),[3,32];case 32:return[3,2];case 33:return[3,40];case 34:return N=_.sent(),u={error:N},[3,40];case 35:return _.trys.push([35,,38,39]),y&&!y.done&&(c=b.return)?[4,c.call(b)]:[3,37];case 36:_.sent(),_.label=37;case 37:return[3,39];case 38:if(u)throw u.error;return[7];case 39:return[7];case 40:return[2,n.map((function(e){return R.modelInstanceCreator(m,e)}))]}}))}))},e.prototype.query=function(e,t,n){return w(this,void 0,void 0,(function(){var r,s,a,u,c,f,l,d,h,p,v,g,b,y;return _(this,(function(w){switch(w.label){case 0:return r=this.getStorenameForModel(e),s=this.namespaceResolver(e),a=n&&n.sort,t?(u=m.a.getPredicates(t))?(c=u.predicates,f=u.type,(l=1===c.length&&c.find((function(e){return Object(i.k)(e)&&"id"===e.field&&"eq"===e.operator})))?(d=l.operand,[4,this.db.get(d,r)]):[3,4]):[3,7]:[3,7];case 1:return(h=w.sent())?[4,this.load(s,e.name,[h])]:[3,3];case 2:return p=E.apply(void 0,[w.sent(),1]),[2,[p[0]]];case 3:return[2,[]];case 4:return[4,this.db.getAll(r)];case 5:return v=w.sent(),g=c?v.filter((function(e){return Object(o.y)(e,f,c)})):v,[4,this.load(s,e.name,this.inMemoryPagination(g,n))];case 6:return[2,w.sent()];case 7:return a?[4,this.db.getAll(r)]:[3,10];case 8:return b=w.sent(),[4,this.load(s,e.name,this.inMemoryPagination(b,n))];case 9:return[2,w.sent()];case 10:return[4,this.db.getAll(r,n)];case 11:return y=w.sent(),[4,this.load(s,e.name,y)];case 12:return[2,w.sent()]}}))}))},e.prototype.inMemoryPagination=function(e,t){if(t){if(t.sort){var n=b.a.getPredicates(t.sort);if(n.length){var r=Object(o.w)(n);e.sort(r)}}var i=t.page,s=void 0===i?0:i,a=t.limit,u=void 0===a?0:a,c=Math.max(0,s*u)||0,f=u>0?c+u:e.length;return e.slice(c,f)}return e},e.prototype.queryOne=function(e,t){return void 0===t&&(t=i.d.FIRST),w(this,void 0,void 0,(function(){var n,r;return _(this,(function(i){switch(i.label){case 0:return n=this.getStorenameForModel(e),[4,this.db.getOne(t,n)];case 1:return[2,(r=i.sent())&&this.modelInstanceCreator(e,r)]}}))}))},e.prototype.delete=function(e,t){return w(this,void 0,void 0,(function(){var n,r,i,s,a,u,c,f,l,d,h,p,v;return _(this,(function(g){switch(g.label){case 0:return n=[],Object(o.s)(e)?(s=e,a=this.namespaceResolver(s),[4,this.query(s,t)]):[3,8];case 1:return r=g.sent(),p=this.schema.namespaces[a].relationships[s.name].relationTypes,void 0===t?[3,4]:[4,this.deleteTraverse(p,r,s.name,a,n)];case 2:return g.sent(),[4,this.deleteItem(n)];case 3:return g.sent(),v=n.reduce((function(e,t){var n=t.items;return e.concat(n)}),[]),[2,[r,v]];case 4:return[4,this.deleteTraverse(p,r,s.name,a,n)];case 5:return g.sent(),[4,this.deleteItem(n)];case 6:return g.sent(),v=n.reduce((function(e,t){var n=t.items;return e.concat(n)}),[]),[2,[r,v]];case 7:return[3,15];case 8:return i=e,s=Object.getPrototypeOf(i).constructor,a=this.namespaceResolver(s),u=this.getStorenameForModel(s),t?[4,this.db.get(i.id,u)]:[3,11];case 9:if(void 0===(c=g.sent()))return h="Model instance not found in storage",A.warn(h,{model:i}),[2,[[i],[]]];if(f=m.a.getPredicates(t),l=f.predicates,d=f.type,!Object(o.y)(c,d,l))throw h="Conditional update failed",A.error(h,{model:c,condition:l}),new Error(h);return p=this.schema.namespaces[a].relationships[s.name].relationTypes,[4,this.deleteTraverse(p,[i],s.name,a,n)];case 10:return g.sent(),[3,13];case 11:return p=this.schema.namespaces[a].relationships[s.name].relationTypes,[4,this.deleteTraverse(p,[i],s.name,a,n)];case 12:g.sent(),g.label=13;case 13:return[4,this.deleteItem(n)];case 14:return g.sent(),v=n.reduce((function(e,t){var n=t.items;return e.concat(n)}),[]),[2,[[i],v]];case 15:return[2]}}))}))},e.prototype.deleteItem=function(e){var t,n,r,i,o,s;return w(this,void 0,void 0,(function(){var a,u,c,f,l,d,h,p,v;return _(this,(function(g){switch(g.label){case 0:g.trys.push([0,17,18,23]),t=S(e),g.label=1;case 1:return[4,t.next()];case 2:if((n=g.sent()).done)return[3,16];a=n.value,u=a.storeName,c=a.items,g.label=3;case 3:g.trys.push([3,9,10,15]),f=S(c),g.label=4;case 4:return[4,f.next()];case 5:return(l=g.sent()).done?[3,8]:(d=l.value)?"object"!==y(d)?[3,7]:(h=d.id,[4,this.db.delete(h,u)]):[3,7];case 6:g.sent(),g.label=7;case 7:return[3,4];case 8:return[3,15];case 9:return p=g.sent(),o={error:p},[3,15];case 10:return g.trys.push([10,,13,14]),l&&!l.done&&(s=f.return)?[4,s.call(f)]:[3,12];case 11:g.sent(),g.label=12;case 12:return[3,14];case 13:if(o)throw o.error;return[7];case 14:return[7];case 15:return[3,1];case 16:return[3,23];case 17:return v=g.sent(),r={error:v},[3,23];case 18:return g.trys.push([18,,21,22]),n&&!n.done&&(i=t.return)?[4,i.call(t)]:[3,20];case 19:g.sent(),g.label=20;case 20:return[3,22];case 21:if(r)throw r.error;return[7];case 22:return[7];case 23:return[2]}}))}))},e.prototype.deleteTraverse=function(e,t,n,r,i){var s,a,u,c,f,l,d,h,p,v,g,m;return w(this,void 0,void 0,(function(){var b,y,w,E,M,A,I,k,O,x,C,T,P=this;return _(this,(function(_){switch(_.label){case 0:_.trys.push([0,35,36,41]),s=S(e),_.label=1;case 1:return[4,s.next()];case 2:if((a=_.sent()).done)return[3,34];switch(b=a.value,y=b.relationType,w=b.modelName,E=this.getStorename(r,w),M=Object(o.g)(this.schema.namespaces[r].relationships[w].relationTypes,n)||Object(o.h)(this.schema.namespaces[r].relationships[w].indexes,b.associatedWith),y){case"HAS_ONE":return[3,3];case"HAS_MANY":return[3,17];case"BELONGS_TO":return[3,31]}return[3,32];case 3:_.trys.push([3,10,11,16]),u=S(t),_.label=4;case 4:return[4,u.next()];case 5:return(c=_.sent()).done?[3,9]:(k=c.value,[4,this.db.getAll(E)]);case 6:return O=_.sent(),A=O.filter((function(e){return e[M]===k.id})),[4,this.deleteTraverse(this.schema.namespaces[r].relationships[w].relationTypes,A,w,r,i)];case 7:_.sent(),_.label=8;case 8:return[3,4];case 9:return[3,16];case 10:return I=_.sent(),p={error:I},[3,16];case 11:return _.trys.push([11,,14,15]),c&&!c.done&&(v=u.return)?[4,v.call(u)]:[3,13];case 12:_.sent(),_.label=13;case 13:return[3,15];case 14:if(p)throw p.error;return[7];case 15:return[7];case 16:return[3,33];case 17:_.trys.push([17,24,25,30]),f=S(t),_.label=18;case 18:return[4,f.next()];case 19:return(l=_.sent()).done?[3,23]:(k=l.value,[4,this.db.getAll(E)]);case 20:return O=_.sent(),x=O.filter((function(e){return e[M]===k.id})),[4,this.deleteTraverse(this.schema.namespaces[r].relationships[w].relationTypes,x,w,r,i)];case 21:_.sent(),_.label=22;case 22:return[3,18];case 23:return[3,30];case 24:return C=_.sent(),g={error:C},[3,30];case 25:return _.trys.push([25,,28,29]),l&&!l.done&&(m=f.return)?[4,m.call(f)]:[3,27];case 26:_.sent(),_.label=27;case 27:return[3,29];case 28:if(g)throw g.error;return[7];case 29:return[7];case 30:case 31:return[3,33];case 32:return Object(o.f)(y),[3,33];case 33:return[3,1];case 34:return[3,41];case 35:return T=_.sent(),d={error:T},[3,41];case 36:return _.trys.push([36,,39,40]),a&&!a.done&&(h=s.return)?[4,h.call(s)]:[3,38];case 37:_.sent(),_.label=38;case 38:return[3,40];case 39:if(d)throw d.error;return[7];case 40:return[7];case 41:return i.push({storeName:this.getStorename(r,n),items:t.map((function(e){return P.modelInstanceCreator(P.getModelConstructorByModelName(r,n),e)}))}),[2]}}))}))},e.prototype.clear=function(){return w(this,void 0,void 0,(function(){return _(this,(function(e){switch(e.label){case 0:return[4,this.db.clear()];case 1:return e.sent(),this.db=void 0,this.initPromise=void 0,[2]}}))}))},e.prototype.batchSave=function(e,t){return w(this,void 0,void 0,(function(){var n,r,i,s,a,u,c,f,l,d,h;return _(this,(function(p){switch(p.label){case 0:n=e.name,r=this.namespaceResolver(e),i=this.getStorename(r,n),s=[],a=function(t){var n=t.id,r=Object(o.x)(e.name,u.modelInstanceCreator(e,t),u.schema.namespaces[u.namespaceResolver(e)],u.modelInstanceCreator,u.getModelConstructorByModelName).find((function(e){return e.instance.id===n})).instance;s.push(r)},u=this;try{for(c=M(t),f=c.next();!f.done;f=c.next())l=f.value,a(l)}catch(e){d={error:e}}finally{try{f&&!f.done&&(h=c.return)&&h.call(c)}finally{if(d)throw d.error}}return[4,this.db.batchSave(i,s)];case 1:return[2,p.sent()]}}))}))},e}();t.default=new I},function(e,t,n){"use strict";n.r(t),n.d(t,"fromUtf8",(function(){return r})),n.d(t,"toUtf8",(function(){return i}));var r=function(e){return"function"==typeof TextEncoder?function(e){return(new TextEncoder).encode(e)}(e):function(e){for(var t=[],n=0,r=e.length;n<r;n++){var i=e.charCodeAt(n);if(i<128)t.push(i);else if(i<2048)t.push(i>>6|192,63&i|128);else if(n+1<e.length&&55296==(64512&i)&&56320==(64512&e.charCodeAt(n+1))){var o=65536+((1023&i)<<10)+(1023&e.charCodeAt(++n));t.push(o>>18|240,o>>12&63|128,o>>6&63|128,63&o|128)}else t.push(i>>12|224,i>>6&63|128,63&i|128)}return Uint8Array.from(t)}(e)},i=function(e){return"function"==typeof TextDecoder?function(e){return new TextDecoder("utf-8").decode(e)}(e):function(e){for(var t="",n=0,r=e.length;n<r;n++){var i=e[n];if(i<128)t+=String.fromCharCode(i);else if(192<=i&&i<224){var o=e[++n];t+=String.fromCharCode((31&i)<<6|63&o)}else if(240<=i&&i<365){var s="%"+[i,e[++n],e[++n],e[++n]].map((function(e){return e.toString(16)})).join("%");t+=decodeURIComponent(s)}else t+=String.fromCharCode((15&i)<<12|(63&e[++n])<<6|63&e[++n])}return t}(e)}},,,,,,,,,,,,,,,,,function(e,t,n){"use strict";n.d(t,"a",(function(){return l})),n.d(t,"b",(function(){return d}));var r,i=n(44),o=(r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),s=function(e,t,n,r){return new(n||(n=Promise))((function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r.throw(e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(s,a)}u((r=r.apply(e,t||[])).next())}))},a=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r.return:o[0]?r.throw||((i=r.return)&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=s.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]<i[3])){s.label=o[1];break}if(6===o[0]&&s.label<i[1]){s.label=i[1],i=o;break}if(i&&s.label<i[2]){s.label=i[2],s.ops.push(o);break}i[2]&&s.ops.pop(),s.trys.pop();continue}o=t.call(e,s)}catch(e){o=[6,e],r=0}finally{n=i=0}if(5&o[0])throw o[1];return{value:o[0]?o[1]:void 0,done:!0}}([o,a])}}},u=function(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,i,o=n.call(e),s=[];try{for(;(void 0===t||t-- >0)&&!(r=o.next()).done;)s.push(r.value)}catch(e){i={error:e}}finally{try{r&&!r.done&&(n=o.return)&&n.call(o)}finally{if(i)throw i.error}}return s},c=function(){for(var e=[],t=0;t<arguments.length;t++)e=e.concat(u(arguments[t]));return e},f=new i.a("Util"),l=function(e){function t(t){var n=e.call(this,t)||this;return n.nonRetryable=!0,n}return o(t,e),t}(Error);var d=function(e,t,n){return void 0===n&&(n=3e5),function e(t,n,r,i){return void 0===i&&(i=1),s(this,void 0,void 0,(function(){var o,s;return a(this,(function(a){switch(a.label){case 0:if("function"!=typeof t)throw Error("functionToRetry must be a function");f.debug(t.name+" attempt #"+i+" with this vars: "+JSON.stringify(n)),a.label=1;case 1:return a.trys.push([1,3,,8]),[4,t.apply(void 0,c(n))];case 2:return[2,a.sent()];case 3:if(o=a.sent(),f.debug("error on "+t.name,o),(u=o)&&u.nonRetryable)throw f.debug(t.name+" non retryable error",o),o;return s=r(i,n,o),f.debug(t.name+" retrying in "+s+" ms"),!1===s?[3,6]:[4,new Promise((function(e){return setTimeout(e,s)}))];case 4:return a.sent(),[4,e(t,n,r,i+1)];case 5:return[2,a.sent()];case 6:throw o;case 7:return[3,8];case 8:return[2]}var u}))}))}(e,t,function(e){return function(t){var n=100*Math.pow(2,t)+100*Math.random();return!(n>e)&&n}}(n))}}])})); - -// version: 3.3.18 diff --git a/docs/javascript/extra.js b/docs/javascript/extra.js deleted file mode 100644 index 603c1ffc2..000000000 --- a/docs/javascript/extra.js +++ /dev/null @@ -1,76 +0,0 @@ -const Amplify = window.aws_amplify.Amplify -const Analytics = Amplify.Analytics -const KinesisFirehoseProvider = window.aws_amplify.AWSKinesisFirehoseProvider - -const awsconfig = { - "aws_project_region": "eu-west-1", - "aws_cognito_identity_pool_id": "eu-west-1:3df3caec-4bb6-4891-b154-ee940c8264b8", - "aws_cognito_region": "eu-west-1", - "aws_kinesis_firehose_stream_name": "ClickStreamKinesisFirehose-OGX7PQdrynUo", -}; - -const RUNTIME = "java" -const BASE_ORIGIN = "docs.powertools.aws.dev" - -function enableSearchOnBlurElement() { - if (document.location.hostname != BASE_ORIGIN) return // prevent unnecessary data - /* Register handler to log search on blur */ - document.addEventListener("DOMContentLoaded", function () { - recordPageView({ - prevLocation: document.referrer - }) - if (document.forms.search) { - let query = document.forms.search.query - query.addEventListener("blur", function () { - // If Search result is ever actionable - // we should populate `value` - if (this.value) { - console.info(`Search value: ${this.value}`) - recordPageView({ - searchPattern: this.value - }) - } - }) - } - }) - - // Register handler for page sections when browser history is changed - window.onpopstate = function (event) { - recordPageView({ - prevLocation: document.referrer - }) - }; -} - -const attachListeners = () => { - enableSearchOnBlurElement() -} - -const init = () => { - Analytics.addPluggable(new KinesisFirehoseProvider()) - Amplify.configure(awsconfig); - - Analytics.configure({ - AWSKinesisFirehose: { - region: awsconfig.aws_project_region - } - }) - - attachListeners() -} - -const recordPageView = ({prevLocation, searchPattern}) => { - Analytics.record({ - data: { - // Do not count page view for search - url: searchPattern ? null : window.location.href, - section: searchPattern ? null : location.pathname, - previous: prevLocation || null, - search: searchPattern || null, - language: RUNTIME - }, - streamName: awsconfig.aws_kinesis_firehose_stream_name - }, 'AWSKinesisFirehose') -} - -init() diff --git a/mkdocs.yml b/mkdocs.yml index 372dfedd7..c75fa90e7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,7 +1,7 @@ site_name: Powertools for AWS Lambda (Java) site_description: Powertools for AWS Lambda (Java) site_author: Amazon Web Services -site_url: https://docs.powertools.aws.dev/lambda/java/ +site_url: https://docs.powertools.aws.dev/lambda/java/latest/ nav: - Homepage: index.md - Changelog: changelog.md @@ -122,9 +122,8 @@ plugins: extra_css: - stylesheets/extra.css extra_javascript: - - javascript/aws-amplify.min.js - - javascript/extra.js - https://docs.powertools.aws.dev/shared/mermaid.min.js + - https://docs.aws.amazon.com/assets/js/awsdocs-boot.js extra: powertools: From 07e8948f470c9980df640f2b9b6e6ae5c15d3e7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:19:46 +0200 Subject: [PATCH 433/577] chore: bump aws.sdk.version from 2.33.2 to 2.34.5 (#2156) Bumps `aws.sdk.version` from 2.33.2 to 2.34.5. Updates `software.amazon.awssdk:bom` from 2.33.2 to 2.34.5 Updates `software.amazon.awssdk:http-client-spi` from 2.33.2 to 2.34.5 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.34.5 Updates `software.amazon.awssdk:dynamodb` from 2.33.2 to 2.34.5 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.34.5 Updates `software.amazon.awssdk:lambda` from 2.33.2 to 2.34.5 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.34.5 Updates `software.amazon.awssdk:cloudwatch` from 2.33.2 to 2.34.5 Updates `software.amazon.awssdk:xray` from 2.33.2 to 2.34.5 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.34.5 Updates `software.amazon.awssdk:cloudformation` from 2.33.2 to 2.34.5 Updates `software.amazon.awssdk:sts` from 2.33.2 to 2.34.5 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.34.5 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.34.5 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.34.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.34.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.34.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.34.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.34.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.34.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-version: 2.34.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.34.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.34.5 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-version: 2.34.5 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index eb762665b..fe2c109fb 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.33.5</aws.sdk.version> + <aws.sdk.version>2.34.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index cb14997c4..f31bcad70 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.1</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.33.5</aws.sdk.version> + <aws.sdk.version>2.34.5</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 9bc7c5e37..4145d4753 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.0</maven.compiler.version> - <aws.sdk.version>2.33.5</aws.sdk.version> + <aws.sdk.version>2.34.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From a22ab8875cf87e0bff07733c07aa281433972ac9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:20:24 +0200 Subject: [PATCH 434/577] chore: bump com.amazonaws:aws-lambda-java-runtime-interface-client (#2149) Bumps [com.amazonaws:aws-lambda-java-runtime-interface-client](https://github.com/aws/aws-lambda-java-libs) from 2.8.3 to 2.8.6. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-runtime-interface-client dependency-version: 2.8.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index fe2c109fb..c437bbe9e 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -77,7 +77,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.3</version> + <version>2.8.6</version> </dependency> </dependencies> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index a47be2458..a366097b3 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -49,7 +49,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.3</version> + <version>2.8.6</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index 7b34c94c2..956b8a9d9 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -43,7 +43,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.3</version> + <version>2.8.6</version> </dependency> <dependency> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 3bd5a5de7..d5aab7ee6 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -49,7 +49,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.3</version> + <version>2.8.6</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index a85e466fe..636435fbb 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -36,7 +36,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.3</version> + <version>2.8.6</version> </dependency> </dependencies> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 4145d4753..03188d2c4 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -120,7 +120,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.3</version> + <version>2.8.6</version> </dependency> </dependencies> </dependencyManagement> From 13499e8bef0335c82af003f84517d1962dc08cca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:21:16 +0200 Subject: [PATCH 435/577] chore: bump io.github.ascopes:protobuf-maven-plugin from 3.9.0 to 3.10.0 (#2155) Bumps [io.github.ascopes:protobuf-maven-plugin](https://github.com/ascopes/protobuf-maven-plugin) from 3.9.0 to 3.10.0. - [Release notes](https://github.com/ascopes/protobuf-maven-plugin/releases) - [Commits](https://github.com/ascopes/protobuf-maven-plugin/compare/v3.9.0...v3.10.0) --- updated-dependencies: - dependency-name: io.github.ascopes:protobuf-maven-plugin dependency-version: 3.10.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 7f9449361..8f2f16d0a 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -141,7 +141,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.9.0</version> + <version>3.10.0</version> <executions> <execution> <goals> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index b0705a204..cac2706b7 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -181,7 +181,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.9.0</version> + <version>3.10.0</version> <executions> <execution> <id>generate-test-sources</id> From e8d0d784ef8361af463d7e95398847c084ff7384 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:21:32 +0200 Subject: [PATCH 436/577] chore: bump github/codeql-action from 3.30.1 to 3.30.5 (#2157) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.1 to 3.30.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f1f6e5f6af878fb37288ce1c627459e94dbf7d01...3599b3baa15b485a2e49ef411a7a4bb2452e7f93) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 8ff72b365..83c5e64d1 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # v3.29.5 + uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.29.5 with: sarif_file: results.sarif From a770e9a09db1db0c6eb1e2629bd4c7a35f891692 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:21:52 +0200 Subject: [PATCH 437/577] chore: bump actions/dependency-review-action from 4.7.3 to 4.8.0 (#2158) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.3 to 4.8.0. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/595b5aeba73380359d98a5e087f648dbb0edce1b...56339e523c0409420f6c2c9a2f4292bbb3c07dd3) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-dependencies-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml index 903b96af9..74b9188c9 100644 --- a/.github/workflows/security-dependencies-check.yml +++ b/.github/workflows/security-dependencies-check.yml @@ -26,6 +26,6 @@ jobs: - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Verify Contents - uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # v4.7.3 + uses: actions/dependency-review-action@56339e523c0409420f6c2c9a2f4292bbb3c07dd3 # v4.8.0 with: config-file: './.github/dependency-review-config.yml' From 66c57a644eb5f20bb37b46e55a9cf7f80ae23a7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:22:21 +0200 Subject: [PATCH 438/577] chore: bump org.apache.maven.plugins:maven-failsafe-plugin (#2159) Bumps [org.apache.maven.plugins:maven-failsafe-plugin](https://github.com/apache/maven-surefire) from 3.5.3 to 3.5.4. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.3...surefire-3.5.4) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-failsafe-plugin dependency-version: 3.5.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index a0d500686..32ea35d36 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -214,7 +214,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <executions> <execution> <goals> @@ -241,7 +241,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <executions> <execution> <goals> From 5f3c5de0d98cce1f049bed378e46df6243dffdc1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:23:15 +0200 Subject: [PATCH 439/577] chore: bump log4j.version from 2.25.1 to 2.25.2 (#2160) Bumps `log4j.version` from 2.25.1 to 2.25.2. Updates `org.apache.logging.log4j:log4j-core` from 2.25.1 to 2.25.2 Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.25.1 to 2.25.2 Updates `org.apache.logging.log4j:log4j-slf4j2-impl` from 2.25.1 to 2.25.2 Updates `org.apache.logging.log4j:log4j-api` from 2.25.1 to 2.25.2 Updates `org.apache.logging.log4j:log4j-layout-template-json` from 2.25.1 to 2.25.2 Updates `org.apache.logging.log4j:log4j-jcl` from 2.25.1 to 2.25.2 --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-version: 2.25.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-slf4j-impl dependency-version: 2.25.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-slf4j2-impl dependency-version: 2.25.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-api dependency-version: 2.25.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-layout-template-json dependency-version: 2.25.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.logging.log4j:log4j-jcl dependency-version: 2.25.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index db3750e53..677a2b4b6 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -11,7 +11,7 @@ <packaging>jar</packaging> <properties> - <log4j.version>2.25.1</log4j.version> + <log4j.version>2.25.2</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index a366097b3..64649fe45 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -9,7 +9,7 @@ <packaging>jar</packaging> <properties> - <log4j.version>2.25.1</log4j.version> + <log4j.version>2.25.2</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index d5aab7ee6..45d272f70 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -8,7 +8,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> <properties> - <log4j.version>2.25.1</log4j.version> + <log4j.version>2.25.2</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/pom.xml b/pom.xml index f31bcad70..51ae56027 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <maven.deploy.plugin.version>3.1.2</maven.deploy.plugin.version> - <log4j.version>2.25.1</log4j.version> + <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> <aws.sdk.version>2.34.5</aws.sdk.version> From f37a4a4cb2f65bd78efaa59a1f11a8d4cdf34090 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:23:33 +0200 Subject: [PATCH 440/577] chore: bump squidfunk/mkdocs-material in /docs (#2164) Bumps squidfunk/mkdocs-material from `86d21da` to `00f9276`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: 00f9276315990b82f5af8c47bb2b71e2c69aef9f02a08f8dffd2515f42310753 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 696d43a12..fe4f2ec55 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -FROM squidfunk/mkdocs-material@sha256:86d21da4f45f16e30774bf911e5b4795da13ce0cd197dbf8d3d059f256b2cc37 +FROM squidfunk/mkdocs-material@sha256:00f9276315990b82f5af8c47bb2b71e2c69aef9f02a08f8dffd2515f42310753 COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From 8a19a2971e827412e28155f92aded425ce722948 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:23:57 +0200 Subject: [PATCH 441/577] chore: bump ossf/scorecard-action from 2.4.2 to 2.4.3 (#2165) Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.2 to 2.4.3. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/05b42c624433fc40578a4040d5cf5e36ddca8cde...4eaacf0543bb3f2c246792bd56e8cdeffafb205a) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-version: 2.4.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 83c5e64d1..243d2f523 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -39,7 +39,7 @@ jobs: with: persist-credentials: false - name: Run Analysis - uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3 with: results_file: results.sarif results_format: sarif From 7762b86771a896377ed12a840894db77253ecd5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 15:11:51 +0200 Subject: [PATCH 442/577] chore: bump graalvm/setup-graalvm from 1.3.6 to 1.4.1 (#2168) Bumps [graalvm/setup-graalvm](https://github.com/graalvm/setup-graalvm) from 1.3.6 to 1.4.1. - [Release notes](https://github.com/graalvm/setup-graalvm/releases) - [Commits](https://github.com/graalvm/setup-graalvm/compare/7a1da54cb7fdef4ea19f6ecdfa9ecf59dc5a48fe...2a2412009026a83f51d179f92dc2b3fd4c8142df) --- updated-dependencies: - dependency-name: graalvm/setup-graalvm dependency-version: 1.4.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 09a232188..0167925f4 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -102,7 +102,7 @@ jobs: powertools-*/** pom.xml - name: Setup GraalVM - uses: graalvm/setup-graalvm@7a1da54cb7fdef4ea19f6ecdfa9ecf59dc5a48fe # v1.3.6 + uses: graalvm/setup-graalvm@2a2412009026a83f51d179f92dc2b3fd4c8142df # v1.4.1 with: java-version: "21" distribution: "graalvm" From 53adbe25b1f4b6d5000f326a52f271e661e0ab9d Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Fri, 3 Oct 2025 11:18:45 +0200 Subject: [PATCH 443/577] chore(docs): Add AWS docs meta tags (#2170) * Add docs meta tags. * Use full Powertools names. --- docs/overrides/main.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/overrides/main.html b/docs/overrides/main.html index e4c38e21b..5f7a59c02 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -6,3 +6,8 @@ <strong>Click here to go to latest.</strong> </a> {% endblock %} + +{% block extrahead %} + <meta name="guide-name" content="Powertools for AWS Lambda (Java)"> + <meta name="service-name" content="Powertools for AWS Lambda"> +{% endblock %} From 267f009897671274adc0b8939899ab4f976e4fa4 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 7 Oct 2025 11:09:52 +0200 Subject: [PATCH 444/577] chore: Add User-Agent execution interceptors (#2166) --- powertools-batch/pom.xml | 23 ++++++--- .../internal/BatchUserAgentInterceptor.java | 37 ++++++++++++++ .../global/handlers/execution.interceptors | 1 + .../BatchUserAgentInterceptorTest.java | 34 +++++++++++++ powertools-cloudformation/pom.xml | 14 ++++++ .../CloudformationUserAgentInterceptor.java | 37 ++++++++++++++ .../reflect-config.json | 4 ++ .../resource-config.json | 2 + .../global/handlers/execution.interceptors | 1 + ...loudformationUserAgentInterceptorTest.java | 34 +++++++++++++ .../internal/UserAgentConfigurator.java | 49 +++++++++++++------ .../internal/UserAgentConfiguratorTest.java | 39 ++++++++++++--- .../powertools-idempotency-dynamodb/pom.xml | 9 ++++ ...empotencyDynamodbUserAgentInterceptor.java | 37 ++++++++++++++ .../reflect-config.json | 4 ++ .../global/handlers/execution.interceptors | 1 + ...tencyDynamodbUserAgentInterceptorTest.java | 34 +++++++++++++ powertools-kafka/pom.xml | 15 ++++++ .../internal/KafkaUserAgentInterceptor.java | 37 ++++++++++++++ .../global/handlers/execution.interceptors | 1 + .../KafkaUserAgentInterceptorTest.java | 34 +++++++++++++ .../LargeMessagesUserAgentInterceptor.java | 37 ++++++++++++++ .../global/handlers/execution.interceptors | 1 + ...LargeMessagesUserAgentInterceptorTest.java | 34 +++++++++++++ .../powertools-logging-log4j/pom.xml | 10 ++++ .../internal/Log4jUserAgentInterceptor.java | 37 ++++++++++++++ .../reflect-config.json | 4 ++ .../resource-config.json | 2 + .../global/handlers/execution.interceptors | 1 + .../Log4jUserAgentInterceptorTest.java | 34 +++++++++++++ .../powertools-logging-logback/pom.xml | 10 ++++ .../internal/LogbackUserAgentInterceptor.java | 37 ++++++++++++++ .../reflect-config.json | 4 ++ .../resource-config.json | 2 + .../global/handlers/execution.interceptors | 1 + .../LogbackUserAgentInterceptorTest.java | 34 +++++++++++++ powertools-metrics/pom.xml | 10 ++++ .../internal/MetricsUserAgentInterceptor.java | 37 ++++++++++++++ .../powertools-metrics/reflect-config.json | 4 ++ .../powertools-metrics/resource-config.json | 3 ++ .../global/handlers/execution.interceptors | 1 + .../MetricsUserAgentInterceptorTest.java | 34 +++++++++++++ .../powertools-parameters-appconfig/pom.xml | 9 ++++ ...rametersAppconfigUserAgentInterceptor.java | 37 ++++++++++++++ .../reflect-config.json | 4 ++ .../global/handlers/execution.interceptors | 1 + ...tersAppconfigUserAgentInterceptorTest.java | 34 +++++++++++++ .../powertools-parameters-dynamodb/pom.xml | 9 ++++ ...arametersDynamodbUserAgentInterceptor.java | 37 ++++++++++++++ .../reflect-config.json | 4 ++ .../global/handlers/execution.interceptors | 1 + ...etersDynamodbUserAgentInterceptorTest.java | 34 +++++++++++++ .../powertools-parameters-secrets/pom.xml | 9 ++++ ...ParametersSecretsUserAgentInterceptor.java | 37 ++++++++++++++ .../reflect-config.json | 4 ++ .../global/handlers/execution.interceptors | 1 + ...metersSecretsUserAgentInterceptorTest.java | 34 +++++++++++++ .../powertools-parameters-ssm/pom.xml | 9 ++++ .../ParametersSsmUserAgentInterceptor.java | 37 ++++++++++++++ .../reflect-config.json | 4 ++ .../global/handlers/execution.interceptors | 1 + ...ParametersSsmUserAgentInterceptorTest.java | 34 +++++++++++++ powertools-tracing/pom.xml | 9 ++++ .../internal/TracingUserAgentInterceptor.java | 37 ++++++++++++++ .../powertools-tracing/reflect-config.json | 4 ++ .../powertools-tracing/resource-config.json | 2 + .../global/handlers/execution.interceptors | 1 + .../TracingUserAgentInterceptorTest.java | 34 +++++++++++++ powertools-validation/pom.xml | 10 ++++ .../ValidationUserAgentInterceptor.java | 37 ++++++++++++++ .../global/handlers/execution.interceptors | 1 + .../ValidationUserAgentInterceptorTest.java | 34 +++++++++++++ 72 files changed, 1263 insertions(+), 30 deletions(-) create mode 100644 powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptor.java create mode 100644 powertools-batch/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptorTest.java create mode 100644 powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptor.java create mode 100644 powertools-cloudformation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptorTest.java create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptor.java create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptorTest.java create mode 100644 powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptor.java create mode 100644 powertools-kafka/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptorTest.java create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptor.java create mode 100644 powertools-large-messages/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptorTest.java create mode 100644 powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptor.java create mode 100644 powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptorTest.java create mode 100644 powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptor.java create mode 100644 powertools-logging/powertools-logging-logback/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptorTest.java create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java create mode 100644 powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptorTest.java create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptor.java create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptorTest.java create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptor.java create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptorTest.java create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptor.java create mode 100644 powertools-parameters/powertools-parameters-secrets/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptorTest.java create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptor.java create mode 100644 powertools-parameters/powertools-parameters-ssm/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptorTest.java create mode 100644 powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptor.java create mode 100644 powertools-tracing/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptorTest.java create mode 100644 powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptor.java create mode 100644 powertools-validation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors create mode 100644 powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptorTest.java diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index b389df6fe..850be6922 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -50,6 +50,16 @@ <artifactId>powertools-serialization</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + <scope>provided</scope> + </dependency> <!-- Test dependencies --> <dependency> @@ -57,12 +67,6 @@ <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-simple</artifactId> - <version>2.0.17</version> - <scope>test</scope> - </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> @@ -83,6 +87,11 @@ <artifactId>slf4j-simple</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> -</project> \ No newline at end of file +</project> diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptor.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptor.java new file mode 100644 index 000000000..f49dbe5c5 --- /dev/null +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.batch.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-batch module is on the classpath. + */ +public final class BatchUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("batch"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-batch/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-batch/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..51764f87f --- /dev/null +++ b/powertools-batch/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.batch.internal.BatchUserAgentInterceptor diff --git a/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptorTest.java b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptorTest.java new file mode 100644 index 000000000..2841a1724 --- /dev/null +++ b/powertools-batch/src/test/java/software/amazon/lambda/powertools/batch/internal/BatchUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.batch.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class BatchUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/BATCH/"); + } +} diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index ca4e7536f..d49fcc2bc 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -42,6 +42,10 @@ <groupId>software.amazon.awssdk</groupId> <artifactId>url-connection-client</artifactId> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> @@ -58,6 +62,11 @@ <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + </dependency> <!-- Test dependencies --> <dependency> @@ -102,6 +111,11 @@ <type>test-jar</type> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptor.java b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptor.java new file mode 100644 index 000000000..c225512d1 --- /dev/null +++ b/powertools-cloudformation/src/main/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.cloudformation.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-cloudformation module is on the classpath. + */ +public final class CloudformationUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("cloudformation"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json index 218382888..092ef9b54 100644 --- a/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json +++ b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/reflect-config.json @@ -428,5 +428,9 @@ { "name":"sun.security.x509.SubjectKeyIdentifierExtension", "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"software.amazon.lambda.powertools.cloudformation.internal.CloudformationUserAgentInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] } ] diff --git a/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json index f3b58337b..cbbfb270d 100644 --- a/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json +++ b/powertools-cloudformation/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-cloudformation/resource-config.json @@ -30,6 +30,8 @@ "pattern":"\\Qorg/eclipse/jetty/version/build.properties\\E" }, { "pattern":"\\Qorg/publicsuffix/list/effective_tld_names.dat\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" }]}, "bundles":[{ "name":"jakarta.servlet.LocalStrings", diff --git a/powertools-cloudformation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-cloudformation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..172ca1d2c --- /dev/null +++ b/powertools-cloudformation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.cloudformation.internal.CloudformationUserAgentInterceptor diff --git a/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptorTest.java b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptorTest.java new file mode 100644 index 000000000..ee500d006 --- /dev/null +++ b/powertools-cloudformation/src/test/java/software/amazon/lambda/powertools/cloudformation/internal/CloudformationUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.cloudformation.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class CloudformationUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/CLOUDFORMATION/"); + } +} diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java index d2e592902..7deca89f1 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java @@ -18,26 +18,27 @@ import java.io.IOException; import java.io.InputStream; +import java.util.Locale; import java.util.Properties; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; - /** * Can be used to create a string that can server as a User-Agent suffix in requests made with the AWS SDK clients */ -public class UserAgentConfigurator { - +public final class UserAgentConfigurator { public static final String NA = "NA"; public static final String VERSION_KEY = "powertools.version"; public static final String PT_FEATURE_VARIABLE = "${PT_FEATURE}"; public static final String PT_EXEC_ENV_VARIABLE = "${PT_EXEC_ENV}"; public static final String VERSION_PROPERTIES_FILENAME = "version.properties"; public static final String AWS_EXECUTION_ENV = "AWS_EXECUTION_ENV"; + private static final String SDK_USER_AGENT_APP_ID = "sdk.ua.appId"; private static final Logger LOG = LoggerFactory.getLogger(UserAgentConfigurator.class); private static final String NO_OP = "no-op"; private static final String POWERTOOLS_VERSION = getProjectVersion(); - private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTEnv/" + private static final String USER_AGENT_PATTERN = "PT/" + PT_FEATURE_VARIABLE + "/" + POWERTOOLS_VERSION + " PTENV/" + PT_EXEC_ENV_VARIABLE; private UserAgentConfigurator() { @@ -53,7 +54,6 @@ static String getProjectVersion() { return getVersionFromProperties(VERSION_PROPERTIES_FILENAME, VERSION_KEY); } - /** * Retrieves the project version from a properties file. * The file should be in the resources folder. @@ -64,28 +64,46 @@ static String getProjectVersion() { * @return the version of the project as configured in the given properties file */ static String getVersionFromProperties(String propertyFileName, String versionKey) { - - InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(propertyFileName); - - if (is != null) { - try { + try (InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(propertyFileName)) { + if (is != null) { Properties properties = new Properties(); properties.load(is); String version = properties.getProperty(versionKey); if (version != null && !version.isEmpty()) { return version; } - } catch (IOException e) { - LOG.warn("Unable to read {} file. Using default version.", propertyFileName); - LOG.debug("Exception:", e); } + } catch (IOException e) { + LOG.warn("Unable to read {} file. Using default version.", propertyFileName); + LOG.debug("Exception:", e); } return NA; } + /** + * Configures the AWS SDK to use Powertools user agent by setting the sdk.ua.appId system property. + * If the property is already set and not empty, appends the Powertools user agent with a "/" separator. + * This should be called during library initialization to ensure the user agent is properly configured. + */ + public static void configureUserAgent(String ptFeature) { + try { + String existingValue = System.getProperty(SDK_USER_AGENT_APP_ID); + String powertoolsUserAgent = getUserAgent(ptFeature); + + if (existingValue != null && !existingValue.isEmpty()) { + System.setProperty(SDK_USER_AGENT_APP_ID, existingValue + "/" + powertoolsUserAgent); + } else { + System.setProperty(SDK_USER_AGENT_APP_ID, powertoolsUserAgent); + } + } catch (Exception e) { + // We don't re-raise since we don't want to break the user if something in this logic doesn't work + LOG.warn("Unable to configure user agent system property", e); + } + } + /** * Retrieves the user agent string for the Powertools for AWS Lambda. - * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTEnv/{PT_EXEC_ENV} + * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTENV/{PT_EXEC_ENV} * The version of the project is automatically retrieved. * The PT_EXEC_ENV is automatically retrieved from the AWS_EXECUTION_ENV environment variable. * If it AWS_EXECUTION_ENV is not set, PT_EXEC_ENV defaults to "NA" @@ -96,7 +114,6 @@ static String getVersionFromProperties(String propertyFileName, String versionKe * @return the user agent string */ public static String getUserAgent(String ptFeature) { - String awsExecutionEnv = getenv(AWS_EXECUTION_ENV); String ptExecEnv = awsExecutionEnv != null ? awsExecutionEnv : NA; String userAgent = USER_AGENT_PATTERN.replace(PT_EXEC_ENV_VARIABLE, ptExecEnv); @@ -105,7 +122,7 @@ public static String getUserAgent(String ptFeature) { ptFeature = NO_OP; } return userAgent - .replace(PT_FEATURE_VARIABLE, ptFeature) + .replace(PT_FEATURE_VARIABLE, ptFeature.toUpperCase(Locale.ROOT)) .replace(PT_EXEC_ENV_VARIABLE, ptExecEnv); } } diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java index 0c7935a55..fbe4529d8 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java @@ -31,11 +31,9 @@ class UserAgentConfiguratorTest { - private static final String SEM_VER_PATTERN = - "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"; + private static final String SEM_VER_PATTERN = "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"; private static final String VERSION = UserAgentConfigurator.getProjectVersion(); - @Test void testGetVersion() { @@ -91,7 +89,7 @@ void testGetUserAgent() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/NA"); + .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); } @@ -101,7 +99,7 @@ void testGetUserAgent_NoFeature() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA"); + .isEqualTo("PT/NO-OP/" + VERSION + " PTENV/NA"); } @Test @@ -110,7 +108,7 @@ void testGetUserAgent_NullFeature() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/no-op/" + VERSION + " PTEnv/NA"); + .isEqualTo("PT/NO-OP/" + VERSION + " PTENV/NA"); } @Test @@ -120,7 +118,34 @@ void testGetUserAgent_SetAWSExecutionEnv() { assertThat(userAgent) .isNotNull() - .isEqualTo("PT/test-feature/" + VERSION + " PTEnv/AWS_Lambda_java8"); + .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/AWS_Lambda_java8"); + } + + @Test + void testConfigureUserAgent() { + System.clearProperty("sdk.ua.appId"); + UserAgentConfigurator.configureUserAgent("test-feature"); + + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); + } + + @Test + void testConfigureUserAgent_WithExistingValue() { + System.setProperty("sdk.ua.appId", "UserValueABC123"); + UserAgentConfigurator.configureUserAgent("test-feature"); + + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("UserValueABC123/PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); + } + + @Test + void testConfigureUserAgent_WithEmptyExistingValue() { + System.setProperty("sdk.ua.appId", ""); + UserAgentConfigurator.configureUserAgent("test-feature"); + + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); } } diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index 191d75eeb..885c9c9cd 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -57,6 +57,10 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + </dependency> <dependency> <groupId>org.crac</groupId> <artifactId>crac</artifactId> @@ -94,6 +98,11 @@ <version>2.2.0</version> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptor.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptor.java new file mode 100644 index 000000000..98d7a7440 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.idempotency.dynamodb.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-idempotency-dynamodb module is on the classpath. + */ +public final class IdempotencyDynamodbUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("idempotency-dynamodb"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json index f0ba9c4c2..6d6fbceb3 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-idempotency-dynamodb/reflect-config.json @@ -321,5 +321,9 @@ { "name":"sun.security.x509.SubjectKeyIdentifierExtension", "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"software.amazon.lambda.powertools.idempotency.dynamodb.internal.IdempotencyDynamodbUserAgentInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] } ] diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..a04caa403 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.idempotency.dynamodb.internal.IdempotencyDynamodbUserAgentInterceptor diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptorTest.java b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptorTest.java new file mode 100644 index 000000000..e6940a760 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-dynamodb/src/test/java/software/amazon/lambda/powertools/idempotency/dynamodb/internal/IdempotencyDynamodbUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.idempotency.dynamodb.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class IdempotencyDynamodbUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/IDEMPOTENCY-DYNAMODB/"); + } +} diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index cac2706b7..65cd7051d 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -78,6 +78,16 @@ <artifactId>aws-lambda-java-serialization</artifactId> <version>${lambda-serialization.version}</version> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + <scope>provided</scope> + </dependency> <!-- Test dependencies --> <dependency> @@ -120,6 +130,11 @@ <artifactId>assertj-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <build> diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptor.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptor.java new file mode 100644 index 000000000..2db4789b3 --- /dev/null +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.kafka.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-kafka module is on the classpath. + */ +public final class KafkaUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("kafka"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-kafka/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-kafka/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..1ce363ad9 --- /dev/null +++ b/powertools-kafka/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.kafka.internal.KafkaUserAgentInterceptor diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptorTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptorTest.java new file mode 100644 index 000000000..4323a42e9 --- /dev/null +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/internal/KafkaUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.kafka.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class KafkaUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/KAFKA/"); + } +} \ No newline at end of file diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptor.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptor.java new file mode 100644 index 000000000..87d179dd7 --- /dev/null +++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.largemessages.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-largemessages module is on the classpath. + */ +public final class LargeMessagesUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("large-messages"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-large-messages/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-large-messages/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..ab5a6f378 --- /dev/null +++ b/powertools-large-messages/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.largemessages.internal.LargeMessagesUserAgentInterceptor diff --git a/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptorTest.java b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptorTest.java new file mode 100644 index 000000000..b32ee1176 --- /dev/null +++ b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessagesUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.largemessages.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class LargeMessagesUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/LARGE-MESSAGES/"); + } +} \ No newline at end of file diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 92283b0cf..2b85a3752 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -39,6 +39,11 @@ <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-layout-template-json</artifactId> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + <scope>provided</scope> + </dependency> <!-- Test dependencies --> <dependency> @@ -93,6 +98,11 @@ <type>test-jar</type> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> <profile> diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptor.java b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptor.java new file mode 100644 index 000000000..510ee858c --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.logging.log4j.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-logging-log4j module is on the classpath. + */ +public final class Log4jUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("logging-log4j"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json index adbd9e0c1..6cbbee583 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json @@ -1083,5 +1083,9 @@ "name":"software.amazon.lambda.powertools.logging.log4j.BufferingAppender", "queryAllDeclaredMethods":true, "methods":[{"name":"createAppender","parameterTypes":["java.lang.String","org.apache.logging.log4j.core.Filter","org.apache.logging.log4j.core.Layout","org.apache.logging.log4j.core.config.AppenderRef[]","org.apache.logging.log4j.core.config.Configuration","java.lang.String","int","boolean"] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.log4j.internal.Log4jUserAgentInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] } ] diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json index cf017fdeb..a4bcd55fa 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/resource-config.json @@ -34,6 +34,8 @@ "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" }, { "pattern":"\\QStackTraceElementLayout.json\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" }]}, "bundles":[] } diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..22150f4b7 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.logging.log4j.internal.Log4jUserAgentInterceptor diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptorTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptorTest.java new file mode 100644 index 000000000..77d5b06e3 --- /dev/null +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/internal/Log4jUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.logging.log4j.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class Log4jUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/LOGGING-LOG4J/"); + } +} diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index ff0312001..17e39dda7 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -36,6 +36,11 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + <scope>provided</scope> + </dependency> <!-- Test dependencies --> <dependency> @@ -90,6 +95,11 @@ <artifactId>junit-pioneer</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptor.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptor.java new file mode 100644 index 000000000..c35171a01 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.logging.logback.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-logging-logback module is on the classpath. + */ +public final class LogbackUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("logging-logback"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json index dfc50427f..d4f4a4d7d 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json @@ -179,5 +179,9 @@ "name":"software.amazon.lambda.powertools.logging.logback.LambdaJsonEncoder", "queryAllPublicMethods":true, "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.logging.logback.internal.LogbackUserAgentInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] } ] diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json index 33d1d61c4..b60a39ad5 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/resource-config.json @@ -10,6 +10,8 @@ "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" }, { "pattern":"\\QMETA-INF/services/software.amazon.lambda.powertools.logging.internal.LoggingManager\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" }]}, "bundles":[] } diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-logging/powertools-logging-logback/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..1ce49119f --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.logging.logback.internal.LogbackUserAgentInterceptor diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptorTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptorTest.java new file mode 100644 index 000000000..622343668 --- /dev/null +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/logback/internal/LogbackUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.logging.logback.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class LogbackUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/LOGGING-LOGBACK/"); + } +} diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index c1ac723f1..58eab8a45 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -73,6 +73,11 @@ <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + <scope>provided</scope> + </dependency> <!-- Test dependencies --> <dependency> @@ -117,6 +122,11 @@ <type>test-jar</type> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java new file mode 100644 index 000000000..5a466cc3a --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.metrics.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the metrics module is on the classpath. + */ +public final class MetricsUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("metrics"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json index 43b2822d6..533335782 100644 --- a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json +++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json @@ -148,5 +148,9 @@ "name": "software.amazon.lambda.powertools.metrics.provider.MetricsProvider", "allDeclaredClasses": true, "queryAllPublicMethods": true + }, + { + "name": "software.amazon.lambda.powertools.metrics.internal.MetricsUserAgentInterceptor", + "methods": [{ "name": "<init>", "parameterTypes": [] }] } ] diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json index d47298855..0667ee26a 100644 --- a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json +++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/resource-config.json @@ -6,6 +6,9 @@ }, { "pattern": "\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, + { + "pattern": "\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" } ] }, diff --git a/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..38e53da3e --- /dev/null +++ b/powertools-metrics/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.metrics.internal.MetricsUserAgentInterceptor diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptorTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptorTest.java new file mode 100644 index 000000000..673f9f7d4 --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/MetricsUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.metrics.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class MetricsUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/METRICS/"); + } +} diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index bbb6a1111..b2c4f3426 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -35,6 +35,10 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> @@ -82,6 +86,11 @@ <artifactId>aspectjweaver</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptor.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptor.java new file mode 100644 index 000000000..01fc8d096 --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.parameters.appconfig.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-parameters-appconfig module is on the classpath. + */ +public final class ParametersAppconfigUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("parameters-appconfig"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json index 7e7b40197..b9ae934d6 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-appconfig/reflect-config.json @@ -361,5 +361,9 @@ { "name":"sun.security.x509.SubjectKeyIdentifierExtension", "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.appconfig.internal.ParametersAppconfigUserAgentInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] } ] diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..c37ecc083 --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.parameters.appconfig.internal.ParametersAppconfigUserAgentInterceptor diff --git a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptorTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptorTest.java new file mode 100644 index 000000000..124b71ef3 --- /dev/null +++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/internal/ParametersAppconfigUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.parameters.appconfig.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class ParametersAppconfigUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/PARAMETERS-APPCONFIG/"); + } +} \ No newline at end of file diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index fa969e585..e03227eb8 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -36,6 +36,10 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> @@ -83,6 +87,11 @@ <artifactId>aspectjweaver</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptor.java b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptor.java new file mode 100644 index 000000000..0b8b01dcb --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.parameters.dynamodb.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-parameters-dynamodb module is on the classpath. + */ +public final class ParametersDynamodbUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("parameters-dynamodb"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json index 77e953aac..e49454b83 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-dynamodb/reflect-config.json @@ -322,5 +322,9 @@ { "name":"sun.security.x509.SubjectKeyIdentifierExtension", "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.dynamodb.internal.ParametersDynamodbUserAgentInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] } ] diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..f7de6e9be --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.parameters.dynamodb.internal.ParametersDynamodbUserAgentInterceptor diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptorTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptorTest.java new file mode 100644 index 000000000..f9c8ebea5 --- /dev/null +++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/internal/ParametersDynamodbUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.parameters.dynamodb.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class ParametersDynamodbUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/PARAMETERS-DYNAMODB/"); + } +} \ No newline at end of file diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 55c254f88..6a576f529 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -36,6 +36,10 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> @@ -83,6 +87,11 @@ <artifactId>aspectjweaver</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptor.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptor.java new file mode 100644 index 000000000..e3eda5889 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.parameters.secrets.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-parameters-secrets module is on the classpath. + */ +public final class ParametersSecretsUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("parameters-secrets"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json b/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json index 7dfaf1b03..097a30784 100644 --- a/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json +++ b/powertools-parameters/powertools-parameters-secrets/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-secrets/reflect-config.json @@ -319,5 +319,9 @@ { "name":"sun.security.x509.SubjectKeyIdentifierExtension", "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.secrets.internal.ParametersSecretsUserAgentInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] } ] diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-parameters/powertools-parameters-secrets/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..ca08369c5 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.parameters.secrets.internal.ParametersSecretsUserAgentInterceptor diff --git a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptorTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptorTest.java new file mode 100644 index 000000000..6d59ff717 --- /dev/null +++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/internal/ParametersSecretsUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.parameters.secrets.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class ParametersSecretsUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/PARAMETERS-SECRETS/"); + } +} \ No newline at end of file diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index d1dc88d84..7758fd906 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -36,6 +36,10 @@ </exclusion> </exclusions> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> @@ -83,6 +87,11 @@ <artifactId>aspectjweaver</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <build> diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptor.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptor.java new file mode 100644 index 000000000..ad1ff65dc --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.parameters.ssm.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-parameters-ssm module is on the classpath. + */ +public final class ParametersSsmUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("parameters-ssm"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json b/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json index 5bc2deb4a..a655e62ce 100644 --- a/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json +++ b/powertools-parameters/powertools-parameters-ssm/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-parameters-ssm/reflect-config.json @@ -337,5 +337,9 @@ { "name":"sun.security.x509.SubjectKeyIdentifierExtension", "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }] +}, +{ + "name":"software.amazon.lambda.powertools.parameters.ssm.internal.ParametersSsmUserAgentInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] } ] diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-parameters/powertools-parameters-ssm/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..4cce863f6 --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.parameters.ssm.internal.ParametersSsmUserAgentInterceptor diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptorTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptorTest.java new file mode 100644 index 000000000..8f6db7e21 --- /dev/null +++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/internal/ParametersSsmUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.parameters.ssm.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class ParametersSsmUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/PARAMETERS-SSM/"); + } +} \ No newline at end of file diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 6081abd66..045e76cbf 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -46,6 +46,10 @@ <groupId>software.amazon.awssdk</groupId> <artifactId>aws-core</artifactId> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> @@ -118,6 +122,11 @@ <artifactId>assertj-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptor.java b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptor.java new file mode 100644 index 000000000..489243517 --- /dev/null +++ b/powertools-tracing/src/main/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.tracing.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-tracing module is on the classpath. + */ +public final class TracingUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("tracing"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json index 94a514dee..a71154276 100644 --- a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json +++ b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json @@ -361,5 +361,9 @@ { "name":"sun.security.provider.SHA", "methods":[{"name":"<init>","parameterTypes":[] }] +}, +{ + "name":"software.amazon.lambda.powertools.tracing.internal.TracingUserAgentInterceptor", + "methods":[{"name":"<init>","parameterTypes":[] }] } ] diff --git a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json index 2ac72d18f..64408b8b6 100644 --- a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json +++ b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/resource-config.json @@ -26,6 +26,8 @@ "pattern":"\\Qcommons-logging.properties\\E" }, { "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E" + }, { + "pattern":"\\Qsoftware/amazon/awssdk/global/handlers/execution.interceptors\\E" }]}, "bundles":[] } diff --git a/powertools-tracing/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-tracing/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..5f15a8000 --- /dev/null +++ b/powertools-tracing/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.tracing.internal.TracingUserAgentInterceptor diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptorTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptorTest.java new file mode 100644 index 000000000..b24f6c6f7 --- /dev/null +++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/TracingUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.tracing.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class TracingUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/TRACING/"); + } +} \ No newline at end of file diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 1c048e66a..6ecee16a1 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -75,6 +75,11 @@ <groupId>org.crac</groupId> <artifactId>crac</artifactId> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>sdk-core</artifactId> + <scope>provided</scope> + </dependency> <!-- Test dependencies --> <dependency> @@ -122,6 +127,11 @@ <artifactId>junit-jupiter-params</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>s3</artifactId> + <scope>test</scope> + </dependency> </dependencies> <profiles> diff --git a/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptor.java b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptor.java new file mode 100644 index 000000000..ee92ff367 --- /dev/null +++ b/powertools-validation/src/main/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptor.java @@ -0,0 +1,37 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.validation.internal; + +import software.amazon.awssdk.core.SdkRequest; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.lambda.powertools.common.internal.UserAgentConfigurator; + +/** + * Global interceptor that configures the User-Agent for all AWS SDK clients + * when the powertools-validation module is on the classpath. + */ +public final class ValidationUserAgentInterceptor implements ExecutionInterceptor { + static { + UserAgentConfigurator.configureUserAgent("validation"); + } + + @Override + public SdkRequest modifyRequest(Context.ModifyRequest context, ExecutionAttributes executionAttributes) { + // This is a no-op interceptor. We use this class to configure the PT User-Agent in the static block. It is + // loaded by AWS SDK Global Interceptors. + return context.request(); + } +} diff --git a/powertools-validation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors b/powertools-validation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors new file mode 100644 index 000000000..bcaa3fabf --- /dev/null +++ b/powertools-validation/src/main/resources/software/amazon/awssdk/global/handlers/execution.interceptors @@ -0,0 +1 @@ +software.amazon.lambda.powertools.validation.internal.ValidationUserAgentInterceptor diff --git a/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptorTest.java b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptorTest.java new file mode 100644 index 000000000..9bacf33f9 --- /dev/null +++ b/powertools-validation/src/test/java/software/amazon/lambda/powertools/validation/internal/ValidationUserAgentInterceptorTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package software.amazon.lambda.powertools.validation.internal; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; + +import static org.assertj.core.api.Assertions.assertThat; + +class ValidationUserAgentInterceptorTest { + + @Test + void shouldConfigureUserAgentWhenCreatingAwsSdkClient() { + // WHEN creating an AWS SDK client, the interceptor should be loaded + // We use S3 client but it can be any arbitrary AWS SDK client + S3Client.builder().region(Region.US_EAST_1).build(); + + // THEN the user agent system property should be set + String userAgent = System.getProperty("sdk.ua.appId"); + assertThat(userAgent).contains("PT/VALIDATION/"); + } +} From 3e7ed05aabc56270ff43e41e9512a6181ccb7588 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:48:41 +0200 Subject: [PATCH 445/577] chore: bump org.apache.maven.plugins:maven-artifact-plugin (#2171) Bumps [org.apache.maven.plugins:maven-artifact-plugin](https://github.com/apache/maven-artifact-plugin) from 3.6.0 to 3.6.1. - [Release notes](https://github.com/apache/maven-artifact-plugin/releases) - [Commits](https://github.com/apache/maven-artifact-plugin/compare/maven-artifact-plugin-3.6.0...maven-artifact-plugin-3.6.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-artifact-plugin dependency-version: 3.6.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 51ae56027..801036a2e 100644 --- a/pom.xml +++ b/pom.xml @@ -466,7 +466,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-artifact-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <configuration> <reproducible>true</reproducible> </configuration> From 3273f4fc6fd18e36d9fabf9b6d716433295e6874 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:48:54 +0200 Subject: [PATCH 446/577] chore: bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0 (#2172) Bumps org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.19.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 801036a2e..9084e0b1c 100644 --- a/pom.xml +++ b/pom.xml @@ -310,7 +310,7 @@ <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> - <version>3.18.0</version> + <version>3.19.0</version> </dependency> <!-- Test dependencies --> From 44ed8c29f27797ea44f2caa44108e92807d944ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:49:05 +0200 Subject: [PATCH 447/577] chore: bump aws.sdk.version from 2.34.5 to 2.34.9 (#2174) Bumps `aws.sdk.version` from 2.34.5 to 2.34.9. Updates `software.amazon.awssdk:bom` from 2.34.5 to 2.34.9 Updates `software.amazon.awssdk:http-client-spi` from 2.34.5 to 2.34.9 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.34.9 Updates `software.amazon.awssdk:dynamodb` from 2.34.5 to 2.34.9 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.34.9 Updates `software.amazon.awssdk:lambda` from 2.34.5 to 2.34.9 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.34.9 Updates `software.amazon.awssdk:cloudwatch` from 2.34.5 to 2.34.9 Updates `software.amazon.awssdk:xray` from 2.34.5 to 2.34.9 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.34.9 Updates `software.amazon.awssdk:cloudformation` from 2.34.5 to 2.34.9 Updates `software.amazon.awssdk:sts` from 2.34.5 to 2.34.9 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.34.9 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.34.9 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.34.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.34.9 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.34.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.34.9 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.34.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.34.9 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.34.9 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.34.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.34.9 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.34.9 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index c437bbe9e..a1f4aadc3 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.34.5</aws.sdk.version> + <aws.sdk.version>2.34.9</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 9084e0b1c..133e7d88c 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.34.5</aws.sdk.version> + <aws.sdk.version>2.34.9</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 03188d2c4..201f38c7f 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.0</maven.compiler.version> - <aws.sdk.version>2.34.5</aws.sdk.version> + <aws.sdk.version>2.34.9</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 26c80fc47b2c0cb5c69571cd8f352110555fc0c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:49:17 +0200 Subject: [PATCH 448/577] chore: bump com.google.protobuf:protobuf-java from 4.32.0 to 4.32.1 (#2175) Bumps [com.google.protobuf:protobuf-java](https://github.com/protocolbuffers/protobuf) from 4.32.0 to 4.32.1. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl) - [Commits](https://github.com/protocolbuffers/protobuf/commits) --- updated-dependencies: - dependency-name: com.google.protobuf:protobuf-java dependency-version: 4.32.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 8f2f16d0a..8a0ac2d89 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -12,7 +12,7 @@ <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> <avro.version>1.12.0</avro.version> - <protobuf.version>4.32.0</protobuf.version> + <protobuf.version>4.32.1</protobuf.version> </properties> <dependencies> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 65cd7051d..b1f1afd3e 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -36,7 +36,7 @@ <properties> <kafka-clients.version>4.1.0</kafka-clients.version> <avro.version>1.12.0</avro.version> - <protobuf.version>4.32.0</protobuf.version> + <protobuf.version>4.32.1</protobuf.version> <lambda-serialization.version>1.1.6</lambda-serialization.version> </properties> From f3689c89b875276e977e8efa641d0e84fc61c00a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:49:32 +0200 Subject: [PATCH 449/577] chore: bump aws-actions/configure-aws-credentials from 5.0.0 to 5.1.0 (#2177) Bumps [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) from 5.0.0 to 5.1.0. - [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases) - [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/a03048d87541d1d9fcf2ecf528a4a65ba9bd7838...00943011d9042930efac3dcd3a170e4273319bc8) --- updated-dependencies: - dependency-name: aws-actions/configure-aws-credentials dependency-version: 5.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 2 +- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/release.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index a9d3fbf7b..8cef6040e 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -41,7 +41,7 @@ jobs: docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 + uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index f18964852..a3c4a7542 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -64,7 +64,7 @@ jobs: java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v5.0.0 + uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 # v5.1.0 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -97,7 +97,7 @@ jobs: java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v5.0.0 + uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 # v5.1.0 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 61dd6234d..d1f094f86 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -281,7 +281,7 @@ jobs: docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 + uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} From e4078ea0a8b9519a7284201e6d587d6251ae2b8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:50:13 +0200 Subject: [PATCH 450/577] chore: bump github/codeql-action from 3.30.5 to 4.30.8 (#2179) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.5 to 4.30.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/3599b3baa15b485a2e49ef411a7a4bb2452e7f93...f443b600d91635bebf5b0d9ebc620189c0d6fba5) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.30.8 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 243d2f523..bd9f16d74 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.29.5 + uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v3.29.5 with: sarif_file: results.sarif From 0a99d5166715119f28079d527889f51d2390de95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 11:54:40 +0200 Subject: [PATCH 451/577] chore: bump actions/dependency-review-action from 4.8.0 to 4.8.1 (#2180) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.8.0 to 4.8.1. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/56339e523c0409420f6c2c9a2f4292bbb3c07dd3...40c09b7dc99638e5ddb0bfd91c1673effc064d8a) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.8.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-dependencies-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml index 74b9188c9..692acd64d 100644 --- a/.github/workflows/security-dependencies-check.yml +++ b/.github/workflows/security-dependencies-check.yml @@ -26,6 +26,6 @@ jobs: - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Verify Contents - uses: actions/dependency-review-action@56339e523c0409420f6c2c9a2f4292bbb3c07dd3 # v4.8.0 + uses: actions/dependency-review-action@40c09b7dc99638e5ddb0bfd91c1673effc064d8a # v4.8.1 with: config-file: './.github/dependency-review-config.yml' From bf621a6c79254cb3365803b67e20afcdaf53c17e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 17:11:09 +0200 Subject: [PATCH 452/577] chore: bump aws.sdk.version from 2.34.9 to 2.35.6 (#2183) Bumps `aws.sdk.version` from 2.34.9 to 2.35.6. Updates `software.amazon.awssdk:bom` from 2.34.9 to 2.35.6 Updates `software.amazon.awssdk:http-client-spi` from 2.34.9 to 2.35.6 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.35.6 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.35.6 Updates `software.amazon.awssdk:dynamodb` from 2.34.9 to 2.35.6 Updates `software.amazon.awssdk:lambda` from 2.34.9 to 2.35.6 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.35.6 Updates `software.amazon.awssdk:cloudwatch` from 2.34.9 to 2.35.6 Updates `software.amazon.awssdk:xray` from 2.34.9 to 2.35.6 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.35.6 Updates `software.amazon.awssdk:cloudformation` from 2.34.9 to 2.35.6 Updates `software.amazon.awssdk:sts` from 2.34.9 to 2.35.6 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.35.6 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.35.6 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.35.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.35.6 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.35.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.35.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.35.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.35.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-version: 2.35.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.35.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.35.6 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-version: 2.35.6 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index a1f4aadc3..c5245e89f 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.34.9</aws.sdk.version> + <aws.sdk.version>2.35.6</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 133e7d88c..e639bdcce 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.34.9</aws.sdk.version> + <aws.sdk.version>2.35.6</aws.sdk.version> <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 201f38c7f..69c55842c 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.0</maven.compiler.version> - <aws.sdk.version>2.34.9</aws.sdk.version> + <aws.sdk.version>2.35.6</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From b1693e022562b20d066945445a663f391814069b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 17:11:26 +0200 Subject: [PATCH 453/577] chore: bump org.assertj:assertj-core from 3.27.4 to 3.27.6 (#2184) Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.27.4 to 3.27.6. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.27.4...assertj-build-3.27.6) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-version: 3.27.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e639bdcce..6d29d6d7e 100644 --- a/pom.xml +++ b/pom.xml @@ -336,7 +336,7 @@ <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> - <version>3.27.4</version> + <version>3.27.6</version> <scope>test</scope> <exclusions> <exclusion> From aadf172563ba14ae0da17bfd6b1116ce783bbd45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 17:13:00 +0200 Subject: [PATCH 454/577] chore: bump org.apache.maven.plugins:maven-javadoc-plugin (#2186) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.3 to 3.12.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.3...maven-javadoc-plugin-3.12.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-version: 3.12.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6d29d6d7e..8a74f6ec1 100644 --- a/pom.xml +++ b/pom.xml @@ -98,7 +98,7 @@ <maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version> <jacoco-maven-plugin.version>0.8.11</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version> - <maven-javadoc-plugin.version>3.11.3</maven-javadoc-plugin.version> + <maven-javadoc-plugin.version>3.12.0</maven-javadoc-plugin.version> <maven-source-plugin.version>3.3.1</maven-source-plugin.version> <maven-gpg-plugin.version>3.2.1</maven-gpg-plugin.version> <aspectj-maven-plugin.version>1.14.1</aspectj-maven-plugin.version> From 66fbe5cd98b53eafd30ce170757fe21344b5d047 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 14 Oct 2025 17:15:25 +0200 Subject: [PATCH 455/577] chore(deps): Use mockito 5.20.0 (#2181) * chore(deps): Use mockito 5.20.0. * Remove non-applicable or not understandable TODOs. * fix pmd findings. * fix pmd findings. * Update protobuf generated classes after version bump. --- .../demo/kafka/protobuf/ProtobufProduct.java | 4 +- .../protobuf/ProtobufProductOrBuilder.java | 2 +- .../protobuf/ProtobufProductOuterClass.java | 6 +-- pom.xml | 25 +--------- .../lambda/powertools/e2e/Function.java | 49 +++++++++---------- .../persistence/BasePersistenceStore.java | 3 +- .../secrets/SecretsProviderBuilder.java | 1 - 7 files changed, 33 insertions(+), 57 deletions(-) diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java index 21961ad2b..e36810e08 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.32.0 +// Protobuf Java Version: 4.32.1 package org.demo.kafka.protobuf; @@ -19,7 +19,7 @@ public final class ProtobufProduct extends com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 32, - /* patch= */ 0, + /* patch= */ 1, /* suffix= */ "", ProtobufProduct.class.getName()); } diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java index 347ea854a..951644b2f 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.32.0 +// Protobuf Java Version: 4.32.1 package org.demo.kafka.protobuf; diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java index 046283d9a..0da2eec57 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java @@ -1,19 +1,19 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.32.0 +// Protobuf Java Version: 4.32.1 package org.demo.kafka.protobuf; @com.google.protobuf.Generated -public final class ProtobufProductOuterClass { +public final class ProtobufProductOuterClass extends com.google.protobuf.GeneratedFile { private ProtobufProductOuterClass() {} static { com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 32, - /* patch= */ 0, + /* patch= */ 1, /* suffix= */ "", ProtobufProductOuterClass.class.getName()); } diff --git a/pom.xml b/pom.xml index 8a74f6ec1..a04780ba2 100644 --- a/pom.xml +++ b/pom.xml @@ -114,8 +114,8 @@ <aws.sdk.v1.version>1.12.781</aws.sdk.v1.version> <versions-maven-plugin.version>2.19.1</versions-maven-plugin.version> <elastic.version>1.7.0</elastic.version> - <mockito.version>5.19.0</mockito.version> - <mockito-junit-jupiter.version>5.19.0</mockito-junit-jupiter.version> + <mockito.version>5.20.0</mockito.version> + <mockito-junit-jupiter.version>5.20.0</mockito-junit-jupiter.version> <junit-pioneer.version>2.3.0</junit-pioneer.version> <crac.version>1.5.0</crac.version> @@ -536,12 +536,6 @@ <profiles> <profile> <id>release</id> - <!-- TODO: Revert once 5.19.1 is stable released. --> - <!-- https://github.com/aws-powertools/powertools-lambda-java/issues/2079 --> - <properties> - <mockito.version>5.19.0</mockito.version> - <mockito-junit-jupiter.version>5.19.0</mockito-junit-jupiter.version> - </properties> <build> <plugins> <plugin> @@ -643,21 +637,6 @@ </plugins> </build> </profile> - <profile> - <id>generate-graalvm-files</id> - <properties> - <mockito.version>5.19.1-SNAPSHOT</mockito.version> - <mockito-junit-jupiter.version>5.19.1-SNAPSHOT</mockito-junit-jupiter.version> - </properties> - </profile> - <profile> - <id>graalvm-native</id> - <properties> - <mockito.version>5.19.1-SNAPSHOT</mockito.version> - <mockito-junit-jupiter.version>5.19.1-SNAPSHOT</mockito-junit-jupiter.version> - </properties> - </profile> - </profiles> </project> diff --git a/powertools-e2e-tests/handlers/batch/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/batch/src/main/java/software/amazon/lambda/powertools/e2e/Function.java index bfde65bc8..36142d3f5 100644 --- a/powertools-e2e-tests/handlers/batch/src/main/java/software/amazon/lambda/powertools/e2e/Function.java +++ b/powertools-e2e-tests/handlers/batch/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -14,15 +14,6 @@ package software.amazon.lambda.powertools.e2e; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; -import com.amazonaws.services.lambda.runtime.events.KinesisEvent; -import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; -import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; -import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer; -import com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; @@ -30,8 +21,20 @@ import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; +import com.amazonaws.services.lambda.runtime.events.KinesisEvent; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; +import com.amazonaws.services.lambda.runtime.serialization.PojoSerializer; +import com.amazonaws.services.lambda.runtime.serialization.events.LambdaEventSerializers; + import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; @@ -39,7 +42,6 @@ import software.amazon.lambda.powertools.batch.handler.BatchMessageHandler; import software.amazon.lambda.powertools.e2e.model.Product; - public class Function implements RequestHandler<InputStream, Object> { private static final Logger LOGGER = LoggerFactory.getLogger(Function.class); @@ -48,7 +50,6 @@ public class Function implements RequestHandler<InputStream, Object> { private final BatchMessageHandler<KinesisEvent, StreamsEventResponse> kinesisHandler; private final BatchMessageHandler<DynamodbEvent, StreamsEventResponse> ddbHandler; private final String ddbOutputTable; - private DynamoDbClient ddbClient; public Function() { sqsHandler = new BatchMessageHandlerBuilder() @@ -69,8 +70,7 @@ public Function() { private void processProductMessage(Product p, Context c) { LOGGER.info("Processing product " + p); - // TODO - write product details to output table - ddbClient = DynamoDbClient.builder() + DynamoDbClient ddbClient = DynamoDbClient.builder() .build(); Map<String, AttributeValue> results = new HashMap<>(); results.put("functionName", AttributeValue.builder() @@ -94,7 +94,7 @@ private void processProductMessage(Product p, Context c) { private void processDdbMessage(DynamodbEvent.DynamodbStreamRecord dynamodbStreamRecord, Context context) { LOGGER.info("Processing DynamoDB Stream Record" + dynamodbStreamRecord); - ddbClient = DynamoDbClient.builder() + DynamoDbClient ddbClient = DynamoDbClient.builder() .build(); String id = dynamodbStreamRecord.getDynamodb().getKeys().get("id").getS(); @@ -118,26 +118,25 @@ public Object createResult(String input, Context context) { LOGGER.info(input); - PojoSerializer<SQSEvent> serializer = - LambdaEventSerializers.serializerFor(SQSEvent.class, this.getClass().getClassLoader()); + PojoSerializer<SQSEvent> serializer = LambdaEventSerializers.serializerFor(SQSEvent.class, + this.getClass().getClassLoader()); SQSEvent event = serializer.fromJson(input); - if (event.getRecords().get(0).getEventSource().equals("aws:sqs")) { + if ("aws:sqs".equals(event.getRecords().get(0).getEventSource())) { LOGGER.info("Running for SQS"); - LOGGER.info(event.toString()); return sqsHandler.processBatch(event, context); } - PojoSerializer<KinesisEvent> kinesisSerializer = - LambdaEventSerializers.serializerFor(KinesisEvent.class, this.getClass().getClassLoader()); + PojoSerializer<KinesisEvent> kinesisSerializer = LambdaEventSerializers.serializerFor(KinesisEvent.class, + this.getClass().getClassLoader()); KinesisEvent kinesisEvent = kinesisSerializer.fromJson(input); - if (kinesisEvent.getRecords().get(0).getEventSource().equals("aws:kinesis")) { + if ("aws:kinesis".equals(kinesisEvent.getRecords().get(0).getEventSource())) { LOGGER.info("Running for Kinesis"); return kinesisHandler.processBatch(kinesisEvent, context); } // Well, let's try dynamo - PojoSerializer<DynamodbEvent> ddbSerializer = - LambdaEventSerializers.serializerFor(DynamodbEvent.class, this.getClass().getClassLoader()); + PojoSerializer<DynamodbEvent> ddbSerializer = LambdaEventSerializers.serializerFor(DynamodbEvent.class, + this.getClass().getClassLoader()); LOGGER.info("Running for DynamoDB"); DynamodbEvent ddbEvent = ddbSerializer.fromJson(input); return ddbHandler.processBatch(ddbEvent, context); @@ -148,8 +147,8 @@ public Object handleRequest(InputStream inputStream, Context context) { String input = new BufferedReader( new InputStreamReader(inputStream, StandardCharsets.UTF_8)) - .lines() - .collect(Collectors.joining("\n")); + .lines() + .collect(Collectors.joining("\n")); return createResult(input, context); } diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java index 8b08434ba..7e93dc00c 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java @@ -132,7 +132,6 @@ public void saveSuccess(JsonNode data, Object result, Instant now) { updateRecord(dataRecord); saveToCache(dataRecord); } catch (JsonProcessingException e) { - // TODO : throw ? throw new RuntimeException("Error while serializing the response", e); } } @@ -405,7 +404,7 @@ void configure(IdempotencyConfig config, String functionName, LRUCache<String, D private static boolean isEqual(String dataRecordPayload, String dataHash) { if (dataHash != null && dataRecordPayload != null) { - return dataHash.length() != dataRecordPayload.length() ? false : dataHash.equals(dataRecordPayload); + return dataHash.length() == dataRecordPayload.length() && dataHash.equals(dataRecordPayload); } else { return false; } diff --git a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java index c5806689f..517274e19 100644 --- a/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java +++ b/powertools-parameters/powertools-parameters-secrets/src/main/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderBuilder.java @@ -52,7 +52,6 @@ private static SecretsManagerClient createClient() { */ public SecretsProvider build() { if (cacheManager == null) { - // TODO - what should we do with this cacheManager = new CacheManager(); } SecretsProvider provider; From 13d54ff5468e9849607345a9bb92c14d4c6db620 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 14 Oct 2025 17:39:46 +0200 Subject: [PATCH 456/577] improv: Make trace id access more robust. (#2188) * improv: Make trace id access more robust. * Update comments. --- .../reflect-config.json | 4 +- powertools-common/pom.xml | 4 ++ .../common/internal/LambdaConstants.java | 7 ++- .../internal/LambdaHandlerProcessor.java | 43 ++++++++++++------- .../internal/LambdaHandlerProcessorTest.java | 26 +++++++++++ .../reflect-config.json | 2 +- .../PowerToolsResolverFactoryTest.java | 2 +- .../reflect-config.json | 2 +- .../internal/LambdaEcsEncoderTest.java | 2 +- .../internal/LambdaJsonEncoderTest.java | 2 +- .../powertools-logging/reflect-config.json | 2 +- .../internal/LambdaLoggingAspectTest.java | 4 +- .../powertools-metrics/reflect-config.json | 2 +- .../metrics/ConfigurationPrecedenceTest.java | 6 +-- .../metrics/MetricsFactoryTest.java | 6 +-- .../metrics/RequestHandlerTest.java | 6 +-- .../internal/EmfMetricsLoggerTest.java | 6 +-- .../internal/LambdaMetricsAspectTest.java | 6 +-- .../powertools-tracing/reflect-config.json | 2 +- .../internal/LambdaTracingAspectTest.java | 2 +- 20 files changed, 91 insertions(+), 45 deletions(-) diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index 962962055..8d3f375f2 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -33,6 +33,6 @@ }, { "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", - "fields":[{"name":"IS_COLD_START"},{"name":"SERVICE_NAME"}] + "fields":[{"name":"isColdStart"},{"name":"serviceName"}] } -] \ No newline at end of file +] diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 7620d84ee..d68bcb63a 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -44,6 +44,10 @@ <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> </dependency> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>utils-lite</artifactId> + </dependency> <!-- Test dependencies --> <dependency> diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java index d27ac1aa2..69fc1283a 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java @@ -14,11 +14,16 @@ package software.amazon.lambda.powertools.common.internal; -public class LambdaConstants { +public final class LambdaConstants { + private LambdaConstants() { + // Constant holder class + } + public static final String LAMBDA_FUNCTION_NAME_ENV = "AWS_LAMBDA_FUNCTION_NAME"; public static final String AWS_REGION_ENV = "AWS_REGION"; public static final String X_AMZN_TRACE_ID = "_X_AMZN_TRACE_ID"; public static final String XRAY_TRACE_HEADER = "com.amazonaws.xray.traceHeader"; + public static final String AWS_LAMBDA_X_TRACE_ID = "AWS_LAMBDA_X_TRACE_ID"; public static final String AWS_SAM_LOCAL = "AWS_SAM_LOCAL"; public static final String ROOT_EQUALS = "Root="; public static final String POWERTOOLS_SERVICE_NAME = "POWERTOOLS_SERVICE_NAME"; diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java index bfacd5204..393835d1e 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java @@ -19,20 +19,24 @@ import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getProperty; import static software.amazon.lambda.powertools.common.internal.SystemWrapper.getenv; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import java.io.InputStream; import java.io.OutputStream; import java.util.Optional; + import org.aspectj.lang.ProceedingJoinPoint; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.RequestStreamHandler; + +import software.amazon.awssdk.utilslite.SdkInternalThreadLocal; + public final class LambdaHandlerProcessor { - // SERVICE_NAME cannot be final for testing purposes - private static String SERVICE_NAME = calculateServiceName(); + // serviceName cannot be final for testing purposes + private static String serviceName = calculateServiceName(); - private static Boolean IS_COLD_START = null; + private static Boolean isColdStart = null; private LambdaHandlerProcessor() { // Hide default constructor @@ -40,7 +44,8 @@ private LambdaHandlerProcessor() { private static String calculateServiceName() { return null != getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME) - ? getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME) : LambdaConstants.SERVICE_UNDEFINED; + ? getenv(LambdaConstants.POWERTOOLS_SERVICE_NAME) + : LambdaConstants.SERVICE_UNDEFINED; } public static boolean isHandlerMethod(final ProceedingJoinPoint pjp) { @@ -79,20 +84,20 @@ public static Context extractContext(final ProceedingJoinPoint pjp) { } public static String serviceName() { - return SERVICE_NAME; + return serviceName; } // Method used for testing purposes protected static void resetServiceName() { - SERVICE_NAME = calculateServiceName(); + serviceName = calculateServiceName(); } public static boolean isColdStart() { - return IS_COLD_START == null; + return isColdStart == null; } public static void coldStartDone() { - IS_COLD_START = false; + isColdStart = false; } public static boolean isSamLocal() { @@ -100,14 +105,20 @@ public static boolean isSamLocal() { } public static Optional<String> getXrayTraceId() { - String X_AMZN_TRACE_ID = getenv(LambdaConstants.X_AMZN_TRACE_ID); + // Try SdkInternalThreadLocal first + String traceId = SdkInternalThreadLocal.get(LambdaConstants.AWS_LAMBDA_X_TRACE_ID); + + // Fallback to environment based approach + if (traceId == null) { + traceId = getenv(LambdaConstants.X_AMZN_TRACE_ID); + } // For the Java Lambda 17+ runtime, the Trace ID is set as a System Property - if (X_AMZN_TRACE_ID == null) { - X_AMZN_TRACE_ID = getProperty(LambdaConstants.XRAY_TRACE_HEADER); + if (traceId == null) { + traceId = getProperty(LambdaConstants.XRAY_TRACE_HEADER); } - if (X_AMZN_TRACE_ID != null) { - return of(X_AMZN_TRACE_ID.split(";")[0].replace(LambdaConstants.ROOT_EQUALS, "")); + if (traceId != null) { + return of(traceId.split(";")[0].replace(LambdaConstants.ROOT_EQUALS, "")); } return empty(); } diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index 17732cdf0..5c6bdc020 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -25,18 +25,26 @@ import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junitpioneer.jupiter.ClearEnvironmentVariable; +import org.junitpioneer.jupiter.ClearSystemProperty; import org.junitpioneer.jupiter.SetEnvironmentVariable; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import software.amazon.awssdk.utilslite.SdkInternalThreadLocal; import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; class LambdaHandlerProcessorTest { + @AfterEach + void cleanup() { + SdkInternalThreadLocal.clear(); + } + @Test void isHandlerMethod_shouldRecognizeRequestHandler() { Context context = new TestLambdaContext(); @@ -159,6 +167,24 @@ void getXrayTraceId_notPresent() { assertThat(isXRayTraceIdPresent).isFalse(); } + @Test + @ClearEnvironmentVariable(key = LambdaConstants.X_AMZN_TRACE_ID) + @ClearSystemProperty(key = LambdaConstants.XRAY_TRACE_HEADER) + void getXrayTraceId_fromSdkInternalThreadLocal() { + // Verify no trace ID initially + assertThat(LambdaHandlerProcessor.getXrayTraceId()).isEmpty(); + + // Set trace ID in SdkInternalThreadLocal + String expectedTraceId = "1-5759e988-bd862e3fe1be46a994272793"; + SdkInternalThreadLocal.put(LambdaConstants.AWS_LAMBDA_X_TRACE_ID, + "Root=" + expectedTraceId + ";Parent=53995c3f42cd8ad8;Sampled=1"); + + // Verify trace ID is now present + Optional<String> traceId = LambdaHandlerProcessor.getXrayTraceId(); + assertThat(traceId).isPresent(); + assertThat(traceId.get()).isEqualTo(expectedTraceId); + } + @Test void extractContext_fromRequestHandler() { Object[] args = { new Object(), new TestLambdaContext() }; diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json index 6cbbee583..43084dad2 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-log4j/reflect-config.json @@ -1077,7 +1077,7 @@ }, { "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", - "fields":[{"name":"IS_COLD_START"}] + "fields":[{"name":"isColdStart"}] }, { "name":"software.amazon.lambda.powertools.logging.log4j.BufferingAppender", diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java index 7ea81d690..b279d7d93 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java @@ -45,7 +45,7 @@ class PowerToolsResolverFactoryTest { @BeforeEach void setUp() throws IllegalAccessException, IOException { MDC.clear(); - writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); + writeStaticField(LambdaHandlerProcessor.class, "isColdStart", null, true); context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { diff --git a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json index d4f4a4d7d..5c5eb83fa 100644 --- a/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json +++ b/powertools-logging/powertools-logging-logback/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging-logback/reflect-config.json @@ -163,7 +163,7 @@ }, { "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", - "fields":[{"name":"IS_COLD_START"}] + "fields":[{"name":"isColdStart"}] }, { "name":"software.amazon.lambda.powertools.logging.logback.BufferingAppender", diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java index 65277e3d6..db3248b56 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java @@ -51,7 +51,7 @@ class LambdaEcsEncoderTest { @BeforeEach void setUp() throws IllegalAccessException, IOException { MDC.clear(); - writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); + writeStaticField(LambdaHandlerProcessor.class, "isColdStart", null, true); context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 912e2fde9..9ea275627 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -73,7 +73,7 @@ class LambdaJsonEncoderTest { @BeforeEach void setUp() throws IllegalAccessException, IOException { MDC.clear(); - writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); + writeStaticField(LambdaHandlerProcessor.class, "isColdStart", null, true); context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { diff --git a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json index 4c66ebd97..9e665e87a 100644 --- a/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json +++ b/powertools-logging/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-logging/reflect-config.json @@ -229,7 +229,7 @@ }, { "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", - "fields":[{"name":"IS_COLD_START"}, {"name":"SERVICE_NAME"}] + "fields":[{"name":"isColdStart"}, {"name":"serviceName"}] }, { "name":"software.amazon.lambda.powertools.logging.argument.StructuredArgumentsTest", diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index 3ff531321..c9baab1d8 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -100,7 +100,7 @@ class LambdaLoggingAspectTest { @BeforeEach void setUp() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException { MDC.clear(); - writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); + writeStaticField(LambdaHandlerProcessor.class, "isColdStart", null, true); context = new TestLambdaContext(); requestHandler = new PowertoolsLogEnabled(); requestStreamHandler = new PowertoolsLogEnabledForStream(); @@ -418,7 +418,7 @@ void shouldHaveNoEffectIfNotUsedOnLambdaHandler() { @Test void shouldLogServiceNameWhenEnvVarSet() throws IllegalAccessException { // GIVEN - writeStaticField(LambdaHandlerProcessor.class, "SERVICE_NAME", "testService", true); + writeStaticField(LambdaHandlerProcessor.class, "serviceName", "testService", true); // WHEN requestHandler.handleRequest(new Object(), context); diff --git a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json index 533335782..a0ac5bfec 100644 --- a/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json +++ b/powertools-metrics/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-metrics/reflect-config.json @@ -126,7 +126,7 @@ }, { "name": "software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", - "fields": [{ "name": "IS_COLD_START" }], + "fields": [{ "name": "isColdStart" }], "methods": [{ "name": "resetServiceName", "parameterTypes": [] }] }, { diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java index ecc7c13a1..c9c772313 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java @@ -52,13 +52,13 @@ class ConfigurationPrecedenceTest { void setUp() throws Exception { System.setOut(new PrintStream(outputStreamCaptor)); - // Reset LambdaHandlerProcessor's SERVICE_NAME + // Reset LambdaHandlerProcessor's serviceName Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); resetServiceName.setAccessible(true); resetServiceName.invoke(null); - // Reset IS_COLD_START - java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + // Reset isColdStart + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("isColdStart"); coldStartField.setAccessible(true); coldStartField.set(null, null); } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java index 962f2c2d7..4fc98d2a5 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java @@ -48,13 +48,13 @@ class MetricsFactoryTest { void setUp() throws Exception { System.setOut(new PrintStream(outputStreamCaptor)); - // Reset LambdaHandlerProcessor's SERVICE_NAME + // Reset LambdaHandlerProcessor's serviceName Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); resetServiceName.setAccessible(true); resetServiceName.invoke(null); - // Reset IS_COLD_START - java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + // Reset isColdStart + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("isColdStart"); coldStartField.setAccessible(true); coldStartField.set(null, null); } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java index d94a6bbe8..d3ed64fe3 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java @@ -40,13 +40,13 @@ void setUp() throws Exception { outputStreamCaptor = new ByteArrayOutputStream(); System.setOut(new PrintStream(outputStreamCaptor)); - // Reset LambdaHandlerProcessor's SERVICE_NAME + // Reset LambdaHandlerProcessor's serviceName Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); resetServiceName.setAccessible(true); resetServiceName.invoke(null); - // Reset IS_COLD_START - java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + // Reset isColdStart + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("isColdStart"); coldStartField.setAccessible(true); coldStartField.set(null, null); } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java index 9f793f977..bab039640 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java @@ -56,13 +56,13 @@ class EmfMetricsLoggerTest { @BeforeEach void setUp() throws Exception { - // Reset LambdaHandlerProcessor's SERVICE_NAME + // Reset LambdaHandlerProcessor's serviceName Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); resetServiceName.setAccessible(true); resetServiceName.invoke(null); - // Reset IS_COLD_START - java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + // Reset isColdStart + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("isColdStart"); coldStartField.setAccessible(true); coldStartField.set(null, null); diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java index 326dd2ffe..031fe4553 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java @@ -49,13 +49,13 @@ class LambdaMetricsAspectTest { void setUp() throws Exception { System.setOut(new PrintStream(outputStreamCaptor)); - // Reset LambdaHandlerProcessor's SERVICE_NAME + // Reset LambdaHandlerProcessor's serviceName Method resetServiceName = LambdaHandlerProcessor.class.getDeclaredMethod("resetServiceName"); resetServiceName.setAccessible(true); resetServiceName.invoke(null); - // Reset IS_COLD_START - java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("IS_COLD_START"); + // Reset isColdStart + java.lang.reflect.Field coldStartField = LambdaHandlerProcessor.class.getDeclaredField("isColdStart"); coldStartField.setAccessible(true); coldStartField.set(null, null); } diff --git a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json index a71154276..97e0a7a86 100644 --- a/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json +++ b/powertools-tracing/src/main/resources/META-INF/native-image/software.amazon.lambda/powertools-tracing/reflect-config.json @@ -302,7 +302,7 @@ }, { "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", - "fields":[{"name":"IS_COLD_START"}] + "fields":[{"name":"isColdStart"}] }, { "name":"software.amazon.lambda.powertools.tracing.handlers.PowerTracerToolEnabled", diff --git a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java index 4d2e481b1..b22f7a9af 100644 --- a/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java +++ b/powertools-tracing/src/test/java/software/amazon/lambda/powertools/tracing/internal/LambdaTracingAspectTest.java @@ -59,7 +59,7 @@ class LambdaTracingAspectTest { @BeforeEach void setUp() throws IllegalAccessException { - writeStaticField(LambdaHandlerProcessor.class, "IS_COLD_START", null, true); + writeStaticField(LambdaHandlerProcessor.class, "isColdStart", null, true); context = new TestLambdaContext(); requestHandler = new PowerTracerToolEnabled(); streamHandler = new PowerTracerToolEnabledForStream(); From bfc4f8c6510537ec37c810c46875157570d8a73d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 17:48:11 +0200 Subject: [PATCH 457/577] chore: bump aws.xray.recorder.version from 2.19.0 to 2.20.0 (#2185) Bumps `aws.xray.recorder.version` from 2.19.0 to 2.20.0. Updates `com.amazonaws:aws-xray-recorder-sdk-core` from 2.19.0 to 2.20.0 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.19.0...v2.20.0) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core` from 2.19.0 to 2.20.0 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.19.0...v2.20.0) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2` from 2.19.0 to 2.20.0 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.19.0...v2.20.0) Updates `com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor` from 2.19.0 to 2.20.0 - [Release notes](https://github.com/aws/aws-xray-sdk-java/releases) - [Changelog](https://github.com/aws/aws-xray-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-xray-sdk-java/compare/v2.19.0...v2.20.0) --- updated-dependencies: - dependency-name: com.amazonaws:aws-xray-recorder-sdk-core dependency-version: 2.20.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-core dependency-version: 2.20.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2 dependency-version: 2.20.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.amazonaws:aws-xray-recorder-sdk-aws-sdk-v2-instrumentor dependency-version: 2.20.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philipp Page <github@philipp.page> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a04780ba2..c1d0720b8 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> <aws.sdk.version>2.35.6</aws.sdk.version> - <aws.xray.recorder.version>2.19.0</aws.xray.recorder.version> + <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <lambda.core.version>1.4.0</lambda.core.version> From 39a7c2ed81abef679a92f697ca6e226b46d76a0c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 13:33:07 +0200 Subject: [PATCH 458/577] chore: bump io.github.ascopes:protobuf-maven-plugin (#2193) Bumps [io.github.ascopes:protobuf-maven-plugin](https://github.com/ascopes/protobuf-maven-plugin) from 3.10.0 to 3.10.2. - [Release notes](https://github.com/ascopes/protobuf-maven-plugin/releases) - [Commits](https://github.com/ascopes/protobuf-maven-plugin/compare/v3.10.0...v3.10.2) --- updated-dependencies: - dependency-name: io.github.ascopes:protobuf-maven-plugin dependency-version: 3.10.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 8a0ac2d89..6527bf278 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -141,7 +141,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.10.0</version> + <version>3.10.2</version> <executions> <execution> <goals> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index b1f1afd3e..2985b3f0d 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -196,7 +196,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.10.0</version> + <version>3.10.2</version> <executions> <execution> <id>generate-test-sources</id> From ac3586c51c4907478126ea36a80ea8f429298a21 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 17:44:21 +0200 Subject: [PATCH 459/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.214.0 to 2.220.0 (#2191) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.214.0 to 2.220.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.214.0...v2.220.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.220.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 491c9ec68..800d896d0 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.4.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.214.0</cdk.version> + <cdk.version>2.220.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.13.4</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 32ea35d36..20d28895e 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.2</constructs.version> - <cdk.version>2.214.0</cdk.version> + <cdk.version>2.220.0</cdk.version> </properties> <dependencies> From 2eb25a3d1cea8ae1af7ba590b0924a5f652a363e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 17:45:02 +0200 Subject: [PATCH 460/577] chore: bump com.github.spotbugs:spotbugs-maven-plugin (#2192) Bumps [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) from 4.9.4.2 to 4.9.7.0. - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.9.4.2...spotbugs-maven-plugin-4.9.7.0) --- updated-dependencies: - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-version: 4.9.7.0 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c1d0720b8..4e805e5ae 100644 --- a/pom.xml +++ b/pom.xml @@ -598,7 +598,7 @@ <plugin> <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> - <version>4.9.4.2</version> + <version>4.9.7.0</version> <executions> <execution> <id>test</id> From 9cce3da3225c846b680733780652291a313b5641 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 17:45:18 +0200 Subject: [PATCH 461/577] chore: bump squidfunk/mkdocs-material in /docs (#2194) Bumps squidfunk/mkdocs-material from `00f9276` to `f5c556a`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: f5c556a6d30ce0c1c0df10e3c38c79bbcafdaea4b1c1be366809d0d4f6f9d57f dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index fe4f2ec55..9b8bde4c5 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -FROM squidfunk/mkdocs-material@sha256:00f9276315990b82f5af8c47bb2b71e2c69aef9f02a08f8dffd2515f42310753 +FROM squidfunk/mkdocs-material@sha256:f5c556a6d30ce0c1c0df10e3c38c79bbcafdaea4b1c1be366809d0d4f6f9d57f COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From 03a5af5b456bb9fdc274f2872b7d76c6f10c10f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 17:45:31 +0200 Subject: [PATCH 462/577] chore: bump sam/build-java21 (#2195) Bumps sam/build-java21 from `fd3b445` to `1d40149`. --- updated-dependencies: - dependency-name: sam/build-java21 dependency-version: 1d40149444f21a5b20e8f54275f9173265d57522ff8669fa3f8fefbaf24657da dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index 5086f4532..e82e5d33e 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:fd3b44561b51626c15ae4437630afcfdc84ad883edca64d2cdb87aad755eb7ac +FROM public.ecr.aws/sam/build-java21@sha256:1d40149444f21a5b20e8f54275f9173265d57522ff8669fa3f8fefbaf24657da # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From a4b1e12877510a44be9f821a7550959928867c69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 18:29:23 +0100 Subject: [PATCH 463/577] chore: bump com.networknt:json-schema-validator from 1.5.8 to 1.5.9 (#2189) Bumps [com.networknt:json-schema-validator](https://github.com/networknt/json-schema-validator) from 1.5.8 to 1.5.9. - [Release notes](https://github.com/networknt/json-schema-validator/releases) - [Changelog](https://github.com/networknt/json-schema-validator/blob/master/CHANGELOG.md) - [Commits](https://github.com/networknt/json-schema-validator/compare/1.5.8...1.5.9) --- updated-dependencies: - dependency-name: com.networknt:json-schema-validator dependency-version: 1.5.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-validation/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 6ecee16a1..4194b4240 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -65,7 +65,7 @@ <dependency> <groupId>com.networknt</groupId> <artifactId>json-schema-validator</artifactId> - <version>1.5.8</version> + <version>1.5.9</version> </dependency> <dependency> <groupId>com.amazonaws</groupId> From a91c09099d838cd6f4f4cc1e426a3c835f13f1c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 18:29:57 +0100 Subject: [PATCH 464/577] chore: bump aws.sdk.version from 2.35.6 to 2.35.7 (#2190) Bumps `aws.sdk.version` from 2.35.6 to 2.35.7. Updates `software.amazon.awssdk:bom` from 2.35.6 to 2.35.7 Updates `software.amazon.awssdk:http-client-spi` from 2.35.6 to 2.35.7 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.35.7 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.35.7 Updates `software.amazon.awssdk:dynamodb` from 2.35.6 to 2.35.7 Updates `software.amazon.awssdk:lambda` from 2.35.6 to 2.35.7 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.35.7 Updates `software.amazon.awssdk:cloudwatch` from 2.35.6 to 2.35.7 Updates `software.amazon.awssdk:xray` from 2.35.6 to 2.35.7 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.35.7 Updates `software.amazon.awssdk:cloudformation` from 2.35.6 to 2.35.7 Updates `software.amazon.awssdk:sts` from 2.35.6 to 2.35.7 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.35.7 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.35.7 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.35.7 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.35.7 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.35.7 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.35.7 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.35.7 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.35.7 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.35.7 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.35.7 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.35.7 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.35.7 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index c5245e89f..bc3084990 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.35.6</aws.sdk.version> + <aws.sdk.version>2.35.7</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 4e805e5ae..0feecd82b 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.35.6</aws.sdk.version> + <aws.sdk.version>2.35.7</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 69c55842c..f7c78c131 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.0</maven.compiler.version> - <aws.sdk.version>2.35.6</aws.sdk.version> + <aws.sdk.version>2.35.7</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From b923cd0b2c3a9dc601d3b3999b30df5eb962d362 Mon Sep 17 00:00:00 2001 From: kjswaruph <jyothiswaruphkolli@gmail.com> Date: Thu, 16 Oct 2025 15:31:09 +0530 Subject: [PATCH 465/577] feat: add CRaC priming support to powertools-kafka module (#2145) * feat: add CRaC priming support to powertools-kafka module - Add maven test profile and classesloaded.txt for preloading - Add Crac dependency and update PowertoolsSerializer to register as Crac Resource - Add tests in PowertoolsSerializerTest to assert beforeCheckpoint and afterRestore hooks do not throw exception * feat: add avro priming * refactor: remove avro priming * fix: add space before opening braces Co-authored-by: Philipp Page <philipp.page@yahoo.de> * Add powertools-kafka to check build workflows. * Make input streams auto-closable in PowertoolsSerializerTest * Wrap result input stream directly in try clause. * Fix PMD finding for IOException input stream. --------- Co-authored-by: Philipp Page <philipp.page@yahoo.de> Co-authored-by: Philipp Page <pagejep@amazon.com> --- .github/workflows/check-build.yml | 1 + .github/workflows/check-spotbugs.yml | 3 +- powertools-kafka/pom.xml | 25 + .../kafka/PowertoolsSerializer.java | 79 +- .../src/main/resources/classesloaded.txt | 6642 +++++++++++++++++ .../kafka/PowertoolsSerializerTest.java | 95 +- 6 files changed, 6806 insertions(+), 39 deletions(-) create mode 100644 powertools-kafka/src/main/resources/classesloaded.txt diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 0167925f4..8bc474c20 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -23,6 +23,7 @@ on: - 'powertools-large-messages/**' - 'powertools-logging/**' - 'powertools-metrics/**' + - 'powertools-kafka/**' - 'powertools-parameters/**' - 'powertools-serialization/**' - 'powertools-sqs/**' diff --git a/.github/workflows/check-spotbugs.yml b/.github/workflows/check-spotbugs.yml index 214125ed4..bf746320d 100644 --- a/.github/workflows/check-spotbugs.yml +++ b/.github/workflows/check-spotbugs.yml @@ -20,6 +20,7 @@ on: - 'powertools-large-messages/**' - 'powertools-logging/**' - 'powertools-metrics/**' + - 'powertools-kafka/**' - 'powertools-parameters/**' - 'powertools-serialization/**' - 'powertools-sqs/**' @@ -47,4 +48,4 @@ jobs: distribution: 'corretto' java-version: 21 - name: Build with Maven for spotbugs check to mark build as fail if voilations found - run: mvn -Pbuild-with-spotbugs -B install --file pom.xml -DskipTests -Dmaven.javadoc.skip=true -Dspotbugs.failOnError=true \ No newline at end of file + run: mvn -Pbuild-with-spotbugs -B install --file pom.xml -DskipTests -Dmaven.javadoc.skip=true -Dspotbugs.failOnError=true diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 2985b3f0d..3dae1ffd2 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -88,6 +88,10 @@ <artifactId>sdk-core</artifactId> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.crac</groupId> + <artifactId>crac</artifactId> + </dependency> <!-- Test dependencies --> <dependency> @@ -238,4 +242,25 @@ </plugins> </build> + <profiles> + <profile> + <id>generate-classesloaded-file</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <argLine> + -Xlog:class+load=info:classesloaded.txt + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + </argLine> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> + </project> diff --git a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializer.java b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializer.java index be8563b8e..619e46729 100644 --- a/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializer.java +++ b/powertools-kafka/src/main/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializer.java @@ -14,12 +14,20 @@ import java.io.InputStream; import java.io.OutputStream; +import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Map; import com.amazonaws.services.lambda.runtime.CustomPojoSerializer; import com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory; +import com.amazonaws.services.lambda.runtime.events.KafkaEvent; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.crac.Context; +import org.crac.Core; +import org.crac.Resource; +import software.amazon.lambda.powertools.common.internal.ClassPreLoader; import software.amazon.lambda.powertools.kafka.internal.DeserializationUtils; import software.amazon.lambda.powertools.kafka.serializers.KafkaAvroDeserializer; import software.amazon.lambda.powertools.kafka.serializers.KafkaJsonDeserializer; @@ -30,11 +38,11 @@ /** * Custom Lambda serializer supporting Kafka events. It delegates to the appropriate deserializer based on the * deserialization type specified by {@link software.amazon.lambda.powertools.kafka.Deserialization} annotation. - * + * * Kafka serializers need to be specified explicitly, otherwise, the default Lambda serializer from * {@link com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory} will be used. */ -public class PowertoolsSerializer implements CustomPojoSerializer { +public class PowertoolsSerializer implements CustomPojoSerializer, Resource { private static final Map<DeserializationType, PowertoolsDeserializer> DESERIALIZERS = Map.of( DeserializationType.KAFKA_JSON, new KafkaJsonDeserializer(), DeserializationType.KAFKA_AVRO, new KafkaAvroDeserializer(), @@ -43,6 +51,13 @@ DeserializationType.KAFKA_PROTOBUF, new KafkaProtobufDeserializer(), private final PowertoolsDeserializer deserializer; + private static final PowertoolsSerializer INSTANCE = new PowertoolsSerializer(); + + // CRaC registration happens at class loading time + static { + Core.getGlobalContext().register(INSTANCE); + } + public PowertoolsSerializer() { this.deserializer = DESERIALIZERS.getOrDefault( DeserializationUtils.determineDeserializationType(), @@ -64,4 +79,64 @@ public <T> void toJson(T value, OutputStream output, Type type) { // This is the Lambda default Output serialization JacksonFactory.getInstance().getSerializer(type).toJson(value, output); } + + @Override + public void beforeCheckpoint(Context<? extends Resource> context) throws Exception { + JacksonFactory.getInstance().getSerializer(KafkaEvent.class); + JacksonFactory.getInstance().getSerializer(ConsumerRecord.class); + JacksonFactory.getInstance().getSerializer(String.class); + + DeserializationUtils.determineDeserializationType(); + + jsonPriming(); + + ClassPreLoader.preloadClasses(); + } + + @Override + public void afterRestore(Context<? extends Resource> context) throws Exception { + // No action needed after restore + } + + private void jsonPriming() { + String kafkaJson = "{\n" + + " \"eventSource\": \"aws:kafka\",\n" + + " \"records\": {\n" + + " \"prime-topic-1\": [\n" + + " {\n" + + " \"topic\": \"prime-topic-1\",\n" + + " \"partition\": 0,\n" + + " \"offset\": 0,\n" + + " \"timestamp\": 1545084650987,\n" + + " \"timestampType\": \"CREATE_TIME\",\n" + + " \"key\": null,\n" + + " \"value\": null,\n" + + " \"headers\": []\n" + + " }\n" + + " ]\n" + + " }\n" + + "}"; + Type consumerRecords = createConsumerRecordsType(String.class, String.class); + PowertoolsDeserializer deserializers = DESERIALIZERS.get(DeserializationType.KAFKA_JSON); + deserializers.fromJson(kafkaJson, consumerRecords); + } + + private Type createConsumerRecordsType(Class<?> keyClass, Class<?> valueClass) { + return new ParameterizedType() { + @Override + public Type[] getActualTypeArguments() { + return new Type[] { keyClass, valueClass }; + } + + @Override + public Type getRawType() { + return ConsumerRecords.class; + } + + @Override + public Type getOwnerType() { + return null; + } + }; + } } diff --git a/powertools-kafka/src/main/resources/classesloaded.txt b/powertools-kafka/src/main/resources/classesloaded.txt new file mode 100644 index 000000000..6b8c000bc --- /dev/null +++ b/powertools-kafka/src/main/resources/classesloaded.txt @@ -0,0 +1,6642 @@ +java.lang.Object +java.io.Serializable +java.lang.Comparable +java.lang.CharSequence +java.lang.constant.Constable +java.lang.constant.ConstantDesc +java.lang.String +java.lang.reflect.AnnotatedElement +java.lang.reflect.GenericDeclaration +java.lang.reflect.Type +java.lang.invoke.TypeDescriptor +java.lang.invoke.TypeDescriptor$OfField +java.lang.Class +java.lang.Cloneable +java.lang.ClassLoader +java.lang.System +java.lang.Throwable +java.lang.Error +java.lang.ThreadDeath +java.lang.Exception +java.lang.RuntimeException +java.lang.SecurityManager +java.security.ProtectionDomain +java.security.AccessControlContext +java.security.AccessController +java.security.SecureClassLoader +java.lang.ReflectiveOperationException +java.lang.ClassNotFoundException +java.lang.Record +java.lang.LinkageError +java.lang.NoClassDefFoundError +java.lang.ClassCastException +java.lang.ArrayStoreException +java.lang.VirtualMachineError +java.lang.InternalError +java.lang.OutOfMemoryError +java.lang.StackOverflowError +java.lang.IllegalMonitorStateException +java.lang.ref.Reference +java.lang.ref.SoftReference +java.lang.ref.WeakReference +java.lang.ref.FinalReference +java.lang.ref.PhantomReference +java.lang.ref.Finalizer +java.lang.Runnable +java.lang.Thread +java.lang.Thread$UncaughtExceptionHandler +java.lang.ThreadGroup +java.util.Dictionary +java.util.Map +java.util.Hashtable +java.util.Properties +java.lang.Module +java.lang.reflect.AccessibleObject +java.lang.reflect.Member +java.lang.reflect.Field +java.lang.reflect.Parameter +java.lang.reflect.Executable +java.lang.reflect.Method +java.lang.reflect.Constructor +jdk.internal.reflect.MagicAccessorImpl +jdk.internal.reflect.MethodAccessor +jdk.internal.reflect.MethodAccessorImpl +jdk.internal.reflect.ConstructorAccessor +jdk.internal.reflect.ConstructorAccessorImpl +jdk.internal.reflect.DelegatingClassLoader +jdk.internal.reflect.ConstantPool +jdk.internal.reflect.FieldAccessor +jdk.internal.reflect.FieldAccessorImpl +jdk.internal.reflect.UnsafeFieldAccessorImpl +jdk.internal.reflect.UnsafeStaticFieldAccessorImpl +java.lang.annotation.Annotation +jdk.internal.reflect.CallerSensitive +jdk.internal.reflect.NativeConstructorAccessorImpl +java.lang.invoke.MethodHandle +java.lang.invoke.DirectMethodHandle +java.lang.invoke.VarHandle +java.lang.invoke.MemberName +java.lang.invoke.ResolvedMethodName +java.lang.invoke.MethodHandleNatives +java.lang.invoke.LambdaForm +java.lang.invoke.TypeDescriptor$OfMethod +java.lang.invoke.MethodType +java.lang.BootstrapMethodError +java.lang.invoke.CallSite +jdk.internal.invoke.NativeEntryPoint +java.lang.invoke.MethodHandleNatives$CallSiteContext +java.lang.invoke.ConstantCallSite +java.lang.invoke.MutableCallSite +java.lang.invoke.VolatileCallSite +java.lang.AssertionStatusDirectives +java.lang.Appendable +java.lang.AbstractStringBuilder +java.lang.StringBuffer +java.lang.StringBuilder +jdk.internal.misc.UnsafeConstants +jdk.internal.misc.Unsafe +jdk.internal.module.Modules +java.lang.AutoCloseable +java.io.Closeable +java.io.InputStream +java.io.ByteArrayInputStream +java.net.URL +java.util.jar.Manifest +jdk.internal.loader.BuiltinClassLoader +jdk.internal.loader.ClassLoaders +jdk.internal.loader.ClassLoaders$AppClassLoader +jdk.internal.loader.ClassLoaders$PlatformClassLoader +java.security.CodeSource +java.util.AbstractMap +java.util.concurrent.ConcurrentMap +java.util.concurrent.ConcurrentHashMap +java.lang.Iterable +java.util.Collection +java.util.AbstractCollection +java.util.List +java.util.AbstractList +java.util.RandomAccess +java.util.ArrayList +java.lang.StackTraceElement +java.nio.Buffer +java.lang.StackWalker +java.lang.StackStreamFactory$AbstractStackWalker +java.lang.StackWalker$StackFrame +java.lang.StackFrameInfo +java.lang.LiveStackFrame +java.lang.LiveStackFrameInfo +java.util.concurrent.locks.AbstractOwnableSynchronizer +java.lang.Boolean +java.lang.Character +java.lang.Number +java.lang.Float +java.lang.Double +java.lang.Byte +java.lang.Short +java.lang.Integer +java.lang.Long +java.util.Iterator +java.lang.reflect.RecordComponent +jdk.internal.vm.vector.VectorSupport +jdk.internal.vm.vector.VectorSupport$VectorPayload +jdk.internal.vm.vector.VectorSupport$Vector +jdk.internal.vm.vector.VectorSupport$VectorMask +jdk.internal.vm.vector.VectorSupport$VectorShuffle +java.lang.Integer$IntegerCache +java.lang.Long$LongCache +java.lang.Byte$ByteCache +java.lang.Short$ShortCache +java.lang.Character$CharacterCache +java.util.jar.Attributes$Name +java.util.ImmutableCollections$AbstractImmutableMap +java.util.ImmutableCollections$MapN +sun.util.locale.BaseLocale +jdk.internal.module.ArchivedModuleGraph +java.lang.module.ModuleFinder +jdk.internal.module.SystemModuleFinders$SystemModuleFinder +java.util.ImmutableCollections$AbstractImmutableCollection +java.util.Set +java.util.ImmutableCollections$AbstractImmutableSet +java.util.ImmutableCollections$SetN +java.lang.module.ModuleReference +jdk.internal.module.ModuleReferenceImpl +java.lang.module.ModuleDescriptor +java.lang.module.ModuleDescriptor$Version +java.util.ImmutableCollections$Set12 +java.lang.module.ModuleDescriptor$Requires +java.lang.Enum +java.lang.module.ModuleDescriptor$Requires$Modifier +java.lang.module.ModuleDescriptor$Exports +java.net.URI +java.util.function.Supplier +jdk.internal.module.SystemModuleFinders$2 +jdk.internal.module.ModuleHashes$HashSupplier +jdk.internal.module.SystemModuleFinders$3 +java.lang.module.ModuleDescriptor$Provides +java.util.ImmutableCollections$AbstractImmutableList +java.util.ImmutableCollections$List12 +java.util.ImmutableCollections$ListN +java.lang.module.ModuleDescriptor$Opens +jdk.internal.module.ModuleTarget +jdk.internal.module.ModuleHashes +java.util.Collections$UnmodifiableMap +java.util.HashMap +java.util.Map$Entry +java.util.HashMap$Node +java.lang.module.Configuration +java.lang.module.ResolvedModule +java.util.function.Function +jdk.internal.module.ModuleLoaderMap$Mapper +java.util.ImmutableCollections +java.lang.ModuleLayer +jdk.internal.math.FDBigInteger +java.lang.NullPointerException +java.lang.ArithmeticException +java.io.ObjectStreamField +java.util.Comparator +java.lang.String$CaseInsensitiveComparator +java.lang.Module$ArchivedData +jdk.internal.misc.CDS +java.util.Objects +jdk.internal.access.JavaLangReflectAccess +java.lang.reflect.ReflectAccess +jdk.internal.access.SharedSecrets +java.lang.invoke.MethodHandles +java.lang.invoke.MemberName$Factory +java.security.Guard +java.security.Permission +java.security.BasicPermission +java.lang.reflect.ReflectPermission +java.lang.StringLatin1 +java.lang.invoke.MethodHandles$Lookup +jdk.internal.reflect.Reflection +java.lang.Math +java.util.AbstractSet +java.util.ImmutableCollections$MapN$1 +java.util.ImmutableCollections$MapN$MapNIterator +java.util.KeyValueHolder +java.util.LinkedHashMap$Entry +java.util.HashMap$TreeNode +java.lang.Runtime +java.util.concurrent.locks.Lock +java.util.concurrent.locks.ReentrantLock +java.util.concurrent.ConcurrentHashMap$Segment +java.util.concurrent.ConcurrentHashMap$CounterCell +java.util.concurrent.ConcurrentHashMap$Node +java.util.concurrent.locks.LockSupport +java.util.concurrent.ConcurrentHashMap$ReservationNode +java.security.PrivilegedAction +jdk.internal.reflect.ReflectionFactory$GetReflectionFactoryAction +jdk.internal.reflect.ReflectionFactory +java.lang.ref.Reference$ReferenceHandler +jdk.internal.ref.Cleaner +java.lang.ref.ReferenceQueue +java.lang.ref.ReferenceQueue$Null +java.lang.ref.ReferenceQueue$Lock +jdk.internal.access.JavaLangRefAccess +java.lang.ref.Reference$1 +java.lang.ref.Finalizer$FinalizerThread +jdk.internal.access.JavaLangAccess +java.lang.System$2 +jdk.internal.misc.VM +jdk.internal.util.SystemProps +jdk.internal.util.SystemProps$Raw +java.lang.StringConcatHelper +java.lang.VersionProps +java.util.Arrays +java.lang.CharacterData +java.lang.CharacterDataLatin1 +java.util.HashMap$EntrySet +java.util.HashMap$HashIterator +java.util.HashMap$EntryIterator +jdk.internal.util.StaticProperty +java.io.FileInputStream +java.io.FileDescriptor +jdk.internal.access.JavaIOFileDescriptorAccess +java.io.FileDescriptor$1 +java.io.Flushable +java.io.OutputStream +java.io.FileOutputStream +java.io.FilterInputStream +java.io.BufferedInputStream +java.io.FilterOutputStream +java.io.PrintStream +java.io.BufferedOutputStream +java.io.Writer +java.io.OutputStreamWriter +java.nio.charset.Charset +java.nio.charset.spi.CharsetProvider +sun.nio.cs.StandardCharsets +java.lang.ThreadLocal +java.util.concurrent.atomic.AtomicInteger +sun.security.action.GetPropertyAction +sun.nio.cs.HistoricallyNamedCharset +sun.nio.cs.Unicode +sun.nio.cs.UTF_8 +sun.nio.cs.StreamEncoder +java.nio.charset.CharsetEncoder +sun.nio.cs.UTF_8$Encoder +java.nio.charset.CodingErrorAction +java.nio.ByteBuffer +jdk.internal.misc.ScopedMemoryAccess +jdk.internal.access.JavaNioAccess +java.nio.Buffer$1 +java.nio.HeapByteBuffer +java.nio.ByteOrder +java.io.BufferedWriter +java.lang.Terminator +jdk.internal.misc.Signal$Handler +java.lang.Terminator$1 +jdk.internal.misc.Signal +java.util.Hashtable$Entry +jdk.internal.misc.Signal$NativeHandler +jdk.internal.misc.OSEnvironment +java.util.Collections +java.util.Collections$EmptySet +java.util.Collections$EmptyList +java.util.Collections$EmptyMap +java.lang.IllegalArgumentException +java.lang.invoke.MethodHandleStatics +jdk.internal.module.ModuleBootstrap +sun.invoke.util.VerifyAccess +java.lang.reflect.Modifier +jdk.internal.access.JavaLangModuleAccess +java.lang.module.ModuleDescriptor$1 +java.io.File +java.io.DefaultFileSystem +java.io.FileSystem +java.io.UnixFileSystem +jdk.internal.util.ArraysSupport +jdk.internal.module.ModulePatcher +jdk.internal.module.ModuleBootstrap$Counters +jdk.internal.module.ArchivedBootLayer +jdk.internal.access.JavaNetUriAccess +java.net.URI$1 +jdk.internal.loader.ArchivedClassLoaders +jdk.internal.loader.ClassLoaders$BootClassLoader +java.security.cert.Certificate +java.lang.ClassLoader$ParallelLoaders +java.util.WeakHashMap +java.util.WeakHashMap$Entry +java.util.Collections$SetFromMap +java.util.WeakHashMap$KeySet +jdk.internal.access.JavaSecurityAccess +java.security.ProtectionDomain$JavaSecurityAccessImpl +java.security.ProtectionDomain$Key +java.security.Principal +jdk.internal.loader.NativeLibraries +jdk.internal.loader.ClassLoaderHelper +java.util.HashSet +java.util.Queue +java.util.Deque +java.util.ArrayDeque +jdk.internal.loader.URLClassPath +java.net.URLStreamHandlerFactory +java.net.URL$DefaultFactory +jdk.internal.access.JavaNetURLAccess +java.net.URL$3 +java.io.File$PathStatus +sun.net.www.ParseUtil +java.util.HexFormat +java.net.URLStreamHandler +sun.net.www.protocol.file.Handler +sun.net.util.IPAddressUtil +jdk.internal.util.Preconditions +sun.net.www.protocol.jar.Handler +jdk.internal.module.ServicesCatalog +jdk.internal.loader.AbstractClassLoaderValue +jdk.internal.loader.ClassLoaderValue +java.util.Optional +jdk.internal.loader.BootLoader +jdk.internal.loader.BuiltinClassLoader$LoadedModule +java.util.ImmutableCollections$SetN$SetNIterator +java.util.ImmutableCollections$Set12$1 +java.util.ListIterator +java.util.ImmutableCollections$ListItr +jdk.internal.module.ModuleLoaderMap +jdk.internal.loader.AbstractClassLoaderValue$Memoizer +jdk.internal.module.ServicesCatalog$ServiceProvider +java.util.concurrent.CopyOnWriteArrayList +java.util.HashMap$KeySet +java.util.HashMap$KeyIterator +java.lang.ModuleLayer$Controller +java.lang.invoke.LambdaMetafactory +java.lang.invoke.MethodType$ConcurrentWeakInternSet +java.lang.Void +java.lang.invoke.MethodTypeForm +java.lang.invoke.MethodType$ConcurrentWeakInternSet$WeakEntry +sun.invoke.util.Wrapper +sun.invoke.util.Wrapper$Format +java.lang.invoke.LambdaForm$NamedFunction +java.lang.invoke.DirectMethodHandle$Holder +sun.invoke.util.ValueConversions +java.lang.invoke.MethodHandleImpl +java.lang.invoke.Invokers +java.lang.invoke.LambdaForm$Kind +java.lang.NoSuchMethodException +java.lang.invoke.LambdaForm$BasicType +java.lang.reflect.Array +java.lang.invoke.LambdaForm$Name +java.lang.invoke.LambdaForm$Holder +java.lang.invoke.InvokerBytecodeGenerator +java.lang.invoke.InvokerBytecodeGenerator$2 +java.lang.invoke.MethodHandleImpl$Intrinsic +java.lang.invoke.BootstrapMethodInvoker +java.lang.invoke.VarHandle$AccessMode +java.lang.invoke.VarHandle$AccessType +java.lang.invoke.Invokers$Holder +jdk.internal.access.JavaLangInvokeAccess +java.lang.invoke.MethodHandleImpl$1 +java.lang.invoke.AbstractValidatingLambdaMetafactory +java.lang.invoke.InnerClassLambdaMetafactory +jdk.internal.org.objectweb.asm.Type +sun.security.action.GetBooleanAction +jdk.internal.org.objectweb.asm.Handle +sun.invoke.util.BytecodeDescriptor +jdk.internal.org.objectweb.asm.ConstantDynamic +java.lang.invoke.MethodHandleInfo +java.lang.invoke.InfoFromMemberName +jdk.internal.org.objectweb.asm.ClassVisitor +jdk.internal.org.objectweb.asm.ClassWriter +jdk.internal.org.objectweb.asm.SymbolTable +jdk.internal.org.objectweb.asm.Symbol +jdk.internal.org.objectweb.asm.SymbolTable$Entry +jdk.internal.org.objectweb.asm.ByteVector +java.lang.invoke.LambdaProxyClassArchive +jdk.internal.org.objectweb.asm.MethodVisitor +jdk.internal.org.objectweb.asm.MethodWriter +jdk.internal.org.objectweb.asm.Label +java.lang.invoke.TypeConvertingMethodAdapter +java.lang.invoke.InnerClassLambdaMetafactory$ForwardingMethodGenerator +jdk.internal.org.objectweb.asm.Handler +jdk.internal.org.objectweb.asm.Attribute +jdk.internal.org.objectweb.asm.AnnotationVisitor +jdk.internal.org.objectweb.asm.AnnotationWriter +java.lang.invoke.MethodHandles$Lookup$ClassOption +java.lang.invoke.MethodHandles$Lookup$ClassFile +jdk.internal.org.objectweb.asm.ClassReader +java.lang.StringUTF16 +java.lang.invoke.MethodHandles$Lookup$ClassDefiner +jdk.internal.module.ModuleBootstrap$$Lambda$1/0x00007f4204040850 +java.lang.invoke.InnerClassLambdaMetafactory$1 +java.lang.Class$ReflectionData +java.lang.Class$Atomic +jdk.internal.reflect.DelegatingConstructorAccessorImpl +java.lang.invoke.BoundMethodHandle +java.lang.invoke.ClassSpecializer +java.lang.invoke.BoundMethodHandle$Specializer +java.lang.invoke.ClassSpecializer$1 +java.lang.invoke.ClassSpecializer$SpeciesData +java.lang.invoke.BoundMethodHandle$SpeciesData +java.lang.invoke.ClassSpecializer$Factory +java.lang.invoke.BoundMethodHandle$Specializer$Factory +java.lang.invoke.SimpleMethodHandle +java.lang.NoSuchFieldException +java.lang.invoke.BoundMethodHandle$Species_L +sun.invoke.util.VerifyType +sun.invoke.empty.Empty +java.lang.invoke.DirectMethodHandle$2 +java.lang.invoke.DirectMethodHandle$Accessor +java.lang.invoke.DelegatingMethodHandle +java.lang.invoke.MethodHandleImpl$IntrinsicMethodHandle +java.lang.invoke.DelegatingMethodHandle$Holder +sun.invoke.util.Wrapper$1 +java.lang.invoke.LambdaFormEditor +java.lang.invoke.LambdaFormEditor$TransformKey +java.lang.invoke.LambdaFormBuffer +java.lang.invoke.LambdaFormEditor$Transform +jdk.internal.org.objectweb.asm.Frame +java.lang.invoke.InvokerBytecodeGenerator$ClassData +java.util.ArrayList$Itr +jdk.internal.org.objectweb.asm.FieldVisitor +jdk.internal.org.objectweb.asm.FieldWriter +java.lang.invoke.LambdaForm$MH/0x00007f4204000400 +jdk.internal.ref.CleanerFactory +java.util.concurrent.ThreadFactory +jdk.internal.ref.CleanerFactory$1 +java.lang.ref.Cleaner +java.lang.ref.Cleaner$1 +jdk.internal.ref.CleanerImpl +java.lang.ref.Cleaner$Cleanable +jdk.internal.ref.PhantomCleanable +jdk.internal.ref.CleanerImpl$PhantomCleanableRef +jdk.internal.ref.CleanerImpl$CleanerCleanable +jdk.internal.misc.InnocuousThread +java.util.ArrayList$SubList +java.lang.Module$ReflectionData +java.lang.WeakPairMap +java.lang.WeakPairMap$Pair +java.lang.WeakPairMap$Pair$Lookup +java.util.function.BiFunction +java.lang.Module$$Lambda$2/0x00007f4204040a90 +java.lang.WeakPairMap$WeakRefPeer +java.lang.WeakPairMap$Pair$Weak +java.lang.WeakPairMap$Pair$Weak$1 +java.lang.WeakPairMap$$Lambda$3/0x00007f42040413e8 +java.lang.invoke.DirectMethodHandle$Constructor +java.lang.invoke.StringConcatFactory +java.lang.invoke.StringConcatFactory$1 +java.lang.invoke.StringConcatFactory$2 +java.lang.invoke.StringConcatFactory$3 +sun.launcher.LauncherHelper +java.lang.StringCoding +java.util.zip.ZipConstants +java.util.zip.ZipFile +java.util.jar.JarFile +jdk.internal.access.JavaUtilZipFileAccess +java.util.zip.ZipFile$1 +jdk.internal.access.JavaUtilJarAccess +java.util.jar.JavaUtilJarAccessImpl +java.lang.Runtime$Version +java.util.zip.ZipFile$CleanableResource +java.util.zip.ZipCoder +java.util.zip.ZipCoder$UTF8ZipCoder +java.util.zip.ZipFile$Source +sun.nio.fs.DefaultFileSystemProvider +java.nio.file.spi.FileSystemProvider +sun.nio.fs.AbstractFileSystemProvider +sun.nio.fs.UnixFileSystemProvider +sun.nio.fs.LinuxFileSystemProvider +java.nio.file.OpenOption +java.nio.file.StandardOpenOption +java.nio.file.FileSystem +sun.nio.fs.UnixFileSystem +sun.nio.fs.LinuxFileSystem +java.nio.file.Watchable +java.nio.file.Path +sun.nio.fs.UnixPath +sun.nio.fs.Util +sun.nio.fs.UnixNativeDispatcher +jdk.internal.loader.NativeLibraries$LibraryPaths +jdk.internal.loader.NativeLibraries$1 +java.util.ArrayDeque$DeqIterator +jdk.internal.loader.NativeLibrary +jdk.internal.loader.NativeLibraries$NativeLibraryImpl +java.util.concurrent.ConcurrentHashMap$CollectionView +java.util.concurrent.ConcurrentHashMap$ValuesView +java.util.concurrent.ConcurrentHashMap$Traverser +java.util.concurrent.ConcurrentHashMap$BaseIterator +java.util.Enumeration +java.util.concurrent.ConcurrentHashMap$ValueIterator +java.nio.file.attribute.BasicFileAttributes +java.nio.file.attribute.PosixFileAttributes +sun.nio.fs.UnixFileAttributes +sun.nio.fs.UnixFileStoreAttributes +sun.nio.fs.UnixMountEntry +java.util.zip.ZipFile$Source$Key +java.nio.file.CopyOption +java.nio.file.LinkOption +java.nio.file.Files +java.nio.file.attribute.DosFileAttributes +java.nio.file.attribute.AttributeView +java.nio.file.attribute.FileAttributeView +java.nio.file.attribute.BasicFileAttributeView +java.nio.file.attribute.DosFileAttributeView +java.nio.file.attribute.UserDefinedFileAttributeView +sun.nio.fs.UnixFileAttributeViews +sun.nio.fs.DynamicFileAttributeView +sun.nio.fs.AbstractBasicFileAttributeView +sun.nio.fs.UnixFileAttributeViews$Basic +sun.nio.fs.NativeBuffers +jdk.internal.misc.TerminatingThreadLocal +sun.nio.fs.NativeBuffers$1 +jdk.internal.misc.TerminatingThreadLocal$1 +java.lang.ThreadLocal$ThreadLocalMap +java.lang.ThreadLocal$ThreadLocalMap$Entry +java.util.IdentityHashMap +java.util.IdentityHashMap$KeySet +sun.nio.fs.NativeBuffer +sun.nio.fs.NativeBuffer$Deallocator +sun.nio.fs.UnixFileAttributes$UnixAsBasicFileAttributes +java.io.DataOutput +java.io.DataInput +java.io.RandomAccessFile +jdk.internal.access.JavaIORandomAccessFileAccess +java.io.RandomAccessFile$2 +java.io.FileCleanable +java.util.zip.ZipFile$Source$End +java.util.zip.ZipUtils +java.util.concurrent.TimeUnit +java.nio.file.attribute.FileTime +jdk.internal.perf.PerfCounter +jdk.internal.perf.Perf$GetPerfAction +jdk.internal.perf.Perf +jdk.internal.perf.PerfCounter$CoreCounters +sun.nio.ch.DirectBuffer +java.nio.MappedByteBuffer +java.nio.DirectByteBuffer +java.nio.Bits +java.util.concurrent.atomic.AtomicLong +jdk.internal.misc.VM$BufferPool +java.nio.Bits$1 +java.nio.LongBuffer +java.nio.DirectLongBufferU +java.util.zip.ZipEntry +java.util.jar.JarEntry +java.util.jar.JarFile$JarFileEntry +java.util.zip.ZipFile$ZipFileInputStream +java.util.zip.InflaterInputStream +java.util.zip.ZipFile$ZipFileInflaterInputStream +java.util.zip.Inflater +java.util.zip.Inflater$InflaterZStreamRef +java.util.zip.ZipFile$InflaterCleanupAction +sun.security.util.SignatureFileVerifier +sun.security.util.Debug +java.util.Locale +sun.util.locale.LocaleUtils +sun.security.action.GetIntegerAction +java.util.jar.JarVerifier +java.security.CodeSigner +java.io.ByteArrayOutputStream +java.util.jar.Attributes +java.util.LinkedHashMap +java.util.jar.Manifest$FastInputStream +java.io.RandomAccessFile$1 +sun.net.util.URLUtil +java.security.PrivilegedExceptionAction +jdk.internal.loader.URLClassPath$3 +jdk.internal.loader.URLClassPath$Loader +jdk.internal.loader.URLClassPath$JarLoader +jdk.internal.loader.URLClassPath$JarLoader$1 +jdk.internal.loader.FileURLMapper +jdk.internal.util.jar.JarIndex +java.util.StringTokenizer +jdk.internal.loader.Resource +jdk.internal.loader.URLClassPath$JarLoader$2 +java.lang.NamedPackage +java.lang.Package +java.lang.Package$VersionInfo +sun.nio.ByteBuffered +java.util.zip.Checksum +java.util.zip.CRC32 +java.util.zip.Checksum$1 +java.security.SecureClassLoader$CodeSourceKey +java.security.SecureClassLoader$1 +java.security.PermissionCollection +sun.security.util.LazyCodeSourcePermissionCollection +java.security.Permissions +java.lang.RuntimePermission +java.security.BasicPermissionCollection +java.security.AllPermission +java.security.UnresolvedPermission +java.security.SecureClassLoader$DebugHolder +org.apache.maven.surefire.booter.ForkedBooter +org.apache.maven.surefire.api.fork.ForkNodeArguments +org.apache.maven.plugin.surefire.log.api.ConsoleLogger +java.lang.SecurityException +java.security.AccessControlException +java.io.IOException +org.apache.maven.surefire.api.provider.CommandListener +org.apache.maven.surefire.api.report.ReporterFactory +java.util.concurrent.ConcurrentHashMap$ForwardingNode +org.apache.maven.surefire.api.provider.CommandChainReader +java.lang.InterruptedException +java.util.concurrent.Executor +java.util.concurrent.ExecutorService +java.util.concurrent.ScheduledExecutorService +java.lang.PublicMethods$MethodList +java.lang.PublicMethods$Key +java.util.concurrent.Semaphore +java.util.concurrent.locks.AbstractQueuedSynchronizer +java.util.concurrent.Semaphore$Sync +java.util.concurrent.Semaphore$NonfairSync +org.apache.maven.surefire.booter.BooterDeserializer +org.apache.maven.surefire.booter.SystemPropertyManager +java.util.Properties$LineReader +java.util.Properties$EntrySet +java.util.concurrent.ConcurrentHashMap$EntrySetView +java.util.Collections$SynchronizedCollection +java.util.Collections$SynchronizedSet +java.util.concurrent.ConcurrentHashMap$EntryIterator +java.util.concurrent.ConcurrentHashMap$MapEntry +java.util.Collections$UnmodifiableCollection +java.util.Collections$UnmodifiableSet +java.util.Collections$UnmodifiableCollection$1 +org.apache.maven.surefire.booter.KeyValueSource +org.apache.maven.surefire.booter.PropertiesWrapper +java.lang.IllegalStateException +java.io.FileInputStream$1 +org.apache.maven.surefire.booter.TypeEncodedValue +org.apache.maven.surefire.api.testset.DirectoryScannerParameters +org.apache.maven.surefire.api.util.RunOrder +org.apache.maven.surefire.api.testset.RunOrderParameters +org.apache.maven.surefire.api.testset.TestArtifactInfo +org.apache.maven.surefire.api.testset.TestRequest +org.apache.maven.surefire.api.testset.TestFilter +org.apache.maven.surefire.api.testset.GenericTestPattern +org.apache.maven.surefire.api.testset.TestListResolver +java.util.Collections$SingletonSet +org.apache.maven.surefire.api.testset.IncludedExcludedPatterns +java.util.LinkedHashSet +java.util.Collections$1 +org.apache.maven.surefire.shared.utils.StringUtils +java.lang.IndexOutOfBoundsException +java.lang.StringIndexOutOfBoundsException +org.apache.maven.surefire.api.testset.ResolvedTest +org.apache.maven.surefire.api.testset.ResolvedTest$Type +org.apache.maven.surefire.api.testset.ResolvedTest$ClassMatcher +org.apache.maven.surefire.api.testset.ResolvedTest$MethodMatcher +org.apache.maven.surefire.api.report.ReporterConfiguration +org.apache.maven.surefire.api.booter.Shutdown +java.lang.Class$3 +jdk.internal.reflect.NativeMethodAccessorImpl +jdk.internal.reflect.DelegatingMethodAccessorImpl +org.apache.maven.surefire.booter.ProviderConfiguration +org.apache.maven.surefire.api.cli.CommandLineOption +org.apache.maven.surefire.api.booter.DumpErrorSingleton +org.apache.maven.surefire.api.util.internal.DumpFileUtils +java.lang.ProcessEnvironment +java.lang.ProcessEnvironment$ExternalData +java.lang.ProcessEnvironment$Variable +java.lang.ProcessEnvironment$Value +java.lang.ProcessEnvironment$StringEnvironment +java.lang.management.ManagementFactory +java.lang.IncompatibleClassChangeError +java.lang.NoSuchMethodError +java.lang.invoke.LambdaForm$DMH/0x00007f4204006000 +java.lang.management.ManagementFactory$$Lambda$4/0x00007f42040451f8 +java.lang.management.PlatformManagedObject +java.lang.management.RuntimeMXBean +java.lang.management.ManagementFactory$PlatformMBeanFinder +java.lang.management.ManagementFactory$PlatformMBeanFinder$1 +java.io.FilePermission +jdk.internal.access.JavaIOFilePermissionAccess +java.io.FilePermission$1 +sun.security.util.FilePermCompat +sun.security.util.SecurityProperties +java.security.Security +jdk.internal.access.JavaSecuritySystemConfiguratorAccess +java.security.Security$1 +java.security.Security$2 +java.security.SystemConfigurator +java.security.SystemConfigurator$1 +sun.security.util.PropertyExpander +java.net.URLConnection +sun.net.www.URLConnection +sun.net.www.protocol.file.FileURLConnection +sun.net.www.MessageHeader +sun.net.ProgressMonitor +sun.net.ProgressMeteringPolicy +sun.net.DefaultProgressMeteringPolicy +jdk.internal.access.JavaSecurityPropertiesAccess +java.security.Security$3 +sun.management.spi.PlatformMBeanProvider +java.util.ServiceLoader +java.util.ServiceLoader$ModuleServicesLookupIterator +java.util.ServiceLoader$LazyClassPathLookupIterator +java.util.ServiceLoader$2 +java.util.ServiceLoader$3 +java.util.concurrent.CopyOnWriteArrayList$COWIterator +com.sun.management.internal.PlatformMBeanProviderImpl +java.util.ServiceLoader$1 +java.util.ServiceLoader$Provider +java.util.ServiceLoader$ProviderImpl +com.sun.management.internal.PlatformMBeanProviderImpl$$Lambda$5/0x00007f42040468a0 +sun.management.spi.PlatformMBeanProvider$PlatformComponent +com.sun.management.internal.PlatformMBeanProviderImpl$1 +java.util.stream.BaseStream +java.util.stream.Stream +java.util.Spliterators +java.util.Spliterators$EmptySpliterator +java.util.Spliterator +java.util.Spliterators$EmptySpliterator$OfRef +java.util.Spliterator$OfPrimitive +java.util.Spliterator$OfInt +java.util.Spliterators$EmptySpliterator$OfInt +java.util.Spliterator$OfLong +java.util.Spliterators$EmptySpliterator$OfLong +java.util.Spliterator$OfDouble +java.util.Spliterators$EmptySpliterator$OfDouble +java.util.Spliterators$ArraySpliterator +java.util.stream.StreamSupport +java.util.stream.PipelineHelper +java.util.stream.AbstractPipeline +java.util.stream.ReferencePipeline +java.util.stream.ReferencePipeline$Head +java.util.stream.StreamOpFlag +java.util.stream.StreamOpFlag$Type +java.util.stream.StreamOpFlag$MaskBuilder +java.util.EnumMap +java.util.EnumMap$1 +sun.reflect.annotation.AnnotationParser +java.util.stream.Collectors +java.util.stream.Collector$Characteristics +java.util.EnumSet +java.util.RegularEnumSet +java.util.stream.Collector +java.util.stream.Collectors$CollectorImpl +java.util.stream.Collectors$$Lambda$30/0x800000041 +java.util.function.BiConsumer +java.lang.invoke.DirectMethodHandle$Interface +java.util.stream.Collectors$$Lambda$22/0x800000035 +java.util.function.BinaryOperator +java.util.stream.Collectors$$Lambda$25/0x80000003c +java.util.stream.Collectors$$Lambda$27/0x80000003e +java.util.stream.ReduceOps +java.util.stream.TerminalOp +java.util.stream.ReduceOps$ReduceOp +java.util.stream.ReduceOps$3 +java.util.stream.StreamShape +java.util.stream.ReduceOps$Box +java.util.function.Consumer +java.util.stream.Sink +java.util.stream.TerminalSink +java.util.stream.ReduceOps$AccumulatingSink +java.util.stream.ReduceOps$3ReducingSink +com.sun.management.internal.PlatformMBeanProviderImpl$2 +com.sun.management.internal.PlatformMBeanProviderImpl$3 +com.sun.management.internal.PlatformMBeanProviderImpl$4 +javax.management.DynamicMBean +com.sun.management.DiagnosticCommandMBean +javax.management.NotificationBroadcaster +javax.management.NotificationEmitter +sun.management.NotificationEmitterSupport +com.sun.management.internal.DiagnosticCommandImpl +sun.management.ManagementFactoryHelper +sun.management.VMManagement +sun.management.VMManagementImpl +com.sun.management.internal.PlatformMBeanProviderImpl$5 +java.util.Collections$UnmodifiableList +java.util.Collections$UnmodifiableRandomAccessList +jdk.management.jfr.internal.FlightRecorderMXBeanProvider +java.util.concurrent.Callable +java.util.Collections$EmptyEnumeration +java.lang.management.DefaultPlatformMBeanProvider +java.lang.management.DefaultPlatformMBeanProvider$1 +java.lang.management.DefaultPlatformMBeanProvider$2 +java.lang.management.DefaultPlatformMBeanProvider$3 +java.lang.management.DefaultPlatformMBeanProvider$4 +java.lang.management.DefaultPlatformMBeanProvider$5 +java.lang.management.DefaultPlatformMBeanProvider$6 +java.lang.management.DefaultPlatformMBeanProvider$7 +java.lang.management.DefaultPlatformMBeanProvider$8 +sun.management.ManagementFactoryHelper$LoggingMXBeanAccess +sun.management.ManagementFactoryHelper$LoggingMXBeanAccess$1 +java.util.logging.LogManager +java.lang.management.DefaultPlatformMBeanProvider$9 +java.lang.management.DefaultPlatformMBeanProvider$10 +java.lang.management.DefaultPlatformMBeanProvider$11 +jdk.management.jfr.FlightRecorderMXBean +jdk.management.jfr.internal.FlightRecorderMXBeanProvider$SingleMBeanComponent +java.util.Collections$SingletonList +java.util.HashMap$Values +java.util.HashMap$HashMapSpliterator +java.util.HashMap$ValueSpliterator +java.util.function.Predicate +java.lang.management.ManagementFactory$PlatformMBeanFinder$$Lambda$10/0x00007f420404c288 +java.util.stream.ReferencePipeline$StatelessOp +java.util.stream.ReferencePipeline$2 +java.lang.management.ManagementFactory$PlatformMBeanFinder$$Lambda$11/0x00007f420404c4e0 +java.util.stream.ReduceOps$2 +java.util.stream.ReduceOps$2ReducingSink +java.util.stream.Sink$ChainedReference +java.util.stream.ReferencePipeline$2$1 +sun.management.RuntimeImpl +java.util.Collections$SingletonMap +java.util.Collections$2 +java.lang.invoke.LambdaForm$DMH/0x00007f4204006400 +sun.management.spi.PlatformMBeanProvider$PlatformComponent$$Lambda$12/0x00007f420404d2d0 +sun.management.spi.PlatformMBeanProvider$PlatformComponent$$Lambda$13/0x00007f420404d528 +java.util.stream.ReferencePipeline$3 +java.util.stream.Collectors$$Lambda$14/0x00007f420404d770 +java.util.stream.Collectors$$Lambda$15/0x00007f420404d990 +java.util.stream.Collectors$$Lambda$16/0x00007f420404dbc0 +java.util.stream.ReferencePipeline$3$1 +sun.management.Util +java.lang.management.ManagementPermission +java.util.Arrays$ArrayList +java.util.Arrays$ArrayItr +org.apache.maven.surefire.booter.ClassLoaderConfiguration +org.apache.maven.surefire.booter.AbstractPathConfiguration +org.apache.maven.surefire.booter.ClasspathConfiguration +org.apache.maven.surefire.booter.Classpath +java.net.MalformedURLException +java.net.URLClassLoader +org.apache.maven.surefire.booter.IsolatedClassLoader +org.apache.maven.surefire.booter.SurefireExecutionException +org.apache.maven.surefire.booter.ProcessCheckerType +org.apache.maven.surefire.booter.StartupConfiguration +org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory +java.util.Spliterators$1Adapter +java.util.HashMap$ValueIterator +jdk.internal.module.Resources +jdk.internal.loader.BuiltinClassLoader$2 +jdk.internal.loader.BuiltinClassLoader$5 +java.lang.module.ModuleReader +jdk.internal.module.SystemModuleFinders$SystemModuleReader +jdk.internal.module.SystemModuleFinders$SystemImage +jdk.internal.jimage.ImageReaderFactory +java.nio.file.Paths +java.nio.file.FileSystems +java.nio.file.FileSystems$DefaultFileSystemHolder +java.nio.file.FileSystems$DefaultFileSystemHolder$1 +java.net.URI$Parser +jdk.internal.jimage.ImageReaderFactory$1 +jdk.internal.jimage.ImageReader +jdk.internal.jimage.BasicImageReader +jdk.internal.jimage.ImageReader$SharedImageReader +jdk.internal.jimage.BasicImageReader$1 +jdk.internal.jimage.NativeImageBuffer +jdk.internal.jimage.NativeImageBuffer$1 +jdk.internal.jimage.ImageHeader +java.nio.IntBuffer +java.nio.DirectIntBufferU +java.nio.DirectByteBufferR +java.nio.DirectIntBufferRU +jdk.internal.jimage.ImageStrings +jdk.internal.jimage.ImageStringsReader +jdk.internal.jimage.decompressor.Decompressor +jdk.internal.jimage.ImageLocation +java.util.Collections$EmptyIterator +jdk.internal.loader.BuiltinClassLoader$1 +java.lang.CompoundEnumeration +jdk.internal.loader.URLClassPath$1 +jdk.internal.loader.URLClassPath$FileLoader +java.util.SortedSet +java.util.NavigableSet +java.util.TreeSet +java.util.SortedMap +java.util.NavigableMap +java.util.TreeMap +java.util.TreeMap$Entry +java.util.TreeMap$KeySet +java.util.TreeMap$PrivateEntryIterator +java.util.TreeMap$KeyIterator +java.lang.Readable +java.io.Reader +java.io.BufferedReader +java.io.InputStreamReader +sun.nio.cs.StreamDecoder +java.nio.charset.CharsetDecoder +sun.nio.cs.UTF_8$Decoder +java.util.Vector +java.nio.CharBuffer +java.nio.HeapCharBuffer +java.nio.charset.CoderResult +java.util.AbstractSequentialList +java.util.LinkedList +java.util.LinkedList$Node +java.net.JarURLConnection +sun.net.www.protocol.jar.JarURLConnection +sun.net.www.protocol.jar.URLJarFile$URLJarFileCloseController +sun.net.www.protocol.jar.JarFileFactory +sun.net.www.protocol.jar.URLJarFile +sun.nio.fs.UnixFileKey +sun.net.www.protocol.jar.URLJarFile$URLJarFileEntry +sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream +java.util.LinkedHashMap$LinkedKeySet +java.util.LinkedHashMap$LinkedHashIterator +java.util.LinkedHashMap$LinkedKeyIterator +org.apache.maven.surefire.booter.spi.AbstractMasterProcessChannelProcessorFactory +org.apache.maven.surefire.booter.spi.LegacyMasterProcessChannelProcessorFactory +org.apache.maven.surefire.api.booter.MasterProcessChannelEncoder +org.apache.maven.surefire.api.booter.MasterProcessChannelDecoder +org.apache.maven.surefire.api.util.internal.DaemonThreadFactory +java.util.concurrent.Executors +java.util.concurrent.Executors$DefaultThreadFactory +org.apache.maven.surefire.api.util.internal.DaemonThreadFactory$NamedThreadFactory +java.util.concurrent.AbstractExecutorService +java.util.concurrent.ThreadPoolExecutor +java.util.concurrent.ScheduledThreadPoolExecutor +java.util.concurrent.RejectedExecutionHandler +java.util.concurrent.ThreadPoolExecutor$AbortPolicy +java.util.concurrent.BlockingQueue +java.util.AbstractQueue +java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue +java.util.concurrent.Future +java.util.concurrent.RunnableFuture +java.util.concurrent.Delayed +java.util.concurrent.ScheduledFuture +java.util.concurrent.RunnableScheduledFuture +java.util.concurrent.locks.ReentrantLock$Sync +java.util.concurrent.locks.ReentrantLock$NonfairSync +java.util.concurrent.locks.Condition +java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject +org.apache.maven.surefire.booter.spi.SurefireMasterProcessChannelProcessorFactory +java.net.URISyntaxException +java.util.concurrent.ExecutionException +java.net.SocketAddress +java.net.InetSocketAddress +java.nio.channels.Channel +java.nio.channels.AsynchronousChannel +java.nio.channels.AsynchronousByteChannel +org.apache.maven.surefire.booter.ForkedNodeArg +java.lang.UnsupportedOperationException +org.apache.maven.plugin.surefire.log.api.NullConsoleLogger +org.apache.maven.surefire.api.util.internal.Channels +org.apache.maven.surefire.api.util.internal.Channels$2 +org.apache.maven.surefire.api.util.internal.Channels$1 +java.nio.channels.WritableByteChannel +org.apache.maven.surefire.api.util.internal.WritableBufferedByteChannel +java.nio.channels.ReadableByteChannel +org.apache.maven.surefire.api.util.internal.AbstractNoninterruptibleWritableChannel +org.apache.maven.surefire.api.util.internal.Channels$4 +java.nio.channels.ClosedChannelException +java.nio.channels.NonWritableChannelException +org.apache.maven.surefire.booter.spi.AbstractMasterProcessChannelProcessorFactory$1 +java.util.concurrent.FutureTask +java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask +java.lang.invoke.VarHandles +java.lang.invoke.VarHandleInts$FieldInstanceReadOnly +java.lang.invoke.VarHandleInts$FieldInstanceReadWrite +java.lang.invoke.VarHandle$1 +jdk.internal.util.Preconditions$1 +java.lang.invoke.VarHandleGuards +java.lang.invoke.VarForm +java.lang.invoke.VarHandleReferences$FieldInstanceReadOnly +java.lang.invoke.VarHandleReferences$FieldInstanceReadWrite +java.util.concurrent.FutureTask$WaitNode +java.util.concurrent.Executors$RunnableAdapter +java.util.concurrent.ThreadPoolExecutor$Worker +java.lang.Thread$State +java.util.concurrent.TimeUnit$1 +java.time.temporal.TemporalUnit +java.time.temporal.ChronoUnit +java.time.temporal.TemporalAmount +java.time.Duration +java.math.BigInteger +java.lang.invoke.VarHandle$AccessDescriptor +org.apache.maven.surefire.api.stream.AbstractStreamEncoder +java.util.concurrent.ForkJoinPool$ManagedBlocker +org.apache.maven.surefire.booter.stream.EventEncoder +org.apache.maven.surefire.booter.spi.EventChannelEncoder +java.util.concurrent.locks.AbstractQueuedSynchronizer$Node +java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode +java.lang.AssertionError +org.apache.maven.surefire.api.booter.ForkedProcessEventType +org.apache.maven.surefire.api.report.ReportEntry +java.util.concurrent.atomic.AtomicBoolean +org.apache.maven.surefire.booter.spi.CommandChannelDecoder +org.apache.maven.surefire.api.stream.MalformedChannelException +org.apache.maven.surefire.api.stream.AbstractStreamDecoder +org.apache.maven.surefire.booter.stream.CommandDecoder +org.apache.maven.surefire.api.util.internal.AbstractNoninterruptibleReadableChannel +org.apache.maven.surefire.api.util.internal.Channels$3 +java.nio.channels.NonReadableChannelException +java.io.EOFException +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$MalformedFrameException +java.io.FileNotFoundException +org.apache.maven.surefire.api.stream.SegmentType +org.apache.maven.surefire.api.booter.Constants +java.nio.charset.StandardCharsets +sun.nio.cs.US_ASCII +sun.nio.cs.ISO_8859_1 +sun.nio.cs.UTF_16BE +sun.nio.cs.UTF_16LE +sun.nio.cs.UTF_16 +org.apache.maven.surefire.api.booter.MasterProcessCommand +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$Segment +org.apache.maven.surefire.booter.ForkedBooter$8 +org.apache.maven.surefire.shared.utils.cli.ShutdownHookUtils +java.lang.ApplicationShutdownHooks +java.lang.ApplicationShutdownHooks$1 +java.lang.Shutdown +java.lang.Shutdown$Lock +org.apache.maven.surefire.api.booter.ForkingReporterFactory +org.apache.maven.surefire.api.report.RunListener +org.apache.maven.surefire.api.report.TestOutputReceiver +org.apache.maven.surefire.api.report.TestReportListener +org.apache.maven.surefire.api.booter.ForkingRunListener +org.apache.maven.surefire.booter.CommandReader +org.apache.maven.surefire.api.testset.TestSetFailedException +java.util.concurrent.ConcurrentLinkedQueue +java.util.concurrent.ConcurrentLinkedQueue$Node +org.apache.maven.surefire.booter.CommandReader$CommandRunnable +java.util.concurrent.atomic.AtomicReference +java.util.concurrent.CountDownLatch +java.util.concurrent.CountDownLatch$Sync +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$Memento +org.apache.maven.surefire.booter.PpidChecker +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$BufferedStream +org.apache.maven.surefire.booter.PpidChecker$ProcessInfoConsumer +org.apache.maven.surefire.booter.PpidChecker$1 +org.apache.maven.surefire.booter.PpidChecker$2 +org.apache.maven.surefire.api.stream.AbstractStreamDecoder$StreamReadStatus +org.apache.maven.surefire.booter.stream.CommandDecoder$1 +java.lang.NoSuchFieldError +org.apache.maven.surefire.shared.lang3.SystemUtils +org.apache.maven.surefire.api.booter.Command +org.apache.maven.surefire.booter.CommandReader$1 +java.util.concurrent.ConcurrentLinkedQueue$Itr +org.apache.maven.surefire.shared.lang3.SystemProperties +org.apache.maven.surefire.shared.lang3.function.Suppliers +org.apache.maven.surefire.shared.lang3.function.Suppliers$$Lambda$17/0x00007f4204010000 +org.apache.maven.surefire.shared.lang3.StringUtils +java.util.regex.Pattern +java.util.regex.Pattern$Node +java.util.regex.Pattern$LastNode +java.util.regex.Pattern$GroupHead +java.util.regex.CharPredicates +java.lang.Character$Subset +java.lang.Character$UnicodeBlock +java.util.regex.Pattern$CharPredicate +java.lang.invoke.LambdaForm$DMH/0x00007f4204014000 +java.util.regex.CharPredicates$$Lambda$18/0x00007f420405bdc8 +java.util.regex.Pattern$BmpCharPredicate +java.util.regex.Pattern$CharProperty +java.util.regex.Pattern$Qtype +java.util.regex.Pattern$BmpCharProperty +java.util.regex.Pattern$CharPropertyGreedy +java.util.regex.Pattern$SliceNode +java.util.regex.Pattern$Slice +java.util.regex.Pattern$Begin +java.util.regex.Pattern$First +java.util.regex.Pattern$Start +java.util.regex.Pattern$StartS +java.util.regex.Pattern$TreeInfo +org.apache.maven.surefire.shared.lang3.JavaVersion +org.apache.maven.surefire.shared.lang3.SystemProperties$$Lambda$19/0x00007f4204010678 +org.apache.maven.surefire.shared.lang3.math.NumberUtils +java.lang.NumberFormatException +java.math.BigDecimal +jdk.internal.math.FloatingDecimal +jdk.internal.math.FloatingDecimal$BinaryToASCIIConverter +jdk.internal.math.FloatingDecimal$ExceptionalBinaryToASCIIBuffer +jdk.internal.math.FloatingDecimal$BinaryToASCIIBuffer +jdk.internal.math.FloatingDecimal$1 +jdk.internal.math.FloatingDecimal$ASCIIToBinaryConverter +jdk.internal.math.FloatingDecimal$PreparedASCIIToBinaryBuffer +jdk.internal.math.FloatingDecimal$ASCIIToBinaryBuffer +org.apache.maven.surefire.shared.lang3.SystemUtils$$Lambda$20/0x00007f4204010ca0 +java.util.regex.Pattern$GroupTail +java.util.regex.CharPredicates$$Lambda$16/0x800000024 +java.util.regex.Pattern$BmpCharPropertyGreedy +java.util.regex.Pattern$$Lambda$18/0x800000028 +java.util.regex.Pattern$Ques +java.util.regex.Pattern$BranchConn +java.util.regex.Pattern$Branch +java.util.regex.ASCII +java.util.regex.Pattern$Curly +java.util.regex.CharPredicates$$Lambda$17/0x800000025 +java.util.regex.Pattern$Dollar +java.util.regex.Pattern$BitClass +org.apache.maven.surefire.booter.ForkedBooter$4 +org.apache.maven.surefire.api.booter.BiProperty +org.apache.maven.surefire.booter.ForkedBooter$3 +org.apache.maven.surefire.booter.ForkedBooter$PingScheduler +org.apache.maven.surefire.api.provider.ProviderParameters +org.apache.maven.surefire.api.booter.BaseProviderFactory +org.apache.maven.surefire.api.util.DirectoryScanner +org.apache.maven.surefire.api.util.ScanResult +org.apache.maven.surefire.api.util.RunOrderCalculator +org.apache.maven.surefire.api.util.ReflectionUtils +org.apache.maven.surefire.api.util.SurefireReflectionException +java.lang.reflect.InvocationTargetException +java.lang.IllegalAccessException +org.apache.maven.surefire.api.provider.SurefireProvider +org.apache.maven.surefire.api.provider.AbstractProvider +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider +org.junit.platform.launcher.Launcher +org.apache.maven.surefire.api.util.ScannerFilter +java.io.StringReader +java.io.UncheckedIOException +org.apache.maven.surefire.junitplatform.LazyLauncher +org.junit.platform.launcher.TagFilter +org.junit.platform.commons.JUnitException +org.junit.platform.commons.util.PreconditionViolationException +org.junit.platform.commons.PreconditionViolationException +org.junit.platform.engine.Filter +org.junit.platform.launcher.PostDiscoveryFilter +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$24/0x00007f4204016200 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$25/0x00007f4204016440 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$26/0x00007f4204016678 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$27/0x00007f42040168b8 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$28/0x00007f4204016af0 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$29/0x00007f4204016d40 +org.apache.maven.surefire.junitplatform.TestMethodFilter +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$30/0x00007f42040171f0 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$31/0x00007f4204017430 +org.junit.platform.launcher.EngineFilter +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$32/0x00007f42040178c0 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$33/0x00007f4204017b00 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$34/0x00007f4204017d38 +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$35/0x00007f4204015000 +org.junit.platform.launcher.TestExecutionListener +org.apache.maven.surefire.report.RunModeSetter +org.apache.maven.surefire.junitplatform.RunListenerAdapter +org.apache.maven.surefire.api.report.OutputReportEntry +org.apache.maven.surefire.api.report.TestSetReportEntry +org.apache.maven.surefire.api.report.StackTraceWriter +org.apache.maven.surefire.report.ClassMethodIndexer +org.apache.maven.surefire.api.report.RunMode +org.apache.maven.surefire.api.report.ConsoleOutputCapture +org.apache.maven.surefire.api.report.ConsoleOutputCapture$ForwardingPrintStream +org.apache.maven.surefire.api.report.ConsoleOutputCapture$NullOutputStream +java.util.logging.Logger +java.util.logging.Handler +java.util.logging.Level +java.util.logging.Level$KnownLevel +java.util.logging.Level$KnownLevel$$Lambda$13/0x800000021 +java.util.logging.Level$KnownLevel$$Lambda$14/0x800000022 +java.util.logging.Logger$LoggerBundle +java.util.logging.Logger$ConfigurationData +java.util.logging.LogManager$1 +java.util.logging.LogManager$LoggerContext +java.util.logging.LogManager$SystemLoggerContext +java.util.logging.LogManager$LogNode +java.util.Collections$SynchronizedMap +java.util.logging.LogManager$Cleaner +java.util.logging.LoggingPermission +sun.util.logging.internal.LoggingProviderImpl$LogManagerAccess +java.util.logging.LogManager$LoggingProviderAccess +java.lang.System$LoggerFinder +jdk.internal.logger.DefaultLoggerFinder +sun.util.logging.internal.LoggingProviderImpl +java.util.logging.LogManager$2 +java.util.logging.LogManager$RootLogger +java.util.logging.LogManager$LoggerWeakRef +java.lang.invoke.MethodHandleImpl$AsVarargsCollector +java.lang.invoke.BoundMethodHandle$Species_LL +java.lang.invoke.LambdaForm$MH/0x00007f420401c000 +java.util.logging.LogManager$VisitedLoggers +java.util.logging.LogManager$LoggerContext$1 +java.util.concurrent.ConcurrentHashMap$KeySetView +java.util.Collections$3 +java.util.concurrent.ConcurrentHashMap$KeyIterator +java.util.Hashtable$Enumerator +java.util.logging.Level$$Lambda$12/0x800000010 +java.util.ArrayList$ArrayListSpliterator +java.util.logging.Level$KnownLevel$$Lambda$15/0x800000023 +java.util.stream.ReferencePipeline$7 +java.util.stream.FindOps +java.util.stream.FindOps$FindSink +java.util.stream.FindOps$FindSink$OfRef +java.util.stream.FindOps$FindOp +java.util.stream.FindOps$FindSink$OfRef$$Lambda$40/0x80000004b +java.util.stream.FindOps$FindSink$OfRef$$Lambda$38/0x800000049 +java.util.stream.FindOps$FindSink$OfRef$$Lambda$39/0x80000004a +java.util.stream.FindOps$FindSink$OfRef$$Lambda$37/0x800000048 +java.util.stream.ReferencePipeline$7$1 +java.util.stream.Streams$AbstractStreamBuilderImpl +java.util.stream.Stream$Builder +java.util.stream.Streams$StreamBuilderImpl +java.util.stream.Streams +java.util.IdentityHashMap$Values +java.lang.System$Logger +sun.util.logging.PlatformLogger$Bridge +sun.util.logging.PlatformLogger$ConfigurableBridge +jdk.internal.logger.BootstrapLogger +jdk.internal.logger.BootstrapLogger$DetectBackend +jdk.internal.logger.BootstrapLogger$DetectBackend$1 +jdk.internal.logger.BootstrapLogger$LoggingBackend +jdk.internal.logger.BootstrapLogger$RedirectedLoggers +jdk.internal.logger.BootstrapLogger$BootstrapExecutors +java.util.logging.LogManager$4 +java.util.logging.Logger$SystemLoggerHelper +java.util.logging.Logger$SystemLoggerHelper$1 +jdk.internal.logger.DefaultLoggerFinder$1 +org.apache.maven.surefire.junitplatform.TestPlanScannerFilter +org.apache.maven.surefire.api.util.DefaultScanResult +jdk.internal.loader.URLClassPath$FileLoader$1 +software.amazon.lambda.powertools.kafka.internal.DeserializationUtilsTest +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder +org.junit.platform.engine.ConfigurationParameters +org.junit.platform.engine.EngineDiscoveryRequest +org.junit.platform.launcher.LauncherDiscoveryRequest +org.junit.platform.engine.reporting.OutputDirectoryProvider +org.junit.platform.engine.DiscoverySelector +org.junit.platform.engine.discovery.DiscoverySelectors +org.junit.platform.commons.util.Preconditions +org.junit.platform.commons.util.StringUtils +org.junit.platform.commons.util.StringUtils$TwoPartSplitResult +java.util.regex.CharPredicates$$Lambda$44/0x00007f420405d900 +org.junit.platform.engine.discovery.ClassSelector +java.lang.invoke.LambdaForm$DMH/0x00007f420401c400 +org.junit.platform.commons.util.Preconditions$$Lambda$45/0x00007f420401a5b0 +org.junit.platform.commons.util.Preconditions$$Lambda$46/0x00007f420401a7e8 +java.lang.invoke.LambdaForm$DMH/0x00007f420401c800 +java.lang.invoke.DirectMethodHandle$Special +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder$$Lambda$47/0x00007f420401aa20 +org.junit.platform.launcher.core.LauncherConfigurationParameters +org.junit.platform.commons.logging.LoggerFactory +org.junit.platform.commons.logging.Logger +org.junit.platform.commons.logging.LoggerFactory$DelegatingLogger +org.junit.platform.launcher.core.LauncherConfigurationParameters$Builder +org.junit.platform.launcher.core.LauncherConfigurationParameters$Builder$$Lambda$48/0x00007f420401b760 +org.junit.platform.commons.util.CollectionUtils +org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider +org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider$2 +org.junit.platform.commons.util.ClassLoaderUtils +org.junit.platform.launcher.core.LauncherConfigurationParameters$ParameterProvider$3 +org.junit.platform.launcher.core.LauncherConfigurationParameters$$Lambda$49/0x00007f420401e458 +org.junit.platform.launcher.core.LauncherConfigurationParameters$$Lambda$50/0x00007f420401e6a0 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners +org.junit.platform.engine.EngineDiscoveryListener +org.junit.platform.launcher.LauncherDiscoveryListener +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$LauncherDiscoveryListenerType +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$LauncherDiscoveryListenerType$$Lambda$51/0x00007f420401f140 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$LauncherDiscoveryListenerType$$Lambda$52/0x00007f420401f360 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$$Lambda$53/0x00007f420401f778 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$$Lambda$54/0x00007f420401f9d0 +org.junit.platform.launcher.listeners.discovery.AbortOnFailureLauncherDiscoveryListener +org.junit.platform.engine.EngineDiscoveryListener$1 +org.junit.platform.launcher.LauncherDiscoveryListener$1 +org.junit.platform.launcher.listeners.discovery.LauncherDiscoveryListeners$$Lambda$55/0x00007f420401d4c0 +org.junit.platform.launcher.core.HierarchicalOutputDirectoryProvider +java.util.regex.Pattern$$Lambda$56/0x00007f420405df20 +java.util.regex.Pattern$CharPredicate$$Lambda$57/0x00007f420405e180 +java.util.regex.Pattern$CharPredicate$$Lambda$21/0x80000002d +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder$$Lambda$59/0x00007f420401d928 +org.junit.platform.launcher.core.DefaultDiscoveryRequest +org.junit.platform.launcher.LauncherSession +org.junit.platform.launcher.core.LauncherFactory +org.junit.platform.launcher.core.LauncherConfig +org.junit.platform.launcher.core.LauncherConfig$Builder +org.junit.platform.launcher.core.DefaultLauncherConfig +org.junit.platform.launcher.core.DefaultLauncherSession +org.junit.platform.launcher.LauncherInterceptor +org.junit.platform.launcher.core.DefaultLauncherSession$1 +org.junit.platform.launcher.core.LauncherConfigurationParameters$$Lambda$60/0x00007f4204020dd0 +org.junit.platform.launcher.core.ClasspathAlignmentCheckingLauncherInterceptor +org.junit.platform.launcher.LauncherSessionListener +org.junit.platform.launcher.core.LauncherFactory$$Lambda$61/0x00007f4204021448 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore +org.junit.platform.launcher.core.LauncherFactory$$Lambda$62/0x00007f4204021898 +org.junit.platform.engine.support.store.NamespacedHierarchicalStoreException +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$CloseAction +java.lang.invoke.LambdaForm$DMH/0x00007f4204024000 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$CloseAction$$Lambda$63/0x00007f4204021f40 +java.util.stream.SliceOps +java.util.stream.ReferencePipeline$StatefulOp +java.util.stream.SliceOps$1 +org.junit.platform.launcher.core.DefaultLauncherSession$$Lambda$64/0x00007f4204022160 +java.util.stream.ReduceOps$1 +java.util.stream.ReduceOps$1ReducingSink +java.util.stream.SliceOps$1$1 +org.junit.platform.launcher.LauncherInterceptor$Invocation +java.lang.invoke.LambdaForm$DMH/0x00007f4204024400 +org.junit.platform.launcher.core.DefaultLauncherSession$$Lambda$65/0x00007f42040225a8 +org.junit.platform.launcher.core.ListenerRegistry +org.junit.platform.launcher.listeners.session.LauncherSessionListeners +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$66/0x00007f4204022c08 +org.junit.platform.launcher.core.ServiceLoaderRegistry +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$67/0x00007f4204023050 +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$68/0x00007f42040232a0 +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$69/0x00007f42040234e8 +org.junit.platform.commons.util.ServiceLoaderUtils +java.util.ServiceLoader$ProviderSpliterator +org.junit.platform.commons.util.ServiceLoaderUtils$$Lambda$70/0x00007f4204023948 +org.junit.platform.commons.util.ServiceLoaderUtils$$Lambda$71/0x00007f4204023ba0 +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$72/0x00007f4204026000 +java.lang.invoke.LambdaForm$DMH/0x00007f4204024800 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$73/0x00007f4204026228 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$74/0x00007f4204026460 +org.junit.platform.launcher.LauncherSessionListener$1 +org.junit.platform.launcher.core.DelegatingLauncher +org.junit.platform.launcher.core.InterceptingLauncher +org.junit.platform.launcher.core.DefaultLauncherSession$$Lambda$75/0x00007f4204026db0 +org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry +org.junit.platform.engine.TestEngine +org.junit.platform.launcher.core.ServiceLoaderTestEngineRegistry$$Lambda$76/0x00007f42040271d8 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$77/0x00007f4204027400 +org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine +org.junit.jupiter.engine.JupiterTestEngine +org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutorService +org.junit.jupiter.engine.config.JupiterConfiguration +org.junit.platform.engine.TestDescriptor +org.junit.platform.engine.support.hierarchical.EngineExecutionContext +org.junit.platform.launcher.core.LauncherFactory$$Lambda$78/0x00007f4204025400 +org.junit.platform.launcher.core.DefaultLauncher +org.junit.platform.launcher.TestPlan +org.junit.platform.launcher.core.InternalTestPlan +org.junit.platform.launcher.core.LauncherListenerRegistry +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$79/0x00007f4204024c00 +org.junit.platform.launcher.core.CompositeTestExecutionListener +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$80/0x00007f42040282a0 +org.junit.platform.launcher.core.EngineExecutionOrchestrator +org.junit.platform.launcher.TestPlan$Visitor +org.junit.platform.engine.EngineExecutionListener +org.junit.platform.launcher.core.DiscoveryIssueException +org.junit.platform.launcher.core.DefaultLauncher$$Lambda$81/0x00007f4204028d68 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator +org.junit.platform.launcher.core.EngineDiscoveryResultValidator +org.junit.platform.launcher.core.EngineIdValidator +org.junit.platform.launcher.core.EngineIdValidator$$Lambda$82/0x00007f42040295d0 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$83/0x00007f42040297f8 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$84/0x00007f4204029a30 +org.junit.platform.commons.util.ClassNamePatternFilterUtils +org.junit.platform.launcher.core.LauncherFactory$$Lambda$85/0x00007f4204029e70 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$86/0x00007f420402a0b0 +java.lang.invoke.LambdaForm$DMH/0x00007f420402c000 +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$87/0x00007f420402a300 +org.junit.platform.launcher.core.ServiceLoaderRegistry$$Lambda$88/0x00007f420402a558 +org.junitpioneer.jupiter.issue.IssueExtensionExecutionListener +org.junitpioneer.jupiter.IssueProcessor +org.junit.platform.launcher.listeners.UniqueIdTrackingListener +org.junit.platform.launcher.core.LauncherFactory$$Lambda$89/0x00007f420402aee8 +org.junit.platform.launcher.core.LauncherFactory$$Lambda$90/0x00007f420402b120 +org.junit.platform.launcher.core.InterceptingLauncher$$Lambda$91/0x00007f420402b358 +org.junit.platform.launcher.core.LauncherPhase +org.junit.platform.engine.UniqueId +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$92/0x00007f420402bbf0 +org.junit.platform.launcher.core.DiscoveryIssueCollector +org.junit.platform.engine.TestSource +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener +org.junit.platform.launcher.core.DelegatingLauncherDiscoveryRequest +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$1 +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener$$Lambda$93/0x00007f420402ecc8 +org.junit.platform.launcher.core.EngineFilterer +org.junit.platform.engine.FilterResult +org.junit.platform.launcher.core.EngineFilterer$$Lambda$94/0x00007f420402f348 +java.lang.invoke.LambdaForm$DMH/0x00007f420402c400 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$95/0x00007f420402f590 +java.util.stream.MatchOps$MatchKind +java.util.stream.MatchOps +java.util.stream.MatchOps$MatchOp +java.util.stream.MatchOps$BooleanTerminalSink +java.util.stream.MatchOps$$Lambda$96/0x00007f4204060150 +java.util.stream.MatchOps$1MatchSink +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$97/0x00007f420402f7e0 +org.junit.platform.engine.UniqueIdFormat +java.io.UnsupportedEncodingException +java.util.Formatter +java.util.regex.Pattern$$Lambda$19/0x800000029 +java.util.regex.Pattern$BmpCharPredicate$$Lambda$20/0x80000002b +java.util.Locale$Category +java.util.Formatter$Conversion +java.util.Formatter$FormatString +java.util.Formatter$FormatSpecifier +java.util.Formatter$Flags +java.util.Formatter$FixedString +java.util.Formattable +java.util.regex.Pattern$$Lambda$100/0x00007f4204060cd8 +java.lang.invoke.LambdaForm$DMH/0x00007f420402c800 +org.junit.platform.engine.UniqueIdFormat$$Lambda$101/0x00007f420402fc28 +java.net.URLEncoder +java.util.BitSet +java.io.CharArrayWriter +org.junit.platform.engine.UniqueIdFormat$$Lambda$102/0x00007f420402d000 +org.junit.platform.engine.UniqueIdFormat$$Lambda$103/0x00007f420402d240 +org.junit.platform.engine.UniqueIdFormat$$Lambda$104/0x00007f420402d480 +org.junit.platform.engine.UniqueIdFormat$$Lambda$105/0x00007f420402d6c0 +org.junit.platform.engine.UniqueIdFormat$$Lambda$106/0x00007f420402d900 +org.junit.platform.engine.UniqueId$Segment +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener$$Lambda$107/0x00007f420402dd60 +org.junit.jupiter.engine.config.CachingJupiterConfiguration +org.junit.jupiter.engine.config.DefaultJupiterConfiguration +org.junit.jupiter.api.parallel.ExecutionMode +org.junit.jupiter.api.TestInstance$Lifecycle +org.junit.jupiter.api.io.CleanupMode +org.junit.jupiter.api.extension.TestInstantiationAwareExtension$ExtensionContextScope +org.junit.jupiter.engine.config.EnumConfigurationParameterConverter +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter +org.junit.jupiter.api.DisplayNameGenerator +org.junit.jupiter.api.MethodOrderer +org.junit.jupiter.api.ClassOrderer +org.junit.jupiter.api.io.TempDirFactory +org.junit.platform.engine.support.hierarchical.Node +org.junit.platform.engine.support.descriptor.AbstractTestDescriptor +org.junit.platform.engine.support.descriptor.EngineDescriptor +org.junit.jupiter.engine.descriptor.JupiterEngineDescriptor +org.junit.jupiter.engine.extension.ExtensionRegistry +org.junit.jupiter.api.extension.ExtensionContext +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver +org.junit.platform.engine.support.discovery.SelectorResolver +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$InitializationContext +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$Builder +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$108/0x00007f42040333f8 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$Builder$$Lambda$109/0x00007f4204033638 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$110/0x00007f4204033880 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$111/0x00007f4204033ac0 +org.junit.platform.engine.TestDescriptor$Visitor +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$112/0x00007f4204033f00 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter +org.junit.platform.engine.DiscoveryIssue +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$$Lambda$113/0x00007f4204034540 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$$Lambda$114/0x00007f4204034788 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$DefaultInitializationContext +org.junit.platform.engine.DiscoveryFilter +org.junit.platform.engine.discovery.ClassNameFilter +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$115/0x00007f4204035040 +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$116/0x00007f4204035298 +org.junit.platform.engine.discovery.PackageNameFilter +org.junit.platform.engine.CompositeFilter +org.junit.platform.engine.CompositeFilter$1 +org.junit.platform.engine.CompositeFilter$1$$Lambda$117/0x00007f4204035b58 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$$Lambda$118/0x00007f4204035da8 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver$$Lambda$119/0x00007f4204035ff0 +java.util.stream.Collectors$$Lambda$120/0x00007f4204061750 +java.util.stream.Collectors$$Lambda$121/0x00007f4204061980 +org.junit.platform.engine.support.discovery.ClassContainerSelectorResolver +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$122/0x00007f4204036740 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$123/0x00007f4204036990 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$124/0x00007f4204036be0 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$125/0x00007f4204036e38 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod +org.junit.jupiter.engine.discovery.predicates.IsTestMethod +org.junit.jupiter.api.Test +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$Condition +org.junit.jupiter.engine.discovery.predicates.IsTestMethod$$Lambda$126/0x00007f4204037960 +org.junit.platform.commons.support.ModifierSupport +java.lang.invoke.LambdaForm$DMH/0x00007f4204038000 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$127/0x00007f4204037d98 +java.lang.invoke.MethodHandle$1 +java.lang.invoke.LambdaForm$DMH/0x00007f4204038400 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$128/0x00007f420403c000 +java.lang.invoke.LambdaForm$DMH/0x00007f4204038800 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$$Lambda$129/0x00007f420403c248 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$130/0x00007f420403c4a0 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$131/0x00007f420403c6f0 +java.lang.invoke.LambdaForm$DMH/0x00007f4204038c00 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$Condition$$Lambda$132/0x00007f420403c938 +org.junit.platform.commons.util.ReflectionUtils +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$133/0x00007f420403cd98 +org.junit.jupiter.engine.discovery.predicates.IsTestableMethod$$Lambda$134/0x00007f420403cfe8 +org.junit.jupiter.engine.discovery.predicates.IsTestFactoryMethod +org.junit.jupiter.api.DynamicNode +java.util.regex.MatchResult +java.util.regex.Matcher +java.util.regex.IntHashSet +org.junit.jupiter.api.TestFactory +org.junit.jupiter.engine.discovery.predicates.IsTestFactoryMethod$$Lambda$135/0x00007f420403d8b8 +org.junit.jupiter.engine.discovery.predicates.IsTestFactoryMethod$$Lambda$136/0x00007f420403dae8 +org.junit.jupiter.engine.discovery.predicates.IsTestFactoryMethod$$Lambda$137/0x00007f420403dd40 +java.util.function.Predicate$$Lambda$138/0x00007f4204062210 +org.junit.jupiter.engine.discovery.predicates.IsTestTemplateMethod +org.junit.jupiter.api.TestTemplate +org.junit.jupiter.engine.discovery.predicates.IsTestTemplateMethod$$Lambda$139/0x00007f420403e3f0 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$140/0x00007f420403e620 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$141/0x00007f420403e870 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$142/0x00007f420403eab8 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$143/0x00007f420403ed08 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$144/0x00007f420403ef48 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$145/0x00007f420403f198 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$146/0x00007f420403f3d8 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$147/0x00007f420403f628 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$148/0x00007f420403f868 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$149/0x00007f420403fab8 +org.junit.jupiter.engine.discovery.ClassSelectorResolver +org.junit.jupiter.engine.descriptor.ResourceLockAware +org.junit.jupiter.engine.descriptor.TestClassAware +org.junit.jupiter.engine.descriptor.Validatable +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor +org.junit.jupiter.engine.descriptor.ClassTestDescriptor +org.junit.jupiter.engine.descriptor.NestedClassTestDescriptor +org.junit.jupiter.api.extension.ClassTemplateInvocationContext +org.junit.jupiter.engine.descriptor.Filterable +org.junit.jupiter.engine.descriptor.ClassTemplateTestDescriptor +org.junit.jupiter.engine.discovery.MethodSelectorResolver +org.junit.jupiter.engine.discovery.MethodFinder +java.util.regex.Pattern$$Lambda$150/0x00007f4204062660 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$TestDescriptorFactory +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor +org.junit.jupiter.engine.extension.ExtensionRegistrar +java.lang.invoke.LambdaForm$DMH/0x00007f4204084000 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$151/0x00007f4204080f00 +org.junit.jupiter.engine.descriptor.TestFactoryTestDescriptor +org.junit.jupiter.engine.descriptor.DynamicNodeTestDescriptor +org.junit.jupiter.engine.descriptor.DynamicContainerTestDescriptor +org.junit.jupiter.engine.descriptor.DynamicTestTestDescriptor +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$152/0x00007f4204082438 +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$153/0x00007f4204082bf0 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor +org.junit.jupiter.engine.discovery.ClassOrderingVisitor +org.junit.jupiter.api.ClassOrdererContext +org.junit.platform.commons.util.LruCache +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$154/0x00007f4204083af0 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$155/0x00007f4204083d38 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$156/0x00007f4204086000 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$157/0x00007f4204086250 +org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter$$Lambda$158/0x00007f4204086498 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$DescriptorWrapperOrderer +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$MessageGenerator +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$DescriptorWrapperOrderer$$Lambda$159/0x00007f4204086ad0 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$DescriptorWrapperOrderer$$Lambda$160/0x00007f4204086cf0 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$161/0x00007f4204086f10 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$162/0x00007f4204087160 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor +org.junit.jupiter.api.MethodOrdererContext +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$163/0x00007f42040877e8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$164/0x00007f4204087a38 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$165/0x00007f4204087c78 +java.lang.invoke.LambdaForm$MH/0x00007f4204084400 +java.util.Comparator$$Lambda$166/0x00007f42040628c0 +java.util.Collections$ReverseComparator +java.util.Comparators$NaturalOrderComparator +java.util.Collections$ReverseComparator2 +java.util.function.UnaryOperator +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$167/0x00007f4204085000 +org.junit.jupiter.engine.discovery.DiscoverySelectorResolver$$Lambda$168/0x00007f4204085260 +org.junit.platform.engine.CompositeTestDescriptorVisitor +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution +org.junit.platform.engine.support.discovery.SelectorResolver$Context +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$DefaultContext +org.junit.platform.engine.support.discovery.SelectorResolver$Match +org.junit.platform.engine.support.discovery.SelectorResolver$Match$$Lambda$169/0x00007f4204084800 +org.junit.platform.engine.support.discovery.SelectorResolver$Match$Type +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$170/0x00007f4204088000 +org.junit.platform.launcher.core.DefaultDiscoveryRequest$$Lambda$171/0x00007f4204088258 +java.util.ArrayDeque$$Lambda$172/0x00007f4204063970 +org.junit.platform.engine.discovery.UniqueIdSelector +org.junit.platform.engine.support.discovery.SelectorResolver$Resolution +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$173/0x00007f4204088900 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$174/0x00007f4204088b48 +org.junit.platform.engine.discovery.ClasspathResourceSelector +org.junit.platform.engine.discovery.ClasspathRootSelector +org.junit.platform.commons.support.ReflectionSupport +org.junit.platform.commons.util.ClasspathScannerLoader +org.junit.platform.commons.support.scanning.ClasspathScanner +java.util.Spliterators$IteratorSpliterator +jdk.internal.misc.ScopedMemoryAccess$Scope +org.junit.platform.commons.support.scanning.DefaultClasspathScanner +java.nio.file.FileVisitor +org.junit.platform.commons.util.ClasspathScannerLoader$$Lambda$175/0x00007f4204089a88 +org.junit.platform.commons.function.Try +java.lang.invoke.LambdaForm$DMH/0x00007f420408c000 +org.junit.platform.commons.util.ClasspathScannerLoader$$Lambda$176/0x00007f4204089ef8 +java.lang.invoke.LambdaForm$DMH/0x00007f420408c400 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$177/0x00007f420408a128 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$178/0x00007f420408a360 +org.junit.platform.commons.function.Try$Failure +org.junit.platform.commons.function.Try$Success +org.junit.platform.commons.function.Try$$Lambda$179/0x00007f420408aa38 +java.util.regex.Pattern$1 +org.junit.platform.engine.discovery.ClassSelector$$Lambda$180/0x00007f420408ac60 +org.junit.jupiter.api.Nested +org.junit.platform.commons.support.AnnotationSupport +org.junit.platform.commons.util.AnnotationUtils +java.lang.annotation.Inherited +sun.reflect.generics.parser.SignatureParser +sun.reflect.generics.tree.Tree +sun.reflect.generics.tree.TypeTree +sun.reflect.generics.tree.TypeArgument +sun.reflect.generics.tree.ReturnType +sun.reflect.generics.tree.TypeSignature +sun.reflect.generics.tree.BaseType +sun.reflect.generics.tree.FieldTypeSignature +sun.reflect.generics.tree.SimpleClassTypeSignature +sun.reflect.generics.tree.ClassTypeSignature +sun.reflect.generics.scope.Scope +sun.reflect.generics.scope.AbstractScope +sun.reflect.generics.scope.ClassScope +sun.reflect.generics.factory.GenericsFactory +sun.reflect.generics.factory.CoreReflectionFactory +sun.reflect.generics.visitor.TypeTreeVisitor +sun.reflect.generics.visitor.Reifier +java.lang.annotation.Target +java.lang.reflect.GenericArrayType +sun.reflect.annotation.AnnotationType +sun.reflect.annotation.AnnotationType$1 +java.lang.annotation.ElementType +java.lang.annotation.Retention +java.lang.annotation.Documented +java.lang.annotation.RetentionPolicy +sun.reflect.annotation.ExceptionProxy +sun.reflect.annotation.AnnotationTypeMismatchExceptionProxy +sun.reflect.annotation.AnnotationParser$1 +java.lang.reflect.InvocationHandler +sun.reflect.annotation.AnnotationInvocationHandler +java.lang.reflect.Proxy +java.lang.ClassValue +java.lang.reflect.Proxy$1 +java.lang.ClassValue$Entry +java.lang.ClassValue$Identity +java.lang.ClassValue$Version +jdk.internal.loader.AbstractClassLoaderValue$Sub +java.lang.reflect.Proxy$$Lambda$181/0x00007f420406bf50 +java.lang.reflect.Proxy$ProxyBuilder +java.lang.PublicMethods +java.util.LinkedHashMap$LinkedValues +java.util.LinkedHashMap$LinkedValueIterator +java.lang.reflect.Proxy$ProxyBuilder$$Lambda$182/0x00007f420406cb68 +java.lang.module.ModuleDescriptor$Modifier +java.lang.module.ModuleDescriptor$Builder +jdk.internal.module.Checks +java.lang.module.ModuleDescriptor$Builder$$Lambda$1/0x800000002 +java.lang.reflect.Proxy$$Lambda$184/0x00007f420406cd98 +java.lang.reflect.ProxyGenerator +java.lang.reflect.ProxyGenerator$ProxyMethod +java.util.StringJoiner +java.lang.reflect.ProxyGenerator$$Lambda$185/0x00007f420406d4e8 +java.lang.reflect.ProxyGenerator$$Lambda$186/0x00007f420406d728 +java.lang.reflect.ProxyGenerator$PrimitiveTypeInfo +jdk.internal.org.objectweb.asm.Edge +jdk.proxy1.$Proxy0 +java.lang.reflect.Proxy$ProxyBuilder$1 +sun.reflect.annotation.AnnotationParser$$Lambda$187/0x00007f420406e218 +java.lang.invoke.LambdaForm$DMH/0x00007f420408c800 +jdk.proxy1.$Proxy1 +jdk.proxy1.$Proxy2 +org.apiguardian.api.API +org.apiguardian.api.API$Status +jdk.proxy2.$Proxy3 +java.lang.reflect.UndeclaredThrowableException +java.lang.Class$AnnotationData +org.junit.platform.commons.util.KotlinReflectionUtils +org.junit.platform.commons.function.Try$Transformer +org.junit.platform.commons.util.KotlinReflectionUtils$$Lambda$188/0x00007f420408e200 +org.junit.jupiter.api.ClassTemplate +jdk.proxy1.$Proxy4 +org.junit.platform.commons.annotation.Testable +jdk.proxy2.$Proxy5 +org.junit.platform.commons.util.ReflectionUtils$HierarchyTraversalMode +org.junit.platform.commons.util.ReflectionUtils$$Lambda$189/0x00007f420408eeb0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$190/0x00007f420408f100 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$191/0x00007f420408f320 +java.util.Arrays$LegacyMergeSort +java.util.TimSort +jdk.proxy2.$Proxy6 +org.junitpioneer.jupiter.SetEnvironmentVariable +java.lang.annotation.Repeatable +org.junitpioneer.jupiter.WritesEnvironmentVariable +org.junit.jupiter.api.extension.ExtendWith +jdk.proxy2.$Proxy7 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$192/0x00007f420408d260 +org.junit.jupiter.api.extension.ExtensionConfigurationException +org.junit.jupiter.api.extension.TestInstanceFactoryContext +org.junit.jupiter.api.extension.Extension +org.junit.jupiter.api.extension.TestInstantiationAwareExtension +org.junit.jupiter.api.extension.TestInstantiationException +org.junit.jupiter.engine.execution.ConditionEvaluator +org.junit.jupiter.engine.execution.ConditionEvaluationException +org.junit.jupiter.api.extension.ConditionEvaluationResult +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker +org.junit.jupiter.api.extension.ReflectiveInvocationContext +org.junit.jupiter.api.extension.InvocationInterceptor$Invocation +org.junit.jupiter.engine.execution.InvocationInterceptorChain +org.junit.jupiter.engine.descriptor.DisplayNameUtils +org.junit.jupiter.api.DisplayNameGenerator$Standard +org.junit.jupiter.api.DisplayNameGenerator$Simple +org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores +org.junit.jupiter.api.DisplayNameGenerator$IndicativeSentences +org.junit.jupiter.api.DisplayNameGenerator$IndicativeSentences$$Lambda$193/0x00007f4204091850 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$194/0x00007f4204091aa0 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$195/0x00007f4204091cc0 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$196/0x00007f4204091ef8 +org.junit.platform.engine.support.descriptor.ClassSource +org.junit.jupiter.api.DisplayName +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$197/0x00007f4204092540 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$198/0x00007f4204092780 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$199/0x00007f42040929d0 +org.junit.jupiter.api.DisplayNameGeneration +java.util.AbstractList$Itr +java.util.AbstractList$ListItr +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$200/0x00007f4204092e10 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$201/0x00007f4204093050 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$202/0x00007f4204093290 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$203/0x00007f42040934d8 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$204/0x00007f4204093700 +org.junit.jupiter.engine.config.DefaultJupiterConfiguration$$Lambda$205/0x00007f4204093948 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$ClassInfo +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$ClassInfo$$Lambda$206/0x00007f4204093d78 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$ClassInfo$$Lambda$207/0x00007f4204093fa0 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$ClassInfo$$Lambda$208/0x00007f42040941c8 +org.junit.jupiter.api.Tag +org.junit.jupiter.api.Tags +jdk.proxy1.$Proxy8 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$209/0x00007f4204094800 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$210/0x00007f4204094a28 +java.lang.invoke.LambdaForm$DMH/0x00007f4204098000 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$211/0x00007f4204094c68 +org.junit.platform.engine.TestTag +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$212/0x00007f42040950d0 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$213/0x00007f4204095310 +org.junit.jupiter.engine.descriptor.JupiterTestDescriptor$$Lambda$214/0x00007f4204095530 +java.lang.invoke.LambdaForm$DMH/0x00007f4204098400 +java.util.function.Function$$Lambda$215/0x00007f420406fd40 +org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils +org.junit.jupiter.api.TestInstance +org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils$$Lambda$216/0x00007f4204095b78 +org.junit.jupiter.engine.descriptor.TestInstanceLifecycleUtils$$Lambda$217/0x00007f4204095db8 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$218/0x00007f4204095fe0 +java.lang.invoke.LambdaForm$DMH/0x00007f4204098800 +org.junit.jupiter.engine.config.EnumConfigurationParameterConverter$$Lambda$219/0x00007f4204096228 +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$1 +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$DefaultExclusiveResourceCollector +org.junit.jupiter.api.parallel.ResourceLock +jdk.internal.reflect.ClassFileConstants +jdk.internal.reflect.AccessorGenerator +jdk.internal.reflect.MethodAccessorGenerator +jdk.internal.reflect.ByteVectorFactory +jdk.internal.reflect.ByteVector +jdk.internal.reflect.ByteVectorImpl +jdk.internal.reflect.ClassFileAssembler +jdk.internal.reflect.UTF8 +jdk.internal.reflect.Label +jdk.internal.reflect.Label$PatchInfo +jdk.internal.reflect.MethodAccessorGenerator$1 +jdk.internal.reflect.ClassDefiner +jdk.internal.reflect.ClassDefiner$1 +jdk.internal.reflect.GeneratedConstructorAccessor1 +java.lang.Class$1 +jdk.internal.reflect.BootstrapConstructorAccessorImpl +org.junit.jupiter.api.parallel.ResourceLocks +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$LifecycleMethods +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$$Lambda$220/0x00007f4204097110 +java.lang.invoke.LambdaForm$DMH/0x00007f4204099000 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$$Lambda$221/0x00007f4204097348 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils +org.junit.jupiter.api.BeforeAll +org.junit.platform.commons.support.HierarchyTraversalMode +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$222/0x00007f420409c000 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$223/0x00007f420409c248 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$224/0x00007f420409c498 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$225/0x00007f420409c6e0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$226/0x00007f420409c938 +java.util.function.IntFunction +org.junit.platform.commons.util.ReflectionUtils$$Lambda$227/0x00007f4204097dd8 +java.util.stream.Nodes +java.util.stream.Node +java.util.stream.Nodes$EmptyNode +java.util.stream.Nodes$EmptyNode$OfRef +java.util.stream.Node$OfPrimitive +java.util.stream.Node$OfInt +java.util.stream.Nodes$EmptyNode$OfInt +java.util.stream.Node$OfLong +java.util.stream.Nodes$EmptyNode$OfLong +java.util.stream.Node$OfDouble +java.util.stream.Nodes$EmptyNode$OfDouble +java.util.stream.Node$Builder +java.util.stream.AbstractSpinedBuffer +java.util.stream.SpinedBuffer +java.util.stream.Nodes$SpinedNodeBuilder +org.junit.platform.commons.util.ReflectionUtils$$Lambda$228/0x00007f420409cb88 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$229/0x00007f420409cde0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$230/0x00007f420409d000 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$231/0x00007f420409d258 +java.util.stream.DistinctOps +java.util.stream.DistinctOps$1 +org.junit.platform.commons.util.CollectionUtils$$Lambda$232/0x00007f420409d478 +java.util.stream.DistinctOps$1$2 +java.util.LinkedHashMap$LinkedEntrySet +java.util.LinkedHashMap$LinkedEntryIterator +org.junitpioneer.jupiter.SetEnvironmentVariable$SetEnvironmentVariables +jdk.proxy2.$Proxy9 +sun.reflect.annotation.AnnotationParser$$Lambda$233/0x00007f42040748a8 +org.junit.jupiter.api.extension.BeforeEachCallback +org.junit.jupiter.api.extension.AfterEachCallback +org.junit.jupiter.api.extension.BeforeAllCallback +org.junit.jupiter.api.extension.AfterAllCallback +org.junitpioneer.jupiter.AbstractEntryBasedExtension +org.junitpioneer.jupiter.EnvironmentVariableExtension +jdk.proxy2.$Proxy10 +org.junit.jupiter.api.parallel.ResourceLockTarget +org.junit.jupiter.api.parallel.ResourceAccessMode +jdk.proxy2.$Proxy11 +jdk.internal.reflect.GeneratedConstructorAccessor2 +org.junit.jupiter.api.extension.Extensions +sun.reflect.annotation.AnnotationInvocationHandler$1 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$234/0x00007f420409f808 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$235/0x00007f420409fa30 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$236/0x00007f420409fc80 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$Condition$$Lambda$237/0x00007f420409a000 +java.util.stream.ReferencePipeline$15 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$238/0x00007f420409a238 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$239/0x00007f420409a480 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$240/0x00007f420409a6d0 +org.junit.platform.engine.support.discovery.DiscoveryIssueReporter$Condition$$Lambda$241/0x00007f420409a918 +java.util.stream.ReferencePipeline$15$1 +org.junit.jupiter.api.AfterAll +jdk.internal.reflect.GeneratedConstructorAccessor3 +org.junit.jupiter.api.BeforeEach +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$242/0x00007f420409af70 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$243/0x00007f420409b1b8 +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$244/0x00007f420409b408 +org.junit.jupiter.api.AfterEach +jdk.internal.reflect.GeneratedConstructorAccessor4 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$245/0x00007f420409b850 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$246/0x00007f420409ba98 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$247/0x00007f420409bcc0 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$248/0x00007f42040a0000 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$249/0x00007f42040a0248 +org.junit.platform.engine.SelectorResolutionResult +org.junit.platform.engine.SelectorResolutionResult$Status +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener$$Lambda$250/0x00007f42040a0ae0 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$251/0x00007f42040a0d18 +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$252/0x00007f42040a0f68 +java.util.stream.ForEachOps +java.util.stream.ForEachOps$ForEachOp +java.util.stream.ForEachOps$ForEachOp$OfRef +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$253/0x00007f42040a11a0 +org.junit.platform.commons.util.ReflectionUtils$CycleErrorHandling +org.junit.platform.commons.util.ReflectionUtils$CycleErrorHandling$1 +org.junit.platform.commons.util.ReflectionUtils$CycleErrorHandling$2 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$254/0x00007f42040a1cd0 +java.lang.invoke.LambdaForm$DMH/0x00007f42040a4000 +java.util.function.Predicate$$Lambda$255/0x00007f42040754b8 +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$256/0x00007f42040a1f08 +java.util.function.Predicate$$Lambda$257/0x00007f4204075710 +java.util.stream.Streams$ConcatSpliterator +java.util.stream.Streams$ConcatSpliterator$OfRef +java.util.stream.Streams$2 +org.junit.platform.engine.discovery.NestedClassSelector +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$258/0x00007f42040a23b0 +java.util.stream.AbstractPipeline$$Lambda$259/0x00007f42040760d8 +java.util.stream.StreamSpliterators$AbstractWrappingSpliterator +java.util.stream.StreamSpliterators$WrappingSpliterator +org.junit.jupiter.engine.discovery.ClassSelectorResolver$$Lambda$260/0x00007f42040a25f8 +java.util.stream.StreamSpliterators +java.util.stream.StreamSpliterators$WrappingSpliterator$$Lambda$261/0x00007f4204076a38 +org.junit.platform.engine.discovery.MethodSelector +org.junit.platform.engine.discovery.MethodSelector$$Lambda$262/0x00007f42040a2a88 +org.junit.platform.commons.util.ClassUtils +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$263/0x00007f42040a2ed0 +org.junit.platform.engine.discovery.IterationSelector +org.junit.platform.engine.discovery.DirectorySelector +org.junit.platform.engine.discovery.FileSelector +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$264/0x00007f42040a37e0 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$265/0x00007f42040a3a08 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$266/0x00007f42040a3c38 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$267/0x00007f42040a6000 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$268/0x00007f42040a6250 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$269/0x00007f42040a6490 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$270/0x00007f42040a66d8 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$271/0x00007f42040a6900 +org.junit.platform.commons.util.ClassUtils$$Lambda$272/0x00007f42040a6b48 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$MethodType$$Lambda$273/0x00007f42040a6d88 +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall$VoidMethodInterceptorCall +org.junit.jupiter.api.extension.InvocationInterceptor +java.lang.invoke.LambdaForm$DMH/0x00007f42040a4400 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$274/0x00007f42040a73b0 +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall$$Lambda$275/0x00007f42040a77d0 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$276/0x00007f42040a79f8 +org.junit.jupiter.api.DisplayNameGenerator$$Lambda$277/0x00007f42040a7c30 +org.junit.platform.engine.support.descriptor.MethodSource +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$MethodInfo +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$MethodInfo$$Lambda$278/0x00007f42040a5438 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$MethodInfo$$Lambda$279/0x00007f42040a5660 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$MethodInfo$$Lambda$280/0x00007f42040a5888 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$281/0x00007f42040a5ac0 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$282/0x00007f42040a5d00 +org.junit.platform.commons.util.AnnotationUtils$$Lambda$283/0x00007f42040a4800 +org.junit.jupiter.engine.discovery.MethodSelectorResolver$$Lambda$284/0x00007f42040a4a40 +jdk.internal.reflect.GeneratedConstructorAccessor5 +java.util.HashMap$KeySpliterator +org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolution$$Lambda$285/0x00007f42040a4c68 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$286/0x00007f42040ac000 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$287/0x00007f42040ac238 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$288/0x00007f42040ac478 +org.junit.jupiter.api.ClassDescriptor +org.junit.jupiter.engine.discovery.AbstractAnnotatedDescriptorWrapper +org.junit.jupiter.engine.discovery.DefaultClassDescriptor +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$289/0x00007f42040acd28 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$$Lambda$290/0x00007f42040acf68 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$$Lambda$291/0x00007f42040ad1c0 +org.junit.jupiter.engine.discovery.AbstractOrderingVisitor$$Lambda$292/0x00007f42040ad408 +org.junit.jupiter.api.Order +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$293/0x00007f42040ad840 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$294/0x00007f42040ada78 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$295/0x00007f42040adcb8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$296/0x00007f42040adef0 +org.junit.platform.engine.TestDescriptor$$Lambda$297/0x00007f42040ae130 +org.junit.jupiter.api.TestClassOrder +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$298/0x00007f42040ae568 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$299/0x00007f42040ae7a8 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$300/0x00007f42040ae9e8 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$301/0x00007f42040aec30 +org.junit.jupiter.engine.discovery.ClassOrderingVisitor$$Lambda$302/0x00007f42040aee58 +org.junit.jupiter.api.TestMethodOrder +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$303/0x00007f42040af298 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$304/0x00007f42040af4d8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$305/0x00007f42040af718 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$306/0x00007f42040af958 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$307/0x00007f42040afb80 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$308/0x00007f42040aa000 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$309/0x00007f42040afdc8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$310/0x00007f42040aa248 +org.junit.jupiter.api.MethodDescriptor +org.junit.jupiter.engine.discovery.DefaultMethodDescriptor +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$311/0x00007f42040aa8d8 +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$312/0x00007f42040aab18 +org.junit.platform.engine.support.hierarchical.Node$ExecutionMode +org.junit.jupiter.engine.discovery.MethodOrderingVisitor$$Lambda$313/0x00007f42040aafa0 +org.junit.jupiter.engine.descriptor.Validatable$$Lambda$314/0x00007f42040ab1d8 +org.junit.jupiter.api.extension.ClassTemplateInvocationLifecycleMethod +org.junit.jupiter.engine.descriptor.LifecycleMethodUtils$$Lambda$315/0x00007f42040ab610 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$316/0x00007f42040ab848 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$317/0x00007f42040aba70 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$318/0x00007f42040abc98 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$319/0x00007f42040a9000 +org.junit.jupiter.engine.descriptor.DisplayNameUtils$$Lambda$320/0x00007f42040a9250 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$321/0x00007f42040a9488 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$322/0x00007f42040a96b0 +org.junit.platform.launcher.core.EngineDiscoveryResultValidator$$Lambda$323/0x00007f42040a98d8 +org.junit.platform.engine.TestDescriptor$Type +org.junit.platform.launcher.core.EngineDiscoveryResultValidator$$Lambda$324/0x00007f42040a8800 +org.junit.platform.launcher.EngineDiscoveryResult +org.junit.platform.launcher.EngineDiscoveryResult$Status +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener$$Lambda$325/0x00007f42040b0000 +java.util.Collections$UnmodifiableList$1 +java.util.ArrayList$ListItr +org.junit.platform.commons.util.ExceptionUtils +java.io.StringWriter +org.junit.platform.launcher.listeners.discovery.AbortOnFailureLauncherDiscoveryListener$$Lambda$326/0x00007f42040b0238 +org.junit.platform.launcher.core.DiscoveryIssueNotifier +org.junit.platform.engine.DiscoveryIssue$Severity +org.junit.platform.launcher.core.LauncherDiscoveryResult$EngineResultInfo +org.junit.platform.launcher.core.EngineFilterer$$Lambda$327/0x00007f42040b0b18 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$328/0x00007f42040b0d58 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$329/0x00007f42040b0fa8 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$330/0x00007f42040b11e8 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$331/0x00007f42040b1428 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$332/0x00007f42040b1680 +org.junit.platform.launcher.core.EngineFilterer$$Lambda$333/0x00007f42040b18a0 +java.lang.invoke.LambdaForm$DMH/0x00007f42040b4000 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$334/0x00007f42040b1af0 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$335/0x00007f42040b1d18 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$336/0x00007f42040b1f50 +java.lang.invoke.LambdaForm$DMH/0x00007f42040b4400 +org.junit.platform.launcher.core.EngineDiscoveryOrchestrator$$Lambda$337/0x00007f42040b2180 +org.junit.platform.engine.TestDescriptor$$Lambda$338/0x00007f42040b23a0 +org.junit.platform.launcher.core.LauncherDiscoveryResult +org.junit.platform.launcher.listeners.discovery.CompositeLauncherDiscoveryListener$$Lambda$339/0x00007f42040b2848 +org.junit.platform.launcher.core.LauncherPhase$$Lambda$340/0x00007f42040b2a80 +org.junit.platform.engine.ConfigurationParameters$$Lambda$341/0x00007f42040b2cc0 +org.junit.platform.launcher.core.LauncherDiscoveryResult$$Lambda$342/0x00007f42040b2f08 +org.junit.platform.launcher.core.LauncherDiscoveryResult$$Lambda$343/0x00007f42040b3158 +org.junit.platform.launcher.TestPlan$$Lambda$344/0x00007f42040b3398 +org.junit.platform.launcher.TestPlan$$Lambda$345/0x00007f42040b35c0 +org.junit.platform.launcher.TestIdentifier +org.junit.platform.launcher.TestIdentifier$SerializedForm +java.io.ObjectStreamClass +java.io.ObjectStreamClass$Caches +java.io.ClassCache +java.io.ObjectStreamClass$Caches$1 +java.io.ClassCache$1 +java.io.ObjectStreamClass$Caches$2 +java.lang.ClassValue$ClassValueMap +java.io.Externalizable +java.io.ObjectStreamClass$2 +jdk.internal.reflect.UnsafeFieldAccessorFactory +jdk.internal.reflect.UnsafeQualifiedStaticFieldAccessorImpl +jdk.internal.reflect.UnsafeQualifiedStaticLongFieldAccessorImpl +java.util.ComparableTimSort +jdk.internal.reflect.SerializationConstructorAccessorImpl +jdk.internal.reflect.GeneratedSerializationConstructorAccessor1 +java.io.ObjectOutput +java.io.ObjectStreamConstants +java.io.ObjectOutputStream +java.io.ObjectInput +java.io.ObjectInputStream +java.lang.Class$$Lambda$346/0x00007f420407a758 +java.util.stream.Collectors$$Lambda$31/0x800000042 +java.util.stream.Collectors$$Lambda$23/0x80000003a +java.util.stream.Collectors$$Lambda$26/0x80000003d +java.util.stream.Collectors$$Lambda$28/0x80000003f +java.lang.CloneNotSupportedException +java.io.ClassCache$CacheRef +java.io.ObjectStreamClass$FieldReflectorKey +java.io.ObjectStreamClass$FieldReflector +org.junit.platform.launcher.TestIdentifier$$Lambda$351/0x00007f42040b3c20 +org.junit.platform.launcher.TestPlan$$Lambda$352/0x00007f42040b6000 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$353/0x00007f42040b6240 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$354/0x00007f42040b6478 +software.amazon.lambda.powertools.kafka.PowertoolsSerializerTest +org.junit.jupiter.api.extension.ParameterResolver +org.mockito.junit.jupiter.MockitoExtension +software.amazon.lambda.powertools.kafka.PowertoolsSerializerTest$1 +org.apache.avro.generic.GenericContainer +org.apache.avro.generic.IndexedRecord +org.apache.avro.specific.SpecificRecord +software.amazon.lambda.powertools.kafka.PowertoolsSerializerTest$InputType +com.fasterxml.jackson.core.JacksonException +com.fasterxml.jackson.core.JsonProcessingException +software.amazon.lambda.powertools.kafka.serializers.PowertoolsDeserializer +software.amazon.lambda.powertools.kafka.serializers.LambdaDefaultDeserializer +org.junit.jupiter.params.ParameterizedTest +org.junit.jupiter.params.ArgumentCountValidationMode +jdk.proxy2.$Proxy12 +org.junit.jupiter.params.provider.MethodSource +org.junit.jupiter.params.provider.ArgumentsSource +jdk.proxy2.$Proxy13 +jdk.proxy2.$Proxy14 +org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider +org.junit.jupiter.params.ParameterizedInvocationContextProvider +org.junit.jupiter.params.ParameterizedTestExtension +org.junit.jupiter.params.provider.MethodSources +org.junit.jupiter.params.provider.ArgumentsProvider +org.junit.jupiter.params.support.AnnotationConsumer +org.junit.jupiter.params.provider.AnnotationBasedArgumentsProvider +org.junit.jupiter.params.provider.MethodArgumentsProvider +jdk.proxy2.$Proxy15 +org.junit.jupiter.params.provider.ArgumentsSources +jdk.internal.reflect.GeneratedConstructorAccessor6 +jdk.internal.reflect.GeneratedConstructorAccessor7 +org.junit.platform.commons.util.ClassUtils$$Lambda$355/0x00007f42040b9840 +java.util.function.BiPredicate +org.junit.jupiter.engine.descriptor.DynamicDescendantFilter +org.junit.jupiter.engine.descriptor.DynamicDescendantFilter$WithoutIndexFiltering +org.junit.jupiter.engine.descriptor.DynamicDescendantFilter$Mode +software.amazon.lambda.powertools.kafka.DeserializationTest +software.amazon.lambda.powertools.kafka.DeserializationTypeTest +software.amazon.lambda.powertools.kafka.serializers.KafkaJsonDeserializerTest +jdk.proxy2.$Proxy16 +com.google.protobuf.MessageLiteOrBuilder +com.google.protobuf.MessageOrBuilder +software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProductOrBuilder +com.google.protobuf.MessageLite +com.google.protobuf.Message +com.google.protobuf.AbstractMessageLite +com.google.protobuf.AbstractMessage +com.google.protobuf.GeneratedMessage +software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct +com.google.protobuf.CheckReturnValue +com.google.protobuf.$Proxy17 +com.google.protobuf.MessageLite$Builder +com.google.protobuf.Internal$ProtobufList +com.google.protobuf.GeneratedMessage$ExtensionDescriptorRetriever +com.google.protobuf.InvalidProtocolBufferException +com.google.protobuf.Reader +com.google.protobuf.Internal$IntList +com.google.protobuf.Internal$LongList +com.google.protobuf.Internal$FloatList +com.google.protobuf.Internal$DoubleList +com.google.protobuf.Internal$BooleanList +com.google.protobuf.MapFieldReflectionAccessor +com.google.protobuf.MutabilityOracle +com.google.protobuf.MapField +com.google.protobuf.Parser +com.google.protobuf.Message$Builder +com.google.protobuf.Descriptors$GenericDescriptor +com.google.protobuf.Descriptors$Descriptor +com.google.protobuf.ByteOutput +com.google.protobuf.CodedOutputStream +com.google.protobuf.ExtensionRegistryLite +com.google.protobuf.CodedInputStream +com.google.protobuf.ByteString +com.google.protobuf.AbstractMessageLite$Builder +com.google.protobuf.AbstractMessage$Builder +com.google.protobuf.GeneratedMessage$Builder +software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct$Builder +com.google.protobuf.FieldSet$FieldDescriptorLite +com.google.protobuf.Descriptors$FieldDescriptor +com.google.protobuf.ExtensionLite +com.google.protobuf.Extension +com.google.protobuf.GeneratedMessage$GeneratedExtension +com.google.protobuf.UnknownFieldSet +com.google.protobuf.Descriptors$OneofDescriptor +com.google.protobuf.AbstractMessage$BuilderParent +com.google.protobuf.GeneratedMessage$FieldAccessorTable +java.lang.reflect.Executable$$Lambda$356/0x00007f420407b2b8 +java.lang.reflect.Executable$$Lambda$357/0x00007f420407b4f8 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$358/0x00007f42040c4030 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$359/0x00007f42040c4270 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$360/0x00007f42040c44b0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$361/0x00007f42040c4708 +com.google.protobuf.GeneratedMessage$UnusedPrivateParameter +java.io.ObjectStreamException +com.google.protobuf.UnknownFieldSet$Builder +com.google.protobuf.MapEntry +java.lang.Deprecated +jdk.proxy1.$Proxy18 +com.google.protobuf.UninitializedMessageException +com.google.protobuf.Schema +org.junit.platform.commons.util.ReflectionUtils$$Lambda$362/0x00007f42040c5760 +com.google.protobuf.GeneratedMessage$CachedDescriptorRetriever +com.google.protobuf.GeneratedMessage$ExtendableMessageOrBuilder +com.google.protobuf.GeneratedMessage$ExtendableBuilder +com.google.protobuf.GeneratedMessage$ExtendableMessage +com.google.protobuf.AbstractMessageLite$InternalOneOfEnum +java.lang.invoke.LambdaForm$DMH/0x00007f42040c8000 +org.junit.jupiter.engine.discovery.predicates.TestClassPredicates$$Lambda$363/0x00007f42040c6f68 +software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProductOuterClass +com.google.protobuf.ExtensionRegistry +com.google.protobuf.Descriptors$FileDescriptor +org.apache.avro.generic.GenericRecord +org.apache.avro.specific.SpecificRecordBase +software.amazon.lambda.powertools.kafka.serializers.test.avro.TestProduct +org.apache.avro.specific.AvroGenerated +jdk.proxy2.$Proxy19 +org.apache.avro.AvroRuntimeException +org.apache.avro.io.Encoder +org.apache.avro.io.BinaryEncoder +org.apache.avro.io.Decoder +org.apache.avro.io.BinaryDecoder +org.apache.avro.generic.GenericData +org.apache.avro.specific.SpecificData +org.apache.avro.message.SchemaStore +org.apache.avro.message.MessageDecoder +org.apache.avro.message.MessageDecoder$BaseDecoder +org.apache.avro.message.BinaryMessageDecoder +org.apache.avro.JsonProperties +org.apache.avro.Schema +org.apache.avro.message.MessageEncoder +org.apache.avro.message.BinaryMessageEncoder +org.apache.avro.data.RecordBuilder +org.apache.avro.data.RecordBuilderBase +org.apache.avro.specific.SpecificRecordBuilderBase +software.amazon.lambda.powertools.kafka.serializers.test.avro.TestProduct$Builder +org.apache.avro.io.parsing.Parser$ActionHandler +org.apache.avro.io.parsing.SkipParser$SkipHandler +org.apache.avro.io.ParsingDecoder +org.apache.avro.io.ValidatingDecoder +org.apache.avro.io.ResolvingDecoder +org.apache.avro.Conversion +software.amazon.lambda.powertools.kafka.serializers.KafkaProtobufDeserializerTest +software.amazon.lambda.powertools.kafka.serializers.KafkaAvroDeserializerTest +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$InputType +jdk.internal.reflect.GeneratedConstructorAccessor8 +jdk.internal.reflect.GeneratedConstructorAccessor9 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializer +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$TestDeserializer +software.amazon.lambda.powertools.kafka.testutils.TestProductPojo +software.amazon.lambda.powertools.kafka.testutils.TestUtils +org.apache.avro.io.DatumWriter +org.apache.maven.surefire.api.util.TestsToRun +org.apache.maven.surefire.api.util.DefaultRunOrderCalculator +java.util.random.RandomGenerator +java.util.Random +org.apache.maven.surefire.api.util.CloseableIterator +org.apache.maven.surefire.api.util.TestsToRun$ClassesIterator +java.util.NoSuchElementException +org.apache.maven.surefire.junitplatform.JUnitPlatformProvider$$Lambda$364/0x00007f42040c9738 +org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder$$Lambda$365/0x00007f42040c9970 +org.junit.platform.launcher.core.InterceptingLauncher$$Lambda$366/0x00007f42040c9ba8 +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$367/0x00007f42040c8c00 +org.junit.platform.launcher.core.CompositeTestExecutionListener$EagerTestExecutionListener +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$368/0x00007f42040d0000 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$369/0x00007f42040d0258 +org.junit.platform.engine.reporting.ReportEntry +java.lang.invoke.LambdaForm$DMH/0x00007f42040d4000 +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$370/0x00007f42040d06b0 +org.junit.platform.launcher.core.StreamInterceptingTestExecutionListener +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$371/0x00007f42040d0bc0 +org.junit.platform.engine.EngineExecutionListener$1 +org.junit.platform.launcher.core.IterationOrder +org.junit.platform.launcher.core.IterationOrder$1 +org.junit.platform.launcher.core.IterationOrder$2 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$372/0x00007f42040d1958 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$373/0x00007f42040d1b90 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$374/0x00007f42040d1db8 +org.junit.platform.launcher.core.CompositeEngineExecutionListener +org.junit.platform.launcher.core.ListenerRegistry$$Lambda$375/0x00007f42040d2270 +org.junit.platform.launcher.core.ExecutionListenerAdapter +org.junit.platform.launcher.core.DelegatingEngineExecutionListener +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$376/0x00007f42040d2c30 +org.junit.platform.launcher.core.OutcomeDelayingEngineExecutionListener +org.junit.platform.engine.ExecutionRequest +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$377/0x00007f42040d3330 +org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService +org.junit.jupiter.engine.execution.JupiterEngineExecutionContext +org.junit.jupiter.engine.descriptor.LauncherStoreFacade +org.junit.jupiter.api.extension.ExtensionContext$Store +org.junit.jupiter.engine.descriptor.LauncherStoreFacade$$Lambda$378/0x00007f42040d6000 +org.junit.jupiter.engine.execution.JupiterEngineExecutionContext$State +org.junit.platform.engine.support.hierarchical.ThrowableCollector$Factory +org.junit.platform.engine.support.hierarchical.ThrowableCollector +org.junit.jupiter.engine.support.JupiterThrowableCollectorFactory +org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector +org.junit.jupiter.engine.JupiterTestEngine$$Lambda$379/0x00007f42040d6cb8 +org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor +org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutorService$TestTask +org.junit.platform.engine.support.hierarchical.NodeTreeWalker +org.junit.platform.engine.support.hierarchical.LockManager +org.junit.platform.engine.support.hierarchical.ResourceLock +java.util.concurrent.locks.ReadWriteLock +org.junit.platform.engine.support.hierarchical.SingleLock +org.junit.platform.engine.support.hierarchical.ExclusiveResource +org.junit.platform.engine.support.hierarchical.ExclusiveResource$LockMode +org.junit.platform.engine.support.hierarchical.ExclusiveResource$$Lambda$380/0x00007f42040d5248 +org.junit.platform.engine.support.hierarchical.ExclusiveResource$$Lambda$381/0x00007f42040d5488 +java.util.Comparator$$Lambda$382/0x00007f420407c258 +java.lang.invoke.LambdaForm$DMH/0x00007f42040d4400 +java.util.Comparator$$Lambda$383/0x00007f420407c4f8 +org.junit.platform.engine.support.hierarchical.ExclusiveResource$$Lambda$384/0x00007f42040d56c8 +org.junit.platform.engine.support.hierarchical.LockManager$$Lambda$385/0x00007f42040d5908 +java.util.concurrent.locks.ReentrantReadWriteLock +java.util.concurrent.locks.ReentrantReadWriteLock$Sync +java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync +java.util.concurrent.locks.ReentrantReadWriteLock$Sync$ThreadLocalHoldCounter +java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock +java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock +org.junit.platform.commons.util.CollectionUtils$$Lambda$386/0x00007f42040d5b48 +org.junit.platform.engine.support.hierarchical.NodeUtils +org.junit.platform.engine.support.hierarchical.NodeUtils$1 +org.junit.platform.engine.support.hierarchical.NodeExecutionAdvisor +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$387/0x00007f42040d4d00 +org.junit.platform.engine.support.hierarchical.NopLock +org.junit.jupiter.api.parallel.ResourceLocksProvider +org.junit.jupiter.engine.descriptor.ClassTestDescriptor$$Lambda$388/0x00007f42040d8490 +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$389/0x00007f42040d86d8 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$390/0x00007f42040d8910 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$391/0x00007f42040d8b38 +org.junit.jupiter.engine.descriptor.ResourceLockAware$1 +java.util.ArrayDeque$DeqSpliterator +org.junit.jupiter.engine.descriptor.ResourceLockAware$$Lambda$392/0x00007f42040d8fc8 +org.junit.jupiter.engine.descriptor.ResourceLockAware$$Lambda$393/0x00007f42040d9208 +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$DefaultExclusiveResourceCollector$$Lambda$394/0x00007f42040d9450 +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$DefaultExclusiveResourceCollector$$Lambda$395/0x00007f42040d96a0 +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$DefaultExclusiveResourceCollector$$Lambda$396/0x00007f42040d98f8 +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$DefaultExclusiveResourceCollector$$Lambda$397/0x00007f42040d9b38 +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$DefaultExclusiveResourceCollector$$Lambda$398/0x00007f42040d9d78 +org.junit.jupiter.engine.descriptor.ResourceLockAware$$Lambda$399/0x00007f42040d9fb8 +org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector$2 +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$400/0x00007f42040da400 +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$401/0x00007f42040da848 +org.junit.platform.engine.support.hierarchical.NodeTreeWalker$$Lambda$402/0x00007f42040daa80 +org.junit.platform.engine.support.hierarchical.NodeTestTaskContext +org.junit.platform.engine.support.hierarchical.NodeTestTask +org.junit.platform.engine.support.hierarchical.Node$DynamicTestExecutor +java.lang.invoke.LambdaForm$DMH/0x00007f42040dc000 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$403/0x00007f42040db348 +org.opentest4j.IncompleteExecutionException +org.opentest4j.TestAbortedException +org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector$$Lambda$404/0x00007f42040dba28 +org.junit.platform.commons.util.UnrecoverableExceptions +org.junit.jupiter.engine.support.OpenTest4JAndJUnit4AwareThrowableCollector$$Lambda$405/0x00007f42040de000 +org.junit.platform.engine.support.hierarchical.ThrowableCollector$Executable +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$406/0x00007f42040de420 +org.junit.jupiter.engine.extension.MutableExtensionRegistry +org.junit.jupiter.engine.extension.MutableExtensionRegistry$Entry +org.junit.jupiter.api.extension.ExecutionCondition +org.junit.jupiter.engine.extension.DisabledCondition +org.junit.jupiter.api.extension.TestInstancePreDestroyCallback +org.junit.jupiter.engine.extension.AutoCloseExtension +org.junit.jupiter.engine.extension.TimeoutExtension +org.junit.jupiter.api.Timeout +org.junit.jupiter.api.extension.ExtensionContext$Namespace +org.junit.jupiter.engine.extension.RepeatedTestExtension +org.junit.jupiter.api.extension.TestTemplateInvocationContext +org.junit.jupiter.engine.extension.TestInfoParameterResolver +org.junit.jupiter.api.TestInfo +org.junit.jupiter.engine.extension.TestReporterParameterResolver +org.junit.jupiter.api.TestReporter +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$407/0x00007f42040ddac0 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$408/0x00007f42040ddcf8 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$409/0x00007f42040dc800 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$Entry$$Lambda$410/0x00007f42040dca28 +org.junit.jupiter.engine.extension.TempDirectory +org.junit.jupiter.api.extension.AnnotatedElementContext +org.junit.jupiter.engine.extension.TempDirectory$Scope +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$411/0x00007f42040e0248 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$412/0x00007f42040e0490 +org.junit.jupiter.engine.extension.ExtensionContextInternal +org.junit.jupiter.engine.descriptor.AbstractExtensionContext +org.junit.jupiter.engine.descriptor.JupiterEngineExtensionContext +org.junit.jupiter.api.extension.ExecutableInvoker +org.junit.jupiter.engine.execution.DefaultExecutableInvoker +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$413/0x00007f42040e14f8 +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$414/0x00007f42040e1738 +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$415/0x00007f42040e1958 +org.junit.jupiter.engine.execution.NamespaceAwareStore +org.junit.jupiter.api.extension.ExtensionContextException +org.junit.platform.engine.support.store.Namespace +java.lang.invoke.LambdaForm$DMH/0x00007f42040e4000 +org.junit.jupiter.engine.descriptor.AbstractExtensionContext$$Lambda$416/0x00007f42040e22c0 +org.junit.jupiter.engine.execution.JupiterEngineExecutionContext$Builder +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$417/0x00007f42040e2720 +org.junit.platform.engine.support.hierarchical.Node$SkipResult +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$418/0x00007f42040e2b68 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$419/0x00007f42040e2da0 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$420/0x00007f42040e2fc8 +org.junit.platform.launcher.TestPlan$$Lambda$421/0x00007f42040e3200 +org.junit.platform.launcher.TestPlan$$Lambda$422/0x00007f42040e3420 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$423/0x00007f42040e3648 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$424/0x00007f42040e3880 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$425/0x00007f42040e3aa8 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$426/0x00007f42040e3ce0 +org.junit.platform.engine.UniqueIdFormat$$Lambda$427/0x00007f42040e6000 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$428/0x00007f42040e6248 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$429/0x00007f42040e64a0 +org.junit.platform.engine.support.hierarchical.Node$Invocation +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$430/0x00007f42040e68c8 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$431/0x00007f42040e6af0 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$432/0x00007f42040e6d18 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$433/0x00007f42040e6f60 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor +java.util.concurrent.CancellationException +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$434/0x00007f42040e73d0 +org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService$$Lambda$435/0x00007f42040e7608 +org.junit.jupiter.engine.descriptor.ExtensionUtils +java.util.function.ToIntFunction +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$436/0x00007f42040e7a40 +java.util.Comparator$$Lambda$437/0x00007f420407df18 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$438/0x00007f42040e7c60 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$439/0x00007f42040e5000 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$440/0x00007f42040e5240 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$LateInitEntry +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$441/0x00007f42040e56c8 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$442/0x00007f42040e5900 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$443/0x00007f42040e5b50 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$444/0x00007f42040e4800 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$445/0x00007f42040e4a50 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$446/0x00007f42040e4c70 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$447/0x00007f42040e4400 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$448/0x00007f42040e8000 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$449/0x00007f42040e8258 +java.util.stream.SortedOps +java.util.stream.SortedOps$OfRef +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$450/0x00007f42040e8478 +java.util.stream.SortedOps$AbstractRefSortingSink +java.util.stream.SortedOps$RefSortingSink +java.util.stream.SortedOps$RefSortingSink$$Lambda$451/0x00007f420407ee38 +org.junit.jupiter.api.extension.TestInstanceFactory +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$452/0x00007f42040e86b0 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$453/0x00007f42040e88f0 +org.junit.jupiter.engine.extension.MutableExtensionRegistry$$Lambda$454/0x00007f42040e8b48 +org.junit.jupiter.engine.extension.ExtensionRegistry$$Lambda$455/0x00007f42040e8d90 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$456/0x00007f42040e8fb0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$457/0x00007f42040e9200 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$458/0x00007f42040e9420 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$459/0x00007f42040e9648 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$460/0x00007f42040e9890 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$461/0x00007f42040e9ad0 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$462/0x00007f42040e9d08 +org.junit.jupiter.engine.execution.BeforeEachMethodAdapter +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$463/0x00007f42040ea140 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$464/0x00007f42040ea388 +org.junit.jupiter.engine.execution.AfterEachMethodAdapter +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$465/0x00007f42040ea7c0 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$466/0x00007f42040eaa08 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$467/0x00007f42040eac40 +org.junit.jupiter.engine.descriptor.ExtensionUtils$$Lambda$468/0x00007f42040eae90 +org.junit.jupiter.engine.descriptor.ClassExtensionContext +org.junit.jupiter.engine.execution.TestInstancesProvider +org.junit.jupiter.api.extension.TestInstances +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$469/0x00007f42040eb9a8 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$470/0x00007f42040ebbe0 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$471/0x00007f42040ebe28 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$FilterType +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$472/0x00007f42040ec4a8 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$473/0x00007f42040ec6f8 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$474/0x00007f42040ec938 +org.junit.platform.commons.util.ClassNamePatternFilterUtils$$Lambda$475/0x00007f42040ecb80 +org.junit.jupiter.engine.execution.ConditionEvaluator$$Lambda$476/0x00007f42040ecdd0 +org.junit.jupiter.engine.execution.ConditionEvaluator$$Lambda$477/0x00007f42040ed018 +org.junit.jupiter.api.Disabled +org.junit.jupiter.engine.extension.DisabledCondition$$Lambda$478/0x00007f42040ed468 +org.junit.jupiter.engine.execution.ConditionEvaluator$$Lambda$479/0x00007f42040ed6b0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$480/0x00007f42040ed8d8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$481/0x00007f42040edb30 +org.junit.platform.launcher.TestIdentifier$$Lambda$482/0x00007f42040edd88 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$483/0x00007f42040edfc8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$484/0x00007f42040ee210 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$485/0x00007f42040ee458 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$486/0x00007f42040ee678 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$487/0x00007f42040ee8c8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$488/0x00007f42040eeb08 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$489/0x00007f42040eed60 +org.apache.maven.surefire.api.report.SimpleReportEntry +org.apache.maven.surefire.api.util.internal.ClassMethod +org.apache.maven.surefire.report.ClassMethodIndexer$$Lambda$490/0x00007f42040ef4b8 +org.apache.maven.surefire.api.util.internal.ImmutableMap +org.apache.maven.surefire.booter.spi.EventChannelEncoder$StackTrace +java.lang.StrictMath +java.nio.StringCharBuffer +org.junit.jupiter.engine.descriptor.CallbackSupport$CallbackInvoker +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$491/0x00007f42040f0200 +org.junit.jupiter.engine.descriptor.CallbackSupport +org.junit.jupiter.engine.descriptor.CallbackSupport$$Lambda$492/0x00007f42040f0628 +org.junit.jupiter.engine.extension.TimeoutDuration +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$493/0x00007f42040f0a78 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$494/0x00007f42040f0cb8 +org.junit.jupiter.api.Timeout$ThreadMode +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$495/0x00007f42040f1138 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$496/0x00007f42040f1378 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$497/0x00007f42040f15b0 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$498/0x00007f42040f1808 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$499/0x00007f42040f1a40 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$500/0x00007f42040f1c90 +org.junit.jupiter.engine.execution.NamespaceAwareStore$$Lambda$501/0x00007f42040f1ed8 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$CompositeKey +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$StoredValue +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$502/0x00007f42040f2520 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$MemoizingSupplier +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$503/0x00007f42040f2998 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$504/0x00007f42040f2bc0 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$MemoizingSupplier$Failure +org.junit.jupiter.api.io.TempDir +org.junit.platform.commons.util.AnnotationUtils$$Lambda$505/0x00007f42040f3410 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$506/0x00007f42040f3668 +org.junit.jupiter.engine.descriptor.ClassExtensionContext$$Lambda$507/0x00007f42040f38a0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$508/0x00007f42040f3ae0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$509/0x00007f42040f3d20 +java.util.stream.Nodes$ArrayNode +java.util.stream.Nodes$FixedNodeBuilder +org.junit.jupiter.engine.descriptor.MethodExtensionContext +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$510/0x00007f42040f4420 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$511/0x00007f42040f4648 +org.junit.jupiter.engine.execution.ExtensionContextSupplier +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$512/0x00007f42040f4a70 +org.junit.jupiter.engine.execution.ExtensionContextSupplier$ScopeBasedExtensionContextSupplier +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$513/0x00007f42040f50e0 +org.junit.jupiter.engine.descriptor.DefaultTestInstanceFactoryContext +org.junit.jupiter.api.extension.TestInstancePreConstructCallback +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$514/0x00007f42040f5760 +java.lang.invoke.LambdaForm$DMH/0x00007f42040f8000 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$515/0x00007f42040f5998 +org.junit.jupiter.engine.execution.ParameterResolutionUtils +org.junit.jupiter.api.extension.ParameterContext +org.junit.jupiter.api.extension.ParameterResolutionException +org.junit.jupiter.engine.execution.ConstructorInvocation +org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptorCall +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$$Lambda$516/0x00007f42040f66b8 +org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation +org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation +org.junit.jupiter.engine.execution.DefaultTestInstances +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$517/0x00007f42040f6fc8 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$518/0x00007f42040f7210 +org.junit.jupiter.api.extension.TestInstancePostProcessor +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$519/0x00007f42040f7638 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$520/0x00007f42040f7870 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$521/0x00007f42040f7ab8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$522/0x00007f42040f7d08 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$523/0x00007f42040fc000 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$524/0x00007f42040fc248 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$525/0x00007f42040fc488 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$526/0x00007f42040fc6d8 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$527/0x00007f42040fc918 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$528/0x00007f42040fcb70 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$529/0x00007f42040fcdc0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$530/0x00007f42040fd000 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$531/0x00007f42040fd250 +org.junit.jupiter.api.extension.ExtensionContext$Store$CloseableResource +org.junit.jupiter.engine.extension.TempDirectory$FailureTracker +org.junit.jupiter.engine.execution.NamespaceAwareStore$$Lambda$532/0x00007f42040fd8b8 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$533/0x00007f42040fdae0 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$534/0x00007f42040fdd08 +org.junit.jupiter.engine.extension.TempDirectory$$Lambda$535/0x00007f42040fdf40 +sun.reflect.generics.repository.AbstractRepository +sun.reflect.generics.repository.GenericDeclRepository +sun.reflect.generics.repository.ClassRepository +java.lang.reflect.TypeVariable +sun.reflect.generics.tree.FormalTypeParameter +sun.reflect.generics.tree.Signature +sun.reflect.generics.tree.ClassSignature +org.junitpioneer.jupiter.ClearEnvironmentVariable +org.junitpioneer.jupiter.RestoreEnvironmentVariables +java.lang.reflect.ParameterizedType +sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl +sun.reflect.generics.reflectiveObjects.LazyReflectiveObjectGenerator +sun.reflect.generics.reflectiveObjects.TypeVariableImpl +org.junitpioneer.internal.PioneerAnnotationUtils +java.lang.invoke.LambdaForm$DMH/0x00007f42040f8400 +org.junitpioneer.internal.PioneerAnnotationUtils$$Lambda$536/0x00007f42040fe798 +java.lang.invoke.LambdaForm$DMH/0x00007f42040f8800 +java.util.stream.Collectors$$Lambda$537/0x00007f42040f97c0 +java.util.stream.Collectors$$Lambda$538/0x00007f42040f99e0 +java.util.stream.Collectors$$Lambda$539/0x00007f42040f9c10 +java.util.stream.Collectors$$Lambda$540/0x00007f42040f8c00 +java.util.ImmutableCollections$Access +jdk.internal.access.JavaUtilCollectionAccess +java.util.ImmutableCollections$Access$1 +sun.reflect.annotation.AnnotationSupport +org.junitpioneer.internal.PioneerAnnotationUtils$$Lambda$541/0x00007f42040febd8 +org.junitpioneer.internal.PioneerAnnotationUtils$$Lambda$542/0x00007f42040fee20 +java.util.AbstractList$RandomAccessSpliterator +java.lang.invoke.MethodHandleImpl$BindCaller +java.lang.invoke.MethodHandleImpl$BindCaller$1 +java.lang.invoke.LambdaForm$MH/0x00007f4204140000 +java.lang.invoke.LambdaForm$MH/0x00007f4204140400 +java.lang.invoke.MethodHandleImpl$CasesHolder +java.lang.invoke.MethodHandleImpl$LoopClauses +java.lang.invoke.MethodHandleImpl$ArrayAccess +java.lang.invoke.MethodHandleImpl$2 +java.lang.invoke.MethodHandleImpl$ArrayAccessor +java.lang.invoke.MethodHandleImpl$ArrayAccessor$1 +java.lang.invoke.LambdaForm$DMH/0x00007f4204140800 +java.lang.invoke.LambdaForm$DMH/0x00007f4204140c00 +java.lang.invoke.LambdaForm$DMH/0x00007f4204141000 +java.lang.invoke.LambdaForm$MH/0x00007f4204141400 +java.lang.invoke.LambdaForm$MH/0x00007f4204141800 +org.junitpioneer.internal.PioneerAnnotationUtils$$InjectedInvoker/0x00007f4204141c00 +java.util.Collections$CopiesList +java.lang.invoke.LambdaForm$MH/0x00007f4204142000 +java.lang.invoke.BoundMethodHandle$Species_LLL +java.lang.invoke.LambdaForm$MH/0x00007f4204142400 +java.lang.invoke.LambdaForm$MH/0x00007f4204142800 +java.lang.invoke.LambdaForm$MH/0x00007f4204142c00 +java.lang.invoke.BoundMethodHandle$Species_LLLL +java.lang.invoke.LambdaForm$MH/0x00007f4204143000 +java.lang.invoke.MethodHandleImpl$WrappedMember +org.junitpioneer.internal.PioneerAnnotationUtils$$Lambda$543/0x00007f42040ff060 +org.junitpioneer.internal.PioneerUtils +org.junitpioneer.internal.PioneerUtils$$Lambda$544/0x00007f42040ff4a8 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$545/0x00007f42040ff6e8 +java.lang.invoke.LambdaForm$DMH/0x00007f4204143400 +java.lang.invoke.LambdaForm$DMH/0x00007f4204143800 +java.lang.invoke.LambdaForm$MH/0x00007f4204143c00 +java.lang.invoke.LambdaForm$DMH/0x00007f4204144000 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$546/0x00007f42040ff920 +java.lang.invoke.LambdaForm$DMH/0x00007f4204144400 +java.lang.invoke.LambdaForm$DMH/0x00007f4204144800 +java.lang.invoke.LambdaForm$MH/0x00007f4204144c00 +org.junitpioneer.jupiter.ClearEnvironmentVariable$ClearEnvironmentVariables +org.junitpioneer.jupiter.EnvironmentVariableExtension$$Lambda$547/0x00007f42040ffd58 +org.junitpioneer.internal.PioneerUtils$$Lambda$548/0x00007f4204146000 +org.junitpioneer.internal.PioneerUtils$$Lambda$549/0x00007f4204146220 +org.junitpioneer.internal.PioneerUtils$$Lambda$550/0x00007f4204146450 +org.junitpioneer.jupiter.EnvironmentVariableExtension$$Lambda$551/0x00007f4204146698 +org.junitpioneer.jupiter.EnvironmentVariableExtension$$Lambda$552/0x00007f42041468d8 +java.util.stream.Collectors$$Lambda$553/0x00007f4204100e30 +java.util.stream.Collectors$$Lambda$554/0x00007f4204101050 +java.util.stream.Collectors$$Lambda$555/0x00007f4204101288 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$556/0x00007f4204146b18 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$557/0x00007f4204146d70 +java.time.temporal.TemporalAccessor +java.time.temporal.Temporal +java.time.temporal.TemporalAdjuster +java.time.chrono.ChronoLocalDateTime +java.time.LocalDateTime +java.time.chrono.ChronoLocalDate +java.time.LocalDate +java.time.temporal.TemporalField +java.time.temporal.ChronoField +java.time.temporal.ValueRange +java.time.LocalTime +java.time.InstantSource +java.time.Clock +java.time.Clock$SystemClock +java.time.ZoneId +java.time.ZoneOffset +java.util.TimeZone +sun.util.calendar.ZoneInfo +sun.util.calendar.ZoneInfoFile +sun.util.calendar.ZoneInfoFile$1 +java.io.DataInputStream +sun.util.calendar.ZoneInfoFile$ZoneOffsetTransitionRule +sun.util.calendar.ZoneInfoFile$Checksum +java.time.ZoneRegion +java.time.zone.ZoneRulesProvider +java.time.zone.ZoneRulesProvider$1 +java.time.zone.TzdbZoneRulesProvider +java.time.zone.Ser +java.time.zone.ZoneRules +java.time.zone.ZoneOffsetTransitionRule +java.time.zone.ZoneOffsetTransition +java.time.Instant +org.junit.platform.engine.reporting.ReportEntry$$Lambda$558/0x00007f4204146fb0 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$559/0x00007f42041471e8 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$560/0x00007f4204147420 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$561/0x00007f4204147648 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$562/0x00007f4204147880 +org.apache.maven.surefire.api.report.TestOutputReportEntry +java.lang.invoke.LambdaForm$MH/0x00007f4204145000 +java.lang.invoke.LambdaForm$MH/0x00007f4204145400 +java.lang.invoke.LambdaForm$MH/0x00007f4204145800 +java.lang.invoke.LambdaForm$MH/0x00007f4204145c00 +java.lang.invoke.LambdaForm$MH/0x00007f4204148000 +java.lang.invoke.BoundMethodHandle$Species_LLLLL +java.lang.invoke.LambdaForm$MH/0x00007f4204148400 +java.lang.invoke.BoundMethodHandle$Species_LLLLLL +java.lang.invoke.LambdaForm$MH/0x00007f4204148800 +java.lang.invoke.BoundMethodHandle$Species_LLLLLLL +java.lang.invoke.LambdaForm$MH/0x00007f4204148c00 +java.lang.invoke.MethodHandles$1 +java.lang.invoke.BoundMethodHandle$Species_LJ +java.lang.invoke.LambdaForm$MH/0x00007f4204149000 +java.lang.invoke.BoundMethodHandle$Species_LLLLLLLL +java.lang.invoke.LambdaForm$MH/0x00007f4204149400 +java.lang.invoke.BoundMethodHandle$Species_LLLLLLLLL +java.lang.invoke.LambdaFormEditor$1 +java.util.TreeMap$EntrySet +java.util.TreeMap$EntryIterator +java.lang.invoke.LambdaForm$MH/0x00007f4204149800 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$EntriesBackup +org.junitpioneer.jupiter.AbstractEntryBasedExtension$EntriesBackup$$Lambda$563/0x00007f420414c000 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$564/0x00007f420414c238 +java.lang.invoke.LambdaForm$DMH/0x00007f4204149c00 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$565/0x00007f420414c470 +org.junitpioneer.jupiter.EnvironmentVariableUtils +java.lang.reflect.InaccessibleObjectException +org.junitpioneer.jupiter.EnvironmentVariableUtils$$Lambda$566/0x00007f420414c8b0 +jdk.internal.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl +jdk.internal.reflect.UnsafeQualifiedFieldAccessorImpl +jdk.internal.reflect.UnsafeQualifiedObjectFieldAccessorImpl +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$567/0x00007f420414cae8 +org.junit.jupiter.api.extension.BeforeTestExecutionCallback +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$568/0x00007f420414cf10 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$569/0x00007f420414d130 +org.junit.jupiter.engine.descriptor.MethodExtensionContext$$Lambda$570/0x00007f420414d358 +org.junit.jupiter.engine.execution.ParameterResolutionUtils$$Lambda$571/0x00007f420414d598 +org.junit.jupiter.engine.execution.MethodInvocation +org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$$Lambda$572/0x00007f420414da58 +org.junit.jupiter.engine.extension.TimeoutExtension$TimeoutProvider +org.junit.jupiter.engine.extension.TimeoutConfiguration +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$573/0x00007f420414e0d0 +org.junit.jupiter.engine.execution.NamespaceAwareStore$$Lambda$574/0x00007f420414e328 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$575/0x00007f420414e550 +org.junit.jupiter.engine.extension.TimeoutDurationParser +java.time.DateTimeException +java.time.format.DateTimeParseException +java.util.regex.Pattern$$Lambda$576/0x00007f4204104db8 +java.lang.CharacterData00 +java.util.regex.Pattern$$Lambda$577/0x00007f4204105408 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$578/0x00007f420414e9a8 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$579/0x00007f420414ebd0 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$580/0x00007f420414ee18 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$581/0x00007f420414f060 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$582/0x00007f420414f288 +software.amazon.lambda.powertools.kafka.internal.DeserializationUtils +org.slf4j.LoggerFactory +org.slf4j.spi.SLF4JServiceProvider +org.slf4j.event.LoggingEvent +java.lang.InstantiationException +java.util.ServiceConfigurationError +org.slf4j.helpers.SubstituteServiceProvider +org.slf4j.IMarkerFactory +org.slf4j.spi.MDCAdapter +org.slf4j.ILoggerFactory +org.slf4j.helpers.SubstituteLoggerFactory +org.slf4j.Logger +java.util.concurrent.LinkedBlockingQueue +java.util.concurrent.LinkedBlockingQueue$Node +org.slf4j.helpers.BasicMarkerFactory +org.slf4j.Marker +org.slf4j.helpers.BasicMDCAdapter +java.lang.InheritableThreadLocal +org.slf4j.helpers.BasicMDCAdapter$1 +org.slf4j.helpers.ThreadLocalMapOfStacks +org.slf4j.helpers.NOP_FallbackServiceProvider +org.slf4j.helpers.NOPLoggerFactory +org.slf4j.helpers.NOPMDCAdapter +org.slf4j.helpers.Util +org.slf4j.simple.SimpleServiceProvider +org.slf4j.MDC +org.slf4j.simple.SimpleLoggerFactory +org.slf4j.helpers.AbstractLogger +org.slf4j.helpers.LegacyAbstractLogger +org.slf4j.simple.SimpleLogger +org.slf4j.spi.LoggingEventBuilder +org.slf4j.simple.SimpleLoggerConfiguration +java.text.Format +java.text.DateFormat +java.text.SimpleDateFormat +org.slf4j.simple.SimpleLoggerConfiguration$$Lambda$583/0x00007f4204151ec0 +org.slf4j.simple.OutputChoice +org.slf4j.simple.OutputChoice$OutputChoiceType +java.text.AttributedCharacterIterator$Attribute +java.text.Format$Field +java.text.DateFormat$Field +java.util.Calendar +java.util.spi.LocaleServiceProvider +sun.util.spi.CalendarProvider +sun.util.locale.provider.LocaleProviderAdapter +sun.util.locale.provider.LocaleProviderAdapter$Type +sun.util.locale.provider.LocaleProviderAdapter$1 +sun.util.locale.provider.ResourceBundleBasedAdapter +sun.util.locale.provider.JRELocaleProviderAdapter +sun.util.cldr.CLDRLocaleProviderAdapter +sun.util.locale.provider.LocaleDataMetaInfo +sun.util.cldr.CLDRBaseLocaleDataMetaInfo +sun.util.locale.LanguageTag +sun.util.locale.ParseStatus +sun.util.locale.StringTokenIterator +sun.util.locale.InternalLocaleBuilder +sun.util.locale.InternalLocaleBuilder$CaseInsensitiveChar +sun.util.locale.BaseLocale$Key +sun.util.locale.LocaleObjectCache +sun.util.locale.BaseLocale$Cache +sun.util.locale.LocaleObjectCache$CacheEntry +java.util.Locale$Cache +sun.util.cldr.CLDRLocaleProviderAdapter$$Lambda$57/0x80000005e +jdk.internal.module.ModulePatcher$PatchedModuleReader +sun.net.www.protocol.jrt.Handler +sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$59/0x800000060 +sun.util.locale.provider.AvailableLanguageTags +sun.util.locale.provider.CalendarProviderImpl +java.util.Calendar$Builder +java.util.GregorianCalendar +sun.util.calendar.CalendarSystem +sun.util.calendar.CalendarSystem$GregorianHolder +sun.util.calendar.AbstractCalendar +sun.util.calendar.BaseCalendar +sun.util.calendar.Gregorian +sun.util.locale.provider.CalendarDataUtility +java.util.Locale$Builder +java.util.spi.CalendarDataProvider +sun.util.locale.provider.LocaleServiceProviderPool +java.text.spi.BreakIteratorProvider +java.text.spi.CollatorProvider +java.text.spi.DateFormatProvider +java.text.spi.DateFormatSymbolsProvider +java.text.spi.DecimalFormatSymbolsProvider +java.text.spi.NumberFormatProvider +java.util.spi.CurrencyNameProvider +java.util.spi.LocaleNameProvider +java.util.spi.TimeZoneNameProvider +sun.util.locale.provider.LocaleServiceProviderPool$LocalizedObjectGetter +sun.util.locale.provider.CalendarDataUtility$CalendarWeekParameterGetter +java.util.ResourceBundle$Control +java.util.ResourceBundle +java.util.ResourceBundle$Control$CandidateListCache +java.util.ResourceBundle$SingleFormatControl +java.util.ResourceBundle$NoFallbackControl +sun.util.cldr.CLDRLocaleProviderAdapter$$Lambda$58/0x80000005f +sun.util.locale.provider.CalendarDataProviderImpl +sun.util.cldr.CLDRCalendarDataProviderImpl +sun.util.locale.provider.LocaleResources +sun.util.resources.LocaleData +sun.util.resources.LocaleData$1 +sun.util.resources.Bundles$Strategy +sun.util.resources.LocaleData$LocaleDataStrategy +sun.util.resources.Bundles +sun.util.resources.Bundles$1 +jdk.internal.access.JavaUtilResourceBundleAccess +java.util.ResourceBundle$1 +java.util.ResourceBundle$2 +sun.util.resources.Bundles$CacheKey +java.util.ListResourceBundle +sun.util.resources.cldr.CalendarData +java.util.ResourceBundle$ResourceBundleProviderHelper +java.util.ResourceBundle$ResourceBundleProviderHelper$$Lambda$11/0x80000000f +sun.util.resources.Bundles$CacheKeyReference +sun.util.resources.Bundles$BundleReference +sun.util.locale.provider.LocaleResources$ResourceReference +sun.util.calendar.CalendarDate +sun.util.calendar.BaseCalendar$Date +sun.util.calendar.Gregorian$Date +sun.util.calendar.CalendarUtils +java.text.DateFormatSymbols +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$61/0x800000062 +sun.util.locale.provider.DateFormatSymbolsProviderImpl +sun.text.resources.cldr.FormatData +sun.text.resources.cldr.FormatData_en +java.text.NumberFormat +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$63/0x800000064 +sun.util.locale.provider.NumberFormatProviderImpl +java.text.DecimalFormatSymbols +sun.util.locale.provider.JRELocaleProviderAdapter$$Lambda$62/0x800000063 +sun.util.locale.provider.DecimalFormatSymbolsProviderImpl +java.lang.StringLatin1$CharsSpliterator +java.util.stream.IntStream +java.util.stream.IntPipeline +java.util.stream.IntPipeline$Head +java.util.function.IntPredicate +java.text.DecimalFormatSymbols$$Lambda$7/0x80000000b +java.util.stream.IntPipeline$StatelessOp +java.util.stream.IntPipeline$10 +java.util.function.IntConsumer +java.util.stream.Sink$OfInt +java.util.stream.FindOps$FindSink$OfInt +java.util.OptionalInt +java.util.stream.FindOps$FindSink$OfInt$$Lambda$36/0x800000047 +java.util.stream.FindOps$FindSink$OfInt$$Lambda$34/0x800000045 +java.util.stream.FindOps$FindSink$OfInt$$Lambda$35/0x800000046 +java.util.stream.FindOps$FindSink$OfInt$$Lambda$33/0x800000044 +java.util.stream.Sink$ChainedInt +java.util.stream.IntPipeline$10$1 +java.lang.StringUTF16$CharsSpliterator +java.text.DecimalFormat +java.text.FieldPosition +java.text.DigitList +java.math.RoundingMode +java.util.Date +org.slf4j.helpers.Reporter +org.slf4j.helpers.Reporter$TargetChoice +org.slf4j.helpers.Reporter$Level +org.slf4j.simple.SimpleLoggerFactory$$Lambda$596/0x00007f42041531c0 +software.amazon.lambda.powertools.kafka.internal.DeserializationUtils$HandlerInfo +com.amazonaws.services.lambda.runtime.RequestHandler +software.amazon.lambda.powertools.kafka.testutils.AvroHandler +org.apache.kafka.clients.consumer.ConsumerRecords +com.amazonaws.services.lambda.runtime.Context +software.amazon.lambda.powertools.kafka.Deserialization +software.amazon.lambda.powertools.kafka.DeserializationType +jdk.proxy2.$Proxy20 +org.slf4j.event.Level +java.text.DontCareFieldPosition +java.text.Format$FieldDelegate +java.text.DontCareFieldPosition$1 +java.text.NumberFormat$Field +org.slf4j.helpers.MessageFormatter +org.slf4j.helpers.FormattingTuple +org.assertj.core.api.InstanceOfAssertFactories +org.assertj.core.api.Assertions +org.assertj.core.api.NumberAssert +org.assertj.core.api.ComparableAssert +org.assertj.core.api.Descriptable +org.assertj.core.api.ExtensionPoints +org.assertj.core.api.Assert +org.assertj.core.api.AbstractAssert +org.assertj.core.api.AbstractObjectAssert +org.assertj.core.api.AbstractComparableAssert +org.assertj.core.api.AbstractBigIntegerAssert +org.assertj.core.api.BigIntegerAssert +org.assertj.core.data.TemporalOffset +org.assertj.core.data.TemporalUnitOffset +org.assertj.core.data.TemporalUnitWithinOffset +org.assertj.core.data.TemporalUnitLessThanOffset +org.assertj.core.configuration.ConfigurationProvider +org.assertj.core.api.AssertionsForClassTypes +org.assertj.core.api.AssertionsForInterfaceTypes +org.assertj.core.api.EnumerableAssert +org.assertj.core.api.AbstractCharSequenceAssert +org.assertj.core.api.CharSequenceAssert +org.assertj.core.api.AbstractStringAssert +org.assertj.core.api.StringAssert +org.assertj.core.api.AbstractDateAssert +org.assertj.core.api.DateAssert +org.assertj.core.api.AbstractTemporalAssert +org.assertj.core.api.AbstractZonedDateTimeAssert +org.assertj.core.api.ZonedDateTimeAssert +org.assertj.core.api.AbstractShortAssert +org.assertj.core.api.ShortAssert +org.assertj.core.api.ArraySortedAssert +org.assertj.core.api.AbstractEnumerableAssert +org.assertj.core.api.AbstractArrayAssert +org.assertj.core.api.AbstractShortArrayAssert +org.assertj.core.api.ShortArrayAssert +org.assertj.core.api.AbstractYearMonthAssert +org.assertj.core.api.YearMonthAssert +org.assertj.core.api.AbstractInstantAssert +org.assertj.core.api.InstantAssert +org.assertj.core.api.AbstractDurationAssert +org.assertj.core.api.DurationAssert +org.assertj.core.api.AbstractPeriodAssert +org.assertj.core.api.PeriodAssert +org.assertj.core.api.AbstractThrowableAssert +org.assertj.core.api.ThrowableAssert +org.assertj.core.api.AbstractLocalDateTimeAssert +org.assertj.core.api.LocalDateTimeAssert +org.assertj.core.api.AbstractOffsetDateTimeAssert +org.assertj.core.api.OffsetDateTimeAssert +org.assertj.core.api.AbstractOffsetTimeAssert +org.assertj.core.api.OffsetTimeAssert +org.assertj.core.api.AbstractLocalTimeAssert +org.assertj.core.api.LocalTimeAssert +org.assertj.core.api.AbstractLocalDateAssert +org.assertj.core.api.LocalDateAssert +org.assertj.core.api.AbstractByteArrayAssert +org.assertj.core.api.ByteArrayAssert +org.assertj.core.api.AbstractByteAssert +org.assertj.core.api.ByteAssert +org.assertj.core.api.AbstractCharacterAssert +org.assertj.core.api.CharacterAssert +org.assertj.core.api.AbstractCharArrayAssert +org.assertj.core.api.CharArrayAssert +org.assertj.core.api.AbstractBooleanAssert +org.assertj.core.api.BooleanAssert +org.assertj.core.api.AbstractBigDecimalAssert +org.assertj.core.api.BigDecimalAssert +org.assertj.core.api.AbstractUriAssert +org.assertj.core.api.UriAssert +org.assertj.core.api.AbstractUrlAssert +org.assertj.core.api.UrlAssert +org.assertj.core.api.AbstractBooleanArrayAssert +org.assertj.core.api.BooleanArrayAssert +org.assertj.core.api.AbstractIntArrayAssert +org.assertj.core.api.IntArrayAssert +org.assertj.core.api.AbstractIntegerAssert +org.assertj.core.api.IntegerAssert +org.assertj.core.api.AbstractFloatArrayAssert +org.assertj.core.api.FloatArrayAssert +org.assertj.core.api.FloatingPointNumberAssert +org.assertj.core.api.AbstractFloatAssert +org.assertj.core.api.FloatAssert +org.assertj.core.api.AbstractLongArrayAssert +org.assertj.core.api.LongArrayAssert +org.assertj.core.api.AbstractLongAssert +org.assertj.core.api.LongAssert +org.assertj.core.api.AbstractDoubleArrayAssert +org.assertj.core.api.DoubleArrayAssert +org.assertj.core.api.AbstractDoubleAssert +org.assertj.core.api.DoubleAssert +org.assertj.core.api.AbstractFileAssert +org.assertj.core.api.FileAssert +org.assertj.core.api.AbstractInputStreamAssert +org.assertj.core.api.InputStreamAssert +org.assertj.core.api.GenericComparableAssert +org.assertj.core.api.AbstractUniversalComparableAssert +org.assertj.core.api.UniversalComparableAssert +org.assertj.core.description.Description +org.assertj.core.description.LazyTextDescription +org.assertj.core.description.TextDescription +org.assertj.core.api.AssertionInfo +org.assertj.core.internal.ComparisonStrategy +org.assertj.core.api.ObjectEnumerableAssert +org.assertj.core.api.IndexedObjectEnumerableAssert +org.assertj.core.api.AbstractIterableAssert +org.assertj.core.api.AbstractCollectionAssert +org.assertj.core.api.AbstractListAssert +org.assertj.core.api.FactoryBasedNavigableListAssert +org.assertj.core.api.ListAssert +org.assertj.core.api.ObjectAssert +org.assertj.core.internal.Objects +org.assertj.core.error.ErrorMessageFactory +org.assertj.core.util.introspection.IntrospectionError +org.assertj.core.internal.AbstractComparisonStrategy +org.assertj.core.internal.StandardComparisonStrategy +org.assertj.core.util.introspection.PropertySupport +org.assertj.core.internal.Failures +org.assertj.core.error.AssertionErrorCreator +org.assertj.core.util.Arrays +org.assertj.core.error.ConstructorInvoker +org.assertj.core.util.introspection.FieldSupport +org.assertj.core.error.GroupTypeDescription +org.assertj.core.internal.Conditions +org.assertj.core.api.WritableAssertionInfo +org.assertj.core.presentation.Representation +org.assertj.core.configuration.Configuration +org.assertj.core.configuration.PreferredAssumptionException +org.assertj.core.configuration.PreferredAssumptionException$1 +org.assertj.core.configuration.Services +org.assertj.core.util.Lists +org.assertj.core.util.Streams +org.assertj.core.util.Lists$$Lambda$597/0x00007f42041958b0 +org.assertj.core.presentation.CompositeRepresentation +java.lang.invoke.LambdaForm$DMH/0x00007f4204154800 +org.assertj.core.presentation.CompositeRepresentation$$Lambda$598/0x00007f4204195d28 +java.util.stream.SortedOps$SizedRefSortingSink +org.assertj.core.presentation.StandardRepresentation +java.time.chrono.ChronoZonedDateTime +java.time.ZonedDateTime +java.time.OffsetDateTime +java.nio.file.DirectoryStream +org.assertj.core.internal.Comparables +org.junit.jupiter.api.extension.AfterTestExecutionCallback +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$599/0x00007f42041967b8 +org.junit.jupiter.engine.descriptor.CallbackSupport$$Lambda$600/0x00007f42041969d8 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$601/0x00007f4204196c10 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$602/0x00007f4204196e38 +org.junit.jupiter.engine.descriptor.CallbackSupport$$Lambda$603/0x00007f4204197058 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$$Lambda$604/0x00007f4204197280 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$EntriesBackup$$Lambda$605/0x00007f42041974b8 +org.junitpioneer.jupiter.EnvironmentVariableUtils$$Lambda$606/0x00007f42041976f0 +org.junitpioneer.jupiter.AbstractEntryBasedExtension$EntriesBackup$$Lambda$607/0x00007f4204197928 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$608/0x00007f4204197b60 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$609/0x00007f4204197d88 +org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$610/0x00007f4204154c00 +org.junit.jupiter.engine.descriptor.MethodExtensionContext$$Lambda$611/0x00007f4204198000 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$612/0x00007f4204198240 +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$613/0x00007f4204198460 +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$614/0x00007f42041986b0 +org.junit.jupiter.api.extension.TestInstancePreDestroyCallback$$Lambda$615/0x00007f42041988e8 +org.junit.jupiter.api.extension.TestInstancePreDestroyCallback$$Lambda$616/0x00007f4204198b28 +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$617/0x00007f4204198d60 +org.junit.jupiter.api.AutoClose +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$618/0x00007f42041991b0 +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$619/0x00007f42041993e8 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$620/0x00007f4204199610 +java.util.concurrent.ConcurrentHashMap$EntrySpliterator +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$EvaluatedValue +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$621/0x00007f4204199a70 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$622/0x00007f4204199cb0 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$EvaluatedValue$$Lambda$623/0x00007f4204199f00 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$624/0x00007f420419a140 +org.junit.platform.engine.support.store.NamespacedHierarchicalStore$$Lambda$625/0x00007f420419a378 +org.junit.jupiter.engine.config.CachingJupiterConfiguration$$Lambda$626/0x00007f420419a5a0 +org.junit.platform.engine.TestExecutionResult +org.junit.platform.engine.TestExecutionResult$Status +org.junit.jupiter.api.extension.TestWatcher +org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$627/0x00007f420419b048 +org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor$$Lambda$628/0x00007f420419b280 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$629/0x00007f420419b4b8 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$630/0x00007f420419b6f8 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$631/0x00007f420419b948 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$632/0x00007f420419bb88 +org.junit.platform.launcher.core.StackTracePruningEngineExecutionListener$$Lambda$633/0x00007f420419bdc8 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$634/0x00007f420419c018 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$635/0x00007f420419c250 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$636/0x00007f420419c478 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$637/0x00007f420419c6b0 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$638/0x00007f420419c8d8 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$639/0x00007f420419cb10 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$640/0x00007f420419cd38 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$1 +software.amazon.lambda.powertools.kafka.testutils.ProtobufHandler +software.amazon.lambda.powertools.kafka.testutils.JsonHandler +java.lang.Throwable$PrintStreamOrWriter +java.lang.Throwable$WrappedPrintStream +java.lang.StackTraceElement$HashedModules +java.lang.invoke.LambdaForm$DMH/0x00007f42041a0000 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$641/0x00007f420419d5f8 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$642/0x00007f420419d830 +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$643/0x00007f420419da50 +org.junit.jupiter.engine.extension.AutoCloseExtension$$Lambda$644/0x00007f420419dca0 +org.apache.maven.surefire.junitplatform.RunListenerAdapter$$Lambda$645/0x00007f420419def0 +org.apache.maven.surefire.api.util.internal.ObjectUtils +org.apache.maven.surefire.api.util.internal.ImmutableMap$Node +org.mockito.session.MockitoSessionLogger +org.mockito.quality.Strictness +org.mockito.junit.jupiter.resolver.CompositeParameterResolver +org.mockito.junit.jupiter.resolver.MockParameterResolver +org.mockito.junit.jupiter.resolver.CaptorParameterResolver +com.fasterxml.jackson.core.Versioned +com.fasterxml.jackson.core.TreeCodec +com.fasterxml.jackson.core.ObjectCodec +com.fasterxml.jackson.databind.ObjectMapper +org.junit.jupiter.api.extension.RegisterExtension +org.mockito.Mock +org.mockito.stubbing.Answer +org.mockito.Answers +org.mockito.Mock$Strictness +org.mockito.invocation.InvocationOnMock +org.mockito.internal.stubbing.defaultanswers.GloballyConfiguredAnswer +org.mockito.internal.stubbing.defaultanswers.ReturnsSmartNulls +org.mockito.internal.stubbing.defaultanswers.RetrieveGenericsForDefaultAnswers$AnswerCallback +org.mockito.internal.stubbing.defaultanswers.ReturnsMoreEmptyValues +org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues +org.mockito.internal.stubbing.defaultanswers.ReturnsMocks +org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs +org.mockito.invocation.DescribedInvocation +org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs$ReturnsDeepStubsSerializationFallback +org.mockito.stubbing.ValidableAnswer +org.mockito.internal.stubbing.answers.CallsRealMethods +org.mockito.exceptions.base.MockitoException +org.mockito.internal.stubbing.defaultanswers.TriesToReturnSelf +jdk.proxy2.$Proxy21 +com.fasterxml.jackson.core.TokenStreamFactory +com.fasterxml.jackson.core.JsonFactory +com.fasterxml.jackson.databind.MappingJsonFactory +com.fasterxml.jackson.databind.jsontype.SubtypeResolver +com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver +com.fasterxml.jackson.databind.DatabindContext +com.fasterxml.jackson.databind.SerializerProvider +com.fasterxml.jackson.databind.ser.DefaultSerializerProvider +com.fasterxml.jackson.databind.ser.DefaultSerializerProvider$Impl +com.fasterxml.jackson.databind.deser.DeserializerFactory +com.fasterxml.jackson.databind.deser.BasicDeserializerFactory +com.fasterxml.jackson.databind.deser.BeanDeserializerFactory +com.fasterxml.jackson.databind.DeserializationContext +com.fasterxml.jackson.databind.deser.DefaultDeserializationContext +com.fasterxml.jackson.databind.deser.DefaultDeserializationContext$Impl +com.fasterxml.jackson.databind.ser.SerializerFactory +com.fasterxml.jackson.databind.ser.BasicSerializerFactory +com.fasterxml.jackson.databind.ser.BeanSerializerFactory +com.fasterxml.jackson.databind.AnnotationIntrospector +com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector +com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy$Provider +com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy$Provider +com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator +com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator$Base +com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator +com.fasterxml.jackson.databind.util.StdDateFormat +com.fasterxml.jackson.databind.DatabindException +com.fasterxml.jackson.databind.JsonMappingException +com.fasterxml.jackson.core.util.BufferRecycler$Gettable +com.fasterxml.jackson.core.io.SegmentedStringWriter +com.fasterxml.jackson.core.util.ByteArrayBuilder +com.fasterxml.jackson.core.TreeNode +com.fasterxml.jackson.databind.JsonSerializable +com.fasterxml.jackson.databind.JsonSerializable$Base +com.fasterxml.jackson.databind.JsonNode +com.fasterxml.jackson.databind.node.BaseJsonNode +com.fasterxml.jackson.databind.node.ValueNode +com.fasterxml.jackson.databind.node.NullNode +com.fasterxml.jackson.databind.introspect.ClassIntrospector +com.fasterxml.jackson.databind.introspect.BasicClassIntrospector +com.fasterxml.jackson.databind.Module$SetupContext +com.fasterxml.jackson.databind.introspect.VisibilityChecker +com.fasterxml.jackson.core.JsonParser +com.fasterxml.jackson.core.base.ParserMinimalBase +com.fasterxml.jackson.databind.node.TreeTraversingParser +com.fasterxml.jackson.core.JsonGenerator +com.fasterxml.jackson.databind.util.TokenBuffer +com.fasterxml.jackson.core.type.ResolvedType +com.fasterxml.jackson.databind.JavaType +com.fasterxml.jackson.databind.type.TypeBase +com.fasterxml.jackson.databind.type.ArrayType +com.fasterxml.jackson.databind.type.CollectionLikeType +com.fasterxml.jackson.databind.type.CollectionType +com.fasterxml.jackson.databind.type.MapLikeType +com.fasterxml.jackson.databind.type.MapType +com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder +com.fasterxml.jackson.databind.exc.MismatchedInputException +com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair +com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector +com.fasterxml.jackson.databind.introspect.Annotated +com.fasterxml.jackson.databind.introspect.TypeResolutionContext +com.fasterxml.jackson.databind.introspect.AnnotatedClass +com.fasterxml.jackson.databind.introspect.AnnotatedMember +com.fasterxml.jackson.databind.introspect.VirtualAnnotatedMember +com.fasterxml.jackson.databind.util.Named +com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition +com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition +com.fasterxml.jackson.databind.BeanProperty +com.fasterxml.jackson.databind.introspect.ConcreteBeanPropertyBase +com.fasterxml.jackson.databind.ser.PropertyWriter +com.fasterxml.jackson.databind.ser.BeanPropertyWriter +com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter +com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter +com.fasterxml.jackson.databind.introspect.AnnotatedWithParams +com.fasterxml.jackson.databind.introspect.AnnotatedMethod +com.fasterxml.jackson.databind.annotation.JsonSerialize +com.fasterxml.jackson.annotation.JsonView +com.fasterxml.jackson.annotation.JsonFormat +com.fasterxml.jackson.annotation.JsonTypeInfo +com.fasterxml.jackson.annotation.JsonRawValue +com.fasterxml.jackson.annotation.JsonUnwrapped +com.fasterxml.jackson.annotation.JsonBackReference +com.fasterxml.jackson.annotation.JsonManagedReference +com.fasterxml.jackson.databind.annotation.JsonDeserialize +com.fasterxml.jackson.annotation.JsonMerge +com.fasterxml.jackson.databind.ext.Java7Support +java.lang.IllegalAccessError +com.fasterxml.jackson.databind.ext.Java7SupportImpl +com.fasterxml.jackson.databind.util.ClassUtil +com.fasterxml.jackson.databind.util.ClassUtil$Ctor +java.lang.reflect.AnnotatedType +java.beans.Transient +java.beans.ConstructorProperties +com.fasterxml.jackson.databind.util.LookupCache +com.fasterxml.jackson.databind.util.LRUMap +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$Builder +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap +java.io.InvalidObjectException +com.fasterxml.jackson.databind.util.internal.Linked +com.fasterxml.jackson.databind.util.internal.LinkedDeque +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$1 +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$2 +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$3 +java.util.concurrent.atomic.AtomicLongArray +java.lang.invoke.VarHandleLongs$Array +java.util.concurrent.atomic.AtomicReferenceArray +java.lang.invoke.VarHandleReferences$Array +com.fasterxml.jackson.databind.cfg.BaseSettings +com.fasterxml.jackson.databind.type.TypeFactory +com.fasterxml.jackson.databind.type.SimpleType +com.fasterxml.jackson.databind.type.IdentityEqualityType +com.fasterxml.jackson.databind.type.PlaceholderForType +com.fasterxml.jackson.databind.type.ReferenceType +com.fasterxml.jackson.databind.type.IterationType +com.fasterxml.jackson.databind.type.ResolvedRecursiveType +com.fasterxml.jackson.databind.type.TypeParser +com.fasterxml.jackson.databind.type.TypeBindings +java.text.ParseException +com.fasterxml.jackson.core.Base64Variants +com.fasterxml.jackson.core.Base64Variant +com.fasterxml.jackson.core.Base64Variant$PaddingReadBehaviour +com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy +com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy +com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy$RecordNaming +com.fasterxml.jackson.databind.cfg.CacheProvider +com.fasterxml.jackson.databind.cfg.DefaultCacheProvider +com.fasterxml.jackson.core.io.DataOutputAsStream +com.fasterxml.jackson.core.SerializableString +com.fasterxml.jackson.core.TSFBuilder +com.fasterxml.jackson.core.JsonFactoryBuilder +java.io.CharArrayReader +com.fasterxml.jackson.core.async.NonBlockingInputFeeder +com.fasterxml.jackson.core.async.ByteBufferFeeder +com.fasterxml.jackson.core.base.ParserBase +com.fasterxml.jackson.core.json.JsonParserBase +com.fasterxml.jackson.core.json.async.NonBlockingJsonParserBase +com.fasterxml.jackson.core.json.async.NonBlockingUtf8JsonParserBase +com.fasterxml.jackson.core.json.async.NonBlockingByteBufferJsonParser +com.fasterxml.jackson.core.json.ReaderBasedJsonParser +com.fasterxml.jackson.core.json.UTF8DataInputJsonParser +com.fasterxml.jackson.core.base.GeneratorBase +com.fasterxml.jackson.core.json.JsonGeneratorImpl +com.fasterxml.jackson.core.json.WriterBasedJsonGenerator +com.fasterxml.jackson.core.json.UTF8JsonGenerator +com.fasterxml.jackson.core.io.UTF8Writer +com.fasterxml.jackson.core.async.ByteArrayFeeder +com.fasterxml.jackson.core.json.async.NonBlockingJsonParser +com.fasterxml.jackson.core.util.JacksonFeature +com.fasterxml.jackson.core.JsonFactory$Feature +com.fasterxml.jackson.core.JsonParser$Feature +com.fasterxml.jackson.core.JsonGenerator$Feature +com.fasterxml.jackson.core.io.SerializedString +com.fasterxml.jackson.core.io.JsonStringEncoder +com.fasterxml.jackson.core.io.CharTypes +com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer +com.fasterxml.jackson.core.exc.StreamConstraintsException +com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer$TableInfo +com.fasterxml.jackson.core.util.JsonRecyclerPools +com.fasterxml.jackson.core.util.RecyclerPool +com.fasterxml.jackson.core.util.RecyclerPool$ThreadLocalPoolBase +com.fasterxml.jackson.core.util.JsonRecyclerPools$ThreadLocalPool +com.fasterxml.jackson.core.util.RecyclerPool$WithPool +com.fasterxml.jackson.core.StreamReadConstraints +com.fasterxml.jackson.core.StreamWriteConstraints +com.fasterxml.jackson.core.ErrorReportConfiguration +com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer +com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer$TableInfo +com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer$Bucket +com.fasterxml.jackson.databind.util.RootNameLookup +com.fasterxml.jackson.databind.introspect.ClassIntrospector$MixInResolver +com.fasterxml.jackson.databind.introspect.SimpleMixInResolver +com.fasterxml.jackson.databind.BeanDescription +com.fasterxml.jackson.databind.introspect.BasicBeanDescription +com.fasterxml.jackson.databind.cfg.MapperConfig +com.fasterxml.jackson.databind.cfg.MapperConfigBase +com.fasterxml.jackson.databind.SerializationConfig +com.fasterxml.jackson.databind.DeserializationConfig +com.fasterxml.jackson.databind.introspect.AnnotatedClassResolver +com.fasterxml.jackson.databind.introspect.AnnotationCollector +com.fasterxml.jackson.databind.util.Annotations +com.fasterxml.jackson.databind.introspect.AnnotationCollector$EmptyCollector +com.fasterxml.jackson.databind.introspect.AnnotationCollector$NoAnnotations +com.fasterxml.jackson.databind.introspect.AnnotatedClass$Creators +com.fasterxml.jackson.databind.introspect.AnnotatedConstructor +com.fasterxml.jackson.databind.cfg.ConfigOverrides +com.fasterxml.jackson.annotation.JacksonAnnotationValue +com.fasterxml.jackson.annotation.JsonInclude$Value +com.fasterxml.jackson.annotation.JsonInclude$Include +com.fasterxml.jackson.annotation.JsonSetter$Value +com.fasterxml.jackson.annotation.Nulls +com.fasterxml.jackson.databind.introspect.VisibilityChecker$Std +com.fasterxml.jackson.annotation.JsonAutoDetect$Visibility +com.fasterxml.jackson.databind.cfg.CoercionConfigs +com.fasterxml.jackson.databind.type.LogicalType +com.fasterxml.jackson.databind.cfg.CoercionAction +com.fasterxml.jackson.databind.cfg.CoercionConfig +com.fasterxml.jackson.databind.cfg.MutableCoercionConfig +com.fasterxml.jackson.databind.cfg.CoercionInputShape +com.fasterxml.jackson.databind.jsontype.DefaultBaseTypeLimitingValidator +com.fasterxml.jackson.core.PrettyPrinter +com.fasterxml.jackson.annotation.JsonFormat$Value +com.fasterxml.jackson.annotation.JsonFormat$Shape +com.fasterxml.jackson.annotation.JsonFormat$Features +com.fasterxml.jackson.databind.cfg.ConfigOverride +com.fasterxml.jackson.databind.cfg.ConfigOverride$Empty +com.fasterxml.jackson.databind.cfg.ConfigFeature +com.fasterxml.jackson.databind.MapperFeature +com.fasterxml.jackson.core.util.Instantiatable +com.fasterxml.jackson.core.util.DefaultPrettyPrinter +com.fasterxml.jackson.core.util.DefaultPrettyPrinter$Indenter +com.fasterxml.jackson.core.util.Separators +com.fasterxml.jackson.core.util.Separators$Spacing +com.fasterxml.jackson.core.util.DefaultPrettyPrinter$NopIndenter +com.fasterxml.jackson.core.util.DefaultPrettyPrinter$FixedSpaceIndenter +com.fasterxml.jackson.core.util.DefaultIndenter +com.fasterxml.jackson.databind.SerializationFeature +com.fasterxml.jackson.databind.cfg.DatatypeFeatures +com.fasterxml.jackson.databind.cfg.DatatypeFeatures$DefaultHolder +com.fasterxml.jackson.databind.cfg.DatatypeFeature +com.fasterxml.jackson.databind.cfg.EnumFeature +com.fasterxml.jackson.databind.cfg.JsonNodeFeature +com.fasterxml.jackson.databind.cfg.ContextAttributes +com.fasterxml.jackson.databind.cfg.ContextAttributes$Impl +com.fasterxml.jackson.databind.DeserializationFeature +com.fasterxml.jackson.databind.node.JsonNodeCreator +com.fasterxml.jackson.databind.node.JsonNodeFactory +com.fasterxml.jackson.databind.node.MissingNode +com.fasterxml.jackson.databind.node.BooleanNode +com.fasterxml.jackson.databind.node.NumericNode +com.fasterxml.jackson.databind.node.DoubleNode +com.fasterxml.jackson.databind.node.DecimalNode +com.fasterxml.jackson.databind.node.IntNode +com.fasterxml.jackson.databind.node.ShortNode +com.fasterxml.jackson.databind.node.BigIntegerNode +com.fasterxml.jackson.databind.node.LongNode +com.fasterxml.jackson.databind.node.FloatNode +com.fasterxml.jackson.databind.node.TextNode +com.fasterxml.jackson.databind.node.BinaryNode +com.fasterxml.jackson.databind.node.POJONode +com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable +com.fasterxml.jackson.databind.JsonSerializer +com.fasterxml.jackson.databind.jsonschema.SchemaAware +com.fasterxml.jackson.databind.ser.std.StdSerializer +com.fasterxml.jackson.databind.ser.std.NullSerializer +com.fasterxml.jackson.databind.ser.impl.FailingSerializer +com.fasterxml.jackson.databind.ser.std.ToEmptyObjectSerializer +com.fasterxml.jackson.databind.ser.impl.UnknownSerializer +com.fasterxml.jackson.databind.ser.ContextualSerializer +com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer +com.fasterxml.jackson.databind.exc.InvalidDefinitionException +com.fasterxml.jackson.databind.exc.InvalidTypeIdException +com.fasterxml.jackson.databind.node.ContainerNode +com.fasterxml.jackson.databind.node.ObjectNode +com.fasterxml.jackson.databind.ser.ResolvableSerializer +com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer +com.fasterxml.jackson.databind.ser.SerializerCache +com.fasterxml.jackson.databind.deser.NullValueProvider +com.fasterxml.jackson.databind.JsonDeserializer +com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer +com.fasterxml.jackson.databind.exc.PropertyBindingException +com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException +com.fasterxml.jackson.databind.exc.InvalidFormatException +com.fasterxml.jackson.databind.exc.ValueInstantiationException +com.fasterxml.jackson.databind.exc.MissingInjectableValueExcepion +com.fasterxml.jackson.databind.deser.UnresolvedForwardReference +com.fasterxml.jackson.databind.deser.ContextualDeserializer +com.fasterxml.jackson.databind.deser.ResolvableDeserializer +com.fasterxml.jackson.databind.deser.ValueInstantiator$Gettable +com.fasterxml.jackson.databind.deser.std.StdDeserializer +com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase +com.fasterxml.jackson.databind.deser.std.EnumMapDeserializer +com.fasterxml.jackson.databind.deser.std.MapDeserializer +com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer +com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer +com.fasterxml.jackson.databind.deser.std.StringDeserializer +com.fasterxml.jackson.databind.deser.std.MapEntryDeserializer +com.fasterxml.jackson.databind.deser.std.TokenBufferDeserializer +com.fasterxml.jackson.databind.introspect.AnnotatedParameter +com.fasterxml.jackson.databind.deser.SettableBeanProperty +com.fasterxml.jackson.databind.deser.CreatorProperty +com.fasterxml.jackson.databind.deser.AbstractDeserializer +com.fasterxml.jackson.databind.deser.std.EnumDeserializer +com.fasterxml.jackson.databind.deser.std.ReferenceTypeDeserializer +com.fasterxml.jackson.databind.deser.std.AtomicReferenceDeserializer +com.fasterxml.jackson.databind.deser.std.StringArrayDeserializer +com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer +com.fasterxml.jackson.databind.deser.std.EnumSetDeserializer +com.fasterxml.jackson.databind.deser.std.CollectionDeserializer +com.fasterxml.jackson.databind.deser.std.ArrayBlockingQueueDeserializer +com.fasterxml.jackson.databind.deser.std.StringCollectionDeserializer +com.fasterxml.jackson.databind.deser.impl.MethodProperty +com.fasterxml.jackson.databind.deser.impl.FieldProperty +com.fasterxml.jackson.databind.deser.impl.SetterlessProperty +com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer +com.fasterxml.jackson.databind.deser.impl.ErrorThrowingDeserializer +com.fasterxml.jackson.annotation.ObjectIdGenerator +com.fasterxml.jackson.annotation.ObjectIdGenerators$Base +com.fasterxml.jackson.annotation.ObjectIdGenerators$PropertyGenerator +com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator +com.fasterxml.jackson.databind.deser.BeanDeserializerBase +com.fasterxml.jackson.databind.deser.BeanDeserializer +com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer +com.fasterxml.jackson.databind.deser.Deserializers +com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig +com.fasterxml.jackson.databind.deser.BeanDeserializerModifier +com.fasterxml.jackson.databind.AbstractTypeResolver +com.fasterxml.jackson.databind.deser.ValueInstantiators +com.fasterxml.jackson.databind.deser.KeyDeserializers +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializers +com.fasterxml.jackson.databind.KeyDeserializer +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$DelegatingKD +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$EnumKD +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringCtorKeyDeserializer +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringFactoryKeyDeserializer +com.fasterxml.jackson.databind.deser.DeserializerCache +com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer +com.fasterxml.jackson.databind.ser.std.JsonValueSerializer +com.fasterxml.jackson.databind.ser.std.SerializableSerializer +com.fasterxml.jackson.databind.ser.std.StdScalarSerializer +com.fasterxml.jackson.databind.ser.std.DateTimeSerializerBase +com.fasterxml.jackson.databind.ser.std.CalendarSerializer +com.fasterxml.jackson.databind.ser.std.DateSerializer +com.fasterxml.jackson.databind.ser.std.ByteBufferSerializer +com.fasterxml.jackson.databind.ser.std.InetAddressSerializer +com.fasterxml.jackson.databind.ser.std.InetSocketAddressSerializer +com.fasterxml.jackson.databind.ser.std.TimeZoneSerializer +com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase +com.fasterxml.jackson.databind.ser.std.ToStringSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializer +com.fasterxml.jackson.databind.ser.ContainerSerializer +com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase +com.fasterxml.jackson.databind.ser.std.CollectionSerializer +com.fasterxml.jackson.databind.ser.std.StaticListSerializerBase +com.fasterxml.jackson.databind.ser.impl.IndexedStringListSerializer +com.fasterxml.jackson.databind.ser.impl.StringCollectionSerializer +com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer +com.fasterxml.jackson.databind.ser.std.EnumSetSerializer +com.fasterxml.jackson.databind.ser.std.MapSerializer +com.fasterxml.jackson.databind.ser.impl.MapEntrySerializer +com.fasterxml.jackson.databind.ser.std.ArraySerializerBase +com.fasterxml.jackson.databind.ser.impl.StringArraySerializer +com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer +com.fasterxml.jackson.databind.ser.std.ReferenceTypeSerializer +com.fasterxml.jackson.databind.ser.impl.IteratorSerializer +com.fasterxml.jackson.databind.ser.std.IterableSerializer +com.fasterxml.jackson.databind.ser.std.EnumSerializer +com.fasterxml.jackson.databind.ser.impl.MapEntryAsPOJOSerializer +com.fasterxml.jackson.databind.ser.std.BeanSerializerBase +com.fasterxml.jackson.databind.ser.BeanSerializer +com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator +com.fasterxml.jackson.databind.introspect.AnnotatedField +com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer +com.fasterxml.jackson.databind.ser.std.StringSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers +com.fasterxml.jackson.databind.ser.std.NumberSerializers$Base +com.fasterxml.jackson.databind.ser.std.NumberSerializers$IntegerSerializer +com.fasterxml.jackson.core.JsonParser$NumberType +com.fasterxml.jackson.databind.ser.std.NumberSerializers$LongSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$IntLikeSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$ShortSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$DoubleSerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$FloatSerializer +com.fasterxml.jackson.databind.ser.std.BooleanSerializer +com.fasterxml.jackson.databind.ser.std.BooleanSerializer$AsNumber +com.fasterxml.jackson.databind.ser.std.NumberSerializer$BigDecimalAsStringSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers +java.util.Currency +java.util.UUID +com.fasterxml.jackson.databind.ser.std.UUIDSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicBooleanSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicIntegerSerializer +com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicLongSerializer +com.fasterxml.jackson.databind.ser.std.FileSerializer +com.fasterxml.jackson.databind.ser.std.ClassSerializer +com.fasterxml.jackson.databind.ser.std.TokenBufferSerializer +com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig +com.fasterxml.jackson.databind.ser.Serializers +com.fasterxml.jackson.databind.ser.BeanSerializerModifier +org.mockito.junit.jupiter.MockitoSettings +org.mockito.junit.jupiter.MockitoExtension$$Lambda$646/0x00007f42041f8000 +org.mockito.ArgumentMatchers +org.mockito.Mockito +org.mockito.ArgumentMatcher +org.mockito.verification.VerificationMode +org.mockito.verification.VerificationAfterDelay +org.mockito.verification.VerificationWithTimeout +org.mockito.session.MockitoSessionBuilder +org.mockito.MockitoFramework +org.mockito.internal.MockitoCore +org.mockito.stubbing.BaseStubber +org.mockito.stubbing.LenientStubber +org.mockito.MockingDetails +org.mockito.ScopedMock +org.mockito.MockedStatic +org.mockito.MockedConstruction +org.mockito.exceptions.misusing.NotAMockException +org.mockito.internal.verification.api.VerificationData +org.mockito.stubbing.Stubber +org.mockito.InOrder +org.mockito.exceptions.misusing.DoNotMockException +org.mockito.internal.verification.api.VerificationDataInOrder +org.mockito.internal.configuration.plugins.Plugins +org.mockito.plugins.MockitoPlugins +org.mockito.internal.configuration.plugins.PluginRegistry +org.mockito.plugins.PluginSwitch +org.mockito.internal.configuration.plugins.PluginLoader +org.mockito.internal.configuration.plugins.DefaultPluginSwitch +org.mockito.internal.configuration.plugins.DefaultMockitoPlugins +org.mockito.plugins.MockMaker +org.mockito.plugins.StackTraceCleanerProvider +org.mockito.plugins.InstantiatorProvider2 +org.mockito.plugins.AnnotationEngine +org.mockito.plugins.MockitoLogger +org.mockito.plugins.MemberAccessor +org.mockito.plugins.DoNotMockEnforcerWithType +org.mockito.internal.configuration.plugins.PluginInitializer +org.mockito.internal.configuration.plugins.PluginFinder +org.mockito.internal.util.collections.Iterables +org.mockito.internal.creation.bytebuddy.ClassCreatingMockMaker +org.mockito.plugins.InlineMockMaker +org.mockito.creation.instance.Instantiator +org.mockito.internal.creation.bytebuddy.InlineByteBuddyMockMaker +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker +org.mockito.exceptions.base.MockitoInitializationException +org.mockito.internal.creation.bytebuddy.BytecodeGenerator +org.mockito.creation.instance.InstantiationException +org.mockito.exceptions.misusing.MockitoConfigurationException +org.mockito.plugins.MockMaker$TypeMockability +org.mockito.plugins.MockMaker$StaticMockControl +org.mockito.plugins.MockMaker$ConstructionMockControl +org.mockito.internal.PremainAttachAccess +org.mockito.internal.PremainAttach +java.lang.instrument.Instrumentation +net.bytebuddy.agent.Installer +java.io.Console +net.bytebuddy.ClassFileVersion +net.bytebuddy.ClassFileVersion$VersionLocator$Resolver +net.bytebuddy.ClassFileVersion$VersionLocator +net.bytebuddy.ClassFileVersion$VersionLocator$Resolved +java.lang.Process +net.bytebuddy.agent.ByteBuddyAgent +net.bytebuddy.agent.ByteBuddyAgent$AgentProvider +net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider +net.bytebuddy.agent.ByteBuddyAgent$AttachmentTypeEvaluator$InstallationAction +net.bytebuddy.agent.ByteBuddyAgent$AttachmentTypeEvaluator +java.security.PrivilegedActionException +com.sun.proxy.jdk.proxy1.$Proxy22 +java.security.DomainCombiner +net.bytebuddy.agent.ByteBuddyAgent$AttachmentTypeEvaluator$ForJava9CapableVm +java.lang.ProcessHandle +java.lang.ProcessHandle$Info +java.util.concurrent.CompletionStage +java.util.concurrent.CompletableFuture +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Compound +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Accessor +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$ForModularizedVm +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$ForJ9Vm +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$ForStandardToolsJarVm +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$ForUserDefinedToolsJar +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$ForEmulatedAttachment +net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider$ForCurrentVm +net.bytebuddy.agent.ByteBuddyAgent$ProcessProvider$ForCurrentVm$ForJava9CapableVm +java.lang.ProcessHandleImpl +java.lang.ProcessHandleImpl$$Lambda$647/0x00007f420410ced8 +java.util.concurrent.ThreadLocalRandom +jdk.internal.util.random.RandomSupport +java.lang.invoke.LambdaForm$DMH/0x00007f4204204000 +java.lang.invoke.LambdaForm$DMH/0x00007f4204204400 +java.lang.ProcessHandleImpl$$Lambda$648/0x00007f420410d0f8 +java.lang.invoke.LambdaForm$DMH/0x00007f4204204800 +java.lang.invoke.LambdaForm$MH/0x00007f4204204c00 +java.util.concurrent.SynchronousQueue +java.util.concurrent.SynchronousQueue$Transferer +java.util.concurrent.SynchronousQueue$TransferStack +java.util.concurrent.SynchronousQueue$TransferStack$SNode +net.bytebuddy.agent.ByteBuddyAgent$AgentProvider$ForByteBuddyAgent +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Accessor$Simple +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Accessor$Simple$WithExternalAttachment +com.sun.tools.attach.VirtualMachine +net.bytebuddy.agent.ByteBuddyAgent$AttachmentProvider$Accessor$ExternalAttachment +java.util.zip.ZipInputStream +java.util.jar.JarInputStream +java.io.PushbackInputStream +sun.security.util.ManifestEntryVerifier +net.bytebuddy.agent.Attacher +java.lang.ProcessBuilder +java.lang.ProcessImpl +java.lang.ProcessImpl$Platform +java.lang.ProcessImpl$LaunchMechanism +java.lang.ProcessImpl$Platform$$Lambda$649/0x00007f420410f8c8 +java.lang.ProcessImpl$$Lambda$650/0x00007f420410faf0 +java.lang.ProcessImpl$1 +java.lang.ProcessImpl$ProcessPipeOutputStream +java.lang.ProcessImpl$ProcessPipeInputStream +java.lang.Process$PipeInputStream +java.lang.ProcessHandleImpl$ExitCompletion +java.util.concurrent.CompletableFuture$AltResult +java.util.concurrent.ForkJoinPool +java.lang.invoke.VarHandleLongs$FieldInstanceReadOnly +java.lang.invoke.VarHandleLongs$FieldInstanceReadWrite +java.lang.invoke.VarHandleInts$FieldStaticReadOnly +java.lang.invoke.VarHandleInts$FieldStaticReadWrite +java.util.concurrent.ForkJoinPool$ForkJoinWorkerThreadFactory +java.util.concurrent.ForkJoinPool$DefaultForkJoinWorkerThreadFactory +java.util.concurrent.ForkJoinPool$1 +java.util.concurrent.ForkJoinPool$DefaultCommonPoolForkJoinWorkerThreadFactory +java.util.concurrent.ForkJoinPool$WorkQueue +java.util.concurrent.CompletableFuture$AsynchronousCompletionTask +java.util.concurrent.ForkJoinTask +java.util.concurrent.CompletableFuture$Completion +java.lang.ProcessHandleImpl$1 +java.lang.ProcessImpl$$Lambda$651/0x00007f4204111920 +java.util.concurrent.CompletableFuture$UniCompletion +java.util.concurrent.CompletableFuture$UniHandle +java.util.concurrent.ForkJoinTask$Aux +jdk.internal.event.Event +jdk.internal.event.ProcessStartEvent +sun.instrument.InstrumentationImpl +sun.instrument.TransformerManager +sun.instrument.TransformerManager$TransformerInfo +java.lang.ProcessBuilder$NullInputStream +java.io.FileOutputStream$1 +java.lang.ProcessBuilder$NullOutputStream +java.io.File$TempDirectory +java.security.SecureRandom +sun.security.jca.Providers +sun.security.jca.ProviderList +sun.security.jca.ProviderConfig +java.security.Provider +sun.security.jca.ProviderList$3 +sun.security.jca.ProviderList$1 +java.security.Provider$ServiceKey +java.security.Provider$EngineDescription +java.security.SecureRandomParameters +java.security.cert.CertStoreParameters +java.security.Policy$Parameters +javax.security.auth.login.Configuration$Parameters +sun.security.jca.ProviderList$2 +sun.security.provider.Sun +sun.security.util.SecurityConstants +java.net.NetPermission +java.security.SecurityPermission +java.net.SocketPermission +sun.security.provider.SunEntries +sun.security.provider.SunEntries$1 +java.security.SecureRandomSpi +sun.security.provider.NativePRNG +sun.security.provider.NativePRNG$Variant +sun.security.provider.NativePRNG$1 +sun.security.provider.NativePRNG$2 +sun.security.provider.NativePRNG$RandomIO +sun.security.provider.FileInputStreamPool +sun.security.provider.FileInputStreamPool$UnclosableInputStream +sun.security.provider.FileInputStreamPool$StreamRef +java.security.Provider$Service +java.security.Provider$UString +sun.security.provider.NativePRNG$Blocking +sun.security.provider.NativePRNG$NonBlocking +sun.security.util.SecurityProviderConstants +sun.security.util.KnownOIDs +sun.security.util.KnownOIDs$1 +sun.security.util.KnownOIDs$2 +sun.security.util.KnownOIDs$3 +sun.security.util.KnownOIDs$4 +sun.security.util.KnownOIDs$5 +sun.security.util.KnownOIDs$6 +sun.security.util.KnownOIDs$7 +sun.security.util.KnownOIDs$8 +sun.security.util.KnownOIDs$9 +sun.security.util.KnownOIDs$10 +jdk.internal.event.SecurityProviderServiceEvent +sun.security.provider.SecureRandom +java.security.MessageDigestSpi +java.security.MessageDigest +sun.security.jca.GetInstance +sun.security.provider.DigestBase +sun.security.provider.SHA +sun.security.jca.GetInstance$Instance +sun.security.util.MessageDigestSpi2 +java.security.MessageDigest$Delegate +java.security.MessageDigest$Delegate$CloneableDelegate +sun.security.provider.ByteArrayAccess +sun.security.provider.ByteArrayAccess$BE +java.lang.invoke.VarHandleByteArrayAsInts$ByteArrayViewVarHandle +java.lang.invoke.VarHandleByteArrayAsInts$ArrayHandle +java.lang.ArrayIndexOutOfBoundsException +java.lang.invoke.VarHandleByteArrayBase +java.lang.invoke.VarHandleByteArrayAsInts +java.lang.invoke.VarHandleByteArrayAsInts$ArrayHandle$$Lambda$652/0x00007f420411ea70 +java.lang.invoke.VarHandleByteArrayAsLongs$ByteArrayViewVarHandle +java.lang.invoke.VarHandleByteArrayAsLongs$ArrayHandle +java.lang.invoke.VarHandleByteArrayAsLongs +java.lang.invoke.VarHandleByteArrayAsLongs$ArrayHandle$$Lambda$653/0x00007f420411f3d8 +java.lang.invoke.VarHandle$TypesAndInvokers +java.lang.invoke.VarHandle$2 +java.lang.invoke.VarHandle$VarHandleDesc$Kind +java.lang.constant.ConstantDescs +java.lang.constant.ClassDesc +java.lang.constant.ConstantUtils +java.lang.constant.ReferenceClassDescImpl +java.lang.constant.DirectMethodHandleDesc$Kind +java.lang.constant.MethodTypeDesc +java.lang.constant.MethodTypeDescImpl +java.lang.constant.MethodHandleDesc +java.lang.constant.MethodHandleDesc$1 +java.lang.constant.DirectMethodHandleDesc +java.lang.constant.DirectMethodHandleDescImpl +java.lang.constant.DirectMethodHandleDescImpl$1 +java.lang.constant.DirectMethodHandleDesc$1 +java.lang.constant.DynamicConstantDesc +java.lang.constant.PrimitiveClassDescImpl +java.lang.constant.DynamicConstantDesc$AnonymousDynamicConstantDesc +java.io.DeleteOnExitHook +java.io.DeleteOnExitHook$1 +java.util.zip.DeflaterOutputStream +java.util.zip.ZipOutputStream +java.util.jar.JarOutputStream +java.util.zip.Deflater +java.util.zip.Deflater$DeflaterZStreamRef +java.util.zip.ZipOutputStream$XEntry +java.util.Vector$Itr +opened:/tmp/mockitoboot10528763096709983050.jar +org.mockito.internal.creation.bytebuddy.inject.MockMethodDispatcher +org.mockito.internal.util.concurrent.WeakConcurrentMap +org.mockito.internal.util.concurrent.DetachedThreadLocal +org.mockito.internal.util.concurrent.DetachedThreadLocal$1 +org.mockito.internal.util.concurrent.WeakConcurrentMap$WithInlinedExpunction +org.mockito.internal.util.concurrent.DetachedThreadLocal$2 +org.mockito.internal.util.concurrent.DetachedThreadLocal$Cleaner +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$$Lambda$654/0x00007f42042076e0 +java.lang.ThreadLocal$SuppliedThreadLocal +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$$Lambda$655/0x00007f4204207900 +org.mockito.internal.creation.bytebuddy.StackWalkerChecker +java.lang.StackWalker$Option +java.lang.invoke.LambdaForm$DMH/0x00007f4204205000 +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$$Lambda$656/0x00007f4204207d88 +org.mockito.internal.creation.bytebuddy.ConstructionCallback +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$$Lambda$657/0x00007f4204205a00 +org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator +net.bytebuddy.matcher.ElementMatcher +net.bytebuddy.TypeCache +net.bytebuddy.TypeCache$WithInlineExpunction +java.lang.instrument.ClassFileTransformer +org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator +net.bytebuddy.implementation.Implementation$Context$Factory +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler +net.bytebuddy.dynamic.scaffold.InstrumentedType$Prepareable +net.bytebuddy.implementation.Implementation +net.bytebuddy.asm.AsmVisitorWrapper +org.mockito.internal.creation.bytebuddy.MockMethodAdvice +java.lang.instrument.UnmodifiableClassException +net.bytebuddy.ByteBuddy +net.bytebuddy.NamingStrategy +net.bytebuddy.implementation.auxiliary.AuxiliaryType$NamingStrategy +net.bytebuddy.matcher.LatentMatcher +net.bytebuddy.utility.AsmClassWriter$Factory +net.bytebuddy.utility.AsmClassReader$Factory +net.bytebuddy.dynamic.VisibilityBridgeStrategy +net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory +net.bytebuddy.implementation.attribute.AnnotationValueFilter$Factory +net.bytebuddy.NamingStrategy$Suffixing$BaseNameResolver +net.bytebuddy.dynamic.DynamicType$Builder +net.bytebuddy.description.NamedElement +net.bytebuddy.description.ModifierReviewable +net.bytebuddy.description.ModifierReviewable$OfByteCodeElement +net.bytebuddy.description.ModifierReviewable$OfAbstraction +net.bytebuddy.description.ModifierReviewable$OfEnumeration +net.bytebuddy.description.ModifierReviewable$ForTypeDefinition +net.bytebuddy.description.type.TypeDefinition +net.bytebuddy.matcher.FilterableList +net.bytebuddy.description.type.TypeList$Generic +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy +net.bytebuddy.description.NamedElement$WithRuntimeName +net.bytebuddy.description.annotation.AnnotationSource +net.bytebuddy.description.type.PackageDescription +net.bytebuddy.description.NamedElement$WithDescriptor +net.bytebuddy.description.DeclaredByType +net.bytebuddy.description.ByteCodeElement +net.bytebuddy.description.TypeVariableSource +net.bytebuddy.description.type.TypeDescription +net.bytebuddy.utility.privilege.GetSystemPropertyAction +net.bytebuddy.dynamic.scaffold.TypeValidation +net.bytebuddy.utility.GraalImageCode +net.bytebuddy.NamingStrategy$AbstractBase +net.bytebuddy.NamingStrategy$Suffixing +net.bytebuddy.NamingStrategy$SuffixingRandom +net.bytebuddy.NamingStrategy$Suffixing$BaseNameResolver$ForUnnamedType +net.bytebuddy.utility.RandomString +net.bytebuddy.implementation.auxiliary.AuxiliaryType$NamingStrategy$SuffixingRandom +net.bytebuddy.implementation.attribute.AnnotationValueFilter +net.bytebuddy.implementation.attribute.AnnotationValueFilter$Default +net.bytebuddy.implementation.attribute.AnnotationValueFilter$Default$1 +net.bytebuddy.implementation.attribute.AnnotationValueFilter$Default$2 +net.bytebuddy.implementation.attribute.AnnotationRetention +net.bytebuddy.implementation.Implementation$Context$Default$Factory +net.bytebuddy.implementation.MethodAccessorFactory +net.bytebuddy.implementation.Implementation$Context +net.bytebuddy.implementation.Implementation$Context$ExtractableView +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$AbstractBase +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default +net.bytebuddy.dynamic.scaffold.MethodGraph +net.bytebuddy.dynamic.scaffold.MethodGraph$Linked +net.bytebuddy.description.type.TypeDescription$Generic$Visitor +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Merger +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Harmonizer +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Harmonizer$ForJavaMethod +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Merger$Directional +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Reifying +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Reifying$1 +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Reifying$2 +net.bytebuddy.description.type.TypeDescription$Generic +net.bytebuddy.matcher.ElementMatchers +net.bytebuddy.matcher.ElementMatcher$Junction +net.bytebuddy.description.ModifierReviewable$ForMethodDescription +net.bytebuddy.description.DeclaredByType$WithMandatoryDeclaration +net.bytebuddy.description.NamedElement$WithGenericName +net.bytebuddy.description.ByteCodeElement$Member +net.bytebuddy.description.ByteCodeElement$TypeDependant +net.bytebuddy.description.method.MethodDescription +net.bytebuddy.description.method.MethodDescription$InDefinedShape +net.bytebuddy.description.ModifierReviewable$ForFieldDescription +net.bytebuddy.description.field.FieldDescription +net.bytebuddy.description.field.FieldDescription$InDefinedShape +net.bytebuddy.matcher.ElementMatcher$Junction$AbstractBase +net.bytebuddy.matcher.BooleanMatcher +net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory$Default +net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory$Default$1 +net.bytebuddy.dynamic.scaffold.InstrumentedType$Factory$Default$2 +net.bytebuddy.implementation.LoadedTypeInitializer +net.bytebuddy.implementation.bytecode.ByteCodeAppender +net.bytebuddy.dynamic.scaffold.TypeInitializer +net.bytebuddy.dynamic.scaffold.InstrumentedType +net.bytebuddy.dynamic.scaffold.InstrumentedType$WithFlexibleName +net.bytebuddy.dynamic.VisibilityBridgeStrategy$Default +net.bytebuddy.dynamic.VisibilityBridgeStrategy$Default$1 +net.bytebuddy.dynamic.VisibilityBridgeStrategy$Default$2 +net.bytebuddy.dynamic.VisibilityBridgeStrategy$Default$3 +net.bytebuddy.utility.AsmClassReader$Factory$Default +net.bytebuddy.utility.AsmClassReader$Factory$Default$1 +net.bytebuddy.utility.AsmClassReader$Factory$Default$2 +net.bytebuddy.utility.AsmClassReader$Factory$Default$3 +net.bytebuddy.utility.AsmClassReader$Factory$Default$4 +net.bytebuddy.utility.AsmClassReader$Factory$Default$5 +net.bytebuddy.utility.AsmClassReader +net.bytebuddy.utility.AsmClassWriter$Factory$Default +net.bytebuddy.utility.AsmClassWriter$Factory$Default$1 +net.bytebuddy.utility.AsmClassWriter$Factory$Default$2 +net.bytebuddy.utility.AsmClassWriter$Factory$Default$3 +net.bytebuddy.utility.AsmClassWriter$Factory$Default$4 +net.bytebuddy.utility.AsmClassWriter$Factory$Default$5 +net.bytebuddy.pool.TypePool +net.bytebuddy.jar.asm.ClassVisitor +net.bytebuddy.jar.asm.ClassWriter +net.bytebuddy.utility.AsmClassWriter$FrameComputingClassWriter +net.bytebuddy.utility.AsmClassWriter +net.bytebuddy.matcher.LatentMatcher$Resolved +net.bytebuddy.matcher.ModifierMatcher$Mode +net.bytebuddy.matcher.ElementMatcher$Junction$ForNonNullValues +net.bytebuddy.matcher.ModifierMatcher +net.bytebuddy.matcher.NameMatcher +net.bytebuddy.matcher.StringMatcher +net.bytebuddy.matcher.StringMatcher$Mode +net.bytebuddy.matcher.StringMatcher$Mode$1 +net.bytebuddy.matcher.StringMatcher$Mode$2 +net.bytebuddy.matcher.StringMatcher$Mode$3 +net.bytebuddy.matcher.StringMatcher$Mode$4 +net.bytebuddy.matcher.StringMatcher$Mode$5 +net.bytebuddy.matcher.StringMatcher$Mode$6 +net.bytebuddy.matcher.StringMatcher$Mode$7 +net.bytebuddy.matcher.StringMatcher$Mode$8 +net.bytebuddy.matcher.StringMatcher$Mode$9 +net.bytebuddy.matcher.MethodParametersMatcher +net.bytebuddy.matcher.CollectionSizeMatcher +net.bytebuddy.matcher.ElementMatcher$Junction$Conjunction +net.bytebuddy.description.ModifierReviewable$ForParameterDescription +net.bytebuddy.description.ModifierReviewable$AbstractBase +net.bytebuddy.description.TypeVariableSource$AbstractBase +net.bytebuddy.description.type.TypeDescription$AbstractBase +net.bytebuddy.description.type.TypeDescription$ForLoadedType +java.lang.ClassFormatError +java.lang.reflect.GenericSignatureFormatError +net.bytebuddy.description.annotation.AnnotationList +net.bytebuddy.description.field.FieldList +net.bytebuddy.description.type.RecordComponentList +net.bytebuddy.matcher.FilterableList$Empty +net.bytebuddy.description.type.RecordComponentList$Empty +net.bytebuddy.matcher.FilterableList$AbstractBase +net.bytebuddy.description.type.RecordComponentList$AbstractBase +net.bytebuddy.description.type.RecordComponentList$ForLoadedRecordComponents +net.bytebuddy.description.method.MethodList +net.bytebuddy.description.type.TypeList +net.bytebuddy.description.type.TypeList$Empty +net.bytebuddy.description.type.TypeList$AbstractBase +net.bytebuddy.description.type.TypeList$ForLoadedTypes +net.bytebuddy.description.type.TypeDescription$ForLoadedType$Dispatcher +net.bytebuddy.utility.dispatcher.JavaDispatcher +net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher +net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader$Resolver$CreationAction +net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader$Resolver +net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader$Resolver$ForModuleSystem +net.bytebuddy.utility.dispatcher.JavaDispatcher$InvokerCreationAction +net.bytebuddy.utility.dispatcher.JavaDispatcher$DynamicClassLoader +net.bytebuddy.utility.Invoker +net.bytebuddy.jar.asm.ClassTooLargeException +net.bytebuddy.jar.asm.FieldVisitor +net.bytebuddy.jar.asm.FieldWriter +net.bytebuddy.jar.asm.AnnotationVisitor +net.bytebuddy.jar.asm.AnnotationWriter +net.bytebuddy.jar.asm.MethodVisitor +net.bytebuddy.jar.asm.MethodWriter +net.bytebuddy.jar.asm.ModuleVisitor +net.bytebuddy.jar.asm.ModuleWriter +net.bytebuddy.jar.asm.RecordComponentVisitor +net.bytebuddy.jar.asm.RecordComponentWriter +java.lang.TypeNotPresentException +net.bytebuddy.jar.asm.SymbolTable +net.bytebuddy.jar.asm.Symbol +net.bytebuddy.jar.asm.SymbolTable$Entry +net.bytebuddy.jar.asm.ByteVector +net.bytebuddy.jar.asm.Type +net.bytebuddy.utility.MethodComparator +net.bytebuddy.jar.asm.Frame +net.bytebuddy.jar.asm.CurrentFrame +net.bytebuddy.jar.asm.MethodTooLargeException +net.bytebuddy.jar.asm.Handler +net.bytebuddy.jar.asm.Attribute +net.bytebuddy.utility.Invoker$Dispatcher +net.bytebuddy.utility.dispatcher.JavaDispatcher$Proxied +net.bytebuddy.utility.dispatcher.JavaDispatcher$Defaults +jdk.proxy2.$Proxy23 +jdk.proxy2.$Proxy24 +net.bytebuddy.utility.dispatcher.JavaDispatcher$Instance +net.bytebuddy.utility.dispatcher.JavaDispatcher$Container +net.bytebuddy.utility.dispatcher.JavaDispatcher$IsStatic +net.bytebuddy.utility.dispatcher.JavaDispatcher$IsConstructor +net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher$ForNonStaticMethod +net.bytebuddy.utility.nullability.MaybeNull +jdk.proxy2.$Proxy25 +net.bytebuddy.utility.dispatcher.JavaDispatcher$ProxiedInvocationHandler +net.bytebuddy.description.type.$Proxy26 +net.bytebuddy.dynamic.TargetType +net.bytebuddy.matcher.EqualityMatcher +net.bytebuddy.matcher.ErasureMatcher +net.bytebuddy.matcher.MethodReturnTypeMatcher +net.bytebuddy.matcher.DeclaringTypeMatcher +net.bytebuddy.matcher.ElementMatcher$Junction$Disjunction +net.bytebuddy.implementation.Implementation$Context$Disabled$Factory +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$ForDeclaredMethods +net.bytebuddy.matcher.MethodSortMatcher$Sort +net.bytebuddy.matcher.MethodSortMatcher$Sort$1 +net.bytebuddy.matcher.MethodSortMatcher$Sort$2 +net.bytebuddy.matcher.MethodSortMatcher$Sort$3 +net.bytebuddy.matcher.MethodSortMatcher$Sort$4 +net.bytebuddy.matcher.MethodSortMatcher$Sort$5 +net.bytebuddy.matcher.MethodSortMatcher +net.bytebuddy.matcher.NegatingMatcher +org.mockito.internal.util.concurrent.WeakConcurrentSet +org.mockito.internal.util.concurrent.WeakConcurrentSet$Cleaner +org.mockito.internal.creation.bytebuddy.SubclassBytecodeGenerator +net.bytebuddy.implementation.attribute.MethodAttributeAppender$Factory +org.mockito.internal.creation.bytebuddy.ModuleHandler +org.mockito.internal.creation.bytebuddy.ModuleHandler$ModuleSystemFound +org.mockito.internal.creation.bytebuddy.ModuleHandler$1 +org.mockito.internal.creation.bytebuddy.ModuleHandler$NoModuleSystemFound +org.mockito.internal.creation.bytebuddy.ModuleHandler$2 +org.mockito.internal.creation.bytebuddy.ModuleHandler$3 +java.lang.instrument.ClassDefinition +org.mockito.internal.creation.bytebuddy.ModuleHandler$MockitoMockClassLoader +jdk.internal.vm.annotation.ForceInline +com.sun.proxy.jdk.proxy1.$Proxy27 +net.bytebuddy.implementation.Implementation$Composable +net.bytebuddy.implementation.MethodDelegation +net.bytebuddy.implementation.bind.MethodDelegationBinder$TerminationHandler +net.bytebuddy.implementation.bind.MethodDelegationBinder$Record +net.bytebuddy.implementation.bind.MethodDelegationBinder$AmbiguityResolver +net.bytebuddy.implementation.MethodDelegation$WithCustomProperties +net.bytebuddy.implementation.bind.MethodDelegationBinder$BindingResolver +net.bytebuddy.implementation.MethodDelegation$ImplementationDelegate +net.bytebuddy.dynamic.scaffold.FieldLocator$Factory +net.bytebuddy.implementation.bind.MethodDelegationBinder$AmbiguityResolver$Compound +net.bytebuddy.implementation.bind.annotation.BindingPriority$Resolver +net.bytebuddy.implementation.bind.annotation.BindingPriority +net.bytebuddy.description.method.MethodList$AbstractBase +net.bytebuddy.description.method.MethodList$ForLoadedMethods +net.bytebuddy.description.method.MethodDescription$AbstractBase +net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase +net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$ForLoadedExecutable +net.bytebuddy.description.method.ParameterDescription$ForLoadedParameter$ParameterAnnotationSource +net.bytebuddy.description.method.MethodDescription$ForLoadedConstructor +net.bytebuddy.description.method.MethodDescription$ForLoadedMethod +net.bytebuddy.utility.ConstructorComparator +net.bytebuddy.description.ByteCodeElement$Token +net.bytebuddy.description.method.MethodDescription$InDefinedShape$AbstractBase$Executable +net.bytebuddy.description.method.$Proxy28 +net.bytebuddy.implementation.bind.DeclaringTypeResolver +net.bytebuddy.implementation.bind.ArgumentTypeResolver +net.bytebuddy.implementation.bind.MethodNameEqualityResolver +net.bytebuddy.implementation.bind.ParameterLengthResolver +net.bytebuddy.implementation.bind.MethodDelegationBinder$AmbiguityResolver$NoOp +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$ParameterBinder +net.bytebuddy.implementation.bind.annotation.Argument$Binder +net.bytebuddy.implementation.bytecode.StackManipulation +net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding +net.bytebuddy.implementation.bind.annotation.Argument +net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic +net.bytebuddy.description.method.MethodList$Explicit +net.bytebuddy.implementation.bind.annotation.AllArguments$Binder +net.bytebuddy.implementation.bind.annotation.AllArguments +net.bytebuddy.implementation.bind.annotation.AllArguments$Assignment +net.bytebuddy.implementation.bind.annotation.Origin$Binder +net.bytebuddy.implementation.bind.annotation.Origin +net.bytebuddy.implementation.bind.annotation.This$Binder +net.bytebuddy.implementation.bind.annotation.This +net.bytebuddy.implementation.bind.annotation.Super$Binder +net.bytebuddy.implementation.bind.annotation.Super +net.bytebuddy.implementation.bind.annotation.Super$Instantiation +net.bytebuddy.implementation.bind.annotation.Default$Binder +net.bytebuddy.implementation.bind.annotation.Default +net.bytebuddy.implementation.bind.annotation.SuperCall$Binder +net.bytebuddy.implementation.bind.annotation.SuperCall +net.bytebuddy.implementation.bind.annotation.SuperCallHandle$Binder +net.bytebuddy.implementation.bind.annotation.SuperCallHandle +net.bytebuddy.implementation.bind.annotation.DefaultCall$Binder +net.bytebuddy.implementation.bind.annotation.DefaultCall$Binder$DefaultMethodLocator +net.bytebuddy.implementation.bind.annotation.DefaultCall +net.bytebuddy.implementation.bind.annotation.DefaultCallHandle$Binder +net.bytebuddy.implementation.bind.annotation.DefaultCallHandle$Binder$DefaultMethodLocator +net.bytebuddy.implementation.bind.annotation.DefaultCallHandle +net.bytebuddy.implementation.bind.annotation.SuperMethod$Binder +net.bytebuddy.implementation.bind.annotation.SuperMethod +net.bytebuddy.implementation.bind.annotation.SuperMethodHandle$Binder +net.bytebuddy.implementation.bind.annotation.SuperMethodHandle +net.bytebuddy.implementation.bind.annotation.Handle$Binder +net.bytebuddy.utility.ConstantValue +net.bytebuddy.utility.JavaConstant +net.bytebuddy.implementation.bind.annotation.Handle +net.bytebuddy.utility.JavaConstant$MethodHandle$HandleType +net.bytebuddy.implementation.bind.annotation.DynamicConstant$Binder +net.bytebuddy.implementation.bind.annotation.DynamicConstant +net.bytebuddy.implementation.bind.annotation.DefaultMethod$Binder +net.bytebuddy.implementation.bind.annotation.DefaultMethod$Binder$MethodLocator +net.bytebuddy.implementation.bind.annotation.DefaultMethod +net.bytebuddy.implementation.bind.annotation.DefaultMethodHandle$Binder +net.bytebuddy.implementation.bind.annotation.DefaultMethodHandle$Binder$MethodLocator +net.bytebuddy.implementation.bind.annotation.DefaultMethodHandle +net.bytebuddy.implementation.bind.annotation.FieldValue$Binder +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$ParameterBinder$ForFieldBinding +net.bytebuddy.implementation.bind.annotation.FieldValue$Binder$Delegate +net.bytebuddy.dynamic.scaffold.FieldLocator +net.bytebuddy.dynamic.scaffold.FieldLocator$AbstractBase +net.bytebuddy.dynamic.scaffold.FieldLocator$ForClassHierarchy +net.bytebuddy.dynamic.scaffold.FieldLocator$ForExactType +net.bytebuddy.implementation.bind.annotation.FieldValue +net.bytebuddy.implementation.bind.annotation.FieldGetterHandle$Binder +net.bytebuddy.implementation.bind.annotation.FieldGetterHandle$Binder$Delegate +net.bytebuddy.implementation.bind.annotation.FieldGetterHandle +net.bytebuddy.implementation.bind.annotation.FieldSetterHandle$Binder +net.bytebuddy.implementation.bind.annotation.FieldSetterHandle$Binder$Delegate +net.bytebuddy.implementation.bind.annotation.FieldSetterHandle +net.bytebuddy.implementation.bind.annotation.StubValue$Binder +net.bytebuddy.implementation.bind.annotation.Empty$Binder +net.bytebuddy.implementation.bind.MethodDelegationBinder$BindingResolver$Default +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$Identifier +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$ParameterBinder$ForFixedValue +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$ParameterBinder$ForFixedValue$OfConstant +net.bytebuddy.utility.CompoundList +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ForReadObject +org.mockito.internal.creation.bytebuddy.access.MockAccess +net.bytebuddy.implementation.bind.MethodDelegationBinder +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$DelegationProcessor +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$DelegationProcessor$Handler +net.bytebuddy.implementation.bind.annotation.StubValue +net.bytebuddy.implementation.bind.annotation.Empty +net.bytebuddy.implementation.MethodDelegation$ImplementationDelegate$ForStaticMethod +net.bytebuddy.implementation.MethodDelegation$ImplementationDelegate$Compiled +net.bytebuddy.implementation.bind.annotation.IgnoreForBinding$Verifier +net.bytebuddy.description.annotation.AnnotationList$AbstractBase +net.bytebuddy.description.annotation.AnnotationList$ForLoadedAnnotations +net.bytebuddy.description.annotation.AnnotationDescription +net.bytebuddy.implementation.bind.annotation.IgnoreForBinding +net.bytebuddy.description.method.ParameterList +net.bytebuddy.description.method.ParameterList$AbstractBase +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$OfMethod +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$OfLegacyVmMethod +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$OfConstructor +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$OfLegacyVmConstructor +net.bytebuddy.description.method.ParameterList$ForLoadedExecutable$Executable +jdk.proxy2.$Proxy29 +net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher$ForInstanceCheck +jdk.internal.reflect.GeneratedConstructorAccessor10 +net.bytebuddy.description.method.$Proxy30 +net.bytebuddy.description.NamedElement$WithOptionalName +net.bytebuddy.description.method.ParameterDescription +net.bytebuddy.description.method.ParameterDescription$InDefinedShape +net.bytebuddy.description.method.ParameterDescription$AbstractBase +net.bytebuddy.description.method.ParameterDescription$InDefinedShape$AbstractBase +net.bytebuddy.description.method.ParameterDescription$ForLoadedParameter +net.bytebuddy.description.method.ParameterDescription$ForLoadedParameter$OfMethod +net.bytebuddy.description.method.ParameterDescription$ForLoadedParameter$Parameter +net.bytebuddy.description.method.$Proxy31 +net.bytebuddy.implementation.bind.annotation.RuntimeType$Verifier +org.mockito.internal.creation.bytebuddy.$Proxy32 +jdk.proxy2.$Proxy33 +net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$1 +net.bytebuddy.implementation.bind.annotation.Argument$BindingMechanic$2 +jdk.proxy2.$Proxy34 +net.bytebuddy.implementation.bind.annotation.RuntimeType +net.bytebuddy.description.annotation.AnnotationDescription$Loadable +net.bytebuddy.description.annotation.AnnotationDescription$AbstractBase +net.bytebuddy.description.annotation.AnnotationDescription$ForLoadedAnnotation +net.bytebuddy.description.annotation.AnnotationValue +net.bytebuddy.description.enumeration.EnumerationDescription +net.bytebuddy.description.type.TypeDefinition$Sort +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader +net.bytebuddy.description.type.TypeDefinition$Sort$AnnotatedType +net.bytebuddy.description.type.$Proxy35 +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$NoOp +net.bytebuddy.description.type.TypeDescription$Generic$AbstractBase +net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType +net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType$ForLoadedType +net.bytebuddy.implementation.bytecode.assign.Assigner$Typing +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$DelegationProcessor$Handler$Unbound +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$DelegationProcessor$Handler$Bound +net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder$Record +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding +net.bytebuddy.implementation.bind.MethodDelegationBinder$TerminationHandler$Default +net.bytebuddy.implementation.bind.MethodDelegationBinder$TerminationHandler$Default$1 +net.bytebuddy.implementation.bind.MethodDelegationBinder$TerminationHandler$Default$2 +net.bytebuddy.implementation.bytecode.assign.Assigner +net.bytebuddy.implementation.bytecode.assign.primitive.VoidAwareAssigner +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveTypeAwareAssigner +net.bytebuddy.implementation.bytecode.assign.reference.ReferenceTypeAwareAssigner +net.bytebuddy.implementation.bytecode.StackManipulation$Trivial +net.bytebuddy.implementation.bytecode.StackManipulation$Illegal +net.bytebuddy.implementation.bytecode.assign.reference.GenericTypeAwareAssigner +org.mockito.internal.creation.bytebuddy.access.MockMethodInterceptor$DispatcherDefaultingToRealMethod +org.mockito.internal.invocation.RealMethod +org.mockito.internal.creation.bytebuddy.access.MockMethodInterceptor +jdk.proxy2.$Proxy36 +jdk.proxy2.$Proxy37 +jdk.proxy2.$Proxy38 +jdk.proxy2.$Proxy39 +jdk.proxy2.$Proxy40 +jdk.proxy2.$Proxy41 +jdk.proxy2.$Proxy42 +jdk.internal.reflect.GeneratedMethodAccessor1 +org.mockito.internal.creation.bytebuddy.access.MockMethodInterceptor$ForHashCode +org.mockito.internal.creation.bytebuddy.access.MockMethodInterceptor$ForEquals +org.mockito.internal.creation.bytebuddy.access.MockMethodInterceptor$ForWriteReplace +net.bytebuddy.TypeCache$Sort +net.bytebuddy.TypeCache$Sort$1 +net.bytebuddy.TypeCache$Sort$2 +net.bytebuddy.TypeCache$Sort$3 +org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$TypeCachingLock +net.bytebuddy.asm.AsmVisitorWrapper$ForDeclaredMethods +net.bytebuddy.asm.AsmVisitorWrapper$ForDeclaredMethods$DispatchingVisitor +net.bytebuddy.matcher.CollectionOneToOneMatcher +net.bytebuddy.matcher.CollectionErasureMatcher +net.bytebuddy.matcher.MethodParameterTypesMatcher +net.bytebuddy.matcher.AnnotationTypeMatcher +net.bytebuddy.matcher.DeclaringAnnotationMatcher +net.bytebuddy.matcher.CollectionItemMatcher +net.bytebuddy.asm.AsmVisitorWrapper$ForDeclaredMethods$MethodVisitorWrapper +net.bytebuddy.asm.Advice +net.bytebuddy.asm.Advice$ExceptionHandler +net.bytebuddy.asm.Advice$Dispatcher +net.bytebuddy.asm.Advice$Dispatcher$Unresolved +net.bytebuddy.dynamic.ClassFileLocator +net.bytebuddy.asm.Advice$Delegator$Factory +net.bytebuddy.asm.Advice$PostProcessor$Factory +net.bytebuddy.utility.visitor.ExceptionTableSensitiveMethodVisitor +net.bytebuddy.utility.visitor.LineNumberPrependingMethodVisitor +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$Relocation +net.bytebuddy.asm.Advice$AdviceVisitor +net.bytebuddy.asm.Advice$AdviceVisitor$WithoutExitAdvice +net.bytebuddy.asm.Advice$AdviceVisitor$WithExitAdvice +net.bytebuddy.asm.Advice$AdviceVisitor$WithExitAdvice$WithoutExceptionHandling +net.bytebuddy.asm.Advice$AdviceVisitor$WithExitAdvice$WithExceptionHandling +net.bytebuddy.asm.Advice$OnMethodEnter +net.bytebuddy.asm.Advice$OnMethodExit +net.bytebuddy.asm.Advice$WithCustomMapping +net.bytebuddy.asm.Advice$OffsetMapping$Factory +net.bytebuddy.asm.Advice$BootstrapArgumentResolver$Factory +net.bytebuddy.asm.Advice$PostProcessor +net.bytebuddy.asm.Advice$PostProcessor$NoOp +net.bytebuddy.asm.Advice$Delegator$ForRegularInvocation$Factory +net.bytebuddy.asm.Advice$Delegator +net.bytebuddy.asm.Advice$OffsetMapping$ForStackManipulation$Factory +net.bytebuddy.asm.Advice$OffsetMapping +net.bytebuddy.utility.ConstantValue$Simple +net.bytebuddy.utility.JavaConstant$Simple +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher +jdk.proxy2.$Proxy43 +net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher$ForContainerCreation +net.bytebuddy.utility.$Proxy44 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfClassDesc +jdk.proxy2.$Proxy45 +net.bytebuddy.utility.dispatcher.JavaDispatcher$Dispatcher$ForStaticMethod +jdk.proxy2.$Proxy46 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfMethodTypeDesc +jdk.proxy2.$Proxy47 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfMethodHandleDesc +jdk.proxy2.$Proxy48 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfDirectMethodHandleDesc +jdk.proxy2.$Proxy49 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfDirectMethodHandleDesc$ForKind +jdk.proxy2.$Proxy50 +net.bytebuddy.utility.JavaConstant$Simple$Dispatcher$OfDynamicConstantDesc +jdk.proxy2.$Proxy51 +net.bytebuddy.utility.JavaConstant$Simple$OfTrivialValue +net.bytebuddy.utility.JavaConstant$Simple$OfTrivialValue$ForString +net.bytebuddy.implementation.bytecode.StackManipulation$AbstractBase +net.bytebuddy.implementation.bytecode.constant.TextConstant +net.bytebuddy.dynamic.ClassFileLocator$ForClassLoader +net.bytebuddy.dynamic.ClassFileLocator$Resolution +net.bytebuddy.dynamic.ClassFileLocator$ForClassLoader$BootLoaderProxyCreationAction +net.bytebuddy.dynamic.loading.ClassLoadingStrategy +net.bytebuddy.asm.Advice$Dispatcher$Resolved +net.bytebuddy.asm.Advice$Dispatcher$Resolved$ForMethodEnter +net.bytebuddy.asm.Advice$Dispatcher$Resolved$ForMethodExit +net.bytebuddy.asm.Advice$Dispatcher$Bound +net.bytebuddy.asm.Advice$Dispatcher$Inactive +net.bytebuddy.asm.Advice$NoExceptionHandler +jdk.proxy2.$Proxy52 +net.bytebuddy.description.annotation.AnnotationValue$AbstractBase +net.bytebuddy.description.annotation.AnnotationValue$ForConstant +net.bytebuddy.description.annotation.AnnotationValue$Loaded +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$1 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$2 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$3 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$4 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$5 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$6 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$7 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$8 +net.bytebuddy.description.annotation.AnnotationValue$ForConstant$PropertyDelegate$ForNonArrayType$9 +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithEagerNavigation +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithEagerNavigation$OfAnnotatedElement +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$ForLoadedReturnType +net.bytebuddy.asm.Advice$Dispatcher$Inlining +net.bytebuddy.asm.Advice$Return +jdk.proxy2.$Proxy53 +net.bytebuddy.asm.Advice$Enter +jdk.proxy2.$Proxy54 +net.bytebuddy.asm.Advice$Local +net.bytebuddy.asm.Advice$OnNonDefaultValue +jdk.proxy2.$Proxy55 +net.bytebuddy.asm.Advice$This +jdk.proxy2.$Proxy56 +net.bytebuddy.asm.Advice$Origin +jdk.proxy2.$Proxy57 +net.bytebuddy.asm.Advice$AllArguments +jdk.proxy2.$Proxy58 +net.bytebuddy.dynamic.ClassFileLocator$Resolution$Explicit +net.bytebuddy.utility.StreamDrainer +net.bytebuddy.utility.OpenedClassReader +net.bytebuddy.utility.AsmClassReader$ForAsm +net.bytebuddy.jar.asm.ClassReader +net.bytebuddy.asm.Advice$Dispatcher$Resolved$AbstractBase +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodEnter +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodEnter$WithRetainedEnterType +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodEnter$WithDiscardedEnterType +net.bytebuddy.asm.Advice$ArgumentHandler +net.bytebuddy.asm.Advice$Dispatcher$Inlining$CodeTranslationVisitor +net.bytebuddy.asm.Advice$OffsetMapping$ForArgument$Unresolved$Factory +net.bytebuddy.asm.Advice$Argument +net.bytebuddy.asm.Advice$OffsetMapping$ForAllArguments$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForThisReference$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForField$Unresolved$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForField +net.bytebuddy.asm.Advice$OffsetMapping$ForField$Unresolved +net.bytebuddy.asm.Advice$OffsetMapping$ForField$Unresolved$WithImplicitType +net.bytebuddy.asm.Advice$OffsetMapping$ForField$Unresolved$WithExplicitType +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle$Unresolved$ReaderFactory +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle$Unresolved +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle$Unresolved$WithImplicitType +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle$Unresolved$WithExplicitType +net.bytebuddy.asm.Advice$FieldGetterHandle +net.bytebuddy.asm.Advice$OffsetMapping$ForFieldHandle$Unresolved$WriterFactory +net.bytebuddy.asm.Advice$FieldSetterHandle +net.bytebuddy.asm.Advice$OffsetMapping$ForOrigin$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForSelfCallHandle$Factory +net.bytebuddy.asm.Advice$SelfCallHandle +net.bytebuddy.asm.Advice$OffsetMapping$ForHandle$Factory +net.bytebuddy.asm.Advice$Handle +net.bytebuddy.asm.Advice$OffsetMapping$ForDynamicConstant$Factory +net.bytebuddy.asm.Advice$DynamicConstant +net.bytebuddy.asm.Advice$OffsetMapping$ForUnusedValue$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForStubValue +net.bytebuddy.asm.Advice$OffsetMapping$Target +net.bytebuddy.asm.Advice$OffsetMapping$ForThrowable$Factory +net.bytebuddy.asm.Advice$Thrown +net.bytebuddy.asm.Advice$OffsetMapping$ForExitValue$Factory +net.bytebuddy.asm.Advice$Exit +net.bytebuddy.asm.Advice$OffsetMapping$Factory$Illegal +net.bytebuddy.asm.Advice$OffsetMapping$ForLocalValue$Factory +net.bytebuddy.description.annotation.AnnotationValue$ForTypeDescription +net.bytebuddy.description.annotation.AnnotationValue$ForMismatchedType +net.bytebuddy.asm.Advice$OffsetMapping$Factory$AdviceType +net.bytebuddy.asm.Advice$FieldValue +net.bytebuddy.asm.Advice$Unused +net.bytebuddy.asm.Advice$StubValue +net.bytebuddy.asm.Advice$OffsetMapping$ForStackManipulation +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$OfMethodParameter +net.bytebuddy.description.type.TypeList$Generic$AbstractBase +net.bytebuddy.description.type.TypeList$Generic$Explicit +net.bytebuddy.description.type.TypeList$Explicit +net.bytebuddy.implementation.bytecode.StackSize +net.bytebuddy.asm.Advice$OffsetMapping$ForThisReference +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForDefaultValue +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForDefaultValue$ReadOnly +net.bytebuddy.asm.Advice$OffsetMapping$Target$ForDefaultValue$ReadWrite +net.bytebuddy.description.enumeration.EnumerationDescription$AbstractBase +net.bytebuddy.description.enumeration.EnumerationDescription$ForLoadedEnumeration +net.bytebuddy.description.annotation.AnnotationValue$ForEnumerationDescription +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod$1 +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod$2 +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod$3 +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod$4 +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedMethod$5 +sun.reflect.generics.scope.MethodScope +sun.reflect.generics.repository.ConstructorRepository +sun.reflect.generics.repository.MethodRepository +sun.reflect.generics.tree.ArrayTypeSignature +sun.reflect.generics.tree.BottomSignature +sun.reflect.generics.tree.Wildcard +sun.reflect.generics.tree.MethodTypeSignature +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedExecutableParameterType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedExecutableParameterType$Dispatcher +jdk.internal.reflect.GeneratedMethodAccessor2 +net.bytebuddy.description.type.$Proxy59 +net.bytebuddy.asm.Advice$OffsetMapping$ForAllArguments +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$Chained +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForComponentType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForComponentType$AnnotatedParameterizedType +java.lang.reflect.AnnotatedArrayType +net.bytebuddy.description.type.$Proxy60 +net.bytebuddy.asm.Advice$Dispatcher$SuppressionHandler +net.bytebuddy.asm.Advice$Dispatcher$SuppressionHandler$Suppressing +net.bytebuddy.asm.Advice$Dispatcher$SuppressionHandler$Bound +net.bytebuddy.asm.Advice$Dispatcher$SuppressionHandler$NoOp +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForType +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$Bound +net.bytebuddy.asm.Advice$OnDefaultValue +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$1 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$2 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$3 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$4 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$5 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$6 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$7 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$8 +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$9 +java.lang.reflect.WildcardType +sun.reflect.generics.reflectiveObjects.WildcardTypeImpl +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedMethodReturnType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedMethodReturnType$Dispatcher +net.bytebuddy.description.type.$Proxy61 +net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType +net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType$ForLoadedType +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$ForValue$OfNonDefault +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodExit +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodExit$WithoutExceptionHandler +net.bytebuddy.asm.Advice$Dispatcher$Inlining$Resolved$ForMethodExit$WithExceptionHandler +net.bytebuddy.asm.Advice$OffsetMapping$ForEnterValue$Factory +sun.reflect.generics.tree.VoidDescriptor +net.bytebuddy.asm.Advice$OffsetMapping$ForReturnValue$Factory +net.bytebuddy.asm.Advice$OffsetMapping$ForReturnValue +net.bytebuddy.asm.Advice$OffsetMapping$ForEnterValue +net.bytebuddy.asm.Advice$Dispatcher$RelocationHandler$Disabled +net.bytebuddy.asm.Advice$ExceptionHandler$Default +net.bytebuddy.asm.Advice$ExceptionHandler$Default$1 +net.bytebuddy.asm.Advice$ExceptionHandler$Default$2 +net.bytebuddy.asm.Advice$ExceptionHandler$Default$3 +net.bytebuddy.implementation.SuperMethodCall +net.bytebuddy.asm.AsmVisitorWrapper$ForDeclaredMethods$Entry +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ForStatic +net.bytebuddy.asm.Advice$OffsetMapping$ForInstrumentedType +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ConstructorShortcut +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ConstructorShortcut$1 +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ForHashCode +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$ForEquals +jdk.proxy2.$Proxy62 +net.bytebuddy.asm.Advice$OffsetMapping$ForArgument +net.bytebuddy.asm.Advice$OffsetMapping$ForArgument$Unresolved +org.mockito.internal.creation.bytebuddy.MockMethodAdvice$SelfCallInfo +org.mockito.internal.util.reflection.ModuleMemberAccessor +org.mockito.internal.util.reflection.InstrumentationMemberAccessor +net.bytebuddy.dynamic.loading.InjectionClassLoader +net.bytebuddy.dynamic.loading.ByteArrayClassLoader +net.bytebuddy.implementation.MethodCall +net.bytebuddy.implementation.MethodCall$WithoutSpecifiedTarget +net.bytebuddy.dynamic.loading.ClassFilePostProcessor +net.bytebuddy.dynamic.loading.PackageDefinitionStrategy +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PackageLookupStrategy$CreationAction +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PackageLookupStrategy +net.bytebuddy.utility.JavaModule +net.bytebuddy.utility.JavaModule$Resolver +net.bytebuddy.utility.$Proxy63 +net.bytebuddy.utility.JavaModule$Module +net.bytebuddy.utility.$Proxy64 +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PackageLookupStrategy$ForJava9CapableVm +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$SynchronizationStrategy$CreationAction +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$SynchronizationStrategy$Initializable +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$SynchronizationStrategy +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$SynchronizationStrategy$ForJava8CapableVm +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PersistenceHandler +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PersistenceHandler$1 +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$PersistenceHandler$2 +net.bytebuddy.dynamic.loading.PackageDefinitionStrategy$Trivial +net.bytebuddy.dynamic.loading.PackageDefinitionStrategy$Definition +net.bytebuddy.dynamic.loading.ClassFilePostProcessor$NoOp +org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$1 +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$2 +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$3 +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$4 +net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy$Default$5 +net.bytebuddy.dynamic.scaffold.MethodRegistry$Handler +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$UsingTypeWriter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter +net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder +net.bytebuddy.dynamic.TypeResolutionStrategy +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ImplementationDefinition +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$TypeVariableDefinition +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ExceptionDefinition +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Optional +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Valuable +net.bytebuddy.implementation.attribute.TypeAttributeAppender +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Delegator +net.bytebuddy.dynamic.DynamicType$Builder$InnerTypeDefinition +net.bytebuddy.dynamic.DynamicType$Builder$InnerTypeDefinition$ForType +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$InnerTypeDefinitionForTypeAdapter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$InnerTypeDefinitionForMethodAdapter +net.bytebuddy.dynamic.DynamicType$Builder$RecordComponentDefinition +net.bytebuddy.dynamic.DynamicType$Builder$RecordComponentDefinition$Optional +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ImplementationDefinition$Optional +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Simple +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Initial +net.bytebuddy.dynamic.DynamicType$Builder$TypeVariableDefinition +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Optional$Valuable +net.bytebuddy.dynamic.scaffold.RecordComponentRegistry +net.bytebuddy.dynamic.scaffold.MethodRegistry +net.bytebuddy.dynamic.scaffold.FieldRegistry +net.bytebuddy.implementation.Implementation$Target$Factory +net.bytebuddy.dynamic.scaffold.TypeWriter$RecordComponentPool +net.bytebuddy.dynamic.scaffold.TypeWriter$FieldPool +net.bytebuddy.description.modifier.ModifierContributor +net.bytebuddy.description.modifier.ModifierContributor$ForType +net.bytebuddy.description.modifier.ModifierContributor$ForMethod +net.bytebuddy.description.modifier.ModifierContributor$ForField +net.bytebuddy.description.modifier.Visibility +net.bytebuddy.description.modifier.TypeManifestation +net.bytebuddy.description.modifier.ModifierContributor$Resolver +net.bytebuddy.description.type.TypeDescription$AbstractBase$OfSimpleType +net.bytebuddy.dynamic.scaffold.InstrumentedType$Default +net.bytebuddy.dynamic.scaffold.TypeInitializer$None +net.bytebuddy.implementation.LoadedTypeInitializer$NoOp +net.bytebuddy.description.type.TypeDescription$LazyProxy +net.bytebuddy.description.modifier.Ownership +net.bytebuddy.description.modifier.ModifierContributor$ForParameter +net.bytebuddy.description.modifier.SyntheticState +net.bytebuddy.description.modifier.EnumerationState +net.bytebuddy.description.TypeVariableSource$Visitor +java.util.LinkedList$ListItr +jdk.proxy2.$Proxy65 +net.bytebuddy.description.type.TypeList$Generic$ForLoadedTypes +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$ForDetachment +net.bytebuddy.dynamic.scaffold.FieldRegistry$Default +net.bytebuddy.dynamic.scaffold.FieldRegistry$Compiled +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default +net.bytebuddy.dynamic.scaffold.MethodRegistry$Prepared +net.bytebuddy.dynamic.scaffold.RecordComponentRegistry$Default +net.bytebuddy.dynamic.scaffold.RecordComponentRegistry$Compiled +net.bytebuddy.implementation.attribute.TypeAttributeAppender$ForInstrumentedType +net.bytebuddy.implementation.attribute.AnnotationAppender$Target +net.bytebuddy.implementation.attribute.AnnotationAppender +net.bytebuddy.asm.AsmVisitorWrapper$NoOp +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ImplementationDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$MethodMatchAdapter +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ReceiverTypeDefinition +net.bytebuddy.implementation.MethodCall$MethodLocator$Factory +net.bytebuddy.implementation.MethodCall$TerminationHandler$Factory +net.bytebuddy.implementation.MethodCall$MethodInvoker$Factory +net.bytebuddy.implementation.MethodCall$TargetHandler$Factory +net.bytebuddy.implementation.MethodCall$ArgumentLoader$Factory +net.bytebuddy.implementation.MethodCall$MethodLocator +net.bytebuddy.implementation.MethodCall$MethodLocator$ForExplicitMethod +net.bytebuddy.implementation.MethodCall$TargetHandler$ForField$Location +net.bytebuddy.implementation.MethodCall$TargetHandler$ForSelfOrStaticInvocation$Factory +net.bytebuddy.implementation.MethodCall$TargetHandler +net.bytebuddy.implementation.MethodCall$MethodInvoker$ForContextualInvocation$Factory +net.bytebuddy.implementation.MethodCall$MethodInvoker +net.bytebuddy.implementation.MethodCall$TerminationHandler +net.bytebuddy.implementation.MethodCall$TerminationHandler$Simple +net.bytebuddy.implementation.MethodCall$TerminationHandler$Simple$1 +net.bytebuddy.implementation.MethodCall$TerminationHandler$Simple$2 +net.bytebuddy.implementation.MethodCall$TerminationHandler$Simple$3 +net.bytebuddy.dynamic.scaffold.MethodRegistry$Handler$ForImplementation +net.bytebuddy.dynamic.scaffold.MethodRegistry$Handler$Compiled +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ReceiverTypeDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$AbstractBase$Adapter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$MethodMatchAdapter$AnnotationAdapter +net.bytebuddy.dynamic.Transformer +net.bytebuddy.implementation.attribute.MethodAttributeAppender +net.bytebuddy.implementation.attribute.MethodAttributeAppender$NoOp +net.bytebuddy.dynamic.Transformer$NoOp +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Entry +net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodCall$Factory +net.bytebuddy.implementation.MethodCall$MethodInvoker$ForVirtualInvocation$WithImplicitType +net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodParameter +net.bytebuddy.implementation.MethodCall$TargetHandler$Resolved +net.bytebuddy.implementation.MethodCall$ArgumentLoader$ArgumentProvider +net.bytebuddy.implementation.MethodCall$ArgumentLoader$ForMethodParameter$Factory +net.bytebuddy.dynamic.TypeResolutionStrategy$Resolved +net.bytebuddy.dynamic.TypeResolutionStrategy$Passive +net.bytebuddy.pool.TypePool$AbstractBase +net.bytebuddy.pool.TypePool$AbstractBase$Hierarchical +net.bytebuddy.pool.TypePool$ClassLoading +net.bytebuddy.pool.TypePool$Resolution +net.bytebuddy.pool.TypePool$CacheProvider +net.bytebuddy.pool.TypePool$Empty +net.bytebuddy.pool.TypePool$CacheProvider$Simple +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithResolvedErasure +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$ForAttachment +net.bytebuddy.description.method.MethodList$TypeSubstituting +net.bytebuddy.description.method.MethodDescription$InGenericShape +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$ForRawType +net.bytebuddy.matcher.VisibilityMatcher +net.bytebuddy.description.method.MethodDescription$TypeSubstituting +net.bytebuddy.description.type.TypeDescription$Generic$OfParameterizedType$ForGenerifiedErasure +net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType$ForErasure +net.bytebuddy.description.type.TypeList$Generic$ForLoadedTypes$OfTypeVariables +net.bytebuddy.description.method.MethodDescription$Token +net.bytebuddy.matcher.TypeSortMatcher +net.bytebuddy.description.ByteCodeElement$Token$TokenList +net.bytebuddy.description.method.ParameterList$TypeSubstituting +net.bytebuddy.description.method.ParameterDescription$InGenericShape +net.bytebuddy.description.type.TypeList$Generic$ForDetachedTypes +net.bytebuddy.description.type.TypeList$Generic$OfConstructorExceptionTypes +jdk.internal.vm.annotation.IntrinsicCandidate +com.sun.proxy.jdk.proxy1.$Proxy66 +net.bytebuddy.description.annotation.AnnotationList$Explicit +net.bytebuddy.description.type.TypeDescription$Generic$LazyProxy +jdk.proxy2.$Proxy67 +net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder$InstrumentableMatcher +net.bytebuddy.description.method.MethodList$ForTokens +net.bytebuddy.description.method.MethodDescription$Latent +net.bytebuddy.description.method.ParameterList$ForTokens +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithLazyNavigation +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$WithLazyNavigation$OfAnnotatedElement +net.bytebuddy.description.type.TypeDescription$Generic$LazyProjection$ForLoadedSuperClass +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store$Entry +net.bytebuddy.description.type.TypeList$Generic$ForDetachedTypes$WithResolvedErasure +net.bytebuddy.description.type.TypeList$Generic$OfLoadedInterfaceTypes +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Harmonized +net.bytebuddy.description.method.MethodDescription$TypeToken +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Harmonizer$ForJavaMethod$Token +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store$Entry$Initial +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store$Entry$Resolved +net.bytebuddy.dynamic.scaffold.MethodGraph$Node +java.util.AbstractMap$SimpleImmutableEntry +net.bytebuddy.description.method.ParameterDescription$TypeSubstituting +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store$Entry$Resolved$Node +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Detached +net.bytebuddy.dynamic.scaffold.MethodGraph$Compiler$Default$Key$Store$Graph +net.bytebuddy.dynamic.scaffold.MethodGraph$Linked$Delegation +net.bytebuddy.matcher.MethodParameterTypeMatcher +net.bytebuddy.matcher.FailSafeMatcher +net.bytebuddy.dynamic.scaffold.MethodGraph$NodeList +net.bytebuddy.dynamic.scaffold.MethodGraph$Node$Sort +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Prepared$Entry +net.bytebuddy.description.method.MethodDescription$Latent$TypeInitializer +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Prepared +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool +net.bytebuddy.dynamic.scaffold.MethodRegistry$Compiled +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Validator +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Validator$1 +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Validator$2 +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Validator$3 +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Validator$ForTypeAnnotations +net.bytebuddy.description.annotation.AnnotationList$Empty +net.bytebuddy.description.type.TypeList$Generic$ForDetachedTypes$OfTypeVariables +net.bytebuddy.description.type.PackageDescription$AbstractBase +net.bytebuddy.description.type.PackageDescription$Simple +net.bytebuddy.description.field.FieldList$AbstractBase +net.bytebuddy.description.field.FieldList$ForTokens +net.bytebuddy.description.method.MethodDescription$SignatureToken +net.bytebuddy.description.annotation.AnnotationValue$ForDescriptionArray +net.bytebuddy.description.annotation.AnnotationValue$Sort +net.bytebuddy.description.annotation.AnnotationValue$State +net.bytebuddy.dynamic.scaffold.subclass.SubclassImplementationTarget$Factory +net.bytebuddy.implementation.Implementation$Target +net.bytebuddy.dynamic.scaffold.subclass.SubclassImplementationTarget$OriginTypeResolver +net.bytebuddy.dynamic.scaffold.subclass.SubclassImplementationTarget$OriginTypeResolver$1 +net.bytebuddy.dynamic.scaffold.subclass.SubclassImplementationTarget$OriginTypeResolver$2 +net.bytebuddy.implementation.Implementation$Target$AbstractBase +net.bytebuddy.dynamic.scaffold.subclass.SubclassImplementationTarget +net.bytebuddy.implementation.Implementation$SpecialMethodInvocation +net.bytebuddy.implementation.Implementation$Target$AbstractBase$DefaultMethodInvocation +net.bytebuddy.implementation.Implementation$Target$AbstractBase$DefaultMethodInvocation$1 +net.bytebuddy.implementation.Implementation$Target$AbstractBase$DefaultMethodInvocation$2 +net.bytebuddy.dynamic.scaffold.MethodRegistry$Handler$ForImplementation$Compiled +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record +net.bytebuddy.implementation.MethodCall$Appender +net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodCall +net.bytebuddy.implementation.MethodCall$MethodInvoker$ForContextualInvocation +net.bytebuddy.implementation.MethodCall$TargetHandler$ForSelfOrStaticInvocation +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Compiled$Entry +net.bytebuddy.implementation.SuperMethodCall$Appender +net.bytebuddy.implementation.SuperMethodCall$Appender$TerminationHandler +net.bytebuddy.implementation.SuperMethodCall$Appender$TerminationHandler$1 +net.bytebuddy.implementation.SuperMethodCall$Appender$TerminationHandler$2 +net.bytebuddy.dynamic.scaffold.MethodRegistry$Default$Compiled +net.bytebuddy.dynamic.scaffold.FieldRegistry$Default$Compiled +net.bytebuddy.dynamic.scaffold.TypeWriter$FieldPool$Record +net.bytebuddy.dynamic.scaffold.RecordComponentRegistry$Default$Compiled +net.bytebuddy.dynamic.scaffold.TypeWriter$RecordComponentPool$Record +net.bytebuddy.pool.TypePool$Explicit +net.bytebuddy.pool.TypePool$CacheProvider$NoOp +net.bytebuddy.dynamic.scaffold.TypeWriter +net.bytebuddy.dynamic.scaffold.TypeWriter$Default +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ClassDumpAction$Dispatcher +net.bytebuddy.dynamic.scaffold.inline.MethodRebaseResolver +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation +net.bytebuddy.utility.visitor.MetadataAwareClassVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation$CreationClassVisitor +net.bytebuddy.utility.visitor.ContextClassVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation$ImplementationContextClassVisitor +net.bytebuddy.dynamic.scaffold.TypeInitializer$Drain +net.bytebuddy.description.type.RecordComponentList$ForTokens +net.bytebuddy.description.type.RecordComponentDescription +net.bytebuddy.description.type.RecordComponentDescription$InDefinedShape +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ClassDumpAction$Dispatcher$Disabled +net.bytebuddy.utility.AsmClassWriter$Factory$Default$EmptyAsmClassReader +net.bytebuddy.utility.AsmClassWriter$ForAsm +net.bytebuddy.implementation.Implementation$Context$FrameGeneration +net.bytebuddy.implementation.Implementation$Context$FrameGeneration$1 +net.bytebuddy.implementation.Implementation$Context$FrameGeneration$2 +net.bytebuddy.implementation.Implementation$Context$FrameGeneration$3 +net.bytebuddy.implementation.Implementation$Context$ExtractableView$AbstractBase +net.bytebuddy.implementation.Implementation$Context$Default +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod +net.bytebuddy.implementation.Implementation$Context$Default$DelegationRecord +net.bytebuddy.implementation.Implementation$Context$Default$AccessorMethodDelegation +net.bytebuddy.implementation.Implementation$Context$Default$FieldGetterDelegation +net.bytebuddy.implementation.Implementation$Context$Default$FieldSetterDelegation +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$Constraint +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$ValidatingFieldVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$ValidatingMethodVisitor +net.bytebuddy.jar.asm.signature.SignatureVisitor +net.bytebuddy.jar.asm.signature.SignatureWriter +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$ForSignatureVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$Constraint$ForClassFileVersion +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$Constraint$ForClass +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ValidatingClassVisitor$Constraint$Compound +net.bytebuddy.implementation.attribute.AnnotationAppender$Default +net.bytebuddy.implementation.attribute.AnnotationAppender$Target$OnType +net.bytebuddy.implementation.attribute.AnnotationAppender$ForTypeAnnotations +java.util.AbstractList$SubList +net.bytebuddy.jar.asm.TypeReference +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$AccessBridgeWrapper +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$Sort +net.bytebuddy.description.modifier.Visibility$1 +net.bytebuddy.description.type.TypeList$Generic$OfMethodExceptionTypes +net.bytebuddy.implementation.MethodCall$TargetHandler$ForSelfOrStaticInvocation$Resolved +net.bytebuddy.implementation.bytecode.Duplication +net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodCall$Resolved +net.bytebuddy.implementation.bytecode.ByteCodeAppender$Size +net.bytebuddy.implementation.bytecode.StackManipulation$Compound +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess$MethodLoading$TypeCastingHandler +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess$OffsetLoading +net.bytebuddy.implementation.bytecode.member.MethodInvocation +net.bytebuddy.implementation.bytecode.member.MethodInvocation$WithImplicitInvocationTargetType +net.bytebuddy.implementation.bytecode.member.MethodInvocation$Invocation +net.bytebuddy.implementation.bytecode.member.MethodReturn +net.bytebuddy.implementation.bytecode.StackManipulation$Size +net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodParameter$Resolved +net.bytebuddy.implementation.MethodCall$ArgumentLoader +net.bytebuddy.implementation.MethodCall$ArgumentLoader$ForMethodParameter +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveWideningDelegate +net.bytebuddy.implementation.bytecode.assign.primitive.PrimitiveWideningDelegate$WideningStackManipulation +net.bytebuddy.description.type.TypeList$Generic$OfMethodExceptionTypes$TypeProjection +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedExecutableExceptionType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedExecutableExceptionType$Dispatcher +net.bytebuddy.description.type.$Proxy68 +net.bytebuddy.matcher.SignatureTokenMatcher +net.bytebuddy.implementation.Implementation$SpecialMethodInvocation$AbstractBase +net.bytebuddy.implementation.Implementation$SpecialMethodInvocation$Simple +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess$MethodLoading +net.bytebuddy.implementation.bytecode.member.MethodVariableAccess$MethodLoading$TypeCastingHandler$NoOp +net.bytebuddy.dynamic.scaffold.TypeInitializer$Drain$Default +net.bytebuddy.description.method.ParameterList$Empty +net.bytebuddy.description.type.TypeList$Generic$Empty +net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForNonImplementedMethod +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$UnresolvedType +net.bytebuddy.dynamic.DynamicType +net.bytebuddy.dynamic.DynamicType$Unloaded +net.bytebuddy.dynamic.DynamicType$AbstractBase +net.bytebuddy.dynamic.DynamicType$Default +net.bytebuddy.dynamic.DynamicType$Default$Unloaded +net.bytebuddy.dynamic.DynamicType$Loaded +net.bytebuddy.dynamic.loading.InjectionClassLoader$Strategy +net.bytebuddy.dynamic.DynamicType$Default$Loaded +java.lang.invoke.LambdaForm$MH/0x00007f42042d0000 +java.lang.invoke.LambdaForm$MH/0x00007f42042d0400 +java.lang.invoke.LambdaForm$MH/0x00007f42042d0800 +net.bytebuddy.dynamic.loading.ByteArrayClassLoader$ClassDefinitionAction +net.bytebuddy.dynamic.loading.PackageDefinitionStrategy$Definition$Trivial +org.mockito.internal.util.reflection.InstrumentationMemberAccessor$Dispatcher$ByteBuddy$41mTxNg6 +java.lang.invoke.LambdaForm$DMH/0x00007f42042d1000 +org.mockito.internal.exceptions.stacktrace.DefaultStackTraceCleanerProvider +org.mockito.internal.configuration.InjectingAnnotationEngine +org.mockito.internal.configuration.IndependentAnnotationEngine +org.mockito.internal.configuration.FieldAnnotationProcessor +org.mockito.internal.configuration.MockAnnotationProcessor +org.mockito.Captor +org.mockito.internal.configuration.CaptorAnnotationProcessor +org.mockito.internal.configuration.SpyAnnotationEngine +org.mockito.internal.util.ConsoleMockitoLogger +org.mockito.plugins.MockResolver +org.mockito.plugins.DoNotMockEnforcer +org.mockito.internal.configuration.DefaultDoNotMockEnforcer +org.mockito.internal.creation.instance.DefaultInstantiatorProvider +org.mockito.internal.creation.instance.ObjenesisInstantiator +org.objenesis.Objenesis +org.objenesis.ObjenesisBase +org.objenesis.ObjenesisStd +org.objenesis.strategy.InstantiatorStrategy +org.mockito.configuration.IMockitoConfiguration +org.mockito.internal.configuration.GlobalConfiguration +org.mockito.configuration.DefaultMockitoConfiguration +org.mockito.internal.configuration.ClassPathLoader +org.objenesis.strategy.BaseInstantiatorStrategy +org.objenesis.strategy.StdInstantiatorStrategy +org.objenesis.instantiator.ObjectInstantiator +org.mockito.internal.session.DefaultMockitoSessionBuilder +org.mockito.MockitoSession +org.mockito.internal.session.MockitoSessionLoggerAdapter +org.mockito.internal.session.MockitoLoggerAdapter +org.mockito.internal.framework.DefaultMockitoSession +org.mockito.exceptions.misusing.RedundantListenerException +org.mockito.listeners.MockitoListener +org.mockito.internal.junit.TestFinishedEvent +org.mockito.listeners.MockCreationListener +org.mockito.internal.junit.MockitoTestListener +org.mockito.internal.listeners.AutoCleanableListener +org.mockito.internal.junit.UniversalTestListener +org.mockito.listeners.StubbingLookupListener +org.mockito.internal.junit.DefaultStubbingLookupListener +org.mockito.internal.framework.DefaultMockitoFramework +org.mockito.invocation.InvocationFactory +org.mockito.internal.util.Checks +org.mockito.internal.progress.ThreadSafeMockingProgress +org.mockito.internal.progress.ThreadSafeMockingProgress$1 +org.mockito.internal.progress.MockingProgress +org.mockito.internal.progress.MockingProgressImpl +org.mockito.internal.progress.ArgumentMatcherStorage +org.mockito.verification.VerificationStrategy +org.mockito.internal.progress.ArgumentMatcherStorageImpl +java.util.Stack +org.mockito.internal.progress.MockingProgressImpl$1 +org.mockito.MockitoAnnotations +org.mockito.internal.util.Supplier +org.mockito.internal.configuration.MockAnnotationProcessor$$Lambda$658/0x00007f42042d86c0 +org.mockito.MockSettings +org.mockito.mock.MockCreationSettings +org.mockito.internal.creation.settings.CreationSettings +org.mockito.internal.creation.MockSettingsImpl +org.mockito.mock.MockName +org.mockito.mock.SerializableMode +org.mockito.internal.util.MockCreationValidator +org.mockito.internal.util.MockUtil +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$1 +org.mockito.mock.MockType +org.mockito.internal.util.MockNameImpl +org.mockito.plugins.DoNotMockEnforcer$Cache +org.mockito.internal.handler.MockHandlerFactory +org.mockito.invocation.MockHandler +org.mockito.internal.handler.MockHandlerImpl +org.mockito.invocation.MatchableInvocation +org.mockito.stubbing.OngoingStubbing +org.mockito.stubbing.Stubbing +org.mockito.invocation.InvocationContainer +org.mockito.internal.invocation.MatchersBinder +org.mockito.internal.stubbing.InvocationContainerImpl +org.mockito.invocation.StubInfo +org.mockito.internal.verification.RegisteredInvocations +org.mockito.internal.verification.DefaultRegisteredInvocations +org.mockito.internal.stubbing.DoAnswerStyleStubbing +org.mockito.internal.handler.NullResultGuardian +org.mockito.internal.handler.InvocationNotifierHandler +org.mockito.listeners.MethodInvocationReport +org.mockito.internal.creation.bytebuddy.MockFeatures +net.bytebuddy.TypeCache$SimpleKey +org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$MockitoMockKey +org.mockito.internal.creation.bytebuddy.TypeCachingBytecodeGenerator$$Lambda$659/0x00007f42042dd328 +net.bytebuddy.TypeCache$LookupKey +org.mockito.internal.creation.bytebuddy.TypeSupport +java.lang.invoke.LambdaForm$DMH/0x00007f42042e0000 +org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator$$Lambda$660/0x00007f42042dd978 +org.mockito.internal.util.concurrent.WeakConcurrentMap$WeakKey +org.mockito.internal.util.concurrent.WeakConcurrentMap$LatentKey +net.bytebuddy.dynamic.ClassFileLocator$Simple +net.bytebuddy.dynamic.scaffold.inline.AbstractInliningDynamicTypeBuilder +net.bytebuddy.dynamic.scaffold.inline.RedefinitionDynamicTypeBuilder +net.bytebuddy.description.field.FieldList$ForLoadedFields +net.bytebuddy.utility.FieldComparator +sun.reflect.annotation.TypeAnnotation$TypeAnnotationTarget +sun.reflect.annotation.TypeAnnotationParser +sun.reflect.annotation.TypeAnnotation +sun.reflect.annotation.TypeAnnotation$LocationInfo +sun.reflect.annotation.TypeAnnotation$LocationInfo$Location +sun.reflect.annotation.AnnotatedTypeFactory +sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$Simple +sun.reflect.generics.tree.TypeVariableSignature +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$Delegator$ForLoadedTypeVariable +net.bytebuddy.description.type.TypeDescription$Generic$OfTypeVariable +net.bytebuddy.description.type.TypeDescription$Generic$OfTypeVariable$ForLoadedType +net.bytebuddy.description.type.TypeVariableToken +net.bytebuddy.description.type.TypeDescription$Generic$OfTypeVariable$ForLoadedType$TypeVariableBoundList +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeVariableBoundType$OfFormalTypeVariable +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeVariableBoundType$OfFormalTypeVariable$FormalTypeVariable +net.bytebuddy.description.type.$Proxy69 +sun.reflect.misc.ReflectUtil +net.bytebuddy.description.type.TypeDescription$Generic$OfTypeVariable$Symbolic +net.bytebuddy.description.method.ParameterDescription$Token +net.bytebuddy.description.type.TypeDescription$Generic$OfNonGenericType$Latent +java.lang.Class$EnclosingMethodInfo +net.bytebuddy.description.type.RecordComponentDescription$Token +net.bytebuddy.implementation.attribute.TypeAttributeAppender$ForInstrumentedType$Differentiating +net.bytebuddy.asm.AsmVisitorWrapper$AbstractBase +org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator$ParameterWritingVisitorWrapper +org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator$ParameterWritingVisitorWrapper$ParameterAddingClassVisitor +net.bytebuddy.asm.AsmVisitorWrapper$Compound +net.bytebuddy.pool.TypePool$Default +net.bytebuddy.pool.TypePool$Default$TypeExtractor +net.bytebuddy.pool.TypePool$Default$ReaderMode +net.bytebuddy.dynamic.scaffold.inline.InliningImplementationMatcher +net.bytebuddy.description.type.TypeDescription$Generic$OfTypeVariable$WithAnnotationOverlay +net.bytebuddy.description.type.TypeList$Generic$ForDetachedTypes$OfTypeVariables$AttachedTypeVariable +net.bytebuddy.description.method.ParameterDescription$Latent +net.bytebuddy.dynamic.scaffold.MethodGraph$Node$Simple +net.bytebuddy.dynamic.scaffold.MethodGraph$Simple +net.bytebuddy.dynamic.scaffold.MethodGraph$Empty +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$RegistryContextClassVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor +net.bytebuddy.jar.asm.commons.Remapper +net.bytebuddy.jar.asm.commons.SimpleRemapper +net.bytebuddy.jar.asm.commons.ClassRemapper +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$OpenedClassRemapper +net.bytebuddy.dynamic.scaffold.inline.MethodRebaseResolver$Disabled +net.bytebuddy.dynamic.scaffold.inline.MethodRebaseResolver$Resolution +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$ContextRegistry +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$InitializationHandler +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor$AttributeObtainingRecordComponentVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor$AttributeObtainingFieldVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor$AttributeObtainingMethodVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor$CodePreservingMethodVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$RedefinitionClassVisitor$DeduplicatingClassVisitor +net.bytebuddy.jar.asm.Context +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForInlining$WithFullProcessing$InitializationHandler$Creating +net.bytebuddy.implementation.Implementation$Context$Disabled +org.mockito.internal.creation.bytebuddy.InlineBytecodeGenerator$ParameterWritingVisitorWrapper$MethodParameterStrippingMethodVisitor +net.bytebuddy.dynamic.scaffold.TypeWriter$Default$SignatureKey +net.bytebuddy.matcher.DescriptorMatcher +jdk.internal.reflect.GeneratedMethodAccessor3 +software.amazon.lambda.powertools.kafka.serializers.PowertoolsDeserializer +net.bytebuddy.dynamic.loading.MultipleParentClassLoader$Builder +net.bytebuddy.dynamic.loading.MultipleParentClassLoader +net.bytebuddy.matcher.LatentMatcher$Disjunction +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$OptionalMethodMatchAdapter +net.bytebuddy.description.modifier.SynchronizationState +net.bytebuddy.dynamic.Transformer$ForMethod +net.bytebuddy.dynamic.Transformer$ForMethod$MethodModifierTransformer +net.bytebuddy.dynamic.Transformer$Compound +net.bytebuddy.implementation.attribute.MethodAttributeAppender$ForInstrumentedMethod +net.bytebuddy.implementation.attribute.MethodAttributeAppender$ForInstrumentedMethod$1 +net.bytebuddy.implementation.attribute.MethodAttributeAppender$ForInstrumentedMethod$2 +net.bytebuddy.implementation.attribute.MethodAttributeAppender$Factory$Compound +net.bytebuddy.description.modifier.FieldManifestation +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Optional$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Optional$Valuable$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$FieldDefinition$Optional$Valuable$AbstractBase$Adapter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$FieldDefinitionAdapter +net.bytebuddy.implementation.attribute.FieldAttributeAppender$Factory +net.bytebuddy.description.field.FieldDescription$Token +net.bytebuddy.implementation.attribute.FieldAttributeAppender +net.bytebuddy.implementation.attribute.FieldAttributeAppender$ForInstrumentedField +net.bytebuddy.matcher.LatentMatcher$ForFieldToken +net.bytebuddy.dynamic.scaffold.FieldRegistry$Default$Entry +net.bytebuddy.implementation.FieldAccessor +net.bytebuddy.implementation.FieldAccessor$FieldLocation +net.bytebuddy.implementation.FieldAccessor$PropertyConfigurable +net.bytebuddy.implementation.FieldAccessor$AssignerConfigurable +net.bytebuddy.implementation.FieldAccessor$OwnerTypeLocatable +net.bytebuddy.implementation.FieldAccessor$FieldNameExtractor +net.bytebuddy.implementation.FieldAccessor$FieldNameExtractor$ForBeanProperty +net.bytebuddy.implementation.FieldAccessor$FieldNameExtractor$ForBeanProperty$1 +net.bytebuddy.implementation.FieldAccessor$FieldNameExtractor$ForBeanProperty$2 +net.bytebuddy.implementation.FieldAccessor$ForImplicitProperty +net.bytebuddy.implementation.FieldAccessor$FieldLocation$Relative +net.bytebuddy.implementation.FieldAccessor$FieldLocation$Prepared +net.bytebuddy.dynamic.scaffold.FieldLocator$ForClassHierarchy$Factory +net.bytebuddy.matcher.SuperTypeMatcher +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$TypeVariableDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ExceptionDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Initial$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$MethodDefinitionAdapter +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$TypeVariableDefinition$Annotatable +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Annotatable +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Simple$Annotatable +net.bytebuddy.description.method.ParameterDescription$Token$TypeList +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Simple$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Simple$Annotatable$AbstractBase +net.bytebuddy.dynamic.DynamicType$Builder$MethodDefinition$ParameterDefinition$Simple$Annotatable$AbstractBase$Adapter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$MethodDefinitionAdapter$SimpleParameterAnnotationAdapter +net.bytebuddy.dynamic.DynamicType$Builder$AbstractBase$Adapter$MethodDefinitionAdapter$AnnotationAdapter +jdk.internal.reflect.GeneratedMethodAccessor4 +net.bytebuddy.dynamic.loading.ClassLoadingStrategy$UsingLookup +net.bytebuddy.dynamic.loading.ClassInjector +net.bytebuddy.dynamic.loading.ClassInjector$AbstractBase +net.bytebuddy.dynamic.loading.ClassInjector$UsingLookup +net.bytebuddy.dynamic.loading.ClassInjector$UsingLookup$MethodHandles +net.bytebuddy.dynamic.loading.$Proxy70 +net.bytebuddy.dynamic.loading.ClassInjector$UsingLookup$MethodHandles$Lookup +jdk.proxy2.$Proxy71 +net.bytebuddy.utility.JavaType +net.bytebuddy.description.type.TypeDescription$Latent +net.bytebuddy.utility.JavaType$LatentTypeWithSimpleName +net.bytebuddy.matcher.LatentMatcher$ForMethodToken +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeVariableBoundType +net.bytebuddy.description.type.TypeDescription$Generic$AnnotationReader$ForTypeVariableBoundType$AnnotatedTypeVariable +java.lang.reflect.AnnotatedTypeVariable +net.bytebuddy.description.type.$Proxy72 +net.bytebuddy.matcher.LatentMatcher$ForMethodToken$ResolvedMatcher +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Reducing +net.bytebuddy.dynamic.Transformer$ForMethod$TransformedMethod +jdk.internal.reflect.GeneratedMethodAccessor5 +net.bytebuddy.implementation.MethodDelegation$ImplementationDelegate$Compiled$ForStaticCall +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodInvoker +net.bytebuddy.implementation.MethodDelegation$Appender +net.bytebuddy.implementation.bind.MethodDelegationBinder$Processor +net.bytebuddy.implementation.attribute.MethodAttributeAppender$Compound +net.bytebuddy.description.type.TypeDescription$Generic$Visitor$Substitutor$WithoutTypeSubstitution +net.bytebuddy.dynamic.Transformer$ForMethod$TransformedMethod$AttachmentVisitor +net.bytebuddy.dynamic.Transformer$ForMethod$TransformedMethod$TransformedParameterList +net.bytebuddy.dynamic.Transformer$ForMethod$TransformedMethod$TransformedParameter +net.bytebuddy.implementation.FieldAccessor$ForImplicitProperty$Appender +net.bytebuddy.implementation.FieldAccessor$FieldLocation$Relative$Prepared +net.bytebuddy.dynamic.scaffold.FieldLocator$Resolution +net.bytebuddy.dynamic.scaffold.FieldRegistry$Default$Compiled$Entry +net.bytebuddy.matcher.LatentMatcher$ForFieldToken$ResolvedMatcher +net.bytebuddy.description.field.FieldDescription$SignatureToken +net.bytebuddy.description.field.FieldDescription$AbstractBase +net.bytebuddy.description.field.FieldDescription$InDefinedShape$AbstractBase +net.bytebuddy.description.field.FieldDescription$Latent +net.bytebuddy.dynamic.scaffold.TypeWriter$FieldPool$Record$ForExplicitField +net.bytebuddy.implementation.attribute.AnnotationAppender$Target$OnField +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodInvoker$Simple +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Builder +net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding$Anonymous +net.bytebuddy.description.annotation.AnnotationValue$Loaded$AbstractBase +net.bytebuddy.description.annotation.AnnotationValue$ForEnumerationDescription$Loaded +net.bytebuddy.implementation.bind.ArgumentTypeResolver$ParameterIndexToken +net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding$Unique +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Builder$Build +net.bytebuddy.implementation.attribute.AnnotationAppender$Target$OnMethod +net.bytebuddy.implementation.bytecode.assign.TypeCasting +net.bytebuddy.description.type.TypeDefinition$SuperClassIterator +net.bytebuddy.description.field.FieldList$Explicit +net.bytebuddy.dynamic.scaffold.FieldLocator$Resolution$Simple +net.bytebuddy.implementation.bytecode.member.FieldAccess +net.bytebuddy.implementation.bytecode.member.FieldAccess$Defined +net.bytebuddy.implementation.bytecode.member.FieldAccess$AccessDispatcher +net.bytebuddy.implementation.bytecode.member.FieldAccess$AccessDispatcher$AbstractFieldInstruction +net.bytebuddy.implementation.bytecode.member.FieldAccess$AccessDispatcher$FieldGetInstruction +net.bytebuddy.implementation.bytecode.constant.MethodConstant +net.bytebuddy.implementation.bytecode.constant.MethodConstant$CanCache +net.bytebuddy.implementation.bytecode.constant.MethodConstant$ForMethod +net.bytebuddy.implementation.bytecode.constant.MethodConstant$CachedMethod +net.bytebuddy.implementation.bytecode.collection.CollectionFactory +net.bytebuddy.implementation.bytecode.collection.ArrayFactory +net.bytebuddy.implementation.bytecode.collection.ArrayFactory$ArrayCreator +net.bytebuddy.implementation.bytecode.collection.ArrayFactory$ArrayCreator$ForReferenceType +net.bytebuddy.implementation.bytecode.collection.ArrayFactory$ArrayStackManipulation +net.bytebuddy.implementation.auxiliary.MethodCallProxy$AssignableSignatureCall +net.bytebuddy.implementation.auxiliary.AuxiliaryType +net.bytebuddy.implementation.bytecode.constant.DefaultValue +net.bytebuddy.implementation.bytecode.constant.IntegerConstant +net.bytebuddy.implementation.bytecode.constant.LongConstant +net.bytebuddy.implementation.bytecode.constant.FloatConstant +net.bytebuddy.implementation.bytecode.constant.DoubleConstant +net.bytebuddy.implementation.bytecode.constant.NullConstant +net.bytebuddy.implementation.bind.MethodDelegationBinder$1 +net.bytebuddy.implementation.bind.MethodDelegationBinder$AmbiguityResolver$Resolution +net.bytebuddy.implementation.Implementation$Context$Default$FieldCacheEntry +net.bytebuddy.implementation.Implementation$Context$Default$CacheValueField +net.bytebuddy.implementation.auxiliary.MethodCallProxy +net.bytebuddy.implementation.MethodAccessorFactory$AccessType +net.bytebuddy.implementation.Implementation$Context$Default$AbstractPropertyAccessorMethod +net.bytebuddy.implementation.Implementation$Context$Default$AccessorMethod +net.bytebuddy.description.method.ParameterList$Explicit$ForTypes +net.bytebuddy.implementation.auxiliary.MethodCallProxy$PrecomputedMethodGraph +net.bytebuddy.implementation.auxiliary.MethodCallProxy$MethodCall +net.bytebuddy.implementation.auxiliary.MethodCallProxy$ConstructorCall +net.bytebuddy.implementation.auxiliary.MethodCallProxy$MethodCall$Appender +net.bytebuddy.implementation.auxiliary.MethodCallProxy$ConstructorCall$Appender +net.bytebuddy.implementation.bytecode.Removal +net.bytebuddy.implementation.bytecode.Removal$1 +net.bytebuddy.implementation.bytecode.Removal$2 +net.bytebuddy.implementation.attribute.AnnotationAppender$Target$OnMethodParameter +net.bytebuddy.implementation.bytecode.member.FieldAccess$AccessDispatcher$FieldPutInstruction +net.bytebuddy.implementation.bytecode.TypeCreation +net.bytebuddy.implementation.bytecode.Duplication$1 +net.bytebuddy.implementation.bytecode.Duplication$2 +net.bytebuddy.implementation.bytecode.Duplication$3 +sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeVariableImpl +net.bytebuddy.dynamic.scaffold.MethodGraph$Node$Unresolved +net.bytebuddy.implementation.Implementation$SpecialMethodInvocation$Illegal +net.bytebuddy.implementation.bind.MethodDelegationBinder$ParameterBinding$Illegal +net.bytebuddy.implementation.bind.MethodDelegationBinder$MethodBinding$Illegal +jdk.internal.reflect.GeneratedMethodAccessor6 +jdk.internal.reflect.GeneratedMethodAccessor7 +net.bytebuddy.dynamic.scaffold.FieldLocator$Resolution$Illegal +net.bytebuddy.implementation.bytecode.ByteCodeAppender$Simple +net.bytebuddy.dynamic.scaffold.TypeInitializer$Simple +net.bytebuddy.implementation.bytecode.ByteCodeAppender$Compound +net.bytebuddy.implementation.bytecode.constant.ClassConstant +net.bytebuddy.implementation.bytecode.constant.ClassConstant$ForReferenceType +net.bytebuddy.description.type.PackageDescription$ForLoadedPackage +software.amazon.lambda.powertools.kafka.serializers.PowertoolsDeserializer$MockitoMock$84ecoPEA +software.amazon.lambda.powertools.kafka.serializers.PowertoolsDeserializer$MockitoMock$84ecoPEA$auxiliary$0oONJkzb +software.amazon.lambda.powertools.kafka.serializers.PowertoolsDeserializer$MockitoMock$84ecoPEA$auxiliary$buK1SnlY +net.bytebuddy.TypeCache$StorageKey +org.mockito.plugins.MemberAccessor$OnConstruction +org.mockito.plugins.MemberAccessor$ConstructionDispatcher +org.mockito.internal.creation.bytebuddy.InlineDelegateByteBuddyMockMaker$$Lambda$661/0x00007f4204315f70 +java.lang.invoke.LambdaForm$MH/0x00007f4204310800 +java.lang.invoke.LambdaForm$MH/0x00007f4204310c00 +java.lang.invoke.LambdaForm$MH/0x00007f4204311000 +java.lang.invoke.LambdaForm$MH/0x00007f4204311400 +sun.invoke.util.ValueConversions$WrapperCache +java.lang.invoke.LambdaForm$MH/0x00007f4204311800 +java.lang.invoke.LambdaForm$MH/0x00007f4204311c00 +java.lang.invoke.LambdaForm$MH/0x00007f4204312000 +java.lang.invoke.LambdaForm$MH/0x00007f4204312400 +java.lang.invoke.LambdaForm$MH/0x00007f4204312800 +org.mockito.internal.util.reflection.InstrumentationMemberAccessor$$Lambda$662/0x00007f4204316198 +org.mockito.invocation.Invocation +org.mockito.internal.creation.bytebuddy.ByteBuddyCrossClassLoaderSerializationSupport +org.mockito.exceptions.base.MockitoSerializationIssue +java.lang.invoke.LambdaForm$MH/0x00007f4204312c00 +java.lang.invoke.LambdaForm$MH/0x00007f4204313000 +java.lang.invoke.LambdaForm$MH/0x00007f4204313400 +java.lang.invoke.LambdaForm$DMH/0x00007f4204313800 +org.mockito.internal.configuration.IndependentAnnotationEngine$$Lambda$663/0x00007f4204316a40 +org.mockito.Spy +org.mockito.plugins.AnnotationEngine$NoAction +org.mockito.internal.util.collections.Sets +org.mockito.internal.util.collections.HashCodeAndEqualsSafeSet +org.mockito.internal.configuration.injection.scanner.InjectMocksScanner +org.mockito.InjectMocks +org.mockito.internal.configuration.injection.scanner.MockScanner +org.mockito.internal.util.reflection.FieldReader +org.mockito.internal.util.collections.HashCodeAndEqualsMockWrapper +java.lang.invoke.DirectMethodHandle$StaticAccessor +java.lang.invoke.LambdaForm$MH/0x00007f4204318000 +org.mockito.internal.util.collections.HashCodeAndEqualsSafeSet$1 +org.mockito.internal.configuration.DefaultInjectionEngine +org.mockito.internal.configuration.injection.MockInjection +org.mockito.internal.configuration.injection.MockInjection$OngoingMockInjection +org.mockito.internal.configuration.injection.MockInjectionStrategy +org.mockito.internal.configuration.injection.ConstructorInjection +org.mockito.internal.configuration.injection.PropertyAndSetterInjection +org.mockito.internal.configuration.injection.SpyOnInjectedFieldsHandler +org.mockito.internal.configuration.injection.MockInjectionStrategy$1 +org.mockito.internal.util.reflection.FieldInitializer$ConstructorArgumentResolver +org.mockito.internal.configuration.injection.filter.MockCandidateFilter +org.mockito.internal.configuration.injection.filter.TypeBasedCandidateFilter +org.mockito.internal.configuration.injection.filter.NameBasedCandidateFilter +org.mockito.internal.configuration.injection.filter.TerminalMockCandidateFilter +org.mockito.internal.configuration.InjectingAnnotationEngine$$Lambda$664/0x00007f420431de08 +org.mockito.internal.configuration.InjectingAnnotationEngine$$Lambda$665/0x00007f420431e030 +com.amazonaws.services.lambda.runtime.CustomPojoSerializer +org.crac.Resource +software.amazon.lambda.powertools.kafka.PowertoolsSerializer +software.amazon.lambda.powertools.kafka.serializers.KafkaJsonDeserializer +org.apache.kafka.common.header.Headers +software.amazon.lambda.powertools.kafka.serializers.KafkaAvroDeserializer +org.apache.avro.io.DatumReader +software.amazon.lambda.powertools.kafka.serializers.KafkaProtobufDeserializer +software.amazon.lambda.powertools.kafka.testutils.InputStreamHandler +org.crac.Core +org.crac.Context +org.crac.GlobalContextWrapper +org.crac.Core$Compat +org.crac.CheckpointException +org.crac.RestoreException +org.assertj.core.internal.Strings +org.junit.jupiter.engine.execution.NamespaceAwareStore$$Lambda$666/0x00007f420431a8a0 +org.mockito.junit.jupiter.MockitoExtension$$Lambda$667/0x00007f420431aac8 +org.mockito.junit.jupiter.MockitoExtension$$Lambda$668/0x00007f420431acf8 +org.mockito.junit.jupiter.MockitoExtension$$Lambda$669/0x00007f420431af28 +org.mockito.internal.framework.DefaultMockitoSession$1 +org.mockito.internal.junit.UniversalTestListener$1 +org.mockito.internal.junit.UnusedStubbingsFinder +org.mockito.internal.junit.UnusedStubbings +org.mockito.internal.invocation.finder.AllInvocationsFinder +org.mockito.internal.stubbing.StubbingComparator +org.mockito.internal.invocation.InvocationComparator +java.util.IdentityHashMap$IdentityHashMapIterator +java.util.IdentityHashMap$KeyIterator +org.mockito.internal.util.DefaultMockingDetails +java.util.TreeMap$TreeMapSpliterator +java.util.TreeMap$KeySpliterator +org.mockito.internal.stubbing.UnusedStubbingReporting +org.mockito.internal.junit.UnusedStubbingsFinder$$Lambda$670/0x00007f4204319750 +org.assertj.core.api.ThrowableAssert$ThrowingCallable +software.amazon.lambda.powertools.kafka.PowertoolsSerializerTest$$Lambda$671/0x00007f4204319ba0 +org.assertj.core.internal.Throwables +org.assertj.core.internal.CommonValidations +org.junit.jupiter.api.extension.TemplateInvocationValidationException +org.junit.jupiter.params.ParameterizedDeclarationContext +org.junit.jupiter.engine.descriptor.TestTemplateExtensionContext +org.junit.jupiter.engine.descriptor.TemplateExecutor +org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor$TestTemplateExecutor +org.junit.jupiter.engine.descriptor.TemplateExecutor$$Lambda$672/0x00007f42043209d0 +org.junit.jupiter.api.RepeatedTest +org.junit.jupiter.params.ParameterizedTestContext +org.junit.jupiter.params.ResolverFacade +org.junit.jupiter.params.support.ParameterDeclaration +org.junit.jupiter.params.support.ParameterDeclarations +org.junit.jupiter.params.ResolverFacade$ResolvableParameterDeclaration +org.junit.jupiter.params.support.FieldContext +org.junit.jupiter.params.ResolverFacade$FieldParameterDeclaration +org.junit.jupiter.params.ResolverFacade$Resolver +org.junit.jupiter.params.ResolverFacade$ExecutableParameterDeclaration +org.junit.jupiter.params.aggregator.ArgumentsAccessor +org.junit.jupiter.params.aggregator.AggregateWith +java.util.TreeMap$Values +java.util.TreeMap$ValueIterator +org.junit.jupiter.params.ResolverFacade$DefaultParameterDeclarations +org.junit.jupiter.engine.descriptor.TemplateExecutor$$Lambda$673/0x00007f4204322990 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$674/0x00007f4204322bb8 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$PartialFormatter +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$675/0x00007f42043231f8 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$676/0x00007f4204323420 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$CachingByArgumentsLengthPartialFormatter +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$677/0x00007f4204323890 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$ArgumentSetNameFormatter +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$PartialFormatters +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$ArgumentsContext +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$PartialFormatter$$Lambda$678/0x00007f4204324140 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$679/0x00007f4204324360 +java.lang.invoke.LambdaForm$DMH/0x00007f4204318400 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$680/0x00007f4204324588 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$681/0x00007f42043247c8 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$PlaceholderPosition +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$682/0x00007f4204324c00 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$683/0x00007f4204325020 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$684/0x00007f4204325260 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$685/0x00007f42043254a8 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$686/0x00007f42043256f0 +org.junit.jupiter.params.provider.Arguments +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$687/0x00007f4204325b38 +org.junit.jupiter.params.ParameterizedInvocationContextProvider$$Lambda$688/0x00007f4204325d80 +org.junit.jupiter.engine.descriptor.TemplateExecutor$$Lambda$689/0x00007f4204325fa8 +org.junit.jupiter.params.ParameterizedTestSpiInstantiator +org.junit.jupiter.params.ParameterizedTestSpiInstantiator$$Lambda$690/0x00007f42043263e8 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$691/0x00007f4204326610 +org.junit.jupiter.params.support.AnnotationConsumerInitializer +org.junit.jupiter.params.support.AnnotationConsumerInitializer$AnnotationConsumingMethodSignature +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$692/0x00007f4204326e80 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$693/0x00007f42043270c0 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$694/0x00007f4204327310 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$695/0x00007f4204327558 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$696/0x00007f42043277b0 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$697/0x00007f4204327a00 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$698/0x00007f4204327c20 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$699/0x00007f4204328000 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$700/0x00007f4204328220 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$701/0x00007f4204328470 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$702/0x00007f42043286c8 +org.junit.jupiter.params.support.AnnotationConsumerInitializer$$Lambda$703/0x00007f4204328908 +org.junit.jupiter.params.provider.AnnotationBasedArgumentsProvider$$Lambda$704/0x00007f4204328b40 +org.junit.jupiter.engine.descriptor.TestTemplateExtensionContext$$Lambda$705/0x00007f4204328d88 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$706/0x00007f4204328fc8 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$707/0x00007f4204329210 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$708/0x00007f4204329458 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$709/0x00007f42043296a0 +org.junit.jupiter.params.provider.ArgumentsUtils +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$710/0x00007f4204329ae8 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$711/0x00007f4204329d28 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$712/0x00007f4204329f50 +org.junit.platform.commons.util.ReflectionUtils$$Lambda$713/0x00007f420432a198 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$714/0x00007f420432a3f0 +org.junit.jupiter.params.provider.MethodArgumentsProvider$$Lambda$715/0x00007f420432a618 +org.junit.jupiter.params.provider.Arguments$$Lambda$716/0x00007f420432aa38 +org.junit.jupiter.params.ParameterizedInvocationContext +org.junit.jupiter.params.ParameterizedTestInvocationContext +java.util.function.IntUnaryOperator +java.lang.invoke.LambdaForm$DMH/0x00007f420432c000 +org.junit.jupiter.params.ParameterizedInvocationContext$$Lambda$717/0x00007f420432b0d0 +org.junit.jupiter.params.EvaluatedArgumentSet +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$718/0x00007f420432b560 +java.lang.invoke.LambdaForm$DMH/0x00007f420432c400 +org.junit.jupiter.params.provider.Arguments$ArgumentSet +org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor +org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor$$Lambda$719/0x00007f420432e000 +org.junit.jupiter.api.Named +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$720/0x00007f420432e420 +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$721/0x00007f420432e660 +java.util.stream.ReferencePipeline$$Lambda$722/0x00007f420412bc70 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$MessageFormatPartialFormatter +java.util.stream.Streams$RangeIntSpliterator +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$723/0x00007f420432ead8 +java.util.stream.IntPipeline$1 +java.util.stream.IntPipeline$1$1 +org.junit.jupiter.params.ResolverFacade$$Lambda$724/0x00007f420432ed00 +org.junit.jupiter.params.ParameterizedInvocationNameFormatter$$Lambda$725/0x00007f420432ef40 +java.text.MessageFormat +java.text.MessageFormat$Field +org.junit.jupiter.engine.descriptor.TemplateExecutor$$Lambda$726/0x00007f420432f180 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$727/0x00007f420432f3b8 +org.junit.platform.launcher.core.CompositeEngineExecutionListener$$Lambda$728/0x00007f420432f5f0 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$729/0x00007f420432f818 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$730/0x00007f420432fa50 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor$$Lambda$731/0x00007f420432fc78 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DynamicTaskState +org.junit.platform.engine.support.hierarchical.NodeTestTask$DynamicTaskState$$Lambda$732/0x00007f420432d200 +org.junit.jupiter.params.ParameterizedInvocationParameterResolver +org.junit.jupiter.params.ParameterizedTestMethodParameterResolver +org.junit.jupiter.params.ResolutionCache +org.junit.jupiter.params.ResolutionCache$$Lambda$733/0x00007f420432dac0 +org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor$$Lambda$734/0x00007f420432dce0 +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$735/0x00007f420432c800 +org.junit.jupiter.params.ParameterizedInvocationContext$$Lambda$736/0x00007f420432ca40 +org.junit.jupiter.params.ParameterizedInvocationContext$$Lambda$737/0x00007f420432cc98 +org.junit.jupiter.params.ParameterizedInvocationContext$CloseableArgument +org.junit.jupiter.params.ParameterizedInvocationContext$$Lambda$738/0x00007f4204330248 +org.junit.jupiter.params.ParameterizedInvocationContext$$Lambda$739/0x00007f4204330488 +org.junit.jupiter.params.ArgumentCountValidator +org.junit.jupiter.params.ArgumentCountValidator$$Lambda$740/0x00007f42043308d8 +org.junit.jupiter.params.ArgumentCountValidator$1 +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$741/0x00007f4204330d28 +org.junit.jupiter.params.aggregator.DefaultArgumentsAccessor +org.junit.jupiter.params.aggregator.ArgumentAccessException +org.junit.jupiter.params.aggregator.DefaultArgumentsAccessor$$Lambda$742/0x00007f42043314d8 +org.junit.jupiter.params.aggregator.DefaultArgumentsAccessor$$Lambda$743/0x00007f4204331710 +org.junit.jupiter.params.support.ParameterInfo +org.junit.jupiter.params.DefaultParameterInfo +org.junit.jupiter.engine.execution.DefaultParameterContext +org.junit.jupiter.engine.execution.ParameterResolutionUtils$$Lambda$744/0x00007f4204332048 +org.mockito.junit.jupiter.resolver.CompositeParameterResolver$$Lambda$745/0x00007f42043322a0 +org.junit.jupiter.params.ResolverFacade$$Lambda$746/0x00007f42043324f8 +org.junit.jupiter.params.ResolverFacade$$Lambda$747/0x00007f4204332718 +java.lang.invoke.LambdaForm$DMH/0x00007f4204334000 +org.junit.jupiter.params.ResolverFacade$$Lambda$748/0x00007f4204332938 +java.lang.invoke.LambdaForm$DMH/0x00007f4204334400 +java.lang.invoke.LambdaForm$DMH/0x00007f4204334800 +java.lang.invoke.LambdaForm$MH/0x00007f4204334c00 +org.junit.jupiter.params.ResolverFacade$$Lambda$749/0x00007f4204332b60 +org.junit.jupiter.params.converter.ConvertWith +org.junit.jupiter.params.ResolverFacade$$Lambda$750/0x00007f4204332fa8 +org.junit.jupiter.params.converter.ArgumentConverter +org.junit.jupiter.params.ResolverFacade$$Lambda$751/0x00007f42043333e8 +org.junit.jupiter.params.ResolverFacade$$Lambda$752/0x00007f4204333630 +org.junit.jupiter.params.ResolverFacade$Converter +org.junit.jupiter.params.ResolverFacade$$Lambda$753/0x00007f4204333ab8 +org.junit.jupiter.params.ResolverFacade$$Lambda$754/0x00007f4204333cf8 +org.junit.jupiter.params.converter.DefaultArgumentConverter +org.junit.platform.commons.support.conversion.ConversionException +org.junit.jupiter.params.converter.ArgumentConversionException +org.junit.jupiter.params.converter.DefaultArgumentConverter$LocaleConversionFormat +org.junit.jupiter.params.converter.DefaultArgumentConverter$$Lambda$755/0x00007f4204336940 +org.junit.jupiter.params.ResolverFacade$ExecutableParameterDeclaration$$Lambda$756/0x00007f4204336b80 +org.junit.jupiter.params.ResolverFacade$ExecutableParameterDeclaration$$Lambda$757/0x00007f4204336dd8 +org.junit.jupiter.params.EvaluatedArgumentSet$$Lambda$758/0x00007f4204337000 +org.junit.jupiter.engine.execution.ParameterResolutionUtils$$Lambda$759/0x00007f4204337240 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$760/0x00007f4204337468 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$761/0x00007f42043376c0 +org.apache.avro.Schema$Parser +org.apache.avro.SchemaParseException +com.fasterxml.jackson.core.exc.StreamReadException +com.fasterxml.jackson.core.JsonParseException +org.apache.avro.NameValidator +org.apache.avro.NameValidator$Result +org.apache.avro.NameValidator$1 +org.apache.avro.NameValidator$2 +org.apache.avro.NameValidator$3 +org.apache.avro.ParseContext +org.apache.avro.Schema$Type +org.apache.avro.AvroTypeException +org.apache.avro.util.SchemaVisitor +org.apache.avro.SchemaParser$ParseResult +org.apache.avro.util.internal.Accessor$JsonPropertiesAccessor +org.apache.avro.JsonProperties$1 +org.apache.avro.Schema$StringSchema +org.apache.avro.Schema$BytesSchema +org.apache.avro.Schema$IntSchema +org.apache.avro.Schema$LongSchema +org.apache.avro.Schema$FloatSchema +org.apache.avro.Schema$DoubleSchema +org.apache.avro.Schema$BooleanSchema +org.apache.avro.Schema$NullSchema +org.apache.avro.Schema$MapSchema +org.apache.avro.Schema$UnionSchema +org.apache.avro.Schema$Field +org.apache.avro.Schema$ArraySchema +org.apache.avro.Schema$NamedSchema +org.apache.avro.Schema$FixedSchema +org.apache.avro.Schema$RecordSchema +org.apache.avro.Schema$EnumSchema +org.apache.avro.util.internal.Accessor +org.apache.avro.JsonProperties$Null +org.apache.avro.Schema$$Lambda$762/0x00007f420433cd10 +org.apache.avro.util.internal.ThreadLocalWithInitial +org.apache.avro.Schema$$Lambda$763/0x00007f420433d138 +org.apache.avro.Schema$$Lambda$764/0x00007f420433d358 +org.apache.avro.Schema$$Lambda$765/0x00007f420433d578 +com.fasterxml.jackson.core.io.ContentReference +com.fasterxml.jackson.core.util.BufferRecyclers +com.fasterxml.jackson.core.util.BufferRecycler +com.fasterxml.jackson.core.io.IOContext +com.fasterxml.jackson.core.util.TextBuffer +com.fasterxml.jackson.core.util.ReadConstrainedTextBuffer +com.fasterxml.jackson.core.exc.InputCoercionException +com.fasterxml.jackson.core.io.JsonEOFException +com.fasterxml.jackson.core.JsonStreamContext +com.fasterxml.jackson.core.json.JsonReadContext +com.fasterxml.jackson.core.StreamReadCapability +com.fasterxml.jackson.core.util.JacksonFeatureSet +com.fasterxml.jackson.core.JsonToken +com.fasterxml.jackson.databind.util.ArrayIterator +com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer +com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer +com.fasterxml.jackson.databind.node.ArrayNode +com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer$ObjectDeserializer +com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer$ArrayDeserializer +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$WeightedValue +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$Node +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$AddTask +com.fasterxml.jackson.databind.util.LinkedNode +com.fasterxml.jackson.databind.annotation.JsonTypeResolver +com.fasterxml.jackson.databind.deser.std.BaseNodeDeserializer$ContainerStack +com.fasterxml.jackson.core.util.InternCache +com.fasterxml.jackson.databind.node.JsonNodeType +org.apache.avro.Schema$Name +java.lang.invoke.LambdaForm$MH/0x00007f4204348000 +java.lang.invoke.LambdaForm$MH/0x00007f4204348400 +java.lang.invoke.LambdaForm$MH/0x00007f4204348800 +java.lang.invoke.LambdaForm$MH/0x00007f4204348c00 +java.lang.invoke.LambdaForm$MH/0x00007f4204349000 +java.lang.invoke.LambdaForm$MH/0x00007f4204349400 +java.lang.invoke.LambdaForm$MH/0x00007f4204349800 +org.apache.avro.JsonProperties$2 +org.apache.avro.Schema$Field$Order +org.apache.avro.util.internal.Accessor$FieldAccessor +org.apache.avro.Schema$Field$1 +org.apache.avro.Schema$$Lambda$766/0x00007f4204345390 +org.apache.avro.util.MapEntry +org.apache.avro.LogicalTypes +org.apache.avro.LogicalType +org.apache.avro.LogicalTypes$Uuid +org.apache.avro.LogicalTypes$Duration +org.apache.avro.LogicalTypes$TimestampMillis +org.apache.avro.LogicalTypes$Decimal +org.apache.avro.LogicalTypes$BigDecimal +org.apache.avro.LogicalTypes$Date +org.apache.avro.LogicalTypes$TimestampMicros +org.apache.avro.LogicalTypes$TimestampNanos +org.apache.avro.LogicalTypes$TimeMillis +org.apache.avro.LogicalTypes$TimeMicros +org.apache.avro.LogicalTypes$LocalTimestampMicros +org.apache.avro.LogicalTypes$LocalTimestampMillis +org.apache.avro.LogicalTypes$LocalTimestampNanos +org.apache.avro.LogicalTypes$LogicalTypeFactory +org.apache.avro.Schema$LockableArrayList +org.apache.avro.util.SchemaResolver$ResolvingVisitor +org.apache.avro.ParseContext$$Lambda$767/0x00007f420434c240 +org.apache.avro.ParseContext$$Lambda$768/0x00007f420434c488 +org.apache.avro.util.Schemas +org.apache.avro.util.Schemas$1 +org.apache.avro.util.SchemaVisitor$SchemaVisitorAction +org.apache.avro.util.Schemas$$Lambda$769/0x00007f420434cf10 +org.apache.avro.util.SchemaResolver +org.apache.avro.util.Schemas$$Lambda$770/0x00007f420434d360 +org.apache.avro.util.Schemas$$Lambda$771/0x00007f420434d588 +org.apache.avro.util.Schemas$$Lambda$772/0x00007f420434d7c0 +org.apache.avro.util.Schemas$$Lambda$773/0x00007f420434da00 +java.util.ArrayDeque$DescendingIterator +org.apache.avro.util.SchemaResolver$1 +org.apache.avro.JsonProperties$2$1 +org.apache.avro.JsonProperties$2$1$1 +org.apache.avro.util.SchemaResolver$ResolvingVisitor$$Lambda$774/0x00007f420434e4a0 +org.apache.avro.util.SchemaResolver$ResolvingVisitor$$Lambda$775/0x00007f420434e6d8 +org.apache.avro.util.SchemaResolver$ResolvingVisitor$$Lambda$776/0x00007f420434e910 +org.apache.avro.util.SchemaResolver$ResolvingVisitor$$Lambda$777/0x00007f420434eb48 +org.apache.avro.ParseContext$$Lambda$778/0x00007f420434ed70 +org.apache.avro.UnresolvedUnionException +org.apache.avro.AvroMissingFieldException +org.apache.avro.specific.ExternalizableInput +org.apache.avro.specific.ExternalizableOutput +org.apache.avro.util.springframework.ConcurrentReferenceHashMap +org.apache.avro.util.springframework.ConcurrentReferenceHashMap$Task +org.apache.avro.util.springframework.ConcurrentReferenceHashMap$2 +org.apache.avro.util.springframework.ConcurrentReferenceHashMap$3 +org.apache.avro.util.springframework.ConcurrentReferenceHashMap$1 +org.apache.avro.util.springframework.ConcurrentReferenceHashMap$4 +org.apache.avro.util.springframework.ConcurrentReferenceHashMap$5 +org.apache.avro.util.springframework.ConcurrentReferenceHashMap$ReferenceType +org.apache.avro.util.springframework.Assert +org.apache.avro.util.springframework.ConcurrentReferenceHashMap$Segment +org.apache.avro.util.springframework.ConcurrentReferenceHashMap$ReferenceManager +org.apache.avro.util.springframework.ConcurrentReferenceHashMap$Reference +org.apache.avro.util.Utf8 +org.apache.avro.util.internal.ClassValueCache +org.apache.avro.util.internal.ClassValueCache$1 +org.apache.avro.specific.SpecificData$$Lambda$779/0x00007f42043504a8 +org.apache.avro.specific.SpecificData$$Lambda$780/0x00007f42043506f0 +org.apache.avro.specific.SpecificData$$Lambda$781/0x00007f4204350930 +org.apache.avro.specific.SpecificData$1 +org.apache.avro.message.RawMessageEncoder +org.apache.avro.message.BinaryMessageEncoder$V1MessageEncoder +org.apache.avro.message.RawMessageEncoder$BufferOutputStream +java.security.GeneralSecurityException +java.security.NoSuchAlgorithmException +org.apache.avro.message.RawMessageEncoder$$Lambda$782/0x00007f42043514c8 +org.apache.avro.generic.GenericDatumWriter +org.apache.avro.specific.SpecificDatumWriter +org.apache.avro.path.PathTracingException +org.apache.avro.path.TracingNullPointException +org.apache.avro.path.TracingClassCastException +org.apache.avro.path.TracingAvroTypeException +org.apache.avro.path.PathElement +java.util.ConcurrentModificationException +org.apache.avro.SchemaNormalization +org.apache.avro.SchemaNormalization$1 +java.lang.invoke.LambdaForm$MH/0x00007f4204354000 +java.lang.invoke.LambdaForm$MH/0x00007f4204354400 +java.lang.invoke.LambdaForm$MH/0x00007f4204354800 +java.lang.invoke.LambdaForm$MH/0x00007f4204354c00 +java.lang.invoke.LambdaForm$MH/0x00007f4204355000 +java.lang.invoke.LambdaForm$MH/0x00007f4204355400 +org.apache.avro.SchemaNormalization$FP64 +org.apache.avro.util.ReusableByteArrayInputStream +org.apache.avro.util.ReusableByteBufferInputStream +org.apache.avro.message.BadHeaderException +org.apache.avro.message.MissingSchemaException +org.apache.avro.message.MessageDecoder$BaseDecoder$$Lambda$783/0x00007f42043538f8 +org.apache.avro.message.MessageDecoder$BaseDecoder$$Lambda$784/0x00007f4204353b18 +org.apache.avro.message.BinaryMessageDecoder$$Lambda$785/0x00007f4204353d38 +org.apache.avro.message.BinaryMessageDecoder$$Lambda$786/0x00007f4204356000 +org.apache.avro.message.RawMessageDecoder +org.apache.avro.generic.GenericDatumReader +org.apache.avro.specific.SpecificDatumReader +org.apache.avro.util.WeakIdentityHashMap +org.apache.avro.generic.GenericDatumReader$$Lambda$787/0x00007f4204356ee8 +org.apache.avro.generic.GenericDatumReader$ReaderCache +org.apache.avro.generic.GenericDatumReader$$Lambda$788/0x00007f4204357328 +java.util.Base64 +java.util.Base64$Encoder +org.apache.avro.io.EncoderFactory +org.apache.avro.io.EncoderFactory$DefaultEncoderFactory +org.apache.avro.io.DirectBinaryEncoder +org.apache.avro.io.BufferedBinaryEncoder +org.apache.avro.io.BlockingDirectBinaryEncoder +org.apache.avro.io.BlockingBinaryEncoder +org.apache.avro.io.BufferedBinaryEncoder$ByteSink +org.apache.avro.io.BufferedBinaryEncoder$OutputStreamSink +java.nio.channels.Channels +java.nio.channels.InterruptibleChannel +java.nio.channels.spi.AbstractInterruptibleChannel +java.nio.channels.Channels$WritableByteChannelImpl +org.apache.avro.generic.GenericDatumWriter$1 +org.apache.avro.io.BinaryData +org.apache.avro.io.BinaryData$Decoders +org.apache.avro.io.BinaryData$$Lambda$789/0x00007f4204358b68 +org.apache.avro.io.BinaryData$HashData +org.apache.avro.io.BinaryData$$Lambda$790/0x00007f4204358fa0 +software.amazon.lambda.powertools.kafka.testutils.TestUtils$1 +com.amazonaws.services.lambda.runtime.events.KafkaEvent +com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper +com.fasterxml.jackson.core.json.UTF8StreamJsonParser +com.fasterxml.jackson.core.io.MergedStream +com.fasterxml.jackson.core.io.UTF32Reader +java.io.CharConversionException +com.fasterxml.jackson.core.JsonEncoding +com.fasterxml.jackson.databind.type.ClassStack +com.fasterxml.jackson.databind.introspect.AnnotationCollector$OneCollector +com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector +com.fasterxml.jackson.annotation.JsonAutoDetect +com.fasterxml.jackson.annotation.JsonIdentityInfo +com.fasterxml.jackson.databind.ext.OptionalHandlerFactory +org.w3c.dom.Node +org.w3c.dom.Document +com.fasterxml.jackson.databind.ext.Java7Handlers +com.fasterxml.jackson.databind.ext.Java7HandlersImpl +com.fasterxml.jackson.databind.ext.NioPathSerializer +com.fasterxml.jackson.databind.ext.NioPathDeserializer +com.fasterxml.jackson.databind.deser.std.JdkDeserializers +com.fasterxml.jackson.databind.deser.std.FromStringDeserializer +com.fasterxml.jackson.databind.deser.std.UUIDDeserializer +com.fasterxml.jackson.databind.deser.std.AtomicBooleanDeserializer +com.fasterxml.jackson.databind.deser.std.AtomicIntegerDeserializer +com.fasterxml.jackson.databind.deser.std.AtomicLongDeserializer +com.fasterxml.jackson.databind.deser.std.ByteBufferDeserializer +com.fasterxml.jackson.databind.deser.std.NullifyingDeserializer +com.fasterxml.jackson.databind.deser.std.StdNodeBasedDeserializer +com.fasterxml.jackson.databind.deser.std.ThreadGroupDeserializer +com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$StringBuilderDeserializer +com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$StringBufferDeserializer +com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$Std +java.net.InetAddress +com.fasterxml.jackson.databind.jsontype.impl.SubTypeValidator +com.fasterxml.jackson.databind.util.BeanUtil +com.fasterxml.jackson.databind.annotation.JsonValueInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators +com.fasterxml.jackson.databind.deser.ValueInstantiator +com.fasterxml.jackson.databind.deser.ValueInstantiator$Base +com.fasterxml.jackson.databind.deser.std.JsonLocationInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$JDKValueInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$ArrayListInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$HashSetInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$LinkedListInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$TreeSetInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$LinkedHashSetInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$ConstantValueInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$LinkedHashMapInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$HashMapInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$ConcurrentHashMapInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$TreeMapInstantiator +com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$PropertiesInstantiator +com.fasterxml.jackson.core.JsonLocation +com.fasterxml.jackson.databind.introspect.PotentialCreators +com.fasterxml.jackson.databind.introspect.CollectorBase +com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector +com.fasterxml.jackson.databind.introspect.AnnotationMap +com.fasterxml.jackson.databind.introspect.TypeResolutionContext$Basic +com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector$FieldBuilder +com.fasterxml.jackson.annotation.JsonKey +com.fasterxml.jackson.annotation.JsonValue +com.fasterxml.jackson.annotation.JsonAnyGetter +com.fasterxml.jackson.annotation.JsonAnySetter +com.fasterxml.jackson.databind.PropertyName +com.fasterxml.jackson.annotation.JsonSetter +com.fasterxml.jackson.annotation.JsonProperty +com.fasterxml.jackson.annotation.JsonAutoDetect$1 +com.fasterxml.jackson.annotation.PropertyAccessor +com.fasterxml.jackson.annotation.JsonIgnore +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$WithMember +com.fasterxml.jackson.databind.AnnotationIntrospector$ReferenceProperty +com.fasterxml.jackson.databind.AnnotationIntrospector$ReferenceProperty$Type +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$Linked +com.fasterxml.jackson.databind.introspect.AnnotatedMethodCollector +com.amazonaws.services.lambda.runtime.events.KafkaEvent$KafkaEventBuilder +com.fasterxml.jackson.databind.introspect.MemberKey +com.fasterxml.jackson.databind.introspect.AnnotatedMethodCollector$MethodBuilder +com.fasterxml.jackson.databind.introspect.AnnotatedMethodMap +com.fasterxml.jackson.annotation.JsonGetter +com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector +com.fasterxml.jackson.databind.introspect.MethodGenericTypeResolver +com.fasterxml.jackson.annotation.JsonCreator +com.fasterxml.jackson.databind.introspect.PotentialCreator +com.fasterxml.jackson.annotation.JsonCreator$Mode +com.fasterxml.jackson.databind.cfg.ConstructorDetector +com.fasterxml.jackson.databind.cfg.ConstructorDetector$SingleArgConstructor +sun.reflect.generics.scope.ConstructorScope +com.amazonaws.services.lambda.runtime.events.KafkaEvent$KafkaEventRecord +com.fasterxml.jackson.databind.type.TypeBindings$TypeParamStash +com.fasterxml.jackson.databind.type.TypeBindings$AsKey +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$5 +com.fasterxml.jackson.annotation.JsonProperty$Access +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$6 +com.fasterxml.jackson.annotation.JacksonInject +com.fasterxml.jackson.databind.annotation.JsonNaming +com.fasterxml.jackson.annotation.JsonPropertyOrder +com.fasterxml.jackson.annotation.JsonPropertyDescription +com.fasterxml.jackson.databind.PropertyMetadata +com.fasterxml.jackson.databind.deser.impl.CreatorCollector +com.fasterxml.jackson.databind.deser.std.StdValueInstantiator +com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder +com.fasterxml.jackson.databind.deser.impl.ObjectIdValueProperty +com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer +com.fasterxml.jackson.annotation.JsonIgnoreProperties +com.fasterxml.jackson.annotation.JsonIgnoreProperties$Value +com.fasterxml.jackson.annotation.JsonIncludeProperties +com.fasterxml.jackson.annotation.JsonIncludeProperties$Value +com.fasterxml.jackson.databind.util.IgnorePropertiesUtil +com.fasterxml.jackson.annotation.JsonIgnoreType +com.fasterxml.jackson.databind.deser.impl.FailingDeserializer +com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider +com.fasterxml.jackson.databind.util.AccessPattern +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$2 +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$4 +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$1 +com.fasterxml.jackson.annotation.JsonAlias +com.fasterxml.jackson.annotation.JsonFormat$Feature +com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap +com.fasterxml.jackson.databind.exc.IgnoredPropertyException +com.fasterxml.jackson.databind.deser.SettableBeanProperty$Delegating +com.fasterxml.jackson.databind.deser.impl.ManagedReferenceProperty +com.fasterxml.jackson.databind.deser.impl.ObjectIdReferenceProperty +com.fasterxml.jackson.databind.deser.impl.InnerClassProperty +com.fasterxml.jackson.databind.deser.impl.MergingSettableBeanProperty +com.fasterxml.jackson.databind.deser.impl.ReadableObjectId$Referring +com.fasterxml.jackson.databind.deser.BeanDeserializer$BeanReferring +com.fasterxml.jackson.databind.deser.impl.BeanAsArrayDeserializer +com.fasterxml.jackson.databind.deser.BasicDeserializerFactory$ContainerDefaultMappings +java.util.concurrent.ConcurrentNavigableMap +java.util.concurrent.ConcurrentSkipListMap +com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringKD +com.fasterxml.jackson.databind.deser.ContextualKeyDeserializer +com.amazonaws.services.lambda.runtime.events.KafkaEvent$SchemaMetadata +com.amazonaws.services.lambda.runtime.events.KafkaEvent$KafkaEventRecord$KafkaEventRecordBuilder +sun.reflect.generics.tree.IntSignature +sun.reflect.generics.tree.LongSignature +sun.reflect.generics.tree.ByteSignature +com.fasterxml.jackson.databind.deser.std.NumberDeserializers +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$PrimitiveOrWrapperDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BooleanDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$LongDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$DoubleDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$CharacterDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$ByteDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$ShortDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$FloatDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$NumberDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BigDecimalDeserializer +com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BigIntegerDeserializer +com.amazonaws.services.lambda.runtime.events.KafkaEvent$SchemaMetadata$SchemaMetadataBuilder +jdk.internal.reflect.GeneratedMethodAccessor8 +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$IntDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$LongDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$ByteDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$ShortDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$FloatDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$DoubleDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$BooleanDeser +com.fasterxml.jackson.databind.deser.std.PrimitiveArrayDeserializers$CharDeser +com.fasterxml.jackson.databind.exc.InvalidNullException +com.fasterxml.jackson.databind.annotation.JacksonStdImpl +com.fasterxml.jackson.annotation.JacksonAnnotation +jdk.proxy2.$Proxy73 +com.fasterxml.jackson.core.io.NumberInput +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializer$SchemaRegistryType +java.util.Base64$Decoder +org.apache.avro.specific.SpecificData$2 +org.apache.avro.specific.SpecificData$$Lambda$791/0x00007f420437eb90 +org.apache.avro.util.MapUtil +org.apache.avro.util.MapUtil$$Lambda$792/0x00007f420437efe0 +org.apache.avro.util.ClassUtils +org.apache.avro.io.DecoderFactory +org.apache.avro.io.DecoderFactory$DefaultDecoderFactory +org.apache.avro.io.DirectBinaryDecoder +org.apache.avro.InvalidNumberEncodingException +org.apache.avro.io.BinaryDecoder$ByteSource +org.apache.avro.io.BinaryDecoder$InputStreamByteSource +org.apache.avro.io.BinaryDecoder$ByteArrayByteSource +org.apache.avro.io.BinaryDecoder$BufferAccessor +org.apache.avro.util.WeakIdentityHashMap$IdentityWeakReference +org.apache.avro.io.parsing.ValidatingGrammarGenerator +org.apache.avro.io.parsing.ResolvingGrammarGenerator +org.apache.avro.util.internal.Accessor$ResolvingGrammarGeneratorAccessor +org.apache.avro.io.parsing.ResolvingGrammarGenerator$1 +org.apache.avro.io.parsing.Symbol +org.apache.avro.io.parsing.Symbol$ImplicitAction +org.apache.avro.io.parsing.Symbol$SkipAction +org.apache.avro.Resolver +org.apache.avro.Resolver$Action +org.apache.avro.Resolver$DoNothing +org.apache.avro.Resolver$ErrorAction +org.apache.avro.Resolver$Container +org.apache.avro.Resolver$1 +org.apache.avro.Resolver$RecordAdjust +org.apache.avro.Schema$SeenPair +org.apache.avro.Resolver$Action$Type +org.apache.avro.generic.GenericData$InstanceSupplier +java.lang.invoke.LambdaForm$DMH/0x00007f4204384000 +org.apache.avro.generic.GenericData$$Lambda$793/0x00007f4204380200 +org.apache.avro.Resolver$Skip +org.apache.avro.Resolver$Promote +org.apache.avro.Resolver$ReaderUnion +org.apache.avro.Resolver$EnumAdjust +org.apache.avro.io.parsing.Symbol$Terminal +org.apache.avro.io.parsing.Symbol$WriterUnionAction +org.apache.avro.io.parsing.Symbol$Repeater +org.apache.avro.io.parsing.Symbol$ResolvingAction +org.apache.avro.io.parsing.Symbol$Root +org.apache.avro.io.parsing.Symbol$Sequence +org.apache.avro.io.parsing.Symbol$ErrorAction +org.apache.avro.io.parsing.Symbol$Alternative +org.apache.avro.io.parsing.Symbol$Kind +org.apache.avro.io.parsing.Symbol$FieldOrderAction +org.apache.avro.io.parsing.ResolvingGrammarGenerator$2 +org.apache.avro.io.parsing.Parser +org.apache.avro.io.parsing.SkipParser +org.apache.avro.generic.GenericDatumReader$1 +org.apache.avro.generic.GenericData$StringType +org.apache.avro.specific.SpecificData$SchemaConstructable +org.apache.avro.generic.GenericDatumReader$IdentitySchemaKey +org.apache.avro.generic.GenericDatumReader$ReaderCache$$Lambda$794/0x00007f4204383748 +org.apache.avro.specific.SpecificDatumReader$1 +org.apache.avro.SystemLimitException +org.apache.kafka.common.header.internals.RecordHeaders +org.apache.kafka.common.header.Header +org.apache.kafka.clients.consumer.ConsumerRecord +org.apache.kafka.common.record.TimestampType +org.apache.kafka.common.TopicPartition +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializer$$Lambda$795/0x00007f4204386b98 +org.assertj.core.api.FactoryBasedNavigableIterableAssert +org.assertj.core.api.IterableAssert +org.assertj.core.api.AbstractIterableSizeAssert +org.assertj.core.api.IterableSizeAssert +org.assertj.core.api.AssertFactory +org.assertj.core.api.IterableAssert$$Lambda$796/0x00007f4204387b40 +org.assertj.core.internal.Iterables +org.assertj.core.internal.Predicates +org.assertj.core.api.ListAssert$$Lambda$797/0x00007f420438b3e0 +org.assertj.core.internal.Lists +org.assertj.core.util.IterableUtil +org.assertj.core.internal.WholeNumbers +org.assertj.core.internal.Numbers +org.assertj.core.internal.Integers +org.assertj.core.internal.RealNumbers +org.assertj.core.internal.Doubles +org.assertj.core.internal.ComparatorBasedComparisonStrategy +org.junit.jupiter.engine.descriptor.TestTemplateExtensionContext$$Lambda$798/0x00007f420438cdf8 +org.junit.platform.engine.support.hierarchical.NodeTestTask$DefaultDynamicTestExecutor$$Lambda$799/0x00007f420438d038 +com.amazonaws.services.lambda.runtime.serialization.factories.PojoSerializerFactory +com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory +com.amazonaws.services.lambda.runtime.serialization.PojoSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.Versioned +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.Module +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.module.SimpleModule +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.JavaTimeModule +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.Jdk8Module +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.TokenStreamFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.DataOutputAsStream +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.SerializableString +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.TSFBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonFactoryBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.async.NonBlockingInputFeeder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.async.ByteBufferFeeder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.base.ParserMinimalBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.base.ParserBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.async.NonBlockingJsonParserBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.async.NonBlockingUtf8JsonParserBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.async.NonBlockingByteBufferJsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.UTF8DataInputJsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.ReaderBasedJsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.base.GeneratorBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.JsonGeneratorImpl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.WriterBasedJsonGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.UTF8JsonGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.UTF8Writer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.async.ByteArrayFeeder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.async.NonBlockingJsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.JacksonFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonFactory$Feature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonParser$Feature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonGenerator$Feature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.PrettyPrinter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.Instantiatable +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.DefaultPrettyPrinter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.DefaultPrettyPrinter$Indenter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.SerializedString +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.JsonStringEncoder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.CharTypes +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.FormatFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.JsonReadFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.JsonWriteFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer$TableInfo +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer$Bucket +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer$TableInfo +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.TreeCodec +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.ObjectCodec +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectMapper +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.json.JsonMapper +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.MappingJsonFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.SubtypeResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.DatabindContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.SerializerProvider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.DefaultSerializerProvider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.DefaultSerializerProvider$Impl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.DeserializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BasicDeserializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.DeserializationContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.DefaultDeserializationContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.DefaultDeserializationContext$Impl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.SerializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BasicSerializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BeanSerializerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.AnnotationIntrospector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy$Provider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy$Provider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.StdDateFormat +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JacksonException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonProcessingException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.DatabindException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonMappingException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.SegmentedStringWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.ByteArrayBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.TreeNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonSerializable +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonSerializable$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.BaseJsonNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.ValueNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.NullNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.ClassIntrospector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.BasicClassIntrospector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.Module$SetupContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.VisibilityChecker +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.TreeTraversingParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.TokenBuffer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.type.ResolvedType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JavaType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.ArrayType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.CollectionLikeType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.CollectionType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.MapLikeType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.MapType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.MismatchedInputException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.Annotated +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.TypeResolutionContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedClass +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedMember +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.VirtualAnnotatedMember +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.Named +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.SimpleBeanPropertyDefinition +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.BeanProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.ConcreteBeanPropertyBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.PropertyWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BeanPropertyWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedWithParams +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedMethod +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonSerialize +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonView +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFormat +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonTypeInfo +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonRawValue +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonUnwrapped +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonBackReference +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonManagedReference +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonDeserialize +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonMerge +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7Support +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.ClassUtil +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.ClassUtil$Ctor +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.LookupCache +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.LRUMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$Builder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.Linked +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.LinkedDeque +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$2 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$DrainStatus$3 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.BaseSettings +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.SimpleType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.PlaceholderForType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.ReferenceType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.ResolvedRecursiveType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeBindings +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.Base64Variants +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.Base64Variant +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.Base64Variant$PaddingReadBehaviour +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AccessorNamingStrategy +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.DefaultAccessorNamingStrategy$RecordNaming +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.MapperBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.json.JsonMapper$Builder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.RootNameLookup +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.ClassIntrospector$MixInResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.SimpleMixInResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.BeanDescription +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.BasicBeanDescription +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.MapperConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.MapperConfigBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.SerializationConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.DeserializationConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedClassResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.Annotations +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationCollector$EmptyCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationCollector$NoAnnotations +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedClass$Creators +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedConstructor +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedParameter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConfigOverrides +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JacksonAnnotationValue +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonInclude$Value +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonInclude$Include +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonSetter$Value +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.Nulls +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.VisibilityChecker$Std +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAutoDetect$Visibility +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.CoercionConfigs +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.LogicalType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.CoercionAction +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.CoercionConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.MutableCoercionConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.CoercionInputShape +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.DefaultBaseTypeLimitingValidator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFormat$Value +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFormat$Shape +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFormat$Features +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConfigOverride +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConfigOverride$Empty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConfigFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.MapperFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.DefaultPrettyPrinter$NopIndenter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.DefaultPrettyPrinter$FixedSpaceIndenter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.DefaultIndenter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.Separators +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.SerializationFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.DatatypeFeatures +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.DatatypeFeatures$DefaultHolder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.DatatypeFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.EnumFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.JsonNodeFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ContextAttributes +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ContextAttributes$Impl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.DeserializationFeature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.JsonNodeCreator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.JsonNodeFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.MissingNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.BooleanNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.NumericNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.DecimalNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.DoubleNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.IntNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.ShortNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.FloatNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.LongNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.BigIntegerNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.TextNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.BinaryNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.POJONode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsonschema.SchemaAware +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NullSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.FailingSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ToEmptyObjectSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.UnknownSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.ContextualSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.InvalidDefinitionException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.InvalidTypeIdException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.ContainerNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.ObjectNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.ResolvableSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.SerializerCache +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.NullValueProvider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.JsonDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.PropertyBindingException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.InvalidFormatException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.ValueInstantiationException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.UnresolvedForwardReference +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ContextualDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ResolvableDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiator$Gettable +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.EnumMapDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.AbstractDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.MapDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StringDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.MapEntryDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.TokenBufferDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.SettableBeanProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.CreatorProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.EnumDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ReferenceTypeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.AtomicReferenceDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StringArrayDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.EnumSetDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.CollectionDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ArrayBlockingQueueDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StringCollectionDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.MethodProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.FieldProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.SetterlessProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.ErrorThrowingDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.ObjectIdGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.ObjectIdGenerators$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.ObjectIdGenerators$PropertyGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.PropertyBasedObjectIdGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyName +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializerModifier +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.AbstractTypeResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiators +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.KeyDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.KeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$DelegatingKD +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$EnumKD +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringCtorKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdKeyDeserializer$StringFactoryKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.DeserializerCache +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.JsonValueSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.SerializableSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdScalarSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.DateTimeSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.CalendarSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.DateSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ByteBufferSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.InetAddressSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.InetSocketAddressSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.TimeZoneSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ToStringSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ToStringSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.ContainerSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.CollectionSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StaticListSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.IndexedStringListSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.StringCollectionSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.EnumSetSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.MapSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.MapEntrySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ArraySerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.StringArraySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ReferenceTypeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.IteratorSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.IterableSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.EnumSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.BeanSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BeanSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedField +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StringSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$IntegerSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonParser$NumberType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$LongSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$IntLikeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$ShortSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$DoubleSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$FloatSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.BooleanSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.BooleanSerializer$AsNumber +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializer$BigDecimalAsStringSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdJdkSerializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.UUIDSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicBooleanSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicIntegerSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.StdJdkSerializers$AtomicLongSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.FileSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.ClassSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.TokenBufferSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BeanSerializerModifier +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.JSR310DeserializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.JSR310DateTimeDeserializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.DurationDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.MonthDayDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.OffsetTimeDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.YearDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.YearMonthDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.JSR310SerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.JSR310FormattedSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.DurationSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializerBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.MonthDaySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.OffsetDateTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.OffsetTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.YearSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.YearMonthSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.ZoneIdSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.key.ZonedDateTimeKeySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.Jsr310KeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.DurationKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.InstantKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.LocalDateTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.LocalDateKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.LocalTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.MonthDayKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.OffsetDateTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.OffsetTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.PeriodKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.YearKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.YearMonthKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.ZonedDateTimeKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.ZoneIdKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.key.ZoneOffsetKeyDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.PackageVersion +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.VersionUtil +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.Version +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.exc.StreamReadException +java.util.regex.Pattern$BnM +java.util.regex.Pattern$Pos +java.time.format.DateTimeFormatter +java.time.format.DateTimeFormatterBuilder +java.time.temporal.TemporalQuery +java.time.format.DateTimeFormatterBuilder$$Lambda$10/0x80000000e +java.time.temporal.IsoFields +java.time.temporal.IsoFields$Field +java.time.temporal.IsoFields$Field$1 +java.time.temporal.IsoFields$Field$2 +java.time.temporal.IsoFields$Field$3 +java.time.temporal.IsoFields$Field$4 +java.time.temporal.IsoFields$Unit +java.time.temporal.JulianFields +java.time.temporal.JulianFields$Field +java.time.format.SignStyle +java.time.format.DateTimeFormatterBuilder$DateTimePrinterParser +java.time.format.DateTimeFormatterBuilder$NumberPrinterParser +java.time.format.DateTimeFormatterBuilder$CharLiteralPrinterParser +java.time.format.ResolverStyle +java.time.chrono.Chronology +java.time.chrono.AbstractChronology +java.time.chrono.IsoChronology +java.time.format.DateTimeFormatterBuilder$CompositePrinterParser +java.time.format.DecimalStyle +java.time.format.DateTimeFormatterBuilder$SettingsParser +java.time.format.DateTimeFormatterBuilder$OffsetIdPrinterParser +java.time.format.DateTimeFormatterBuilder$FractionPrinterParser +java.time.format.DateTimeFormatterBuilder$ZoneIdPrinterParser +java.time.format.DateTimeFormatterBuilder$StringLiteralPrinterParser +java.time.format.DateTimeFormatterBuilder$InstantPrinterParser +java.time.format.TextStyle +java.time.format.DateTimeTextProvider$LocaleStore +java.time.format.DateTimeTextProvider +java.time.format.DateTimeTextProvider$1 +java.time.format.DateTimeFormatterBuilder$1 +java.time.format.DateTimeFormatterBuilder$TextPrinterParser +java.time.chrono.ChronoPeriod +java.time.Period +java.time.format.DateTimeFormatter$$Lambda$8/0x80000000c +java.time.format.DateTimeFormatter$$Lambda$9/0x80000000d +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$803/0x00007f42043e9648 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$FromIntegerArguments +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$804/0x00007f42043e9a98 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$FromDecimalArguments +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$805/0x00007f42043e9ee8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$806/0x00007f42043ea128 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$807/0x00007f42043ea358 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$808/0x00007f42043ea598 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$809/0x00007f42043ea7d8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$810/0x00007f42043eaa18 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$811/0x00007f42043eac48 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$812/0x00007f42043eae88 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$813/0x00007f42043eb0c8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer$$Lambda$814/0x00007f42043eb308 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.module.SimpleDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.ClassKey +java.time.MonthDay +java.time.OffsetTime +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.deser.JSR310StringParsableDeserializer +java.time.Year +java.time.YearMonth +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.module.SimpleSerializers +java.util.function.ToLongFunction +java.lang.invoke.LambdaForm$DMH/0x00007f42043f0000 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer$$Lambda$815/0x00007f42043ec758 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer$$Lambda$816/0x00007f42043ec978 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer$$Lambda$817/0x00007f42043ecb98 +java.lang.invoke.LambdaForm$DMH/0x00007f42043f0400 +java.lang.invoke.LambdaForm$DMH/0x00007f42043f0800 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.OffsetDateTimeSerializer$$Lambda$818/0x00007f42043ecdb8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.OffsetDateTimeSerializer$$Lambda$819/0x00007f42043ecfd8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.OffsetDateTimeSerializer$$Lambda$820/0x00007f42043ed1f8 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer$$Lambda$821/0x00007f42043ed418 +java.lang.invoke.LambdaForm$DMH/0x00007f42043f0c00 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer$$Lambda$822/0x00007f42043ed638 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.ser.ZonedDateTimeSerializer$$Lambda$823/0x00007f42043ed858 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.module.SimpleKeyDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectMapper$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.ArrayBuilders +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiators$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jsr310.JavaTimeModule$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeModifier +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.Jdk8TypeModifier +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.Jdk8BeanSerializerModifier +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.PackageVersion +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.Jdk8Serializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalIntSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalLongSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalDoubleSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.LongStreamSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.IntStreamSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.DoubleStreamSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.StreamSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.Jdk8Deserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.BaseScalarOptionalDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalIntDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalLongDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.datatype.jdk8.OptionalDoubleDeserializer +com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory$InternalSerializer +com.amazonaws.services.lambda.runtime.serialization.factories.JacksonFactory$TypeSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.ClassStack +java.util.OptionalLong +java.util.OptionalDouble +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$WeightedValue +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$Node +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$AddTask +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectReader +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.filter.TokenFilter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.filter.JsonPointerBasedFilter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.node.ArrayNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.JsonParserDelegate +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.filter.FilteringParserDelegate +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonParseException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationCollector$OneCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAutoDetect +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIdentityInfo +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.ArrayIterator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.OptionalHandlerFactory +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7Handlers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.NioPathSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.NioPathDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.JdkDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.FromStringDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.UUIDDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.AtomicBooleanDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.AtomicIntegerDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.AtomicLongDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.ByteBufferDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NullifyingDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$StringBuilderDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$StringBufferDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.FromStringDeserializer$Std +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.jsontype.impl.SubTypeValidator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.BeanUtil +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonValueInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.ValueInstantiator$Base +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.JsonLocationInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$ArrayListInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$ConstantValueInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$LinkedHashMapInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators$HashMapInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonLocation +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConstructorDetector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.cfg.ConstructorDetector$SingleArgConstructor +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.CreatorCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.StdValueInstantiator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.CollectorBase +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotationMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.TypeResolutionContext$Basic +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector$FieldBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonKey +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonValue +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAnyGetter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAnySetter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.InternCache +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonSetter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAutoDetect$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.PropertyAccessor +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIgnore +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$WithMember +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.AnnotationIntrospector$ReferenceProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.AnnotationIntrospector$ReferenceProperty$Type +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$Linked +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedMethodCollector +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.MemberKey +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedMethodCollector$MethodBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedMethodMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonGetter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector +sun.reflect.generics.tree.DoubleSignature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeBindings$TypeParamStash +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.type.TypeBindings$AsKey +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$5 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonProperty$Access +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$6 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JacksonInject +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonNaming +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonPropertyOrder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonPropertyDescription +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.PropertyMetadata +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BasicDeserializerFactory$CreatorCollectionState +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonCreator +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonCreator$Mode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.ObjectIdValueProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BuilderBasedDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIgnoreProperties +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIgnoreProperties$Value +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIncludeProperties +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIncludeProperties$Value +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.IgnorePropertiesUtil +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonIgnoreType +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonTypeResolver +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.FailingDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.NullsConstantProvider +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.AccessPattern +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$2 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$4 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonAlias +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFormat$Feature +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.IgnoredPropertyException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.SettableBeanProperty$Delegating +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.ManagedReferenceProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.ObjectIdReferenceProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.InnerClassProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.MergingSettableBeanProperty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.ReadableObjectId$Referring +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BeanDeserializer$BeanReferring +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.impl.BeanAsArrayDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$PrimitiveOrWrapperDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$IntegerDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BooleanDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$LongDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$DoubleDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$CharacterDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$ByteDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$ShortDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$FloatDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$NumberDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BigDecimalDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.std.NumberDeserializers$BigIntegerDeserializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.BasicDeserializerFactory$ContainerDefaultMappings +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.LinkedNode +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JacksonStdImpl +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JacksonAnnotation +jdk.proxy2.$Proxy74 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.MinimalPrettyPrinter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectWriter$GeneratorSettings +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ObjectWriter$Prefetch +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.RuntimeJsonMappingException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonEncoding +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.ContentReference +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.IOContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.BufferRecyclers +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.BufferRecycler +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.exc.StreamWriteException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonGenerationException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonStreamContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.JsonWriteContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.StreamWriteCapability +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.JacksonFeatureSet +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap$Bucket +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.TypeKey +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap$$Lambda$824/0x00007f4204413340 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$EntrySet +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$EntryIterator +java.util.stream.LongStream +java.util.stream.DoubleStream +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.BeanSerializerBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.PropertyBuilder +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonInclude +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$3 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonTypeId +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.BeanProperty$Std +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.PropertyBuilder$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Empty +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Single +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.annotation.JsonAppend +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.annotation.JsonFilter +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.BeanAsArraySerializer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.std.NumberSerializers$1 +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.NumberOutput +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$SerializerAndMapResult +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Double +org.assertj.core.internal.Strings$$Lambda$825/0x00007f42044178b8 +org.assertj.core.internal.Strings$$Lambda$826/0x00007f4204417b10 +jdk.internal.reflect.GeneratedConstructorAccessor11 +com.google.protobuf.RuntimeVersion$RuntimeDomain +com.google.protobuf.RuntimeVersion +com.google.protobuf.RuntimeVersion$ProtobufRuntimeVersionException +com.google.protobuf.AbstractParser +com.google.protobuf.UnknownFieldSet$Parser +com.google.protobuf.AbstractMessageLite$Builder$LimitedInputStream +com.google.protobuf.Protobuf +com.google.protobuf.SchemaFactory +com.google.protobuf.ManifestSchemaFactory +com.google.protobuf.MessageInfoFactory +com.google.protobuf.ManifestSchemaFactory$1 +com.google.protobuf.ManifestSchemaFactory$CompositeMessageInfoFactory +com.google.protobuf.GeneratedMessageInfoFactory +com.google.protobuf.DescriptorMessageInfoFactory +com.google.protobuf.Internal$EnumVerifier +com.google.protobuf.MessageInfo +com.google.protobuf.DescriptorMessageInfoFactory$IsInitializedCheckAnalyzer +com.google.protobuf.FieldType +com.google.protobuf.Internal$EnumLite +com.google.protobuf.ProtocolMessageEnum +com.google.protobuf.DescriptorProtos$Edition +com.google.protobuf.ProtoSyntax +com.google.protobuf.DescriptorMessageInfoFactory$OneofState +com.google.protobuf.FieldInfo +com.google.protobuf.Internal +com.google.protobuf.CodedInputStream$ArrayDecoder +com.google.protobuf.CodedInputStream$UnsafeDirectNioDecoder +com.google.protobuf.CodedInputStream$IterableDirectByteBufferDecoder +com.google.protobuf.IterableByteBufferInputStream +com.google.protobuf.CodedInputStream$StreamDecoder +com.google.protobuf.InvalidProtocolBufferException$InvalidWireTypeException +com.google.protobuf.ExtensionRegistryFactory +com.google.protobuf.ExtensionRegistry$ExtensionInfo +com.google.protobuf.Extension$ExtensionType +software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct$1 +com.google.protobuf.CodedOutputStream$AbstractBufferedEncoder +com.google.protobuf.CodedOutputStream$OutputStreamEncoder +com.google.protobuf.CodedOutputStream$ByteOutputEncoder +com.google.protobuf.CodedOutputStream$ArrayEncoder +com.google.protobuf.CodedOutputStream$HeapNioEncoder +com.google.protobuf.Utf8$UnpairedSurrogateException +com.google.protobuf.CodedOutputStream$OutOfSpaceException +com.google.protobuf.CodedOutputStream$UnsafeDirectNioEncoder +com.google.protobuf.CodedOutputStream$SafeDirectNioEncoder +com.google.protobuf.Writer +com.google.protobuf.UnsafeUtil +com.google.protobuf.UnsafeUtil$MemoryAccessor +com.google.protobuf.UnsafeUtil$Android64MemoryAccessor +com.google.protobuf.UnsafeUtil$Android32MemoryAccessor +com.google.protobuf.UnsafeUtil$JvmMemoryAccessor +com.google.protobuf.UnsafeUtil$1 +sun.misc.Unsafe +com.google.protobuf.Android +jdk.internal.access.foreign.MemorySegmentProxy +com.google.protobuf.WireFormat +com.google.protobuf.Utf8 +com.google.protobuf.Utf8$Processor +com.google.protobuf.Utf8$UnsafeProcessor +com.google.protobuf.Utf8$SafeProcessor +software.amazon.lambda.powertools.kafka.serializers.KafkaProtobufDeserializer$1 +com.fasterxml.jackson.core.exc.StreamWriteException +com.fasterxml.jackson.core.JsonGenerationException +com.fasterxml.jackson.core.json.JsonWriteContext +com.fasterxml.jackson.core.StreamWriteCapability +com.fasterxml.jackson.core.FormatFeature +com.fasterxml.jackson.core.json.JsonWriteFeature +com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap +com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap$Bucket +com.fasterxml.jackson.databind.util.TypeKey +com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap$$Lambda$827/0x00007f4204423ad8 +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$EntrySet +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$EntryIterator +com.fasterxml.jackson.databind.ObjectReader +com.fasterxml.jackson.databind.ObjectWriter +com.fasterxml.jackson.databind.ser.BeanSerializerBuilder +com.fasterxml.jackson.databind.ser.PropertyBuilder +com.fasterxml.jackson.annotation.JsonInclude +com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder$3 +com.fasterxml.jackson.annotation.JsonTypeId +com.fasterxml.jackson.databind.BeanProperty$Std +com.fasterxml.jackson.databind.ser.PropertyBuilder$1 +com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanPropertyWriter +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Empty +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Single +com.fasterxml.jackson.databind.annotation.JsonAppend +com.fasterxml.jackson.annotation.JsonFilter +com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer +com.fasterxml.jackson.databind.ser.impl.BeanAsArraySerializer +com.fasterxml.jackson.databind.ser.std.NumberSerializers$1 +com.fasterxml.jackson.databind.ser.AnyGetterWriter +com.fasterxml.jackson.core.io.NumberOutput +sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$SerializerAndMapResult +com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap$Double +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.UTF8StreamJsonParser +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.MergedStream +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.UTF32Reader +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.exc.InputCoercionException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.JsonEOFException +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.json.JsonReadContext +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.StreamReadCapability +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.util.TextBuffer +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.JsonToken +com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.core.io.NumberInput +org.assertj.core.util.Lists$$Lambda$828/0x00007f420442b718 +org.assertj.core.util.Preconditions +org.assertj.core.internal.IterableDiff +org.assertj.core.internal.IterableDiff$$Lambda$829/0x00007f420442bd58 +org.assertj.core.internal.StandardComparisonStrategy$$Lambda$830/0x00007f420442bfb0 +java.util.AbstractMap$SimpleEntry +com.fasterxml.jackson.databind.util.internal.PrivateMaxEntriesMap$WriteThroughEntry +com.fasterxml.jackson.core.StreamReadFeature +software.amazon.lambda.powertools.kafka.testutils.StringHandler +software.amazon.lambda.powertools.kafka.testutils.DefaultHandler +jdk.internal.reflect.GeneratedConstructorAccessor12 +software.amazon.lambda.powertools.kafka.DeserializationTest$1TestHandler +org.assertj.core.api.AbstractClassAssert +org.assertj.core.api.ClassAssert +org.assertj.core.internal.Classes +org.assertj.core.api.AbstractObjectArrayAssert +org.assertj.core.api.ObjectArrayAssert +org.assertj.core.internal.ObjectArrays +org.assertj.core.internal.Arrays +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$831/0x00007f420442fc20 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$832/0x00007f4204435150 +org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$833/0x00007f4204435370 +org.junit.jupiter.engine.extension.TimeoutExtension$$Lambda$834/0x00007f4204435598 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$835/0x00007f42044357f0 +org.junit.jupiter.engine.extension.TimeoutConfiguration$$Lambda$836/0x00007f4204435a18 +software.amazon.lambda.powertools.kafka.serializers.KafkaJsonDeserializerTest$$Lambda$837/0x00007f4204435c40 +software.amazon.lambda.powertools.kafka.serializers.KafkaProtobufDeserializerTest$$Lambda$838/0x00007f4204435e68 +org.apache.kafka.common.utils.ByteUtils +software.amazon.lambda.powertools.kafka.serializers.KafkaProtobufDeserializerTest$$Lambda$839/0x00007f4204436298 +software.amazon.lambda.powertools.kafka.serializers.KafkaAvroDeserializerTest$$Lambda$840/0x00007f42044364c0 +software.amazon.lambda.powertools.kafka.serializers.KafkaAvroDeserializerTest$$Lambda$841/0x00007f42044366e8 +java.util.AbstractMap$2 +java.util.AbstractMap$2$1 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$842/0x00007f4204436b08 +org.assertj.core.util.Throwables +org.assertj.core.util.Throwables$$Lambda$843/0x00007f4204436f38 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$844/0x00007f4204437178 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$845/0x00007f42044373a0 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$846/0x00007f42044375c8 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$847/0x00007f42044377f0 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$848/0x00007f4204437a18 +jdk.internal.reflect.GeneratedConstructorAccessor13 +jdk.internal.reflect.GeneratedMethodAccessor9 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$849/0x00007f4204437c40 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$850/0x00007f4204432000 +jdk.internal.reflect.GeneratedMethodAccessor10 +com.fasterxml.jackson.databind.util.ArrayBuilders +com.fasterxml.jackson.databind.util.PrimitiveArrayBuilder +com.fasterxml.jackson.databind.util.ArrayBuilders$ByteBuilder +org.apache.kafka.common.header.internals.RecordHeader +jdk.internal.reflect.GeneratedConstructorAccessor14 +jdk.internal.reflect.GeneratedMethodAccessor11 +jdk.internal.reflect.GeneratedConstructorAccessor15 +jdk.internal.reflect.GeneratedMethodAccessor12 +jdk.internal.reflect.GeneratedMethodAccessor13 +jdk.internal.reflect.GeneratedMethodAccessor14 +jdk.internal.reflect.GeneratedMethodAccessor15 +jdk.internal.reflect.GeneratedMethodAccessor16 +jdk.internal.reflect.GeneratedMethodAccessor17 +jdk.internal.reflect.GeneratedMethodAccessor18 +jdk.internal.reflect.GeneratedMethodAccessor19 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$851/0x00007f4204432ce0 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$852/0x00007f4204432f08 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$853/0x00007f4204433130 +software.amazon.lambda.powertools.kafka.serializers.AbstractKafkaDeserializerTest$$Lambda$854/0x00007f4204433358 +jdk.internal.reflect.GeneratedConstructorAccessor16 +jdk.internal.reflect.GeneratedConstructorAccessor17 +jdk.internal.reflect.GeneratedMethodAccessor20 +jdk.internal.reflect.GeneratedMethodAccessor21 +jdk.internal.reflect.GeneratedMethodAccessor22 +jdk.internal.reflect.GeneratedMethodAccessor23 +jdk.internal.reflect.GeneratedConstructorAccessor18 +jdk.internal.reflect.GeneratedMethodAccessor24 +jdk.internal.reflect.GeneratedMethodAccessor25 +jdk.internal.reflect.GeneratedMethodAccessor26 +jdk.internal.reflect.GeneratedMethodAccessor27 +jdk.internal.reflect.GeneratedMethodAccessor28 +org.junit.platform.launcher.core.OutcomeDelayingEngineExecutionListener$Outcome +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$855/0x00007f4204433bb8 +org.junit.platform.launcher.core.CompositeTestExecutionListener$$Lambda$856/0x00007f420443e000 +java.lang.invoke.LambdaForm$DMH/0x00007f420443cc00 +org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$857/0x00007f420443e228 +org.junit.platform.launcher.core.DefaultLauncherSession$ClosedLauncher +org.apache.maven.surefire.api.suite.RunResult +org.apache.maven.surefire.booter.ForkedBooter$6 +org.apache.maven.surefire.booter.ForkedBooter$7 +java.util.concurrent.locks.AbstractQueuedSynchronizer$SharedNode +org.apache.maven.surefire.booter.ForkedBooter$1 +org.apache.maven.surefire.booter.spi.AbstractMasterProcessChannelProcessorFactory$2 +java.util.concurrent.locks.AbstractQueuedSynchronizer$ExclusiveNode diff --git a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializerTest.java b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializerTest.java index 6ce57ecd5..d7d045877 100644 --- a/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializerTest.java +++ b/powertools-kafka/src/test/java/software/amazon/lambda/powertools/kafka/PowertoolsSerializerTest.java @@ -13,7 +13,9 @@ package software.amazon.lambda.powertools.kafka; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; import static software.amazon.lambda.powertools.kafka.testutils.TestUtils.createConsumerRecordsType; import static software.amazon.lambda.powertools.kafka.testutils.TestUtils.serializeAvro; @@ -30,6 +32,8 @@ import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.clients.consumer.ConsumerRecords; import org.apache.kafka.common.TopicPartition; +import org.crac.Context; +import org.crac.Resource; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; @@ -62,7 +66,7 @@ static Stream<InputType> inputTypes() { @ParameterizedTest @MethodSource("inputTypes") @SetEnvironmentVariable(key = "_HANDLER", value = "") - void shouldUseDefaultDeserializerWhenHandlerNotFound(InputType inputType) throws JsonProcessingException { + void shouldUseDefaultDeserializerWhenHandlerNotFound(InputType inputType) throws JsonProcessingException, IOException { // When PowertoolsSerializer serializer = new PowertoolsSerializer(); @@ -73,8 +77,9 @@ void shouldUseDefaultDeserializerWhenHandlerNotFound(InputType inputType) throws // This will use the Lambda default deserializer (no Kafka logic) TestProductPojo result; if (inputType == InputType.INPUT_STREAM) { - ByteArrayInputStream input = new ByteArrayInputStream(json.getBytes()); - result = serializer.fromJson(input, TestProductPojo.class); + try (ByteArrayInputStream input = new ByteArrayInputStream(json.getBytes())) { + result = serializer.fromJson(input, TestProductPojo.class); + } } else { result = serializer.fromJson(json, TestProductPojo.class); } @@ -88,7 +93,7 @@ void shouldUseDefaultDeserializerWhenHandlerNotFound(InputType inputType) throws @ParameterizedTest @MethodSource("inputTypes") @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.DefaultHandler::handleRequest") - void shouldUseLambdaDefaultDeserializer(InputType inputType) throws JsonProcessingException { + void shouldUseLambdaDefaultDeserializer(InputType inputType) throws JsonProcessingException, IOException { // When PowertoolsSerializer serializer = new PowertoolsSerializer(); @@ -99,8 +104,9 @@ void shouldUseLambdaDefaultDeserializer(InputType inputType) throws JsonProcessi // This will use the Lambda default deserializer (no Kafka logic) TestProductPojo result; if (inputType == InputType.INPUT_STREAM) { - ByteArrayInputStream input = new ByteArrayInputStream(json.getBytes()); - result = serializer.fromJson(input, TestProductPojo.class); + try (ByteArrayInputStream input = new ByteArrayInputStream(json.getBytes())) { + result = serializer.fromJson(input, TestProductPojo.class); + } } else { result = serializer.fromJson(json, TestProductPojo.class); } @@ -134,30 +140,28 @@ void shouldHandleInputStreamType() throws IOException { // Then String testInput = "This is a test string"; - ByteArrayInputStream inputStream = new ByteArrayInputStream(testInput.getBytes()); - - // This should return the input stream directly - InputStream result = serializer.fromJson(inputStream, InputStream.class); - - // Read the content to verify it's the same - String resultString = new String(result.readAllBytes()); - assertThat(resultString).isEqualTo(testInput); + try (ByteArrayInputStream inputStream = new ByteArrayInputStream(testInput.getBytes()); + InputStream result = serializer.fromJson(inputStream, InputStream.class)) { + // Read the content to verify it's the same + String resultString = new String(result.readAllBytes()); + assertThat(resultString).isEqualTo(testInput); + } } @Test - void shouldConvertInputStreamToString() { + void shouldConvertInputStreamToString() throws IOException { // When LambdaDefaultDeserializer deserializer = new LambdaDefaultDeserializer(); // Then String expected = "This is a test string"; - ByteArrayInputStream inputStream = new ByteArrayInputStream(expected.getBytes()); - - // Convert InputStream to String - String result = deserializer.fromJson(inputStream, String.class); + try (ByteArrayInputStream inputStream = new ByteArrayInputStream(expected.getBytes())) { + // Convert InputStream to String + String result = deserializer.fromJson(inputStream, String.class); - // Verify the result - assertThat(result).isEqualTo(expected); + // Verify the result + assertThat(result).isEqualTo(expected); + } } @Test @@ -166,7 +170,7 @@ void shouldThrowRuntimeExceptionWhenInputStreamIsInvalid() { LambdaDefaultDeserializer deserializer = new LambdaDefaultDeserializer(); // Create a problematic InputStream that throws IOException when read - InputStream problematicStream = new InputStream() { + try (InputStream problematicStream = new InputStream() { @Override public int read() throws IOException { throw new IOException("Simulated IO error"); @@ -176,12 +180,14 @@ public int read() throws IOException { public byte[] readAllBytes() throws IOException { throw new IOException("Simulated IO error"); } - }; - - // Then - assertThatThrownBy(() -> deserializer.fromJson(problematicStream, String.class)) - .isInstanceOf(RuntimeException.class) - .hasMessageContaining("Failed to read input stream as String"); + }) { + // Then + assertThatThrownBy(() -> deserializer.fromJson(problematicStream, String.class)) + .isInstanceOf(RuntimeException.class) + .hasMessageContaining("Failed to read input stream as String"); + } catch (IOException e) { + // Expected for this test case + } } @Test @@ -203,7 +209,7 @@ void shouldConvertStringToByteArray() { @ParameterizedTest @MethodSource("inputTypes") @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.JsonHandler::handleRequest") - void shouldUseKafkaJsonDeserializer(InputType inputType) throws JsonProcessingException { + void shouldUseKafkaJsonDeserializer(InputType inputType) throws IOException { // When PowertoolsSerializer serializer = new PowertoolsSerializer(); @@ -237,8 +243,9 @@ void shouldUseKafkaJsonDeserializer(InputType inputType) throws JsonProcessingEx ConsumerRecords<String, TestProductPojo> records; if (inputType == InputType.INPUT_STREAM) { - ByteArrayInputStream input = new ByteArrayInputStream(kafkaJson.getBytes()); - records = serializer.fromJson(input, type); + try (ByteArrayInputStream input = new ByteArrayInputStream(kafkaJson.getBytes())) { + records = serializer.fromJson(input, type); + } } else { records = serializer.fromJson(kafkaJson, type); } @@ -298,8 +305,9 @@ void shouldUseKafkaAvroDeserializer(InputType inputType) throws IOException { ConsumerRecords<String, software.amazon.lambda.powertools.kafka.serializers.test.avro.TestProduct> records; if (inputType == InputType.INPUT_STREAM) { - ByteArrayInputStream input = new ByteArrayInputStream(kafkaJson.getBytes()); - records = serializer.fromJson(input, type); + try (ByteArrayInputStream input = new ByteArrayInputStream(kafkaJson.getBytes())) { + records = serializer.fromJson(input, type); + } } else { records = serializer.fromJson(kafkaJson, type); } @@ -326,7 +334,7 @@ void shouldUseKafkaAvroDeserializer(InputType inputType) throws IOException { @ParameterizedTest @MethodSource("inputTypes") @SetEnvironmentVariable(key = "_HANDLER", value = "software.amazon.lambda.powertools.kafka.testutils.ProtobufHandler::handleRequest") - void shouldUseKafkaProtobufDeserializer(InputType inputType) { + void shouldUseKafkaProtobufDeserializer(InputType inputType) throws IOException { // When PowertoolsSerializer serializer = new PowertoolsSerializer(); @@ -365,8 +373,9 @@ void shouldUseKafkaProtobufDeserializer(InputType inputType) { ConsumerRecords<String, software.amazon.lambda.powertools.kafka.serializers.test.protobuf.TestProduct> records; if (inputType == InputType.INPUT_STREAM) { - ByteArrayInputStream input = new ByteArrayInputStream(kafkaJson.getBytes()); - records = serializer.fromJson(input, type); + try (ByteArrayInputStream input = new ByteArrayInputStream(kafkaJson.getBytes())) { + records = serializer.fromJson(input, type); + } } else { records = serializer.fromJson(kafkaJson, type); } @@ -414,4 +423,18 @@ void shouldDelegateToJsonOutput() { private enum InputType { INPUT_STREAM, STRING } + + @Test + void testBeforeCheckpointDoesNotThrowException() { + PowertoolsSerializer serializer = new PowertoolsSerializer(); + Context<Resource> context = mock(Context.class); + assertThatNoException().isThrownBy(() -> serializer.beforeCheckpoint(context)); + } + + @Test + void testAfterRestoreDoesNotThrowException() { + PowertoolsSerializer serializer = new PowertoolsSerializer(); + Context<Resource> context = mock(Context.class); + assertThatNoException().isThrownBy(() -> serializer.afterRestore(context)); + } } From fab11efc8828fd49366c96df8d94a7574bed4b04 Mon Sep 17 00:00:00 2001 From: Connor Kirkpatrick <17845406+ConnorKirk@users.noreply.github.com> Date: Fri, 17 Oct 2025 13:11:31 +0100 Subject: [PATCH 466/577] chore: update contributing.md (#2203) --- CONTRIBUTING.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c4330cf8e..080643027 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,6 +21,9 @@ Thank you for your interest in contributing to our project. Whether it's a [bug report](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=bug%2C+triage&projects=&template=bug_report.md&title=Bug%3A+TITLE), [new feature](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=feature-request%2C+triage&projects=&template=feature_request.md&title=Feature+request%3A+TITLE) or [additional documentation](https://github.com/aws-powertools/powertools-lambda-java/issues/new?assignees=&labels=documentation%2Ctriage&projects=&template=documentation_improvements.yml&title=Docs%3A+TITLE), we greatly value feedback and contributions from our community. <!-- markdownlint-enable MD013 --> +We encourage contributions from the community and we will work with contributors to merge their pull requests. +Rarely, we may close pull requests that do not meet our guidelines specified in CONTRIBUTING.md, or will require unreasonable effort to meet our quality bar. + Please read through this document before submitting any issues or pull requests to ensure we have all the necessary information to effectively respond to your bug report or contribution. From 0fa97ec29d0f2ec46e9462cb84aff608e24e9c03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:20:54 +0200 Subject: [PATCH 467/577] chore: bump com.google.protobuf:protobuf-java from 4.32.1 to 4.33.0 (#2198) Bumps [com.google.protobuf:protobuf-java](https://github.com/protocolbuffers/protobuf) from 4.32.1 to 4.33.0. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl) - [Commits](https://github.com/protocolbuffers/protobuf/commits) --- updated-dependencies: - dependency-name: com.google.protobuf:protobuf-java dependency-version: 4.33.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 6527bf278..d7778c896 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -12,7 +12,7 @@ <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> <avro.version>1.12.0</avro.version> - <protobuf.version>4.32.1</protobuf.version> + <protobuf.version>4.33.0</protobuf.version> </properties> <dependencies> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 3dae1ffd2..a6a090b5d 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -36,7 +36,7 @@ <properties> <kafka-clients.version>4.1.0</kafka-clients.version> <avro.version>1.12.0</avro.version> - <protobuf.version>4.32.1</protobuf.version> + <protobuf.version>4.33.0</protobuf.version> <lambda-serialization.version>1.1.6</lambda-serialization.version> </properties> From eeea68dc9ca6c179b843f9a1281b89615d663c58 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:21:12 +0200 Subject: [PATCH 468/577] chore: bump aws.sdk.version from 2.35.7 to 2.35.8 (#2197) Bumps `aws.sdk.version` from 2.35.7 to 2.35.8. Updates `software.amazon.awssdk:bom` from 2.35.7 to 2.35.8 Updates `software.amazon.awssdk:http-client-spi` from 2.35.7 to 2.35.8 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.35.8 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.35.8 Updates `software.amazon.awssdk:dynamodb` from 2.35.7 to 2.35.8 Updates `software.amazon.awssdk:lambda` from 2.35.7 to 2.35.8 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.35.8 Updates `software.amazon.awssdk:cloudwatch` from 2.35.7 to 2.35.8 Updates `software.amazon.awssdk:xray` from 2.35.7 to 2.35.8 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.35.8 Updates `software.amazon.awssdk:cloudformation` from 2.35.7 to 2.35.8 Updates `software.amazon.awssdk:sts` from 2.35.7 to 2.35.8 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.35.8 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.35.8 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.35.8 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.35.8 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.35.8 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.35.8 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.35.8 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.35.8 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.35.8 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.35.8 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.35.8 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.35.8 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index bc3084990..39f09da04 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.35.7</aws.sdk.version> + <aws.sdk.version>2.35.8</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 0feecd82b..e77ca1620 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.35.7</aws.sdk.version> + <aws.sdk.version>2.35.8</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index f7c78c131..b67207e75 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.0</maven.compiler.version> - <aws.sdk.version>2.35.7</aws.sdk.version> + <aws.sdk.version>2.35.8</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From faa915b8124247aba600c111c17738a8ad7daff4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:21:30 +0200 Subject: [PATCH 469/577] chore: bump org.sonatype.central:central-publishing-maven-plugin (#2196) Bumps [org.sonatype.central:central-publishing-maven-plugin](https://github.com/sonatype/central-publishing-maven-plugin) from 0.8.0 to 0.9.0. - [Commits](https://github.com/sonatype/central-publishing-maven-plugin/commits) --- updated-dependencies: - dependency-name: org.sonatype.central:central-publishing-maven-plugin dependency-version: 0.9.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e77ca1620..8bed88cd0 100644 --- a/pom.xml +++ b/pom.xml @@ -524,7 +524,7 @@ <plugin> <groupId>org.sonatype.central</groupId> <artifactId>central-publishing-maven-plugin</artifactId> - <version>0.8.0</version> + <version>0.9.0</version> <extensions>true</extensions> <configuration> <publishingServerId>central</publishingServerId> From 291f2b48778a93b2a850535309d169abb082a0ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:21:54 +0200 Subject: [PATCH 470/577] chore: bump sam/build-java21 (#2201) Bumps sam/build-java21 from `1d40149` to `e12c501`. --- updated-dependencies: - dependency-name: sam/build-java21 dependency-version: e12c501aa7d3d3dc04be0d900115a0339c73f523ad73a9aecd9e99499413c465 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index e82e5d33e..7dc04ec90 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:1d40149444f21a5b20e8f54275f9173265d57522ff8669fa3f8fefbaf24657da +FROM public.ecr.aws/sam/build-java21@sha256:e12c501aa7d3d3dc04be0d900115a0339c73f523ad73a9aecd9e99499413c465 # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From d0cdebd659d7cf0cff8159c6ffb0d79c277cf451 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 10:34:25 +0200 Subject: [PATCH 471/577] chore: bump github/codeql-action from 4.30.8 to 4.30.9 (#2209) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.8 to 4.30.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f443b600d91635bebf5b0d9ebc620189c0d6fba5...16140ae1a102900babc80a33c44059580f687047) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.30.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index bd9f16d74..d4df1e675 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v3.29.5 + uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v3.29.5 with: sarif_file: results.sarif From dd7a49c25a6193a729a68dcb03f9d3f33af44920 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 21 Oct 2025 11:13:34 +0200 Subject: [PATCH 472/577] Fix flaky unit tests. (#2211) --- .../json/resolver/PowerToolsResolverFactoryTest.java | 8 ++++++-- .../json/resolver/PowertoolsResolverArgumentsTest.java | 10 +++++++--- .../logging/log4j/BufferingAppenderTest.java | 6 +++++- .../logging/internal/LambdaEcsEncoderTest.java | 6 +++++- .../logging/internal/LambdaJsonEncoderTest.java | 6 +++++- .../powertools/logging/internal/KeyBufferTest.java | 9 +++++++-- .../logging/internal/LambdaLoggingAspectTest.java | 6 +++++- 7 files changed, 40 insertions(+), 11 deletions(-) diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java index b279d7d93..7eeffc78f 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java @@ -58,8 +58,12 @@ void setUp() throws IllegalAccessException, IOException { @AfterEach void cleanUp() throws IOException { - FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); - FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // file may not exist on the first launch + } } @Test diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java index 5432e45ae..546d54579 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java @@ -59,9 +59,13 @@ void setUp() throws IOException { @AfterEach void cleanUp() throws IOException { - // Make sure file is cleaned up before running full stack logging regression - FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); - FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + try { + // Make sure file is cleaned up before running full stack logging regression + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } } @Test diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppenderTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppenderTest.java index 434d3983b..a0fac8d7a 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppenderTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/software/amazon/lambda/powertools/logging/log4j/BufferingAppenderTest.java @@ -36,7 +36,11 @@ void setUp() throws IOException { @AfterEach void cleanUp() throws IOException { - FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } } @Test diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java index db3248b56..898abec2e 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java @@ -63,7 +63,11 @@ void setUp() throws IllegalAccessException, IOException { @AfterEach void cleanUp() throws IOException { - FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + try { + FileChannel.open(Paths.get("target/ecslogfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // file may not exist on the first launch + } } @Test diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 9ea275627..326fa4b19 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -85,7 +85,11 @@ void setUp() throws IllegalAccessException, IOException { @AfterEach void cleanUp() throws IOException { - FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // file may not exist on the first launch + } } @Test diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/KeyBufferTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/KeyBufferTest.java index 15a54fa5c..fac85e230 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/KeyBufferTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/KeyBufferTest.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.PrintStream; import java.nio.channels.FileChannel; +import java.nio.file.NoSuchFileException; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.Deque; @@ -44,7 +45,7 @@ void setUp() throws IOException { // Clean up log file before each test try { FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); - } catch (IOException e) { + } catch (NoSuchFileException e) { // may not be there in the first run } } @@ -52,7 +53,11 @@ void setUp() throws IOException { @AfterEach void cleanUp() throws IOException { // Make sure file is cleaned up after each test - FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } } @Test diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index c9baab1d8..f77997a77 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -126,7 +126,11 @@ void setUp() throws IllegalAccessException, NoSuchMethodException, InvocationTar @AfterEach void cleanUp() throws IOException { // Make sure file is cleaned up before running full stack logging regression - FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } } @Test From 87851cec37a42e6edb68510f7dc86114642b98ca Mon Sep 17 00:00:00 2001 From: Simon Thulbourn <sthulb@users.noreply.github.com> Date: Tue, 21 Oct 2025 11:26:58 +0200 Subject: [PATCH 473/577] chore(ci): fix changelog generation (#2207) * chore(ci): fix changelog generation * update change log on release * update to use sha256 --------- Co-authored-by: Philipp Page <github@philipp.page> --- .chglog/CHANGELOG.tpl.md | 67 ++ .chglog/config.yml | 37 + .github/workflows/release.yml | 3 +- CHANGELOG.md | 1293 ++++++++++++++++++++++++++------- 4 files changed, 1121 insertions(+), 279 deletions(-) create mode 100644 .chglog/CHANGELOG.tpl.md create mode 100644 .chglog/config.yml diff --git a/.chglog/CHANGELOG.tpl.md b/.chglog/CHANGELOG.tpl.md new file mode 100644 index 000000000..beb340ad6 --- /dev/null +++ b/.chglog/CHANGELOG.tpl.md @@ -0,0 +1,67 @@ +<!-- changelog is partially generated, so it doesn't follow headings and required structure, so we disable it. --> +<!-- markdownlint-disable --> + +{{ if .Versions -}} +<a name="unreleased"></a> +# Unreleased + +{{ if .Unreleased.CommitGroups -}} +{{ range .Unreleased.CommitGroups -}} +## {{ .Title }} + +{{ range .Commits -}} +{{ if and (not (hasPrefix .Subject "changelog rebuild")) (not (hasPrefix .Subject "layer docs update")) (not (hasPrefix .Subject "bump version to")) -}} +* {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end -}} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} + +{{ range .Versions }} +<a name="{{ .Tag.Name }}"></a> +## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }} +{{ range .CommitGroups -}} + +## {{ .Title }} + +{{ range .Commits -}} +{{ if and (not (hasPrefix .Subject "changelog rebuild")) (not (hasPrefix .Subject "layer docs update")) (not (hasPrefix .Subject "bump version to")) -}} +* {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }} +{{ end -}} +{{ end }} +{{ end -}} + +{{- if .RevertCommits -}} +## Reverts +{{ range .RevertCommits -}} +* {{ .Revert.Header }} +{{ end }} +{{ end -}} + +{{- if .MergeCommits -}} +## Pull Requests + +{{ range .MergeCommits -}} +* {{ .Header }} +{{ end }} +{{ end -}} + +{{- if .NoteGroups -}} +{{ range .NoteGroups -}} +## {{ .Title }} +{{ range .Notes }} +{{ .Body }} +{{ end }} +{{ end -}} +{{ end -}} +{{ end -}} + +{{- if .Versions }} +[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD +{{ range .Versions -}} +{{ if .Tag.Previous -}} +[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }} +{{ end -}} +{{ end -}} +{{ end -}} diff --git a/.chglog/config.yml b/.chglog/config.yml new file mode 100644 index 000000000..4b78ec16e --- /dev/null +++ b/.chglog/config.yml @@ -0,0 +1,37 @@ +style: github +template: CHANGELOG.tpl.md +info: + title: CHANGELOG + repository_url: https://github.com/aws-powertools/powertools-lambda-java +options: + commits: + filters: + Type: + - feat + - fix + - perf + - refactor + - docs + - chore + - revert + commit_groups: + title_maps: + feat: Features + fix: Bug Fixes + perf: Performance Improvements + refactor: Code Refactoring + docs: Documentation + chore: Maintenance + revert: Regression + header: + pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$" + pattern_maps: + - Type + - Scope + - Subject + notes: + keywords: + - BREAKING CHANGE + # issues: + # prefix: + # - # diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d1f094f86..c6a3e415b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -240,9 +240,10 @@ jobs: git config pull.rebase true git config remote.origin.url >&- - id: branch - name: Create branch + name: Create branch and update change log run: | git checkout -b ci-${{ github.run_id }} + docker run -v "${PWD}":/workdir quay.io/git-chglog/git-chglog:sha256:c791b1e8264387690cce4ce32e18b4f59ca3ffd8d55cb4093dc6de74529493f4 > CHANGELOG.md git commit -am "chore(ci): bump version to ${{ inputs.version }}" git push origin ci-${{ github.run_id }} - id: create_pr diff --git a/CHANGELOG.md b/CHANGELOG.md index 20a04c488..a07df5d3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,378 +1,1115 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -This project follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format for changes and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - - - -## [Unreleased] - -## [1.20.1] - 2025-04-08 - -* docs: fix 2 typos (#1739) by @ntestor -* docs: Correct XML formatting for Maven configuration in Large Messages utility docs (#1796) by @jreijn -* fix: Load version.properties file as resource stream to fix loading when packaged as jar (#1813) by @phipag - -## [1.20.0] - 2025-03-25 - -* feat(cfn-custom-resource): Add optional 'reason' field for detailed failure reporting (#1758) by @moizsh - -## [1.19.0] - 2025-03-07 - -* chore(deps): Update deps for jackson ([#1793](https://github.com/aws-powertools/powertools-lambda-java/pull/1793)) by [@sthulb](https://github.com/sthulb) -* build(deps): bump log4j.version from 2.22.1 to 2.24.3 ([#1777](https://github.com/aws-powertools/powertools-lambda-java/pull/1777)) by [@dependabot](https://github.com/dependabot) -* chore(deps): update JSII to 1.108 ([#1791](https://github.com/aws-powertools/powertools-lambda-java/pull/1791)) by [@sthulb](https://github.com/sthulb) -* build(deps): bump jinja2 from 3.1.5 to 3.1.6 in /docs ([#1789](https://github.com/aws-powertools/powertools-lambda-java/pull/1789)) by [@dependabot](https://github.com/dependabot) -* chore: Update netty version ([#1768](https://github.com/aws-powertools/powertools-lambda-java/pull/1768)) by [@sthulb](https://github.com/sthulb) -* chore: Set versions of transitive dependencies ([#1767](https://github.com/aws-powertools/powertools-lambda-java/pull/1767)) by [@sthulb](https://github.com/sthulb) -* chore: update Jackson in examples ([#1766](https://github.com/aws-powertools/powertools-lambda-java/pull/1766)) by [@sthulb](https://github.com/sthulb) -* build(deps): bump org.apache.maven.plugins:maven-jar-plugin from 3.4.1 to 3.4.2 ([#1731](https://github.com/aws-powertools/powertools-lambda-java/pull/1731)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.xray.recorder.version from 2.15.3 to 2.18.1 ([#1726](https://github.com/aws-powertools/powertools-lambda-java/pull/1726)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.26.29 to 2.27.12 ([#1724](https://github.com/aws-powertools/powertools-lambda-java/pull/1724)) by [@dependabot](https://github.com/dependabot) -* fix: Allow empty responses as well as null response in AppConfig ([#1673](https://github.com/aws-powertools/powertools-lambda-java/pull/1673)) by [@chrisclayson](https://github.com/chrisclayson) -* build(deps): bump aws.sdk.version from 2.27.2 to 2.27.7 ([#1715](https://github.com/aws-powertools/powertools-lambda-java/pull/1715)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.26.29 to 2.27.2 ([#1714](https://github.com/aws-powertools/powertools-lambda-java/pull/1714)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.25.26 to 2.26.29 ([#1713](https://github.com/aws-powertools/powertools-lambda-java/pull/1713)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.26.25 to 2.26.29 ([#1712](https://github.com/aws-powertools/powertools-lambda-java/pull/1712)) by [@dependabot](https://github.com/dependabot) -* chore: deprecate java1.8 al1 ([#1706](https://github.com/aws-powertools/powertools-lambda-java/pull/1706)) by [@jeromevdl](https://github.com/jeromevdl) -* chore: java 1.8 AL1 is deprecated, fix E2E tests ([#1692](https://github.com/aws-powertools/powertools-lambda-java/pull/1692)) by [@jeromevdl](https://github.com/jeromevdl) -* build(deps): bump aws.sdk.version from 2.26.21 to 2.26.25 ([#1703](https://github.com/aws-powertools/powertools-lambda-java/pull/1703)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.26.3 to 2.26.21 ([#1697](https://github.com/aws-powertools/powertools-lambda-java/pull/1697)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump jackson.version from 2.17.0 to 2.17.2 ([#1696](https://github.com/aws-powertools/powertools-lambda-java/pull/1696)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.apache.commons:commons-lang3 from 3.13.0 to 3.14.0 ([#1694](https://github.com/aws-powertools/powertools-lambda-java/pull/1694)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump commons-io:commons-io from 2.15.1 to 2.16.1 ([#1691](https://github.com/aws-powertools/powertools-lambda-java/pull/1691)) by [@dependabot](https://github.com/dependabot) -* docs: improve tracing doc for sdk instrumentation ([#1687](https://github.com/aws-powertools/powertools-lambda-java/pull/1687)) by [@jeromevdl](https://github.com/jeromevdl) -* docs: fix tracing links for xray ([#1686](https://github.com/aws-powertools/powertools-lambda-java/pull/1686)) by [@jeromevdl](https://github.com/jeromevdl) -* build(deps): bump org.apache.maven.plugins:maven-failsafe-plugin from 3.2.5 to 3.3.0 ([#1679](https://github.com/aws-powertools/powertools-lambda-java/pull/1679)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.25.69 to 2.26.3 ([#1658](https://github.com/aws-powertools/powertools-lambda-java/pull/1658)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump com.github.spotbugs:spotbugs-maven-plugin from 4.7.3.6 to 4.8.5.0 ([#1657](https://github.com/aws-powertools/powertools-lambda-java/pull/1657)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.apache.maven.plugins:maven-checkstyle-plugin from 3.3.0 to 3.4.0 ([#1653](https://github.com/aws-powertools/powertools-lambda-java/pull/1653)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.25.50 to 2.25.69 ([#1652](https://github.com/aws-powertools/powertools-lambda-java/pull/1652)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.apache.maven.plugins:maven-source-plugin from 3.3.0 to 3.3.1 ([#1646](https://github.com/aws-powertools/powertools-lambda-java/pull/1646)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.assertj:assertj-core from 3.25.3 to 3.26.0 ([#1644](https://github.com/aws-powertools/powertools-lambda-java/pull/1644)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.xray.recorder.version from 2.15.1 to 2.15.3 ([#1643](https://github.com/aws-powertools/powertools-lambda-java/pull/1643)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.25.35 to 2.25.50 ([#1642](https://github.com/aws-powertools/powertools-lambda-java/pull/1642)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump com.amazonaws:aws-lambda-java-events from 3.11.2 to 3.11.4 ([#1597](https://github.com/aws-powertools/powertools-lambda-java/pull/1597)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.24.10 to 2.25.6 ([#1603](https://github.com/aws-powertools/powertools-lambda-java/pull/1603)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.apache.maven.plugins:maven-surefire-plugin from 3.1.2 to 3.2.5 ([#1596](https://github.com/aws-powertools/powertools-lambda-java/pull/1596)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.codehaus.mojo:exec-maven-plugin from 3.1.0 to 3.2.0 ([#1585](https://github.com/aws-powertools/powertools-lambda-java/pull/1585)) by [@dependabot](https://github.com/dependabot) -* build(deps-dev): bump software.amazon.awscdk:aws-cdk-lib from 2.100.0 to 2.130.0 ([#1586](https://github.com/aws-powertools/powertools-lambda-java/pull/1586)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump io.burt:jmespath-jackson from 0.5.1 to 0.6.0 ([#1587](https://github.com/aws-powertools/powertools-lambda-java/pull/1587)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.21.0 to 2.24.10 ([#1581](https://github.com/aws-powertools/powertools-lambda-java/pull/1581)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump commons-io:commons-io from 2.13.0 to 2.15.1 ([#1584](https://github.com/aws-powertools/powertools-lambda-java/pull/1584)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.xray.recorder.version from 2.14.0 to 2.15.1 ([#1583](https://github.com/aws-powertools/powertools-lambda-java/pull/1583)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.apache.maven.plugins:maven-shade-plugin from 3.5.0 to 3.5.2 ([#1582](https://github.com/aws-powertools/powertools-lambda-java/pull/1582)) by [@dependabot](https://github.com/dependabot) -* build(deps-dev): bump org.yaml:snakeyaml from 2.1 to 2.2 ([#1400](https://github.com/aws-powertools/powertools-lambda-java/pull/1400)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump log4j.version from 2.20.0 to 2.22.1 ([#1547](https://github.com/aws-powertools/powertools-lambda-java/pull/1547)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.apache.maven.plugins:maven-artifact-plugin from 3.4.1 to 3.5.0 ([#1485](https://github.com/aws-powertools/powertools-lambda-java/pull/1485)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump com.amazonaws:aws-lambda-java-serialization from 1.1.2 to 1.1.5 ([#1573](https://github.com/aws-powertools/powertools-lambda-java/pull/1573)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.jacoco:jacoco-maven-plugin from 0.8.10 to 0.8.11 ([#1509](https://github.com/aws-powertools/powertools-lambda-java/pull/1509)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aspectj to 1.9.21 for jdk21 ([#1536](https://github.com/aws-powertools/powertools-lambda-java/pull/1536)) by [@jeromevdl](https://github.com/jeromevdl) -* docs: HelloWorldStreamFunction in examples fails with sam ([#1532](https://github.com/aws-powertools/powertools-lambda-java/pull/1532)) by [@jasoniharris](https://github.com/jasoniharris) -* chore: Testing java21 aspectj pre-release ([#1519](https://github.com/aws-powertools/powertools-lambda-java/pull/1519)) by [@scottgerring](https://github.com/scottgerring) -* fix: LargeMessageIdempotentE2ET Flaky ([#1518](https://github.com/aws-powertools/powertools-lambda-java/pull/1518)) by [@scottgerring](https://github.com/scottgerring) -* build(deps): bump software.amazon.payloadoffloading:payloadoffloading-common from 2.1.3 to 2.2.0 ([#1639](https://github.com/aws-powertools/powertools-lambda-java/pull/1639)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.apache.maven.plugins:maven-jar-plugin from 3.3.0 to 3.4.1 ([#1638](https://github.com/aws-powertools/powertools-lambda-java/pull/1638)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump jackson.version from 2.15.3 to 2.17.0 ([#1637](https://github.com/aws-powertools/powertools-lambda-java/pull/1637)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.25.31 to 2.25.35 ([#1629](https://github.com/aws-powertools/powertools-lambda-java/pull/1629)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.25.16 to 2.25.31 ([#1625](https://github.com/aws-powertools/powertools-lambda-java/pull/1625)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.21.1 to 2.25.26 ([#1622](https://github.com/aws-powertools/powertools-lambda-java/pull/1622)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.apache.maven.plugins:maven-failsafe-plugin from 3.1.2 to 3.2.5 ([#1619](https://github.com/aws-powertools/powertools-lambda-java/pull/1619)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump com.fasterxml.jackson.datatype:jackson-datatype-joda from 2.15.2 to 2.17.0 ([#1616](https://github.com/aws-powertools/powertools-lambda-java/pull/1616)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump aws.sdk.version from 2.25.6 to 2.25.16 ([#1613](https://github.com/aws-powertools/powertools-lambda-java/pull/1613)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.apache.maven.plugins:maven-gpg-plugin from 3.1.0 to 3.2.1 ([#1610](https://github.com/aws-powertools/powertools-lambda-java/pull/1610)) by [@dependabot](https://github.com/dependabot) -* build(deps): bump org.assertj:assertj-core from 3.24.2 to 3.25.3 ([#1609](https://github.com/aws-powertools/powertools-lambda-java/pull/1609)) by [@dependabot](https://github.com/dependabot) - -## [1.18.0] - 2023-11-16 - -### Added - -* feat: add support for [Lambda Advanced Logging Controls (ALC)](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced) (#1514) by @jeromevdl -* feat: Add support for POWERTOOLS_LOGGER_LOG_EVENT (#1510) by @AlexeySoshin - -### Maintenance - -* fix: json schema 403 error (#1457) by @jeromevdl -* fix: array jmespath fail in idempotency module (#1420) by @jeromevdl -* chore: java21 support in our build (#1488) by @jeromevdl -* chore: Addition of Warn Message If Invalid Annotation Key While Tracing #1511 (#1512) by @jdoherty -* fix: null namespace should fallback to default namespace (#1506) by @jeromevdl -* fix: get trace id from system property when env var is not set (#1503) by @mriccia -* chore: artifacts size on good branches (#1493) by @jeromevdl -* fix: enforce jackson databind version (#1472) by @jeromevdl -* chore: add missing projects and improve workflow (#1487) by @jeromevdl -* chore: Reporting size of the jars in GitHub comments (#1196) by @jeromevdl -* Deps: Bump third party dependencies to the latest versions. - -### Documentation - -* docs(customer-reference): add Vertex Pharmaceuticals as a customer reference (#1486) by @scottgerring -* docs: Adding Kotlin example. (#1454) by @jasoniharris -* docs: Terraform example (#1478) by @skal111 -* docs: Add Serveless Framework example (#1363) by @AlexeySoshin -* docs: Fix link to SQS large message migration guide (#1422) by @scottgerring -* docs(logging): correct log example keys (#1411) by @walmsles -* docs: Update gradle configuration readme (#1359) by @scottgerring - -## [1.17.0] - 2023-08-21 - -### Added -* Feat: Add Batch Processor module in (#1317) by @scottgerring -* Feat: Add SNS+SQS large messages module (#1310) by @jeromevdl - -### Maintenance -* fix: use default credentials provider for all provided SDK clients in (#1303) by @roamingthings -* Chore: Make request for Logger explicitly for current class in (#1307) by @jreijn -* Chore: checkstyle formater & linter in (#1316) by @jeromevdl -* Chore: Add powertools specific user-agent-suffix to the AWS SDK v2 clients by @eldimi in (#1306) -* Chore: Add 'v2' branch to build workflows to prepare for v2 work in (#1341) by @scottgerring -* Deps: Bump third party dependencies to the latest versions. - -### Documentation -* Docs: Add maintainers guide in (#1326) by @scottgerring -* Docs: improve contributing guide in (#1334) by @jeromevdl -* Docs: Improve example documentation in (#1291) by @scottgerring -* Docs: Add discord + sec disclosure links to readme in (#1311) by @scottgerring -* Docs: Add external examples from AWS SAM CLI App Templates in (#1318) by @AlexeySoshin -* Docs: Add CDK example in (#1321) by @AlexeySoshin +<!-- changelog is partially generated, so it doesn't follow headings and required structure, so we disable it. --> +<!-- markdownlint-disable --> + +<a name="unreleased"></a> +# Unreleased + +## Documentation + +* **logger:** Fix logging environment variables names in documentation ([#2161](https://github.com/aws-powertools/powertools-lambda-java/issues/2161)) + +## Features + +* add CRaC priming support to powertools-kafka module ([#2145](https://github.com/aws-powertools/powertools-lambda-java/issues/2145)) +* **metrics:** introduce Metrics.flushMetrics ([#2154](https://github.com/aws-powertools/powertools-lambda-java/issues/2154)) + +## Maintenance + +* bump aws.sdk.version from 2.35.6 to 2.35.7 ([#2190](https://github.com/aws-powertools/powertools-lambda-java/issues/2190)) +* bump com.networknt:json-schema-validator from 1.5.8 to 1.5.9 ([#2189](https://github.com/aws-powertools/powertools-lambda-java/issues/2189)) +* bump sam/build-java21 ([#2195](https://github.com/aws-powertools/powertools-lambda-java/issues/2195)) +* bump squidfunk/mkdocs-material in /docs ([#2194](https://github.com/aws-powertools/powertools-lambda-java/issues/2194)) +* bump com.github.spotbugs:spotbugs-maven-plugin ([#2192](https://github.com/aws-powertools/powertools-lambda-java/issues/2192)) +* bump software.amazon.awscdk:aws-cdk-lib from 2.214.0 to 2.220.0 ([#2191](https://github.com/aws-powertools/powertools-lambda-java/issues/2191)) +* bump io.github.ascopes:protobuf-maven-plugin ([#2193](https://github.com/aws-powertools/powertools-lambda-java/issues/2193)) +* bump aws.xray.recorder.version from 2.19.0 to 2.20.0 ([#2185](https://github.com/aws-powertools/powertools-lambda-java/issues/2185)) +* bump aws.sdk.version from 2.33.2 to 2.33.5 ([#2132](https://github.com/aws-powertools/powertools-lambda-java/issues/2132)) +* bump org.apache.maven.plugins:maven-javadoc-plugin ([#2186](https://github.com/aws-powertools/powertools-lambda-java/issues/2186)) +* bump org.assertj:assertj-core from 3.27.4 to 3.27.6 ([#2184](https://github.com/aws-powertools/powertools-lambda-java/issues/2184)) +* bump aws.sdk.version from 2.34.9 to 2.35.6 ([#2183](https://github.com/aws-powertools/powertools-lambda-java/issues/2183)) +* bump actions/dependency-review-action from 4.8.0 to 4.8.1 ([#2180](https://github.com/aws-powertools/powertools-lambda-java/issues/2180)) +* bump github/codeql-action from 3.30.5 to 4.30.8 ([#2179](https://github.com/aws-powertools/powertools-lambda-java/issues/2179)) +* bump aws-actions/configure-aws-credentials from 5.0.0 to 5.1.0 ([#2177](https://github.com/aws-powertools/powertools-lambda-java/issues/2177)) +* bump com.google.protobuf:protobuf-java from 4.32.0 to 4.32.1 ([#2175](https://github.com/aws-powertools/powertools-lambda-java/issues/2175)) +* bump aws.sdk.version from 2.34.5 to 2.34.9 ([#2174](https://github.com/aws-powertools/powertools-lambda-java/issues/2174)) +* bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0 ([#2172](https://github.com/aws-powertools/powertools-lambda-java/issues/2172)) +* bump org.apache.maven.plugins:maven-artifact-plugin ([#2171](https://github.com/aws-powertools/powertools-lambda-java/issues/2171)) +* Add User-Agent execution interceptors ([#2166](https://github.com/aws-powertools/powertools-lambda-java/issues/2166)) +* bump org.apache.kafka:kafka-clients from 4.0.0 to 4.1.0 ([#2134](https://github.com/aws-powertools/powertools-lambda-java/issues/2134)) +* bump graalvm/setup-graalvm from 1.3.6 to 1.4.1 ([#2168](https://github.com/aws-powertools/powertools-lambda-java/issues/2168)) +* bump ossf/scorecard-action from 2.4.2 to 2.4.3 ([#2165](https://github.com/aws-powertools/powertools-lambda-java/issues/2165)) +* bump squidfunk/mkdocs-material in /docs ([#2164](https://github.com/aws-powertools/powertools-lambda-java/issues/2164)) +* bump log4j.version from 2.25.1 to 2.25.2 ([#2160](https://github.com/aws-powertools/powertools-lambda-java/issues/2160)) +* bump org.apache.maven.plugins:maven-failsafe-plugin ([#2159](https://github.com/aws-powertools/powertools-lambda-java/issues/2159)) +* bump actions/dependency-review-action from 4.7.3 to 4.8.0 ([#2158](https://github.com/aws-powertools/powertools-lambda-java/issues/2158)) +* bump github/codeql-action from 3.30.1 to 3.30.5 ([#2157](https://github.com/aws-powertools/powertools-lambda-java/issues/2157)) +* bump io.github.ascopes:protobuf-maven-plugin from 3.9.0 to 3.10.0 ([#2155](https://github.com/aws-powertools/powertools-lambda-java/issues/2155)) +* bump com.amazonaws:aws-lambda-java-runtime-interface-client ([#2149](https://github.com/aws-powertools/powertools-lambda-java/issues/2149)) +* bump aws.sdk.version from 2.33.2 to 2.34.5 ([#2156](https://github.com/aws-powertools/powertools-lambda-java/issues/2156)) +* bump org.codehaus.mojo:versions-maven-plugin ([#2148](https://github.com/aws-powertools/powertools-lambda-java/issues/2148)) +* bump squidfunk/mkdocs-material in /docs ([#2144](https://github.com/aws-powertools/powertools-lambda-java/issues/2144)) +* bump tj-actions/changed-files from 46.0.5 to 47.0.0 ([#2143](https://github.com/aws-powertools/powertools-lambda-java/issues/2143)) +* bump sam/build-java21 ([#2141](https://github.com/aws-powertools/powertools-lambda-java/issues/2141)) +* bump com.amazonaws:aws-lambda-java-core from 1.3.0 to 1.4.0 ([#2135](https://github.com/aws-powertools/powertools-lambda-java/issues/2135)) +* **deps:** Use mockito 5.20.0 ([#2181](https://github.com/aws-powertools/powertools-lambda-java/issues/2181)) +* **docs:** Add AWS docs meta tags ([#2170](https://github.com/aws-powertools/powertools-lambda-java/issues/2170)) + + +<a name="v2.4.0"></a> +## [v2.4.0] - 2025-09-09 +## Bug Fixes + +* **ci:** Update branch protection output ([#2053](https://github.com/aws-powertools/powertools-lambda-java/issues/2053)) + +## Documentation + +* Add AWS copyright footer. ([#2119](https://github.com/aws-powertools/powertools-lambda-java/issues/2119)) +* Update docs introduction +* Rename wrong POWERTOOLS_DISABLE_METRICS to correct POWERTOOLS_METRICS_DISABLED environment variable. ([#2043](https://github.com/aws-powertools/powertools-lambda-java/issues/2043)) +* update readme ([#2045](https://github.com/aws-powertools/powertools-lambda-java/issues/2045)) + +## Features + +* Support CRaC priming of powertools validation ([#2081](https://github.com/aws-powertools/powertools-lambda-java/issues/2081)) +* **graalvm:** GraalVM support for powertools-cloudformation ([#2090](https://github.com/aws-powertools/powertools-lambda-java/issues/2090)) +* **graalvm:** GraalVM support for Idempotency utility ([#2080](https://github.com/aws-powertools/powertools-lambda-java/issues/2080)) +* **logging:** Log buffering support for Logj42 and Logback ([#2103](https://github.com/aws-powertools/powertools-lambda-java/issues/2103)) + +## Maintenance + +* bump dev.aspectj:aspectj-maven-plugin from 1.13.1 to 1.14.1 ([#2099](https://github.com/aws-powertools/powertools-lambda-java/issues/2099)) +* bump dev.aspectj:aspectj-maven-plugin from 1.14 to 1.14.1 ([#2037](https://github.com/aws-powertools/powertools-lambda-java/issues/2037)) +* bump github/codeql-action from 3.29.8 to 3.29.9 ([#2038](https://github.com/aws-powertools/powertools-lambda-java/issues/2038)) +* bump org.apache.maven.plugins:maven-deploy-plugin ([#2040](https://github.com/aws-powertools/powertools-lambda-java/issues/2040)) +* bump org.yaml:snakeyaml from 2.4 to 2.5 ([#2111](https://github.com/aws-powertools/powertools-lambda-java/issues/2111)) +* bump io.github.ascopes:protobuf-maven-plugin from 3.8.1 to 3.9.0 ([#2114](https://github.com/aws-powertools/powertools-lambda-java/issues/2114)) +* bump aws.sdk.version from 2.32.31 to 2.33.1 ([#2115](https://github.com/aws-powertools/powertools-lambda-java/issues/2115)) +* bump graalvm/setup-graalvm from 1.3.5 to 1.3.6 ([#2116](https://github.com/aws-powertools/powertools-lambda-java/issues/2116)) +* bump software.amazon.awscdk:aws-cdk-lib from 2.213.0 to 2.214.0 ([#2117](https://github.com/aws-powertools/powertools-lambda-java/issues/2117)) +* bump aws-actions/configure-aws-credentials from 4.3.1 to 5.0.0 ([#2120](https://github.com/aws-powertools/powertools-lambda-java/issues/2120)) +* bump com.github.spotbugs:spotbugs-maven-plugin ([#2125](https://github.com/aws-powertools/powertools-lambda-java/issues/2125)) +* bump github/codeql-action from 3.30.0 to 3.30.1 ([#2126](https://github.com/aws-powertools/powertools-lambda-java/issues/2126)) +* bump squidfunk/mkdocs-material in /docs ([#2127](https://github.com/aws-powertools/powertools-lambda-java/issues/2127)) +* bump jackson.version from 2.19.2 to 2.20 ([#2097](https://github.com/aws-powertools/powertools-lambda-java/issues/2097)) +* bump aws.sdk.version from 2.32.18 to 2.32.21 ([#2041](https://github.com/aws-powertools/powertools-lambda-java/issues/2041)) +* bump aws.sdk.version from 2.32.26 to 2.32.31 ([#2098](https://github.com/aws-powertools/powertools-lambda-java/issues/2098)) +* bump github/codeql-action from 3.29.11 to 3.30.0 ([#2106](https://github.com/aws-powertools/powertools-lambda-java/issues/2106)) +* bump software.amazon.awscdk:aws-cdk-lib from 2.212.0 to 2.213.0 ([#2100](https://github.com/aws-powertools/powertools-lambda-java/issues/2100)) +* bump org.apache.maven.plugins:maven-compiler-plugin ([#2094](https://github.com/aws-powertools/powertools-lambda-java/issues/2094)) +* bump actions/checkout from 4.2.2 to 5.0.0 ([#2087](https://github.com/aws-powertools/powertools-lambda-java/issues/2087)) +* bump org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions ([#2088](https://github.com/aws-powertools/powertools-lambda-java/issues/2088)) +* bump io.github.ascopes:protobuf-maven-plugin from 3.8.0 to 3.8.1 ([#2085](https://github.com/aws-powertools/powertools-lambda-java/issues/2085)) +* bump com.github.spotbugs:spotbugs-maven-plugin ([#2084](https://github.com/aws-powertools/powertools-lambda-java/issues/2084)) +* bump sam/build-java21 ([#2083](https://github.com/aws-powertools/powertools-lambda-java/issues/2083)) +* bump aws.sdk.version from 2.32.30 to 2.32.31 ([#2093](https://github.com/aws-powertools/powertools-lambda-java/issues/2093)) +* bump actions/dependency-review-action from 4.7.2 to 4.7.3 ([#2092](https://github.com/aws-powertools/powertools-lambda-java/issues/2092)) +* bump aws.sdk.version from 2.32.28 to 2.32.30 ([#2089](https://github.com/aws-powertools/powertools-lambda-java/issues/2089)) +* bump software.amazon.awscdk:aws-cdk-lib from 2.210.0 to 2.211.0 ([#2042](https://github.com/aws-powertools/powertools-lambda-java/issues/2042)) +* bump aws.sdk.version from 2.32.21 to 2.32.22 ([#2046](https://github.com/aws-powertools/powertools-lambda-java/issues/2046)) +* bump com.google.protobuf:protobuf-java from 4.31.1 to 4.32.0 ([#2050](https://github.com/aws-powertools/powertools-lambda-java/issues/2050)) +* bump aws.sdk.version from 2.32.23 to 2.32.25 ([#2054](https://github.com/aws-powertools/powertools-lambda-java/issues/2054)) +* bump squidfunk/mkdocs-material in /docs ([#2074](https://github.com/aws-powertools/powertools-lambda-java/issues/2074)) +* bump github/codeql-action from 3.29.10 to 3.29.11 ([#2073](https://github.com/aws-powertools/powertools-lambda-java/issues/2073)) +* bump log4j.version from 2.25.1 to 2.25.1 ([#2072](https://github.com/aws-powertools/powertools-lambda-java/issues/2072)) +* bump org.apache.maven.plugins:maven-shade-plugin ([#2071](https://github.com/aws-powertools/powertools-lambda-java/issues/2071)) +* bump org.graalvm.buildtools:native-maven-plugin ([#2070](https://github.com/aws-powertools/powertools-lambda-java/issues/2070)) +* bump com.amazonaws:aws-lambda-java-runtime-interface-client ([#2069](https://github.com/aws-powertools/powertools-lambda-java/issues/2069)) +* bump aws.sdk.version from 2.32.2 to 2.32.28 ([#2068](https://github.com/aws-powertools/powertools-lambda-java/issues/2068)) +* bump actions/setup-java from 4.7.1 to 5.0.0 ([#2067](https://github.com/aws-powertools/powertools-lambda-java/issues/2067)) +* bump software.amazon.awscdk:aws-cdk-lib from 2.211.0 to 2.212.0 ([#2066](https://github.com/aws-powertools/powertools-lambda-java/issues/2066)) +* bump org.apache.maven.plugins:maven-javadoc-plugin ([#2065](https://github.com/aws-powertools/powertools-lambda-java/issues/2065)) +* bump aws.sdk.version from 2.32.25 to 2.32.27 ([#2064](https://github.com/aws-powertools/powertools-lambda-java/issues/2064)) +* bump aws.sdk.version from 2.32.22 to 2.32.23 ([#2048](https://github.com/aws-powertools/powertools-lambda-java/issues/2048)) +* bump squidfunk/mkdocs-material in /docs ([#2058](https://github.com/aws-powertools/powertools-lambda-java/issues/2058)) +* bump org.apache.maven.plugins:maven-javadoc-plugin ([#2059](https://github.com/aws-powertools/powertools-lambda-java/issues/2059)) +* bump io.github.ascopes:protobuf-maven-plugin from 3.7.0 to 3.8.0 ([#2057](https://github.com/aws-powertools/powertools-lambda-java/issues/2057)) +* bump actions/checkout from 4.2.2 to 5.0.0 ([#2036](https://github.com/aws-powertools/powertools-lambda-java/issues/2036)) +* bump actions/dependency-review-action from 4.7.1 to 4.7.2 ([#2055](https://github.com/aws-powertools/powertools-lambda-java/issues/2055)) +* bump sam/build-java21 ([#2075](https://github.com/aws-powertools/powertools-lambda-java/issues/2075)) +* bump aws.sdk.version from 2.32.19 to 2.32.26 ([#2060](https://github.com/aws-powertools/powertools-lambda-java/issues/2060)) +* bump github/codeql-action from 3.29.9 to 3.29.10 ([#2056](https://github.com/aws-powertools/powertools-lambda-java/issues/2056)) +* **ci:** Add powertools-e2e-tests/handlers as module to capture it in GitHub actions version upgrades. ([#2063](https://github.com/aws-powertools/powertools-lambda-java/issues/2063)) +* **ci:** Fix bug where docs were released with old version during release workflow. ([#2076](https://github.com/aws-powertools/powertools-lambda-java/issues/2076)) +* **ci:** Run unit tests for GraalVM as well during build. ([#2047](https://github.com/aws-powertools/powertools-lambda-java/issues/2047)) +* **ci:** Remove non-PR triggers for verify dependencies workflow. ([#2044](https://github.com/aws-powertools/powertools-lambda-java/issues/2044)) +* **ci:** Fix circular dependency in dynamodb-local and maven packaging phases. ([#2129](https://github.com/aws-powertools/powertools-lambda-java/issues/2129)) +* **ci:** Do not use Mockito SNAPSHOT version for release. ([#2137](https://github.com/aws-powertools/powertools-lambda-java/issues/2137)) +* **ci:** Set mockito SNAPSHOT version only for Graal profiles. ([#2138](https://github.com/aws-powertools/powertools-lambda-java/issues/2138)) +* **gitignore:** add .kiro, .claude, .amazonq to prevent deletion ([#2078](https://github.com/aws-powertools/powertools-lambda-java/issues/2078)) + + +<a name="v2.3.0"></a> +## [v2.3.0] - 2025-08-12 +## Documentation + +* **examples:** Add Bazel example for core utilities ([#2022](https://github.com/aws-powertools/powertools-lambda-java/issues/2022)) +* **examples:** Add Logging and Tracing to idempotency example with correct configuration. ([#1993](https://github.com/aws-powertools/powertools-lambda-java/issues/1993)) +* **examples:** Enable end to end tracing for SQS batch example. ([#1995](https://github.com/aws-powertools/powertools-lambda-java/issues/1995)) + +## Features + +* Support CRaC priming of powertools metrics and idempotency-dynamodb ([#1861](https://github.com/aws-powertools/powertools-lambda-java/issues/1861)) + +## Maintenance + +* bump github/codeql-action from 3.29.4 to 3.29.5 ([#1992](https://github.com/aws-powertools/powertools-lambda-java/issues/1992)) +* bump org.assertj:assertj-core from 3.27.3 to 3.27.4 ([#2031](https://github.com/aws-powertools/powertools-lambda-java/issues/2031)) +* bump software.amazon.awscdk:aws-cdk-lib from 2.208.0 to 2.210.0 ([#2030](https://github.com/aws-powertools/powertools-lambda-java/issues/2030)) +* bump aws.sdk.version from 2.32.18 to 2.32.19 ([#2029](https://github.com/aws-powertools/powertools-lambda-java/issues/2029)) +* bump co.elastic.logging:logback-ecs-encoder from 1.6.0 to 1.7.0 ([#2028](https://github.com/aws-powertools/powertools-lambda-java/issues/2028)) +* bump com.github.spotbugs:spotbugs-maven-plugin from 4.8.4.0 to 4.9.3.2 ([#2010](https://github.com/aws-powertools/powertools-lambda-java/issues/2010)) +* bump com.amazonaws:aws-lambda-java-runtime-interface-client ([#2026](https://github.com/aws-powertools/powertools-lambda-java/issues/2026)) +* bump github/codeql-action from 3.29.7 to 3.29.8 ([#2027](https://github.com/aws-powertools/powertools-lambda-java/issues/2027)) +* bump org.crac:crac from 1.4.0 to 1.5.0 ([#2025](https://github.com/aws-powertools/powertools-lambda-java/issues/2025)) +* bump aws.sdk.version from 2.32.6 to 2.32.18 ([#2024](https://github.com/aws-powertools/powertools-lambda-java/issues/2024)) +* bump org.junit.jupiter:junit-jupiter from 5.11.1 to 5.13.4 ([#2023](https://github.com/aws-powertools/powertools-lambda-java/issues/2023)) +* bump org.codehaus.mojo:exec-maven-plugin from 3.3.0 to 3.5.1 ([#2015](https://github.com/aws-powertools/powertools-lambda-java/issues/2015)) +* bump aws.sdk.version from 2.32.10 to 2.32.16 ([#2014](https://github.com/aws-powertools/powertools-lambda-java/issues/2014)) +* bump io.github.ascopes:protobuf-maven-plugin from 3.6.1 to 3.7.0 ([#2016](https://github.com/aws-powertools/powertools-lambda-java/issues/2016)) +* bump actions/download-artifact from 4.3.0 to 5.0.0 ([#2017](https://github.com/aws-powertools/powertools-lambda-java/issues/2017)) +* bump squidfunk/mkdocs-material in /docs ([#1984](https://github.com/aws-powertools/powertools-lambda-java/issues/1984)) +* bump org.apache.maven.plugins:maven-surefire-plugin ([#2013](https://github.com/aws-powertools/powertools-lambda-java/issues/2013)) +* bump aws-actions/configure-aws-credentials from 4.2.1 to 4.3.1 ([#2011](https://github.com/aws-powertools/powertools-lambda-java/issues/2011)) +* bump software.amazon.awscdk:aws-cdk-lib from 2.162.1 to 2.208.0 ([#1990](https://github.com/aws-powertools/powertools-lambda-java/issues/1990)) +* **ci:** Make E2E tests compatible with latest CDK lib version. Improve retry implementation. ([#2008](https://github.com/aws-powertools/powertools-lambda-java/issues/2008)) +* **ci:** Improve reliability of retries in TracingE2ET ([#2018](https://github.com/aws-powertools/powertools-lambda-java/issues/2018)) + + +<a name="v2.2.1"></a> +## [v2.2.1] - 2025-07-29 +## Bug Fixes + +* **parameters:** Correctly check for empty values in AppConfig Parameters Provider. ([#1982](https://github.com/aws-powertools/powertools-lambda-java/issues/1982)) + +## Maintenance + +* bump dependabot/fetch-metadata from 2.3.0 to 2.4.0 ([#1954](https://github.com/aws-powertools/powertools-lambda-java/issues/1954)) +* bump github/codeql-action from 3.29.3 to 3.29.4 ([#1978](https://github.com/aws-powertools/powertools-lambda-java/issues/1978)) +* bump org.apache.logging.log4j:log4j-transform-maven-shade-plugin-extensions ([#1977](https://github.com/aws-powertools/powertools-lambda-java/issues/1977)) +* bump aws.sdk.version from 2.31.78 to 2.32.6 ([#1976](https://github.com/aws-powertools/powertools-lambda-java/issues/1976)) +* bump com.amazonaws:aws-lambda-java-events from 3.16.0 to 3.16.1 ([#1975](https://github.com/aws-powertools/powertools-lambda-java/issues/1975)) +* bump com.networknt:json-schema-validator from 1.5.1 to 1.5.8 ([#1974](https://github.com/aws-powertools/powertools-lambda-java/issues/1974)) +* bump ossf/scorecard-action from 2.4.0 to 2.4.2 ([#1950](https://github.com/aws-powertools/powertools-lambda-java/issues/1950)) +* bump org.apache.maven.plugins:maven-compiler-plugin ([#1972](https://github.com/aws-powertools/powertools-lambda-java/issues/1972)) +* bump actions/download-artifact from 4.2.1 to 4.3.0 ([#1967](https://github.com/aws-powertools/powertools-lambda-java/issues/1967)) +* bump aws-actions/configure-aws-credentials from 2.2.0 to 4.2.1 ([#1965](https://github.com/aws-powertools/powertools-lambda-java/issues/1965)) +* bump actions/dependency-review-action from 4.5.0 to 4.7.1 ([#1968](https://github.com/aws-powertools/powertools-lambda-java/issues/1968)) +* bump actions/checkout from 3.5.3 to 4.2.2 ([#1963](https://github.com/aws-powertools/powertools-lambda-java/issues/1963)) +* bump sam/build-java21 ([#1962](https://github.com/aws-powertools/powertools-lambda-java/issues/1962)) +* bump squidfunk/mkdocs-material in /docs ([#1961](https://github.com/aws-powertools/powertools-lambda-java/issues/1961)) +* bump actions/upload-artifact from 4.5.0 to 4.6.2 ([#1953](https://github.com/aws-powertools/powertools-lambda-java/issues/1953)) +* bump github/codeql-action from 3.27.9 to 3.29.3 ([#1958](https://github.com/aws-powertools/powertools-lambda-java/issues/1958)) +* bump actions/setup-java from 3.11.0 to 4.7.1 ([#1957](https://github.com/aws-powertools/powertools-lambda-java/issues/1957)) +* **ci:** Add Docker paths via globs to dependabot and update Dockerfiles to pin sha256 ([#1960](https://github.com/aws-powertools/powertools-lambda-java/issues/1960)) +* **ci:** Remove osv workflow. ([#1973](https://github.com/aws-powertools/powertools-lambda-java/issues/1973)) +* **ci:** add new dependabot package ecosystems ([#1948](https://github.com/aws-powertools/powertools-lambda-java/issues/1948)) +* **ci:** Add GraalVM E2E tests and GH workflows ([#1945](https://github.com/aws-powertools/powertools-lambda-java/issues/1945)) + + +<a name="v2.2.0"></a> +## [v2.2.0] - 2025-07-15 +## Bug Fixes + +* **examples:** Fix GraalVM metadata after common runtime client changes ([#1935](https://github.com/aws-powertools/powertools-lambda-java/issues/1935)) + +## Features + +* **batch:** add support for batch execution in parallel with custom Executor ([#1900](https://github.com/aws-powertools/powertools-lambda-java/issues/1900)) +* **serialization:** Add GraalVM metadata configuration ([#1905](https://github.com/aws-powertools/powertools-lambda-java/issues/1905)) + +## Maintenance + +* update issue, PR, and discussion templates ([#1915](https://github.com/aws-powertools/powertools-lambda-java/issues/1915)) +* **ci:** remove v2 dependabot configuration. Restore OSSF scorecard workflow. ([#1924](https://github.com/aws-powertools/powertools-lambda-java/issues/1924)) +* **ci:** Update branch protection rules ([#1914](https://github.com/aws-powertools/powertools-lambda-java/issues/1914)) + + +<a name="v2.1.1"></a> +## [v2.1.1] - 2025-06-20 +## Bug Fixes + +* **kafka:** Handle message indices in proto data also for Glue Schema Registry ([#1907](https://github.com/aws-powertools/powertools-lambda-java/issues/1907)) + +## Maintenance + + + +<a name="v2.1.0"></a> +## [v2.1.0] - 2025-06-19 +## Bug Fixes + +* **ci:** Add maven project description to Kafka utility. ([#1903](https://github.com/aws-powertools/powertools-lambda-java/issues/1903)) +* **kafka:** Add support for confluent message indices. ([#1902](https://github.com/aws-powertools/powertools-lambda-java/issues/1902)) +* **metrics:** Do not flush when no metrics were added to avoid printing root-level _aws dict ([#1891](https://github.com/aws-powertools/powertools-lambda-java/issues/1891)) -## [1.16.1] - 2023-07-19 +## Documentation -* Fix: idempotency timeout bug (#1285) by @scottgerring -* Fix: ParamManager cannot provide default SSM & Secrets providers (#1282) by @jeromevdl -* Fix: Handle batch failures in FIFO queues correctly (#1183) by @scottgerring -* Deps: Bump third party dependencies to the latest versions. +* Announce deprecation of v1 +* Version documentation ([#1878](https://github.com/aws-powertools/powertools-lambda-java/issues/1878)) +## Features -## [1.16.0] - 2023-06-29 +* **kafka:** New Kafka utility ([#1898](https://github.com/aws-powertools/powertools-lambda-java/issues/1898)) +## Maintenance -### Added -* Feature: Add AppConfig provider to parameters module (#1104) by @scottgerring +* **ci:** Update workflows to make v2 the default ([#1888](https://github.com/aws-powertools/powertools-lambda-java/issues/1888)) -### Maintenance -* Fix: missing idempotency key should not persist any data (#1201) by @jeromevdl -* Fix:Removing env var credentials provider as default. (#1161) by @msailes -* Chore: Swap implementation of `aspectj-maven-plugin` to support Java 17 (#1172) by @mriccia -* Test: end-to-end tests for core modules and idempotency (#970) by @jeromevdl -* Chore: cleanup spotbugs maven profiles (#1236) by @jeromevdl -* Chore: removing logback from all components (#1227) by @jeromevdl -* Chore: Roll SLF4J log4j bindings to v2 (#1190) by @scottgerring -* Deps: Bump third party dependencies to the latest versions. +<a name="v2.0.0"></a> +## [v2.0.0] - 2025-06-12 +## Maintenance -## [1.15.0] - 2023-03-20 -### Added -* Feature: Add DynamoDB provider to parameters module (#1091) by @scottgerring -* Feature: Update to powertools-cloudformation to deprecate `Response.success()` and `Response.failed()` methods. New helper methods are added to make it easier to follow best practices `Response.success(String physicalResourceId)` and `Response.failed(String physicalResourceId)`. For a detailed explanation please read the [powertools-cloudformation documentation page](https://docs.powertools.aws.dev/lambda-java/utilities/custom_resources/). (#1082) by @msailes -* Update how a Lambda request handler method is identified (#1058) by @humanzz -### Maintenance -* Deps: Bump third party dependencies to the latest versions. -* Examples: Import examples from aws-samples/aws-lambda-powertools-examples (#1051) by @scottgerring -* Deprecate withMetricLogger in favor of withMetricsLogger (#1060) by @humanzz -* Update issue templates (#1062) by @machafer -* Send code coverage report (jacoco) to codecov (#1094) by @jeromevdl +<a name="v2.0.0-RC1"></a> +## [v2.0.0-RC1] - 2025-06-11 +## Bug Fixes -### Documentation +* workflow paths for examples v2 builds +* add aspectj-rt to batch e2e ([#1410](https://github.com/aws-powertools/powertools-lambda-java/issues/1410)) +* **ci:** Fix failing E2E tests and temporarily exclude TracingE2E ([#1847](https://github.com/aws-powertools/powertools-lambda-java/issues/1847)) +* **ci:** add user/pass to javasetup ([#1832](https://github.com/aws-powertools/powertools-lambda-java/issues/1832)) +* **ci:** Update control flow to allow for better skipping of things ([#1831](https://github.com/aws-powertools/powertools-lambda-java/issues/1831)) +* **ci:** Checkout repo on doc release ([#1869](https://github.com/aws-powertools/powertools-lambda-java/issues/1869)) +* **logging:** Prevent accidental overwriting of reserved keys via structured arguments +* **logging:** Escape double-quotes when serializing strings into JSON. ([#1845](https://github.com/aws-powertools/powertools-lambda-java/issues/1845)) +* **v2:** Fix params builder to provide default transformation manager ([#1549](https://github.com/aws-powertools/powertools-lambda-java/issues/1549)) -* Improve `powertools-cloudformation` docs (#1090) by @mriccia -* Add link to Powertools for AWS Lambda (Java) workshop (#1095) by @scottgerring -* Fix mdocs and git revision plugin integration (#1066) by @machafer +## Documentation +* v2 documentation maintenance fixing formatting and dependency issues as well as adding roadmap and llms.txt ([#1819](https://github.com/aws-powertools/powertools-lambda-java/issues/1819)) +* **metrics:** Add upgrade guide for re-designed Metrics utility ([#1868](https://github.com/aws-powertools/powertools-lambda-java/issues/1868)) +* **v2:** Create upgrade guide and versioning policy ([#1856](https://github.com/aws-powertools/powertools-lambda-java/issues/1856)) -## [1.14.0] - 2023-02-17 +## Features -### Added +* advanced logging ([#1539](https://github.com/aws-powertools/powertools-lambda-java/issues/1539)) +* upgraded embedded metrics library for high resolution metrics ([#1550](https://github.com/aws-powertools/powertools-lambda-java/issues/1550)) +* **cfn-custom-resource:** Add optional 'reason' field for detailed failure reporting ([#1810](https://github.com/aws-powertools/powertools-lambda-java/issues/1810)) +* **idempotency:** Add support for ReturnValuesOnConditionCheckFailure in Idempotency. ([#1821](https://github.com/aws-powertools/powertools-lambda-java/issues/1821)) +* **idempotency:** Add response hook feature ([#1814](https://github.com/aws-powertools/powertools-lambda-java/issues/1814)) +* **metrics:** New metrics module implementation with support for Metrics providers and usage without annotations ([#1863](https://github.com/aws-powertools/powertools-lambda-java/issues/1863)) +* **v2:** Add GraalVM reachability metadata for core utilities ([#1753](https://github.com/aws-powertools/powertools-lambda-java/issues/1753)) +* **v2:** parallel batch processing ([#1620](https://github.com/aws-powertools/powertools-lambda-java/issues/1620)) +* **v2:** batch validation with partial failure ([#1621](https://github.com/aws-powertools/powertools-lambda-java/issues/1621)) +* **v2:** publish snapshots ([#1655](https://github.com/aws-powertools/powertools-lambda-java/issues/1655)) +* **v2:** GraalVM support for parameters module ([#1824](https://github.com/aws-powertools/powertools-lambda-java/issues/1824)) +* **v2:** new logging module ([#1435](https://github.com/aws-powertools/powertools-lambda-java/issues/1435)) +* **v2:** Validation failures return 400s ([#1489](https://github.com/aws-powertools/powertools-lambda-java/issues/1489)) -* Feature: Introduce `MetricsUtils.withMetricsLogger()` utility method (#1000) by @humanzz +## Maintenance -#### Maintenance +* Support spotbugs running anywhere ([#1537](https://github.com/aws-powertools/powertools-lambda-java/issues/1537)) +* V2 update from main ([#1365](https://github.com/aws-powertools/powertools-lambda-java/issues/1365)) +* remove Java 8 from v2 examples ([#1531](https://github.com/aws-powertools/powertools-lambda-java/issues/1531)) +* fix end 2 end build ([#1534](https://github.com/aws-powertools/powertools-lambda-java/issues/1534)) +* cleanup poms and reduce warning noise ([#1535](https://github.com/aws-powertools/powertools-lambda-java/issues/1535)) +* [V2] rename 'core' module to 'common' ([#1364](https://github.com/aws-powertools/powertools-lambda-java/issues/1364)) +* update v2 ([#1409](https://github.com/aws-powertools/powertools-lambda-java/issues/1409)) +* remove aspectj-rt from the library ([#1408](https://github.com/aws-powertools/powertools-lambda-java/issues/1408)) +* Start V2 branch ([#1346](https://github.com/aws-powertools/powertools-lambda-java/issues/1346)) +* **automation:** Update automation workflows ([#1779](https://github.com/aws-powertools/powertools-lambda-java/issues/1779)) ([#1830](https://github.com/aws-powertools/powertools-lambda-java/issues/1830)) +* **ci:** Set snapshot repository to "central" server ID +* **ci:** Publish to Maven Central instead of OSSRH instance ([#1858](https://github.com/aws-powertools/powertools-lambda-java/issues/1858)) +* **v2:** Merge down from main ([#1574](https://github.com/aws-powertools/powertools-lambda-java/issues/1574)) +* **v2:** Split parameters module up by parameter provider ([#1403](https://github.com/aws-powertools/powertools-lambda-java/issues/1403)) +* **v2:** Fix IaC lint ([#1576](https://github.com/aws-powertools/powertools-lambda-java/issues/1576)) +* **v2:** e2e tests ([#1571](https://github.com/aws-powertools/powertools-lambda-java/issues/1571)) +* **v2:** clean examples ([#1495](https://github.com/aws-powertools/powertools-lambda-java/issues/1495)) +* **v2:** document use of aws-crt-client ([#1092](https://github.com/aws-powertools/powertools-lambda-java/issues/1092)) ([#1605](https://github.com/aws-powertools/powertools-lambda-java/issues/1605)) +* **v2:** remove java 1.8 relics from the code ([#1659](https://github.com/aws-powertools/powertools-lambda-java/issues/1659)) +* **v2:** remove deprecated code ([#1624](https://github.com/aws-powertools/powertools-lambda-java/issues/1624)) +* **v2:** Remove rule preventing production release of 2.0.0 ([#1867](https://github.com/aws-powertools/powertools-lambda-java/issues/1867)) +* **v2:** Split powertools idempotency module (without redis impl) ([#1559](https://github.com/aws-powertools/powertools-lambda-java/issues/1559)) -* Update logic for recording documentation pages views to use correct runtime name (#1047) by @kozub -* Deps: Bump third party dependencies to the latest versions. +## Pull Requests -### Documentation +* Merge pull request [#1608](https://github.com/aws-powertools/powertools-lambda-java/issues/1608) from aws-powertools/chore/v2-merge-main-down +* Merge pull request [#1525](https://github.com/aws-powertools/powertools-lambda-java/issues/1525) from aws-powertools/chore/main-into-v2 +* Merge pull request [#1494](https://github.com/aws-powertools/powertools-lambda-java/issues/1494) from aws-powertools/chore/merge-main-into-v2 +* Merge pull request [#1492](https://github.com/aws-powertools/powertools-lambda-java/issues/1492) from aws-powertools/main-into-v2-again +* Merge pull request [#1477](https://github.com/aws-powertools/powertools-lambda-java/issues/1477) from aws-powertools/chore/main-into-v2 -* Docs: Update Powertools for AWS Lambda (Java) definition by @heitorlessa -* Docs: Add information about other supported langauges to README and docs (#1033) by @kozub -## [1.13.0] - 2022-12-14 +<a name="v1.20.2"></a> +## [v1.20.2] - 2025-05-20 +## Bug Fixes -### Added +* **ci:** update release workflow ([#1854](https://github.com/aws-powertools/powertools-lambda-java/issues/1854)) +* **ci:** minor fixes for workflows ([#1829](https://github.com/aws-powertools/powertools-lambda-java/issues/1829)) -* Feature: Idempotency - Handle Lambda timeout scenarios for INPROGRESS records (#933) by @jeromevdl +## Documentation -### Bug Fixes +* Add version policy page and llms.txt, enable privacy plugin, fix formatting ([#1823](https://github.com/aws-powertools/powertools-lambda-java/issues/1823)) -* Fix: Envelope is not taken into account with built-in types (#960) by @jeromevdl -* Fix: Code suggestion from CodeGuru (#984) by @kozub -* Fix: Compilation warning with SqsLargeMessageAspect on gradle (#998) by @jeromevdl -* Fix: Log message processing exceptions as occur (#1011) by @nem0-97 +## Maintenance -### Documentation +* **automation:** Update automation workflows ([#1779](https://github.com/aws-powertools/powertools-lambda-java/issues/1779)) -* Docs: Add missing grammar article (#976) by @fsmiamoto -## [1.12.3] - 2022-07-12 +<a name="v1.20.1"></a> +## [v1.20.1] - 2025-04-08 +## Bug Fixes -#### Maintenance +* Load version.properties file as resource stream to fix loading when packaged as jar. ([#1813](https://github.com/aws-powertools/powertools-lambda-java/issues/1813)) -* Fixes to resolve vulnerable transitive dependencies ([919](https://github.com/aws-powertools/powertools-lambda-java/issues/919)) +## Documentation +* fix 2 typos +* Correct XML formatting for Maven configuration in Large Messages utility docs -## [1.12.2] - 2022-04-29 +## Maintenance -### Bug Fixes +* Prep release 1.20.1 ([#1817](https://github.com/aws-powertools/powertools-lambda-java/issues/1817)) -* **SQS Large message processing**: Classpath conflict on `PayloadS3Pointer` when consumer application depends on `payloadoffloading-common`, introduced in [v1.8.0](https://github.com/aws-powertools/powertools-lambda-java/releases/tag/v1.8.0). ([#851](https://github.com/aws-powertools/powertools-lambda-java/pull/851)) +<a name="v1.20.0"></a> +## [v1.20.0] - 2025-03-25 +## Features -## [1.12.1] - 2022-04-21 +* **cfn-custom-resource:** Add optional 'reason' field for detailed failure reporting ([#1758](https://github.com/aws-powertools/powertools-lambda-java/issues/1758)) -### Bug Fixes +## Maintenance -* **Idempotency**: thread-safety issue of MessageDigest ([#817](https://github.com/aws-powertools/powertools-lambda-java/pull/817)) -* **Idempotency**: disable dynamodb client creation in persistent store when disabling idempotency ([#796](https://github.com/aws-powertools/powertools-lambda-java/pull/796)) +* Prep release 1.20.0 ([#1811](https://github.com/aws-powertools/powertools-lambda-java/issues/1811)) -### Maintenance +<a name="v1.19.0"></a> +## [v1.19.0] - 2025-03-07 +## Bug Fixes -* **deps**: Bump third party dependencies to the latest versions. +* add workflow dispatch to OSV +* Allow empty responses as well as null response in AppConfig ([#1673](https://github.com/aws-powertools/powertools-lambda-java/issues/1673)) +* **ci:** Add workflow_dispatch to build script ([#1792](https://github.com/aws-powertools/powertools-lambda-java/issues/1792)) +* **ci:** add permissions to release workflow +* **ci:** Permissions ([#1771](https://github.com/aws-powertools/powertools-lambda-java/issues/1771)) +* **ci:** OSSF Changes ([#1769](https://github.com/aws-powertools/powertools-lambda-java/issues/1769)) +## Documentation -## [1.12.0] - 2022-03-01 +* add roadmap page and include roadmap for 2025 +* improve tracing doc for sdk instrumentation ([#1687](https://github.com/aws-powertools/powertools-lambda-java/issues/1687)) +* add link to Powertools for AWS Lambda workshop ([#1641](https://github.com/aws-powertools/powertools-lambda-java/issues/1641)) +* HelloWorldStreamFunction in examples fails with sam ([#1532](https://github.com/aws-powertools/powertools-lambda-java/issues/1532)) -### Added - * **Easy Event Deserialization**: Extraction and deserialization of the main content of events (body, messages, ...) [#757](https://github.com/aws-powertools/powertools-lambda-java/pull/757) +## Features -### Bug Fixes - * Different behavior while using SSMProvider with or without trailing slash in parameter names [#758](https://github.com/aws-powertools/powertools-lambda-java/issues/758) +* **build:** remove java 8 support in v2 ([#1606](https://github.com/aws-powertools/powertools-lambda-java/issues/1606)) +* **ci:** Add OSV +## Maintenance -## [1.11.0] - 2022-02-16 +* deprecate java1.8 al1 ([#1706](https://github.com/aws-powertools/powertools-lambda-java/issues/1706)) +* Testing java21 aspectj pre-release ([#1519](https://github.com/aws-powertools/powertools-lambda-java/issues/1519)) +* Remove build cruft +* SAM and Terraform IaC extracted from pr_build and simplified approach. ([#1533](https://github.com/aws-powertools/powertools-lambda-java/issues/1533)) +* Update netty version ([#1768](https://github.com/aws-powertools/powertools-lambda-java/issues/1768)) +* Set versions of transitive dependencies ([#1767](https://github.com/aws-powertools/powertools-lambda-java/issues/1767)) +* update Jackson +* Remove empty CDK test ([#1542](https://github.com/aws-powertools/powertools-lambda-java/issues/1542)) +* add openssf to repo +* remove auto-merge +* remove unecessary creds acquisition ([#1572](https://github.com/aws-powertools/powertools-lambda-java/issues/1572)) +* update version to next snapshot: 1-19.0-SNAPSHOT ([#1516](https://github.com/aws-powertools/powertools-lambda-java/issues/1516)) +* **ci:** update permissions ([#1764](https://github.com/aws-powertools/powertools-lambda-java/issues/1764)) +* **ci:** Add release environment +* **ci:** Remove RELEASE variable ([#1772](https://github.com/aws-powertools/powertools-lambda-java/issues/1772)) +* **deps:** update JSII to 1.108 ([#1791](https://github.com/aws-powertools/powertools-lambda-java/issues/1791)) +* **deps:** Update deps for jackson ([#1793](https://github.com/aws-powertools/powertools-lambda-java/issues/1793)) +* **docs:** load self hosted mermaid.js -### Added - * Powertools for AWS Lambda (Java) Idempotency module: New module to get your Lambda function [Idempotent](https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/) (#717) - * Powertools for AWS Lambda (Java) Serialization module: New module to handle JSON (de)serialization (Jackson ObjectMapper, JMESPath functions) +## Pull Requests +* Merge pull request [#1720](https://github.com/aws-powertools/powertools-lambda-java/issues/1720) from aws-powertools/chore/docs_script_self -## [1.10.3] - 2022-02-01 -### Bug Fixes +<a name="v1.18.0"></a> +## [v1.18.0] - 2023-11-16 +## Bug Fixes -* **SQS Batch processing**: Prevent message to be marked as success if failed sending to DLQ for non retryable exceptions. [#731](https://github.com/aws-powertools/powertools-lambda-java/pull/731) +* get trace id from system property when env var is not set ([#1503](https://github.com/aws-powertools/powertools-lambda-java/issues/1503)) +* Fix schema validation unit test build issues ([#1456](https://github.com/aws-powertools/powertools-lambda-java/issues/1456)) -### Documentation +## Documentation +* Update gradle configuration readme ([#1359](https://github.com/aws-powertools/powertools-lambda-java/issues/1359)) +* Adding Kotlin example. ([#1454](https://github.com/aws-powertools/powertools-lambda-java/issues/1454)) +* apply line highlight only for default light mode ([#1453](https://github.com/aws-powertools/powertools-lambda-java/issues/1453)) +* Add Serveless Framework example ([#1363](https://github.com/aws-powertools/powertools-lambda-java/issues/1363)) +* Fix link to SQS large message migration guide ([#1422](https://github.com/aws-powertools/powertools-lambda-java/issues/1422)) +* Change link to absolute versioned path for examples ([#1374](https://github.com/aws-powertools/powertools-lambda-java/issues/1374)) +* **customer-reference:** add Vertex Pharmaceuticals as a customer reference ([#1486](https://github.com/aws-powertools/powertools-lambda-java/issues/1486)) +* **logging:** align example cloudwatch example to correct output from code: lambda_request_id --> function_request_id ([#1411](https://github.com/aws-powertools/powertools-lambda-java/issues/1411)) -* **SQS Batch processing**: Improve [documentation](https://docs.powertools.aws.dev/lambda-java/utilities/batch/#iam-permissions) on IAM premissions required by function when using utility with an encrypted SQS queue with customer managed KMS keys. +## Features +* ALC ([#1514](https://github.com/aws-powertools/powertools-lambda-java/issues/1514)) +* Add support for POWERTOOLS_LOGGER_LOG_EVENT ([#1510](https://github.com/aws-powertools/powertools-lambda-java/issues/1510)) +* Terraform example ([#1478](https://github.com/aws-powertools/powertools-lambda-java/issues/1478)) -## [1.10.2] - 2022-01-07 +## Maintenance -* **Tracing**: Ability to override object mapper used for serializing method response as trace metadata when enabled. This provides users ability to customize how and what you want to capture as metadata from method response object. [#698](https://github.com/aws-powertools/powertools-lambda-java/pull/698) +* Addition of Warn Message If Invalid Annotation Key While Tracing [#1511](https://github.com/aws-powertools/powertools-lambda-java/issues/1511) ([#1512](https://github.com/aws-powertools/powertools-lambda-java/issues/1512)) +* artifacts size on good branches ([#1493](https://github.com/aws-powertools/powertools-lambda-java/issues/1493)) +* add missing projects and improve workflow ([#1487](https://github.com/aws-powertools/powertools-lambda-java/issues/1487)) +* java21 support in our build ([#1488](https://github.com/aws-powertools/powertools-lambda-java/issues/1488)) +* Reporting size of the jars in GitHub comments ([#1196](https://github.com/aws-powertools/powertools-lambda-java/issues/1196)) +* secure github actions using hash instead of versions ([#1232](https://github.com/aws-powertools/powertools-lambda-java/issues/1232)) -## [1.10.1] - 2022-01-06 -* **Logging**: Upgrade Log4j to version 2.17.1 for [CVE-2021-44832](https://nvd.nist.gov/vuln/detail/CVE-2021-44832) +<a name="v1.17.0"></a> +## [v1.17.0] - 2023-08-21 +## Bug Fixes -## [1.10.0] - 2021-12-27 +* Roll log4j shade transformer forwards ([#1376](https://github.com/aws-powertools/powertools-lambda-java/issues/1376)) +* Rollback doc changes ([#1323](https://github.com/aws-powertools/powertools-lambda-java/issues/1323)) +* use default credentials provider for all provided SDK clients ([#1303](https://github.com/aws-powertools/powertools-lambda-java/issues/1303)) -* **Logging**: Modern log4j configuration to customise structured logging. Refer [docs](https://docs.powertools.aws.dev/lambda-java/core/logging/#upgrade-to-jsontemplatelayout-from-deprecated-lambdajsonlayout-configuration-in-log4j2xml) to start using new config. [#670](https://github.com/aws-powertools/powertools-lambda-java/pull/670) -* **SQS Batch**: Support batch size greater than 10. [#667](https://github.com/aws-powertools/powertools-lambda-java/pull/667) +## Documentation -## [1.9.0] - 2021-12-21 +* Adding CDK example ([#1321](https://github.com/aws-powertools/powertools-lambda-java/issues/1321)) +* improve contributing guide ([#1334](https://github.com/aws-powertools/powertools-lambda-java/issues/1334)) +* Add maintainers guide ([#1326](https://github.com/aws-powertools/powertools-lambda-java/issues/1326)) +* versioning - fix typo ([#1322](https://github.com/aws-powertools/powertools-lambda-java/issues/1322)) +* add support for docs versioning ([#1239](https://github.com/aws-powertools/powertools-lambda-java/issues/1239)) ([#1293](https://github.com/aws-powertools/powertools-lambda-java/issues/1293)) +* Started cleaning up example doc ([#1291](https://github.com/aws-powertools/powertools-lambda-java/issues/1291)) -* **Logging**: Upgrade Log4j to version 2.17.0 for [CVE-2021-45105](https://nvd.nist.gov/vuln/detail/CVE-2021-45105) -* **Tracing**: add `Service` annotation. [#654](https://github.com/aws-powertools/powertools-lambda-java/issues/654) +## Features -## [1.8.2] - 2021-12-15 +* Add Batch Processor module ([#1317](https://github.com/aws-powertools/powertools-lambda-java/issues/1317)) +* large message in SQS and SNS ([#1310](https://github.com/aws-powertools/powertools-lambda-java/issues/1310)) -## Security +## Maintenance -* Upgrading Log4j to version 2.16.0 for [CVE-2021-45046](https://nvd.nist.gov/vuln/detail/CVE-2021-45046) +* Fix missing version change pieces ([#1382](https://github.com/aws-powertools/powertools-lambda-java/issues/1382)) +* apply checkstyle again ([#1339](https://github.com/aws-powertools/powertools-lambda-java/issues/1339)) +* Add powertools specific user-agent-suffix to the AWS SDK v2 clients ([#1306](https://github.com/aws-powertools/powertools-lambda-java/issues/1306)) +* checkstyle formater & linter ([#1316](https://github.com/aws-powertools/powertools-lambda-java/issues/1316)) +* update poms to SNAPSHOT version for dev ([#1299](https://github.com/aws-powertools/powertools-lambda-java/issues/1299)) -## [1.8.1] - 2021-12-10 -## Security +<a name="v1.16.1"></a> +## [v1.16.1] - 2023-07-19 +## Bug Fixes -* Upgrading Log4j to version 2.15.0 for [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) +* idempotency timeout bug ([#1285](https://github.com/aws-powertools/powertools-lambda-java/issues/1285)) +* ParamManager cannot provide default SSM & Secrets providers ([#1282](https://github.com/aws-powertools/powertools-lambda-java/issues/1282)) +* Handle batch failures in FIFO queues correctly ([#1183](https://github.com/aws-powertools/powertools-lambda-java/issues/1183)) +* examples shouldn't be deployed to mvn central ([#1253](https://github.com/aws-powertools/powertools-lambda-java/issues/1253)) -## [1.8.0] - 2021-11-05 +## Documentation -### Added +* update README.md ([#1294](https://github.com/aws-powertools/powertools-lambda-java/issues/1294)) +* adding our customer references ([#1287](https://github.com/aws-powertools/powertools-lambda-java/issues/1287)) +* update documentation for aspectJ ([#1273](https://github.com/aws-powertools/powertools-lambda-java/issues/1273)) -* **Powertools for AWS Lambda (Java) Cloudformation module (NEW)**: New module simplifying [AWS Lambda-backed custom resources](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html) written in Java. [#560](https://github.com/aws-powertools/powertools-lambda-java/pull/560) -* **SQS Large message processing**: Ability to override the default `S3Client` use to fetch payload from S3. [#602](https://github.com/aws-powertools/powertools-lambda-java/pull/602) +## Maintenance -### Regression +* **unit-test:** Add missing unit tests in modules with low coverage ([#1264](https://github.com/aws-powertools/powertools-lambda-java/issues/1264)) -* **Logging**: `@Logging` annotation now works with `@Tracing` annotation on `RequestStreamHandler` when used in `logEvent` mode. [#567](https://github.com/aws-powertools/powertools-lambda-java/pull/567) -### Maintenance +<a name="v1.16.0"></a> +## [v1.16.0] - 2023-06-29 +## Bug Fixes -* **deps**: Bump third party dependencies to the latest versions. +* e2e tests on JDK8 ([#1225](https://github.com/aws-powertools/powertools-lambda-java/issues/1225)) +* codecov URL ([#1222](https://github.com/aws-powertools/powertools-lambda-java/issues/1222)) +* remove GH pages ([#1211](https://github.com/aws-powertools/powertools-lambda-java/issues/1211)) +* update references to other variants +* missing idempotency key should not persist any data ([#1201](https://github.com/aws-powertools/powertools-lambda-java/issues/1201)) +* **docs:** add site_url to docs -## [1.7.3] - 2021-09-14 +## Features -* **SQS Batch processing**: Ability to move non retryable message to configured dead letter queue(DLQ). [#500](https://github.com/aws-powertools/powertools-lambda-java/pull/500) +* Add AppConfig provider to parameters module ([#1104](https://github.com/aws-powertools/powertools-lambda-java/issues/1104)) +* end-to-end tests for core modules and idempotency ([#970](https://github.com/aws-powertools/powertools-lambda-java/issues/970)) +* **docs:** adds S3 Docs uploader -## [1.7.2] - 2021-08-03 +## Maintenance -* **Powertools for AWS Lambda (Java) All Modules**: Upgrade to the latest(1.14.0) aspectj-maven-plugin which also supports Java 9 and newer versions. -Users no longer need to depend on [com.nickwongdev](https://mvnrepository.com/artifact/com.nickwongdev/aspectj-maven-plugin/1.12.6) as a workaround. [#489](https://github.com/aws-powertools/powertools-lambda-java/pull/489) -* **Logging**: Performance optimisation to improve cold start. [#484](https://github.com/aws-powertools/powertools-lambda-java/pull/484) -* **SQS Batch processing/Large message**: Module now lazy loads default SQS client. [#484](https://github.com/aws-powertools/powertools-lambda-java/pull/484) +* Update docs base origin url ([#1238](https://github.com/aws-powertools/powertools-lambda-java/issues/1238)) +* E2E tests GitHub action ([#1175](https://github.com/aws-powertools/powertools-lambda-java/issues/1175)) +* add all java versions and use corretto for build ([#1191](https://github.com/aws-powertools/powertools-lambda-java/issues/1191)) +* Change repo URL to the new location ([#1171](https://github.com/aws-powertools/powertools-lambda-java/issues/1171)) +* Swap implementation of `aspectj-maven-plugin` to support Java 17 ([#1172](https://github.com/aws-powertools/powertools-lambda-java/issues/1172)) +* update e2e-tests with latest Powertools version ([#1173](https://github.com/aws-powertools/powertools-lambda-java/issues/1173)) +* rename project from Powertools to Powertools for AWS Lambda (Java) ([#1169](https://github.com/aws-powertools/powertools-lambda-java/issues/1169)) +* **ci:** add workflow to dispatch analytics fetching ([#1143](https://github.com/aws-powertools/powertools-lambda-java/issues/1143)) -## [1.7.1] - 2021-07-06 -* **Powertools for AWS Lambda (Java) All Modules**: Fix static code analysis violations done via [spotbugs](https://github.com/spotbugs/spotbugs) ([#458](https://github.com/aws-powertools/powertools-lambda-java/pull/458)). +<a name="v1.15.0"></a> +## [v1.15.0] - 2023-03-21 +## Bug Fixes -## [1.7.0] - 2021-07-05 +* **cloudformation-module:** Use physicalResourceId when not provided by custom resource ([#1082](https://github.com/aws-powertools/powertools-lambda-java/issues/1082)) -### Added +## Documentation -* **Logging**: Support for extracting Correlation id using `@Logging` annotation via `correlationIdPath` attribute and `setCorrelationId()` method in `LoggingUtils`([#448](https://github.com/aws-powertools/powertools-lambda-java/pull/448)). -* **Logging**: New `clearState` attribute on `@Logging` annotation to clear previously added custom keys upon invocation([#453](https://github.com/aws-powertools/powertools-lambda-java/pull/453)). +* **cloudformation-module:** Improve Docs ([#1090](https://github.com/aws-powertools/powertools-lambda-java/issues/1090)) +* **plugin:** fix mdocs and git revision plugin integration ([#1066](https://github.com/aws-powertools/powertools-lambda-java/issues/1066)) -### Maintenance +## Features -* **deps**: Bump third party dependencies to the latest versions. +* Add DynamoDB provider to parameters module ([#1091](https://github.com/aws-powertools/powertools-lambda-java/issues/1091)) -## [1.6.0] - 2021-06-21 +## Maintenance -### Added +* update the project version to 1.15.0 ([#1097](https://github.com/aws-powertools/powertools-lambda-java/issues/1097)) +* **governance:** update issue templates ([#1062](https://github.com/aws-powertools/powertools-lambda-java/issues/1062)) +* **metrics:** deprecate withMetricLogger in favor of withMetricsLogger ([#1060](https://github.com/aws-powertools/powertools-lambda-java/issues/1060)) -* **Tracing**: Support for Boolean and Number type as value in `TracingUtils.putAnnotation()`([#423](https://github.com/aws-powertools/powertools-lambda-java/pull/432)). -* **Logging**: API to remove any additional custom key from logger entry using `LoggingUtils.removeKeys()`([#395](https://github.com/aws-powertools/powertools-lambda-java/pull/395)). -### Maintenance +<a name="v1.14.0"></a> +## [v1.14.0] - 2023-02-17 +## Documentation -* **deps**: Bump third party dependencies to the latest versions. +* **home:** update powertools definition -## [1.5.0] - 2021-03-30 +## Features -* **Metrics**: Ability to set multiple dimensions as default dimensions via `MetricsUtils.defaultDimensions()`. - Introduced in [v1.4.0](https://github.com/aws-powertools/powertools-lambda-java/releases/tag/v1.4.0) - `MetricsUtils.defaultDimensionSet()` is deprecated now for better user experience. +* **metrics:** introduce MetricsUtils.withMetricsLogger utility ([#1000](https://github.com/aws-powertools/powertools-lambda-java/issues/1000)) -## [1.4.0] - 2021-03-11 -* **Metrics**: Ability to set default dimension for metrics via `MetricsUtils.defaultDimensionSet()`. - - **Note**: If your monitoring depends on [default dimensions](https://github.com/awslabs/aws-embedded-metrics-java/blob/main/src/main/java/software/amazon/cloudwatchlogs/emf/logger/MetricsLogger.java#L173) captured before via [aws-embedded-metrics-java](https://github.com/awslabs/aws-embedded-metrics-java), - those either need to be updated or has to be explicitly captured via `MetricsUtils.defaultDimensionSet()`. - +## Maintenance -* **Metrics**: Remove validation of having minimum one dimension. EMF now support [Dimension set being empty](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html) as well. +* update the project version to 1.14.0 ([#1052](https://github.com/aws-powertools/powertools-lambda-java/issues/1052)) -## [1.3.0] - 2021-03-05 -* **Powertools**: It now works out of the box with [code guru profile handler implementation](https://docs.aws.amazon.com/codeguru/latest/profiler-ug/lambda-custom.html). -* **Logging**: Ability to override object mapper used for logging event. This provides customers ability to customize how and what they want to log from event. -* **Metrics**: Module now by default captures AWS Request id as property if used together with Metrics annotation. It will also capture Xray Trace ID as property if tracing is enabled. This ensures good observability and tracing. -* **Metrics**:`withSingleMetric` from `MetricsUtils can now pick the default namespace specified either on Metrics annotation or via POWERTOOLS_METRICS_NAMESPACE env var, without need to specify explicitly for each call. -* **Metrics**:`Metrics` annotation captures metrics even in case of unhandled exception from Lambda function. -* **Docs**: Migrated from Gatsby to MKdocs documentation system +<a name="v1.13.0"></a> +## [v1.13.0] - 2022-12-14 +## Bug Fixes + +* envelope is not taken into account with built-in types ([#960](https://github.com/aws-powertools/powertools-lambda-java/issues/960)) + +## Documentation + +* add missing grammar article ([#976](https://github.com/aws-powertools/powertools-lambda-java/issues/976)) + +## Features + +* **idempotency:** handle lambda timeout scenarios for INPROGRESS records ([#933](https://github.com/aws-powertools/powertools-lambda-java/issues/933)) + +## Maintenance + +* update the project version to 1.13.0 ([#1018](https://github.com/aws-powertools/powertools-lambda-java/issues/1018)) + + +<a name="v1.12.3"></a> +## [v1.12.3] - 2022-07-12 +## Maintenance + +* **ci:** fix build ([#853](https://github.com/aws-powertools/powertools-lambda-java/issues/853)) +* **ci:** Address GitHub workaround for CVE-2022-24765. +* **ci:** upgrade to checkout v3 + + +<a name="v1.12.2"></a> +## [v1.12.2] - 2022-04-29 +## Bug Fixes + +* remove local implementation of PayloadS3Pointer.java and use payloadoffloading-common ([#851](https://github.com/aws-powertools/powertools-lambda-java/issues/851)) + + +<a name="v1.12.1"></a> +## [v1.12.1] - 2022-04-21 +## Bug Fixes + +* disable idempotency doesn't disable dynamodb client creation in persistent store ([#796](https://github.com/aws-powertools/powertools-lambda-java/issues/796)) + +## Maintenance + +* correct bug fix release number +* **docs:** additional rename of project name ([#781](https://github.com/aws-powertools/powertools-lambda-java/issues/781)) ([#789](https://github.com/aws-powertools/powertools-lambda-java/issues/789)) + +## Reverts +* chore: correct bug fix release number + + +<a name="v1.12.0"></a> +## [v1.12.0] - 2022-03-01 +## Bug Fixes + +* **docs:** fix title for custom resources page ([#763](https://github.com/aws-powertools/powertools-lambda-java/issues/763)) + +## Features + +* Easy Event Deserialization ([#757](https://github.com/aws-powertools/powertools-lambda-java/issues/757)) + +## Maintenance + +* remove examples from the project as it was moved to aws-lambda-powertools-examples ([#772](https://github.com/aws-powertools/powertools-lambda-java/issues/772)) +* remove SQS and Idempotency examples ([#754](https://github.com/aws-powertools/powertools-lambda-java/issues/754)) +* downgrade release plugin to validate release fail issue +* downgrade release plugin to validate release fail issue + + +<a name="v1.11.0"></a> +## [v1.11.0] - 2022-02-16 +## Maintenance + +* **docs:** FAQ for Kotlin projects +* **docs:** Clarify test config needed for Tracing module ([#735](https://github.com/aws-powertools/powertools-lambda-java/issues/735)) +* **docs:** typo in CHANGELOG.md + + +<a name="v1.10.3"></a> +## [v1.10.3] - 2022-02-01 +## Bug Fixes + +* Prevent message to be marked as success if failed sending to DLQ ([#731](https://github.com/aws-powertools/powertools-lambda-java/issues/731)) +* **gradle:** Fix gradle example and docs to work with java 12+ ([#703](https://github.com/aws-powertools/powertools-lambda-java/issues/703)) + +## Maintenance + +* move core utilities example to aws-samples/aws-lambda-powertools-examples ([#733](https://github.com/aws-powertools/powertools-lambda-java/issues/733)) +* Update readme to refer examples repo +* **ci:** set release env variable for auto closing issue + + +<a name="v1.10.2"></a> +## [v1.10.2] - 2022-01-07 +## Features + +* **tracing:** ability to override object mapper ([#698](https://github.com/aws-powertools/powertools-lambda-java/issues/698)) + +## Maintenance + +* Automate release prep ([#696](https://github.com/aws-powertools/powertools-lambda-java/issues/696)) +* **automation:** find replace pom.xml at all levels +* **automation:** find replace pom.xml at all levels +* **docs:** Add FAQs section to docs with information about Lombok support. ([#680](https://github.com/aws-powertools/powertools-lambda-java/issues/680)) + + +<a name="v1.10.1"></a> +## [v1.10.1] - 2022-01-06 +## Features + +* **ci:** auto-notify & close issues on release + +## Maintenance + +* prep release 1.10.1 +* action to automate release prep +* action to automate release prep +* **docs:** Latest version of aspectj.post-compile-weaving +* **docs:** Full gradle config in example for each module +* **docs:** use free fair gradle aspect plugin ([#679](https://github.com/aws-powertools/powertools-lambda-java/issues/679)) + + +<a name="v1.10.0"></a> +## [v1.10.0] - 2021-12-27 + +<a name="v1.9.1"></a> +## [v1.9.1] - 2021-12-27 +## Bug Fixes + +* support batch size greater than 10 processing ([#667](https://github.com/aws-powertools/powertools-lambda-java/issues/667)) + +## Features + +* Json layout modern implementation ([#670](https://github.com/aws-powertools/powertools-lambda-java/issues/670)) + +## Maintenance + +* prep release 1.10.0 ([#671](https://github.com/aws-powertools/powertools-lambda-java/issues/671)) +* Fix docs layout + + +<a name="v1.8.3"></a> +## [v1.8.3] - 2021-12-21 + +<a name="v1.9.0"></a> +## [v1.9.0] - 2021-12-21 +## Features + +* **tracing:** add service annotation ([#655](https://github.com/aws-powertools/powertools-lambda-java/issues/655)) + +## Maintenance + +* prep release 1.9.0 ([#666](https://github.com/aws-powertools/powertools-lambda-java/issues/666)) +* localise abstract json layout implementation ([#664](https://github.com/aws-powertools/powertools-lambda-java/issues/664)) +* Update edit url prefix on doc +* Update docs to reflect latest gradle plugin fix ([#656](https://github.com/aws-powertools/powertools-lambda-java/issues/656)) + + +<a name="v1.8.2"></a> +## [v1.8.2] - 2021-12-15 +## Maintenance + +* prep release 1.8.2 ([#653](https://github.com/aws-powertools/powertools-lambda-java/issues/653)) + + +<a name="v1.8.1"></a> +## [v1.8.1] - 2021-12-10 +## Documentation + +* **tenets:** update Idiomatic tenet to Progressive ([#615](https://github.com/aws-powertools/powertools-lambda-java/issues/615)) + +## Maintenance + +* prep release 1.8.1 ([#647](https://github.com/aws-powertools/powertools-lambda-java/issues/647)) + + +<a name="v1.8.0"></a> +## [v1.8.0] - 2021-11-05 +## Bug Fixes + +* LoggingAspect precedence to be last for accepting mutated args ([#567](https://github.com/aws-powertools/powertools-lambda-java/issues/567)) + +## Features + +* create Java cfn-response equivalent ([#558](https://github.com/aws-powertools/powertools-lambda-java/issues/558)) ([#560](https://github.com/aws-powertools/powertools-lambda-java/issues/560)) + +## Maintenance + +* prep release 1.8.0 ([#608](https://github.com/aws-powertools/powertools-lambda-java/issues/608)) +* Fix failing build and auto merge only when build is success +* spotbug check ([#565](https://github.com/aws-powertools/powertools-lambda-java/issues/565)) +* Fix/Ignore spotbugs violations + + +<a name="v1.7.3"></a> +## [v1.7.3] - 2021-09-14 +## Bug Fixes + +* reset cold start only when placed on handler ([#508](https://github.com/aws-powertools/powertools-lambda-java/issues/508)) + +## Documentation + +* **batch-processing:** Support for moving non retryable msg to DLQ ([#531](https://github.com/aws-powertools/powertools-lambda-java/issues/531)) + +## Features + +* **batch-processing:** move non retry-able message to DLQ ([#500](https://github.com/aws-powertools/powertools-lambda-java/issues/500)) + +## Maintenance + +* prep release 1.7.3 + + +<a name="v1.7.2"></a> +## [v1.7.2] - 2021-08-03 +## Documentation + +* status badges + +## Maintenance + +* prep release 1.7.2 ([#490](https://github.com/aws-powertools/powertools-lambda-java/issues/490)) +* Upgrade to latest(1.14.0) aspectj-maven-plugin ([#489](https://github.com/aws-powertools/powertools-lambda-java/issues/489)) +* Logging and SQS utility Optimisations ([#484](https://github.com/aws-powertools/powertools-lambda-java/issues/484)) +* wait for merge until check is green +* wait for merge until check is green +* wait for spotbugs check before automerge + + +<a name="v1.7.1"></a> +## [v1.7.1] - 2021-07-06 +## Maintenance + +* prep release 1.7.1 ([#459](https://github.com/aws-powertools/powertools-lambda-java/issues/459)) + + +<a name="v1.7.0"></a> +## [v1.7.0] - 2021-07-05 +## Features + +* Clear logger state ([#453](https://github.com/aws-powertools/powertools-lambda-java/issues/453)) + +## Maintenance + +* prep release 1.7.0 ([#457](https://github.com/aws-powertools/powertools-lambda-java/issues/457)) + + +<a name="v1.6.0"></a> +## [v1.6.0] - 2021-06-20 +## Features + +* [#421](https://github.com/aws-powertools/powertools-lambda-java/issues/421) Support for Boolean and Number type as value in TracingUtils putAnnotation ([#423](https://github.com/aws-powertools/powertools-lambda-java/issues/423)) +* logger-Remove custom keys interface ([#395](https://github.com/aws-powertools/powertools-lambda-java/issues/395)) + +## Maintenance + +* prep release 1.6.0 ([#436](https://github.com/aws-powertools/powertools-lambda-java/issues/436)) +* setup-java v2 ([#353](https://github.com/aws-powertools/powertools-lambda-java/issues/353)) +* add JDK 16 to build matrix ([#367](https://github.com/aws-powertools/powertools-lambda-java/issues/367)) + + +<a name="v1.5.0"></a> +## [v1.5.0] - 2021-03-31 +## Features + +* remove deprecated attributes on Tracing annotation ([#330](https://github.com/aws-powertools/powertools-lambda-java/issues/330)) + +## Maintenance + +* prep release 1.5.0 ([#345](https://github.com/aws-powertools/powertools-lambda-java/issues/345)) +* rename automerge workflow name +* fix auto merge dependabot PR ([#342](https://github.com/aws-powertools/powertools-lambda-java/issues/342)) + + +<a name="v1.4.0"></a> +## [v1.4.0] - 2021-03-11 +## Bug Fixes + +* null check on dimension + +## Features + +* Default dimensions from powertools instead of emf library ([#317](https://github.com/aws-powertools/powertools-lambda-java/issues/317)) + +## Maintenance + +* prep release 1.4.0 ([#324](https://github.com/aws-powertools/powertools-lambda-java/issues/324)) + + +<a name="v1.3.0"></a> +## [v1.3.0] - 2021-03-05 +## Bug Fixes + +* powertools specific log level env var to not conflict with the system LOG_LEVEL ([#306](https://github.com/aws-powertools/powertools-lambda-java/issues/306)) +* **example:** Update the example to v1.2.0 ([#288](https://github.com/aws-powertools/powertools-lambda-java/issues/288)) + +## Documentation + +* ability to override object mapper used for logging event ([#303](https://github.com/aws-powertools/powertools-lambda-java/issues/303)) + +## Features + +* single metric utility method to pick default namespace ([#305](https://github.com/aws-powertools/powertools-lambda-java/issues/305)) +* ability to override object mapper used for logging event ([#302](https://github.com/aws-powertools/powertools-lambda-java/issues/302)) +* respect code guru profile handler implementation ([#304](https://github.com/aws-powertools/powertools-lambda-java/issues/304)) +* capture metrics even when handler results in exception ([#286](https://github.com/aws-powertools/powertools-lambda-java/issues/286)) + +## Maintenance + +* Prep release 1.3.0 ([#316](https://github.com/aws-powertools/powertools-lambda-java/issues/316)) +* migrate docs from gatsby to mkdocs ([#308](https://github.com/aws-powertools/powertools-lambda-java/issues/308)) +* consistent field names for trace and req id with logger ([#309](https://github.com/aws-powertools/powertools-lambda-java/issues/309)) + + +<a name="v1.2.0"></a> +## [v1.2.0] - 2021-01-13 +## Code Refactoring + +* replace Apache Commons Logging with SLF4J ([#212](https://github.com/aws-powertools/powertools-lambda-java/issues/212)) + +## Documentation + +* shadow sidebar to remain expanded ([#208](https://github.com/aws-powertools/powertools-lambda-java/issues/208)) + +## Features + +* support for env variable in tracing capture modes ([#249](https://github.com/aws-powertools/powertools-lambda-java/issues/249)) +* custom segment names ([#221](https://github.com/aws-powertools/powertools-lambda-java/issues/221)) + +## Maintenance + +* Prep release 1.2.0 ([#250](https://github.com/aws-powertools/powertools-lambda-java/issues/250)) +* Consistent env variable names for tracing ([#251](https://github.com/aws-powertools/powertools-lambda-java/issues/251)) +* update docs dependencies ([#214](https://github.com/aws-powertools/powertools-lambda-java/issues/214)) + + +<a name="v1.1.0"></a> +## [v1.1.0] - 2020-12-03 +## Documentation + +* add source code link in nav bar ([#199](https://github.com/aws-powertools/powertools-lambda-java/issues/199)) + +## Features + +* Parameters injection ([#201](https://github.com/aws-powertools/powertools-lambda-java/issues/201)) + +## Maintenance + +* Prep release 1.1.0 ([#205](https://github.com/aws-powertools/powertools-lambda-java/issues/205)) + + +<a name="v1.0.1"></a> +## [v1.0.1] - 2020-11-26 +## Bug Fixes + +* fixing dependencies security issues ([#169](https://github.com/aws-powertools/powertools-lambda-java/issues/169)) + +## Maintenance + +* Prep for release (1.0.1) ([#198](https://github.com/aws-powertools/powertools-lambda-java/issues/198)) +* upgrade AspectjGradlePlugin to latest and example project to java 11 ([#189](https://github.com/aws-powertools/powertools-lambda-java/issues/189)) + +## Performance Improvements + +* Make UrlConnectionHttpClient default client for params fetch ([#185](https://github.com/aws-powertools/powertools-lambda-java/issues/185)) + + +<a name="v1.0.0"></a> +## [v1.0.0] - 2020-11-04 +## Bug Fixes + +* **docs:** Correct url and not for gradle ([#158](https://github.com/aws-powertools/powertools-lambda-java/issues/158)) + +## Code Refactoring + +* Rename helpers for validation module ([#167](https://github.com/aws-powertools/powertools-lambda-java/issues/167)) +* Rename annotations for GA ([#165](https://github.com/aws-powertools/powertools-lambda-java/issues/165)) + + +<a name="v0.6.0-beta"></a> +## [v0.6.0-beta] - 2020-10-27 +## Documentation + +* Update all the environment variables used ([#127](https://github.com/aws-powertools/powertools-lambda-java/issues/127)) + +## Features + +* log aws request id ([#133](https://github.com/aws-powertools/powertools-lambda-java/issues/133)) + +## Maintenance + +* Prepare for 0.6.0-beta ([#155](https://github.com/aws-powertools/powertools-lambda-java/issues/155)) +* gradle example ([#147](https://github.com/aws-powertools/powertools-lambda-java/issues/147)) + + +<a name="v0.5.0-beta"></a> +## [v0.5.0-beta] - 2020-10-06 +## Features + +* SQS Partial batch Utility ([#120](https://github.com/aws-powertools/powertools-lambda-java/issues/120)) + +## Maintenance + +* Prepare for 0.5.0-beta ([#124](https://github.com/aws-powertools/powertools-lambda-java/issues/124)) + + +<a name="v0.4.0-beta"></a> +## [v0.4.0-beta] - 2020-10-02 +## Bug Fixes + +* Log event via object mapper and not depend on toString ([#113](https://github.com/aws-powertools/powertools-lambda-java/issues/113)) + +## Features + +* integration with CloudWatch ServiceLens [#88](https://github.com/aws-powertools/powertools-lambda-java/issues/88) ([#111](https://github.com/aws-powertools/powertools-lambda-java/issues/111)) + + +<a name="v0.3.1-beta"></a> +## [v0.3.1-beta] - 2020-09-25 +## Bug Fixes + +* Removing Log4J dependencies from the tracing module. ([#106](https://github.com/aws-powertools/powertools-lambda-java/issues/106)) +* Removing v1 Java SDK dependencies for X-Ray ([#105](https://github.com/aws-powertools/powertools-lambda-java/issues/105)) + +## Documentation + +* fixes to the documentation ([#102](https://github.com/aws-powertools/powertools-lambda-java/issues/102)) + + +<a name="v0.3.0-beta"></a> +## [v0.3.0-beta] - 2020-09-22 +## Features + +* Metrics utility ([#91](https://github.com/aws-powertools/powertools-lambda-java/issues/91)) + + +<a name="v0.2.0-beta"></a> +## [v0.2.0-beta] - 2020-09-01 +## Bug Fixes + +* **general:** clean up typos and code ([#62](https://github.com/aws-powertools/powertools-lambda-java/issues/62)) + +## Documentation + +* Readme update ([#72](https://github.com/aws-powertools/powertools-lambda-java/issues/72)) +* Update SQS large payload docs ([#60](https://github.com/aws-powertools/powertools-lambda-java/issues/60)) +* fixing documentation ([#59](https://github.com/aws-powertools/powertools-lambda-java/issues/59)) + +## Features + +* Utility without annotation ([#61](https://github.com/aws-powertools/powertools-lambda-java/issues/61)) +* SQS Large message handling ([#55](https://github.com/aws-powertools/powertools-lambda-java/issues/55)) + + +<a name="v0.1.0-beta"></a> +## v0.1.0-beta - 2020-08-31 +## Bug Fixes + +* Fixing security issues on package.json dependencies ([#22](https://github.com/aws-powertools/powertools-lambda-java/issues/22)) +* Fixing package versions for security purpose ([#16](https://github.com/aws-powertools/powertools-lambda-java/issues/16)) +* Rename Java ArtifactId and GroupId to be compliant with new AWS standard. +* docs pipeline +* Fix Readme.md documentation and remove unecessary parts. + +## Code Refactoring + +* consistent naming of powertools tracing and initial docs. ([#48](https://github.com/aws-powertools/powertools-lambda-java/issues/48)) +* consistent naming of powertools. ([#46](https://github.com/aws-powertools/powertools-lambda-java/issues/46)) +* Split Tracing and Logging packages Dependency split ([#45](https://github.com/aws-powertools/powertools-lambda-java/issues/45)) +* move groupId from software.aws.lambda to softwarte.amazon.lambda ([#23](https://github.com/aws-powertools/powertools-lambda-java/issues/23)) + +## Documentation + +* Adding license to each source file ([#44](https://github.com/aws-powertools/powertools-lambda-java/issues/44)) +* Initial javadocs for PowerLogger class. ([#43](https://github.com/aws-powertools/powertools-lambda-java/issues/43)) +* Implement Logger and Tracer part ([#27](https://github.com/aws-powertools/powertools-lambda-java/issues/27)) +* Initial javadocs for our logging annotation. ([#40](https://github.com/aws-powertools/powertools-lambda-java/issues/40)) +* update maven artifactId and groupId to new one +* Improving README file +* Init project documentation ci: init Github actions flow + +## Pull Requests + +* Merge pull request [#1](https://github.com/aws-powertools/powertools-lambda-java/issues/1) from stevehouel/master + + +[Unreleased]: https://github.com/aws-powertools/powertools-lambda-java/compare/v2.4.0...HEAD +[v2.4.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v2.3.0...v2.4.0 +[v2.3.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v2.2.1...v2.3.0 +[v2.2.1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v2.2.0...v2.2.1 +[v2.2.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v2.1.1...v2.2.0 +[v2.1.1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v2.1.0...v2.1.1 +[v2.1.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v2.0.0...v2.1.0 +[v2.0.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v2.0.0-RC1...v2.0.0 +[v2.0.0-RC1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.20.2...v2.0.0-RC1 +[v1.20.2]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.20.1...v1.20.2 +[v1.20.1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.20.0...v1.20.1 +[v1.20.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.19.0...v1.20.0 +[v1.19.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.18.0...v1.19.0 +[v1.18.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.17.0...v1.18.0 +[v1.17.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.16.1...v1.17.0 +[v1.16.1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.16.0...v1.16.1 +[v1.16.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.15.0...v1.16.0 +[v1.15.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.14.0...v1.15.0 +[v1.14.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.13.0...v1.14.0 +[v1.13.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.12.3...v1.13.0 +[v1.12.3]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.12.2...v1.12.3 +[v1.12.2]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.12.1...v1.12.2 +[v1.12.1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.12.0...v1.12.1 +[v1.12.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.11.0...v1.12.0 +[v1.11.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.10.3...v1.11.0 +[v1.10.3]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.10.2...v1.10.3 +[v1.10.2]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.10.1...v1.10.2 +[v1.10.1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.10.0...v1.10.1 +[v1.10.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.9.1...v1.10.0 +[v1.9.1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.8.3...v1.9.1 +[v1.8.3]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.9.0...v1.8.3 +[v1.9.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.8.2...v1.9.0 +[v1.8.2]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.8.1...v1.8.2 +[v1.8.1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.8.0...v1.8.1 +[v1.8.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.7.3...v1.8.0 +[v1.7.3]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.7.2...v1.7.3 +[v1.7.2]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.7.1...v1.7.2 +[v1.7.1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.7.0...v1.7.1 +[v1.7.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.6.0...v1.7.0 +[v1.6.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.5.0...v1.6.0 +[v1.5.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.4.0...v1.5.0 +[v1.4.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.3.0...v1.4.0 +[v1.3.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.2.0...v1.3.0 +[v1.2.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.1.0...v1.2.0 +[v1.1.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.0.1...v1.1.0 +[v1.0.1]: https://github.com/aws-powertools/powertools-lambda-java/compare/v1.0.0...v1.0.1 +[v1.0.0]: https://github.com/aws-powertools/powertools-lambda-java/compare/v0.6.0-beta...v1.0.0 +[v0.6.0-beta]: https://github.com/aws-powertools/powertools-lambda-java/compare/v0.5.0-beta...v0.6.0-beta +[v0.5.0-beta]: https://github.com/aws-powertools/powertools-lambda-java/compare/v0.4.0-beta...v0.5.0-beta +[v0.4.0-beta]: https://github.com/aws-powertools/powertools-lambda-java/compare/v0.3.1-beta...v0.4.0-beta +[v0.3.1-beta]: https://github.com/aws-powertools/powertools-lambda-java/compare/v0.3.0-beta...v0.3.1-beta +[v0.3.0-beta]: https://github.com/aws-powertools/powertools-lambda-java/compare/v0.2.0-beta...v0.3.0-beta +[v0.2.0-beta]: https://github.com/aws-powertools/powertools-lambda-java/compare/v0.1.0-beta...v0.2.0-beta From a43da0a492dcf89bd23cb556f88653c34014b61b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 11:46:03 +0200 Subject: [PATCH 474/577] chore: bump org.codehaus.mojo:exec-maven-plugin from 3.5.1 to 3.6.2 (#2208) Bumps [org.codehaus.mojo:exec-maven-plugin](https://github.com/mojohaus/exec-maven-plugin) from 3.5.1 to 3.6.2. - [Release notes](https://github.com/mojohaus/exec-maven-plugin/releases) - [Commits](https://github.com/mojohaus/exec-maven-plugin/compare/3.5.1...3.6.2) --- updated-dependencies: - dependency-name: org.codehaus.mojo:exec-maven-plugin dependency-version: 3.6.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 800d896d0..c96236480 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -25,7 +25,7 @@ <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> - <version>3.5.1</version> + <version>3.6.2</version> <configuration> <mainClass>cdk.CdkApp</mainClass> </configuration> diff --git a/pom.xml b/pom.xml index 8bed88cd0..82b713b10 100644 --- a/pom.xml +++ b/pom.xml @@ -449,7 +449,7 @@ <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> - <version>3.5.1</version> + <version>3.6.2</version> </plugin> </plugins> </pluginManagement> From bcda58fc9eff74ed2b6b86b0c840ec67fc407ce8 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 21 Oct 2025 13:55:26 +0200 Subject: [PATCH 475/577] chore(ci): Fix sha256 formatting in git-chglog docker image reference (#2218) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c6a3e415b..a2263aa89 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -243,7 +243,7 @@ jobs: name: Create branch and update change log run: | git checkout -b ci-${{ github.run_id }} - docker run -v "${PWD}":/workdir quay.io/git-chglog/git-chglog:sha256:c791b1e8264387690cce4ce32e18b4f59ca3ffd8d55cb4093dc6de74529493f4 > CHANGELOG.md + docker run -v "${PWD}":/workdir quay.io/git-chglog/git-chglog@sha256:c791b1e8264387690cce4ce32e18b4f59ca3ffd8d55cb4093dc6de74529493f4 > CHANGELOG.md git commit -am "chore(ci): bump version to ${{ inputs.version }}" git push origin ci-${{ github.run_id }} - id: create_pr From 326f4b8d39dfab59d24aaea34112535be0f56cc6 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 21 Oct 2025 14:31:24 +0200 Subject: [PATCH 476/577] chore(ci): Move tag step before changelog generation. (#2219) --- .github/workflows/release.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a2263aa89..13c7c34d2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -239,6 +239,11 @@ jobs: git config user.email "151832416+aws-powertools-bot@users.noreply.github.com" git config pull.rebase true git config remote.origin.url >&- + - id: tag + name: Create tag + run: | + git tag -a v${{ inputs.version }} -m "Release v${{ inputs.version }}" + git push origin v${{ inputs.version }} - id: branch name: Create branch and update change log run: | @@ -254,11 +259,6 @@ jobs: --body "This is an automated PR created from the following workflow: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - id: tag - name: Create tag - run: | - git tag -a v${{ inputs.version }} -m "Release v${{ inputs.version }}" - git push origin v${{ inputs.version }} docs: runs-on: ubuntu-latest From 07db6313b4f6133546cc449a1fc4c069d0538d76 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 15:27:07 +0200 Subject: [PATCH 477/577] chore(ci): bump version to 2.5.0 (#2220) * chore(ci): bump version to 2.5.0 * Restore CHANGELOG.md from main. --------- Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Philipp Page <pagejep@amazon.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/README.md | 4 ++-- .../infra/sam-graalvm/README.md | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- .../powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- .../powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/handlers/batch/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency/pom.xml | 2 +- powertools-e2e-tests/handlers/largemessage/pom.xml | 2 +- .../handlers/largemessage_idempotent/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-log4j/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-logback/pom.xml | 2 +- powertools-e2e-tests/handlers/metrics/pom.xml | 2 +- powertools-e2e-tests/handlers/parameters/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/handlers/tracing/pom.xml | 2 +- powertools-e2e-tests/handlers/validation-alb-event/pom.xml | 2 +- .../handlers/validation-apigw-event/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 58 files changed, 65 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 5e0266744..b53d5aeb1 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-metrics</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </dependency> ... </dependencies> diff --git a/examples/pom.xml b/examples/pom.xml index b892f43ce..71d924c26 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-examples</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Examples</name> diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index c31277d6a..2a6579074 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-batch</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Batch</name> diff --git a/examples/powertools-examples-cloudformation/README.md b/examples/powertools-examples-cloudformation/README.md index 262a6b14f..b26007d44 100644 --- a/examples/powertools-examples-cloudformation/README.md +++ b/examples/powertools-examples-cloudformation/README.md @@ -15,7 +15,7 @@ Run the following in your shell: ```bash cd infra/sam sam build -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.4.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.5.0718 ``` ### Deploy with CDK @@ -32,5 +32,5 @@ To build and deploy this application for the first time, run the following in yo cd infra/cdk mvn package cdk synth -cdk deploy -c BucketNameParam=my-unique-bucket-2.4.0718 +cdk deploy -c BucketNameParam=my-unique-bucket-2.5.0718 ``` \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md index 0f06fe084..b577855ce 100644 --- a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md +++ b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md @@ -40,7 +40,7 @@ sam build ## Deploy the sample application ```shell -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.4.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.5.0718 ``` This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting started with SAM in [the examples directory](../../../README.md) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 39f09da04..ad4cd2265 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-cloudformation</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 677a2b4b6..991c6bc60 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ <groupId>software.amazon.lambda.examples</groupId> <!-- TODO TODO TODO this should build from SNAPSHOT, but it doesn't, because the snapshots don't appear in the docker environment CDK builds it in in our CDK tests. How to procede? V2 blocker --> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-core-utilities-cdk</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index c96236480..6b6b1b699 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <artifactId>cdk</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.220.0</cdk.version> diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 1325eadaf..9b89d923a 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.4.0' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.4.0' - aspect 'software.amazon.lambda:powertools-metrics:2.4.0' + aspect 'software.amazon.lambda:powertools-tracing:2.5.0' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.5.0' + aspect 'software.amazon.lambda:powertools-metrics:2.5.0' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 98c41093f..85ec540a9 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.4.0") - aspect("software.amazon.lambda:powertools-logging-log4j:2.4.0") - aspect("software.amazon.lambda:powertools-metrics:2.4.0") + aspect("software.amazon.lambda:powertools-tracing:2.5.0") + aspect("software.amazon.lambda:powertools-logging-log4j:2.5.0") + aspect("software.amazon.lambda:powertools-metrics:2.5.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 64649fe45..6ae05168c 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-core-utilities-sam-graalvm</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 3647509c6..bcfcbba6d 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-core-utilities-sam</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index b5236b11e..a7af92c94 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-core-utilities-serverless</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 95fcc07c1..8bef2d669 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-core-utilities-terraform</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index 956b8a9d9..89703a154 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-idempotency-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency GraalVM</name> diff --git a/examples/powertools-examples-idempotency/sam/pom.xml b/examples/powertools-examples-idempotency/sam/pom.xml index 8bc2a6311..b4120a082 100644 --- a/examples/powertools-examples-idempotency/sam/pom.xml +++ b/examples/powertools-examples-idempotency/sam/pom.xml @@ -17,7 +17,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-idempotency</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency</name> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index d7778c896..1eb55ae36 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-kafka</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Kafka</name> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 45d272f70..e2448c879 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-parameters-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 09a67104f..5d7ddf089 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-parameters-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters</name> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index 636435fbb..f496570cc 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-serialization-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 2bdaafbd1..683faf783 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-serialization-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization</name> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 303ce73cb..b84fac5bb 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <artifactId>powertools-examples-validation</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Validation</name> diff --git a/mkdocs.yml b/mkdocs.yml index c75fa90e7..62e211728 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -127,7 +127,7 @@ extra_javascript: extra: powertools: - version: 2.4.0 + version: 2.5.0 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index 82b713b10..6c54d8635 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Parent</name> diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 850be6922..edb849cea 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <description>A suite of utilities that makes batch message processing using AWS Lambda easier.</description> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index d49fcc2bc..5e40ee503 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Cloudformation</name> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index d68bcb63a..d78e84970 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Common Internal Utilities</name> diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index 99ce7d3c4..21161f9e7 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-batch</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index 79fd5b8e0..7c0e957fe 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-idempotency</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index 3aa6c5bee..469a9a48a 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-largemessage</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index 4261ff459..1e89edd67 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-large-msg-idempotent</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-log4j/pom.xml b/powertools-e2e-tests/handlers/logging-log4j/pom.xml index 792e19fba..dddc84152 100644 --- a/powertools-e2e-tests/handlers/logging-log4j/pom.xml +++ b/powertools-e2e-tests/handlers/logging-log4j/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-logging-log4j</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-logback/pom.xml b/powertools-e2e-tests/handlers/logging-logback/pom.xml index ac643b969..4f3a28c72 100644 --- a/powertools-e2e-tests/handlers/logging-logback/pom.xml +++ b/powertools-e2e-tests/handlers/logging-logback/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-logging-logback</artifactId> diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 54f9015c5..84006df9a 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-metrics</artifactId> diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index 957242f0f..e0a58f9bd 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-parameters</artifactId> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index b67207e75..da5fd7974 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -4,7 +4,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> <packaging>pom</packaging> <name>Handlers for End-to-End tests</name> <description>Fake handlers that use Powertools for AWS Lambda (Java).</description> diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index 0a88cc92c..5f6943ca6 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-tracing</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml index dcecfc0a8..e9e8f5c47 100644 --- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-validation-alb-event</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml index f4e9ff341..21e80c20e 100644 --- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>e2e-test-handler-validation-apigw-event</artifactId> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 20d28895e..9186ff04e 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>powertools-e2e-tests</artifactId> diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 096c6ea07..8961701d3 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>powertools-idempotency</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index b2a6459a5..e982a075e 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>powertools-idempotency-core</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index 885c9c9cd..a1115c20c 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>powertools-idempotency-dynamodb</artifactId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index a6a090b5d..a8d272b15 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>powertools-kafka</artifactId> diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index b78fa225b..a405941d7 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>powertools-large-messages</artifactId> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 14cc8898d..39fbc4386 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Logging</name> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 2b85a3752..a25c00a1b 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 17e39dda7..e376db085 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 58eab8a45..d4cdb7ed6 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Metrics</name> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index f7347c03a..7fca07497 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>powertools-parameters</artifactId> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index b2c4f3426..560f4b2d9 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index e03227eb8..bca6bf7d4 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 6a576f529..6e450a93e 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 7758fd906..d7c6e52a8 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 136b2ef43..41ea635de 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.4.0</version> + <version>2.5.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 2cc8fa5d4..5d3ff8874 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <artifactId>powertools-serialization</artifactId> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 045e76cbf..e53a7c080 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Tracing</name> diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 4194b4240..57f8f25fb 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.4.0</version> + <version>2.5.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Validation</name> From b474aef9dada2c6503263c3a4e326aeb9b770fc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 16:02:49 +0200 Subject: [PATCH 478/577] chore: bump aws.sdk.version from 2.35.8 to 2.35.10 (#2214) Bumps `aws.sdk.version` from 2.35.8 to 2.35.10. Updates `software.amazon.awssdk:bom` from 2.35.8 to 2.35.10 Updates `software.amazon.awssdk:http-client-spi` from 2.35.8 to 2.35.10 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.35.10 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.35.10 Updates `software.amazon.awssdk:dynamodb` from 2.35.8 to 2.35.10 Updates `software.amazon.awssdk:lambda` from 2.35.8 to 2.35.10 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.35.10 Updates `software.amazon.awssdk:cloudwatch` from 2.35.8 to 2.35.10 Updates `software.amazon.awssdk:xray` from 2.35.8 to 2.35.10 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.35.10 Updates `software.amazon.awssdk:cloudformation` from 2.35.8 to 2.35.10 Updates `software.amazon.awssdk:sts` from 2.35.8 to 2.35.10 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.35.10 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.35.10 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.35.10 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.35.10 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.35.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.35.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.35.10 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.35.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.35.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.35.10 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.35.10 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.35.10 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index ad4cd2265..043949b08 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.35.8</aws.sdk.version> + <aws.sdk.version>2.35.10</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 6c54d8635..2cada7d19 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.35.8</aws.sdk.version> + <aws.sdk.version>2.35.10</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index da5fd7974..a31458ba9 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.0</maven.compiler.version> - <aws.sdk.version>2.35.8</aws.sdk.version> + <aws.sdk.version>2.35.10</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 5e94a4166f44feeede0b6352f4c31376b4248728 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 16:33:18 +0200 Subject: [PATCH 479/577] chore: bump avro.version from 1.12.0 to 1.12.1 (#2215) Bumps `avro.version` from 1.12.0 to 1.12.1. Updates `org.apache.avro:avro` from 1.12.0 to 1.12.1 Updates `org.apache.avro:avro-maven-plugin` from 1.12.0 to 1.12.1 --- updated-dependencies: - dependency-name: org.apache.avro:avro dependency-version: 1.12.1 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.apache.avro:avro-maven-plugin dependency-version: 1.12.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 1eb55ae36..210371fdf 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -11,7 +11,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <avro.version>1.12.0</avro.version> + <avro.version>1.12.1</avro.version> <protobuf.version>4.33.0</protobuf.version> </properties> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index a8d272b15..fd001f575 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -35,7 +35,7 @@ <properties> <kafka-clients.version>4.1.0</kafka-clients.version> - <avro.version>1.12.0</avro.version> + <avro.version>1.12.1</avro.version> <protobuf.version>4.33.0</protobuf.version> <lambda-serialization.version>1.1.6</lambda-serialization.version> </properties> From 78f158c32315acf20a378de7e92e4b6c9baab1a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 16:33:37 +0200 Subject: [PATCH 480/577] chore: bump com.github.spotbugs:spotbugs-maven-plugin (#2216) Bumps [com.github.spotbugs:spotbugs-maven-plugin](https://github.com/spotbugs/spotbugs-maven-plugin) from 4.9.7.0 to 4.9.8.1. - [Release notes](https://github.com/spotbugs/spotbugs-maven-plugin/releases) - [Commits](https://github.com/spotbugs/spotbugs-maven-plugin/compare/spotbugs-maven-plugin-4.9.7.0...spotbugs-maven-plugin-4.9.8.1) --- updated-dependencies: - dependency-name: com.github.spotbugs:spotbugs-maven-plugin dependency-version: 4.9.8.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2cada7d19..15bbf8429 100644 --- a/pom.xml +++ b/pom.xml @@ -598,7 +598,7 @@ <plugin> <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> - <version>4.9.7.0</version> + <version>4.9.8.1</version> <executions> <execution> <id>test</id> From b1b976ee3c9e1f042f6988437b629673dd51952b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 16:34:04 +0200 Subject: [PATCH 481/577] chore: bump org.apache.maven.plugins:maven-compiler-plugin (#2217) Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.14.0 to 3.14.1. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.14.0...maven-compiler-plugin-3.14.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-version: 3.14.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 6b6b1b699..495e3556a 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -16,7 +16,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> - <version>3.14.0</version> + <version>3.14.1</version> <configuration> <source>11</source> <target>11</target> diff --git a/pom.xml b/pom.xml index 15bbf8429..7163e1da4 100644 --- a/pom.xml +++ b/pom.xml @@ -92,7 +92,7 @@ <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> <lambda.serial.version>1.1.6</lambda.serial.version> - <maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version> + <maven-compiler-plugin.version>3.14.1</maven-compiler-plugin.version> <aspectj.version>1.9.7</aspectj.version> <aspectj-maven-plugin.version>1.13.1</aspectj-maven-plugin.version> <maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index a31458ba9..efb6929cc 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -18,7 +18,7 @@ <lambda.java.events>3.16.1</lambda.java.events> <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> - <maven.compiler.version>3.14.0</maven.compiler.version> + <maven.compiler.version>3.14.1</maven.compiler.version> <aws.sdk.version>2.35.10</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 9186ff04e..0b11ce4e0 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -197,7 +197,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> - <version>3.14.0</version> + <version>3.14.1</version> <configuration> <source>${maven.compiler.source}</source> <target>${maven.compiler.target}</target> From 9316011b3cb27d149cc5d5125712af854090e9b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 17:34:30 +0200 Subject: [PATCH 482/577] chore: bump org.graalvm.buildtools:native-maven-plugin (#2225) Bumps [org.graalvm.buildtools:native-maven-plugin](https://github.com/graalvm/native-build-tools) from 0.11.0 to 0.11.2. - [Release notes](https://github.com/graalvm/native-build-tools/releases) - [Commits](https://github.com/graalvm/native-build-tools/compare/0.11.0...0.11.2) --- updated-dependencies: - dependency-name: org.graalvm.buildtools:native-maven-plugin dependency-version: 0.11.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- powertools-parameters/powertools-parameters-appconfig/pom.xml | 2 +- powertools-parameters/powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 043949b08..9b8d48912 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -159,7 +159,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 6ae05168c..f35757cce 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -158,7 +158,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index 89703a154..a86387b94 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -139,7 +139,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index e2448c879..49a6352c0 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -176,7 +176,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index f496570cc..cdf131482 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -61,7 +61,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 5e40ee503..f6d8ad33f 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -159,7 +159,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index d78e84970..9b1639b31 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -133,7 +133,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index efb6929cc..4d9d49d0b 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -199,7 +199,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index e982a075e..64907072f 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -114,7 +114,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index a1115c20c..a55947d4b 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -143,7 +143,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 39fbc4386..8c26d5be9 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -143,7 +143,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index a25c00a1b..94952eba5 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -132,7 +132,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index e376db085..f106970b9 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -130,7 +130,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index d4cdb7ed6..74b4ca7c4 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -188,7 +188,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 7fca07497..95acb65b2 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -118,7 +118,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 560f4b2d9..e8757f28d 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -142,7 +142,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index bca6bf7d4..099627265 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -143,7 +143,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 6e450a93e..cbf07e345 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -143,7 +143,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index d7c6e52a8..64d6cefcd 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -157,7 +157,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 41ea635de..40a942515 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -144,7 +144,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 5d3ff8874..457feec23 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -120,7 +120,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index e53a7c080..2b2f9b5be 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -157,7 +157,7 @@ <plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> - <version>0.11.0</version> + <version>0.11.2</version> <extensions>true</extensions> <executions> <execution> From fea5d4a26d3a044d1bcb0d726769cac04ad21e53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 17:35:22 +0200 Subject: [PATCH 483/577] chore: bump sam/build-java21 (#2226) Bumps sam/build-java21 from `e12c501` to `068d2ab`. --- updated-dependencies: - dependency-name: sam/build-java21 dependency-version: '068d2ab1eee017c2557b7a3879a9f9cc79ba0d5d8b177af5949437eee96458cd' dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index 7dc04ec90..c537351c8 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:e12c501aa7d3d3dc04be0d900115a0339c73f523ad73a9aecd9e99499413c465 +FROM public.ecr.aws/sam/build-java21@sha256:068d2ab1eee017c2557b7a3879a9f9cc79ba0d5d8b177af5949437eee96458cd # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From eace667e609f232f26121ecb8dec254164c9172e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 17:35:51 +0200 Subject: [PATCH 484/577] chore: bump aws.sdk.version from 2.35.10 to 2.35.11 (#2222) Bumps `aws.sdk.version` from 2.35.10 to 2.35.11. Updates `software.amazon.awssdk:bom` from 2.35.10 to 2.35.11 Updates `software.amazon.awssdk:http-client-spi` from 2.35.10 to 2.35.11 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.35.11 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.35.11 Updates `software.amazon.awssdk:dynamodb` from 2.35.10 to 2.35.11 Updates `software.amazon.awssdk:lambda` from 2.35.10 to 2.35.11 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.35.11 Updates `software.amazon.awssdk:cloudwatch` from 2.35.10 to 2.35.11 Updates `software.amazon.awssdk:xray` from 2.35.10 to 2.35.11 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.35.11 Updates `software.amazon.awssdk:cloudformation` from 2.35.10 to 2.35.11 Updates `software.amazon.awssdk:sts` from 2.35.10 to 2.35.11 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.35.11 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.35.11 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.35.11 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.35.11 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.35.11 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.35.11 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.35.11 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.35.11 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.35.11 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.35.11 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.35.11 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.35.11 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 9b8d48912..21c16891d 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.35.10</aws.sdk.version> + <aws.sdk.version>2.35.11</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 7163e1da4..2d9b7db00 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.35.10</aws.sdk.version> + <aws.sdk.version>2.35.11</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 4d9d49d0b..8ba1d76cd 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.0</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.35.10</aws.sdk.version> + <aws.sdk.version>2.35.11</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 16924198fb70dd882bb662dd30b89bd2d2a06058 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 17:38:31 +0200 Subject: [PATCH 485/577] chore: bump org.jacoco:jacoco-maven-plugin from 0.8.13 to 0.8.14 (#2224) Bumps [org.jacoco:jacoco-maven-plugin](https://github.com/jacoco/jacoco) from 0.8.13 to 0.8.14. - [Release notes](https://github.com/jacoco/jacoco/releases) - [Commits](https://github.com/jacoco/jacoco/compare/v0.8.13...v0.8.14) --- updated-dependencies: - dependency-name: org.jacoco:jacoco-maven-plugin dependency-version: 0.8.14 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2d9b7db00..1493020d4 100644 --- a/pom.xml +++ b/pom.xml @@ -103,7 +103,7 @@ <maven-gpg-plugin.version>3.2.1</maven-gpg-plugin.version> <aspectj-maven-plugin.version>1.14.1</aspectj-maven-plugin.version> <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version> - <jacoco-maven-plugin.version>0.8.13</jacoco-maven-plugin.version> + <jacoco-maven-plugin.version>0.8.14</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version> <maven-javadoc-plugin.version>3.11.3</maven-javadoc-plugin.version> <maven-source-plugin.version>3.3.1</maven-source-plugin.version> From e249cef0dd4f806c3203065f453762aceff5d56f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 Oct 2025 21:07:15 +0200 Subject: [PATCH 486/577] chore: bump org.junit:junit-bom from 5.13.4 to 5.14.0 (#2199) --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1493020d4..b9c3ec419 100644 --- a/pom.xml +++ b/pom.xml @@ -108,7 +108,7 @@ <maven-javadoc-plugin.version>3.11.3</maven-javadoc-plugin.version> <maven-source-plugin.version>3.3.1</maven-source-plugin.version> <maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version> - <junit.version>5.13.4</junit.version> + <junit.version>5.14.0</junit.version> <aws-embedded-metrics.version>4.1.2</aws-embedded-metrics.version> <jmespath.version>0.6.0</jmespath.version> <aws.sdk.v1.version>1.12.781</aws.sdk.v1.version> From aae50c9d1952c22efda4e8ab9196c3856d11bde2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 10:42:21 +0100 Subject: [PATCH 487/577] chore: bump org.apache.maven.plugins:maven-shade-plugin (#2230) Bumps [org.apache.maven.plugins:maven-shade-plugin](https://github.com/apache/maven-shade-plugin) from 3.6.0 to 3.6.1. - [Release notes](https://github.com/apache/maven-shade-plugin/releases) - [Commits](https://github.com/apache/maven-shade-plugin/compare/maven-shade-plugin-3.6.0...maven-shade-plugin-3.6.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-shade-plugin dependency-version: 3.6.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- examples/powertools-examples-core-utilities/serverless/pom.xml | 2 +- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 2a6579074..eac85eafe 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -120,7 +120,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 21c16891d..bc7bc5ece 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -116,7 +116,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 991c6bc60..8a5ac6601 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -104,7 +104,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index f35757cce..71b93be66 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -116,7 +116,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index bcfcbba6d..60d6b796f 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -90,7 +90,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index a7af92c94..01e734f6f 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -91,7 +91,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 8bef2d669..d4aa3e257 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -91,7 +91,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index a86387b94..6ee70def3 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -96,7 +96,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/examples/powertools-examples-idempotency/sam/pom.xml b/examples/powertools-examples-idempotency/sam/pom.xml index b4120a082..d84651e15 100644 --- a/examples/powertools-examples-idempotency/sam/pom.xml +++ b/examples/powertools-examples-idempotency/sam/pom.xml @@ -107,7 +107,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 210371fdf..fe56c6b1e 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -64,7 +64,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 49a6352c0..caf75943f 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -134,7 +134,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.6.0</version> + <version>3.6.1</version> <executions> <execution> <phase>package</phase> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 8ba1d76cd..90740d364 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -16,7 +16,7 @@ <lambda.java.core>1.4.0</lambda.java.core> <lambda.java.serialization>1.1.6</lambda.java.serialization> <lambda.java.events>3.16.1</lambda.java.events> - <maven.shade.version>3.6.0</maven.shade.version> + <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> <aws.sdk.version>2.35.11</aws.sdk.version> From cc21a1421674f95d46824b043177f46095a88101 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 10:43:23 +0100 Subject: [PATCH 488/577] chore: bump aws.sdk.version from 2.35.11 to 2.36.0 (#2227) Bumps `aws.sdk.version` from 2.35.11 to 2.36.0. Updates `software.amazon.awssdk:bom` from 2.35.11 to 2.36.0 Updates `software.amazon.awssdk:http-client-spi` from 2.35.11 to 2.36.0 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.36.0 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.36.0 Updates `software.amazon.awssdk:dynamodb` from 2.35.11 to 2.36.0 Updates `software.amazon.awssdk:lambda` from 2.35.11 to 2.36.0 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.36.0 Updates `software.amazon.awssdk:cloudwatch` from 2.35.11 to 2.36.0 Updates `software.amazon.awssdk:xray` from 2.35.11 to 2.36.0 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.36.0 Updates `software.amazon.awssdk:cloudformation` from 2.35.11 to 2.36.0 Updates `software.amazon.awssdk:sts` from 2.35.11 to 2.36.0 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.36.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.36.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.36.0 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.36.0 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.36.0 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.36.0 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.36.0 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.36.0 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-version: 2.36.0 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.36.0 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.36.0 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-version: 2.36.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index bc7bc5ece..b9c7e9fd8 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.35.11</aws.sdk.version> + <aws.sdk.version>2.36.0</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index b9c3ec419..7fc665854 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.35.11</aws.sdk.version> + <aws.sdk.version>2.36.0</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 90740d364..337316d58 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.35.11</aws.sdk.version> + <aws.sdk.version>2.36.0</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From fdbf448bc390188616ae2690ec105c20d2eb1be6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 10:46:19 +0100 Subject: [PATCH 489/577] chore: bump org.apache.maven.plugins:maven-surefire-plugin (#2228) Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.3 to 3.5.4. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.3...surefire-3.5.4) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-version: 3.5.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/terraform/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- pom.xml | 4 ++-- powertools-common/pom.xml | 2 +- powertools-logging/pom.xml | 4 ++-- powertools-logging/powertools-logging-log4j/pom.xml | 4 ++-- powertools-logging/powertools-logging-logback/pom.xml | 4 ++-- powertools-parameters/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-appconfig/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-dynamodb/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-secrets/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-ssm/pom.xml | 4 ++-- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- 16 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index d4aa3e257..4b7d19fe4 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -126,7 +126,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <environmentVariables> <LAMBDA_TASK_ROOT>handler</LAMBDA_TASK_ROOT> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index caf75943f..e72df3086 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -99,7 +99,7 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <!-- JUnit 5 requires Surefire version 3.1.0 or higher --> - <version>3.5.3</version> + <version>3.5.4</version> </plugin> <plugin> <groupId>dev.aspectj</groupId> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 5d7ddf089..e2ee15f26 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -73,7 +73,7 @@ <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <!-- JUnit 5 requires Surefire version 3.1.0 or higher --> - <version>3.5.3</version> + <version>3.5.4</version> </plugin> <plugin> <groupId>dev.aspectj</groupId> diff --git a/pom.xml b/pom.xml index 7fc665854..7a884ce12 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,7 @@ <maven-source-plugin.version>3.3.1</maven-source-plugin.version> <maven-gpg-plugin.version>3.2.1</maven-gpg-plugin.version> <aspectj-maven-plugin.version>1.14.1</aspectj-maven-plugin.version> - <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version> + <maven-surefire-plugin.version>3.5.4</maven-surefire-plugin.version> <jacoco-maven-plugin.version>0.8.14</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version> <maven-javadoc-plugin.version>3.11.3</maven-javadoc-plugin.version> @@ -625,7 +625,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> @{argLine} diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 9b1639b31..3583a4dc0 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -106,7 +106,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 8c26d5be9..b08a4b695 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -123,7 +123,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -182,7 +182,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <environmentVariables> <AWS_LAMBDA_LOG_FORMAT>JSON</AWS_LAMBDA_LOG_FORMAT> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 94952eba5..b4800ab54 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -112,7 +112,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -204,7 +204,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <environmentVariables> <POWERTOOLS_SERVICE_NAME>testLog4j</POWERTOOLS_SERVICE_NAME> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index f106970b9..0cfbb6104 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -110,7 +110,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -203,7 +203,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <environmentVariables> <POWERTOOLS_SERVICE_NAME>testLogback</POWERTOOLS_SERVICE_NAME> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 95acb65b2..f1e4eae57 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -80,7 +80,7 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> @@ -98,7 +98,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index e8757f28d..eefc46ac5 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -108,7 +108,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -175,7 +175,7 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 099627265..cfc8f64d3 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -109,7 +109,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -176,7 +176,7 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index cbf07e345..9d3ca0500 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -109,7 +109,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -176,7 +176,7 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 64d6cefcd..a277337a7 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -98,7 +98,7 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> @@ -123,7 +123,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 40a942515..61fb4c3b9 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -110,7 +110,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 457feec23..89fb2056a 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -103,7 +103,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 2b2f9b5be..c1f1433a1 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -137,7 +137,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.3</version> + <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent From d262d3a3ea30bd3c611ff55253086dbc3a8c612f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 12:54:22 +0100 Subject: [PATCH 490/577] chore: bump aws.sdk.version from 2.36.0 to 2.36.1 (#2231) Bumps `aws.sdk.version` from 2.36.0 to 2.36.1. Updates `software.amazon.awssdk:bom` from 2.36.0 to 2.36.1 Updates `software.amazon.awssdk:http-client-spi` from 2.36.0 to 2.36.1 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.36.1 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.36.1 Updates `software.amazon.awssdk:dynamodb` from 2.36.0 to 2.36.1 Updates `software.amazon.awssdk:lambda` from 2.36.0 to 2.36.1 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.36.1 Updates `software.amazon.awssdk:cloudwatch` from 2.36.0 to 2.36.1 Updates `software.amazon.awssdk:xray` from 2.36.0 to 2.36.1 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.36.1 Updates `software.amazon.awssdk:cloudformation` from 2.36.0 to 2.36.1 Updates `software.amazon.awssdk:sts` from 2.36.0 to 2.36.1 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.36.1 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.36.1 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.36.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.36.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.36.1 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.36.1 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.36.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.36.1 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.36.1 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.36.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.36.1 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.36.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index b9c7e9fd8..b37c468c0 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.36.0</aws.sdk.version> + <aws.sdk.version>2.36.1</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 7a884ce12..a7eac97fd 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.36.0</aws.sdk.version> + <aws.sdk.version>2.36.1</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 337316d58..fd2a3bae1 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.36.0</aws.sdk.version> + <aws.sdk.version>2.36.1</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 7a5d0c95c4d4dd0381323d80a2bff61fde423a4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 12:55:00 +0100 Subject: [PATCH 491/577] chore: bump org.junit.jupiter:junit-jupiter from 5.13.4 to 5.14.0 (#2232) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework) from 5.13.4 to 5.14.0. - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](https://github.com/junit-team/junit-framework/compare/r5.13.4...r5.14.0) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.14.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 495e3556a..31d5f7e99 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -9,7 +9,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.220.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> - <junit.version>5.13.4</junit.version> + <junit.version>5.14.0</junit.version> </properties> <build> <plugins> From 5fcb05f16e21feff635fe034abbffebe126b847e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 12:55:23 +0100 Subject: [PATCH 492/577] chore: bump sam/build-java21 (#2233) Bumps sam/build-java21 from `068d2ab` to `72709a0`. --- updated-dependencies: - dependency-name: sam/build-java21 dependency-version: 72709a010ebfc993fb402c1bce599a0b754110b873d1a58e60c52136e8c8f3f1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index c537351c8..8d26b4770 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:068d2ab1eee017c2557b7a3879a9f9cc79ba0d5d8b177af5949437eee96458cd +FROM public.ecr.aws/sam/build-java21@sha256:72709a010ebfc993fb402c1bce599a0b754110b873d1a58e60c52136e8c8f3f1 # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From 1e5166092bb5ec99e6dd60906bf11cd10bcf591a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 09:53:57 +0100 Subject: [PATCH 493/577] chore: bump org.apache.maven.plugins:maven-javadoc-plugin (#2223) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.11.3 to 3.12.0. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.11.3...maven-javadoc-plugin-3.12.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-version: 3.12.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a7eac97fd..8a8474f0a 100644 --- a/pom.xml +++ b/pom.xml @@ -105,7 +105,7 @@ <maven-surefire-plugin.version>3.5.4</maven-surefire-plugin.version> <jacoco-maven-plugin.version>0.8.14</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version> - <maven-javadoc-plugin.version>3.11.3</maven-javadoc-plugin.version> + <maven-javadoc-plugin.version>3.12.0</maven-javadoc-plugin.version> <maven-source-plugin.version>3.3.1</maven-source-plugin.version> <maven-gpg-plugin.version>3.2.8</maven-gpg-plugin.version> <junit.version>5.14.0</junit.version> From 1296a9d93da866def5789fb54f0492f15fbbf4db Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Mon, 27 Oct 2025 12:13:15 +0100 Subject: [PATCH 494/577] feat(logging): Support functional interface in addition to AspectJ `@Logging` annotation (#2205) * Initial version of PowertoolsLogging.initializeLogging API. * Add logging-function E2E tests for new PowertoolsLogging.initializeLogging functional interface. * Add service name env var for powertools-logging unit tests. * Catch NoSuchFileException instead of IOException base class in KeyBufferTest.java. * Catch NoSuchFileException also on cleanup since order of test execution is not guaranteed. * Fix spotbugs issue. This is intended design to support unit tests. The class is in internal package. * Reduce cognitive complexity of LambdaLoggingAspect. * Suppress sonar findings needed for internal unit tests. * Add naming convention findings to sonar ignore list. * Make PowertoolsLogging thread-safe. * Make cold start tracking thread-safe. * Update protobuf generated classes after version bump. * Add merged version bump to non-release e2e logging function handler. * Add withLogging callback based interface to PowertoolsLogging. --- .../demo/kafka/protobuf/ProtobufProduct.java | 8 +- .../protobuf/ProtobufProductOrBuilder.java | 2 +- .../protobuf/ProtobufProductOuterClass.java | 10 +- .../handlers/logging-functional/pom.xml | 60 +++ .../lambda/powertools/e2e/Function.java | 40 ++ .../amazon/lambda/powertools/e2e/Input.java | 38 ++ .../aws-lambda-java-core/reflect-config.json | 13 + .../reflect-config.json | 35 ++ .../jni-config.json | 11 + .../native-image.properties | 1 + .../reflect-config.json | 61 +++ .../resource-config.json | 19 + .../reflect-config.json | 25 + .../reflect-config.json | 20 + .../resource-config.json | 7 + .../src/main/resources/log4j2.xml | 17 + powertools-e2e-tests/handlers/pom.xml | 6 + .../amazon/lambda/powertools/LoggingE2ET.java | 2 +- powertools-logging/pom.xml | 1 + .../PowerToolsResolverFactoryTest.java | 5 + .../internal/LambdaEcsEncoderTest.java | 22 +- .../internal/LambdaJsonEncoderTest.java | 6 + .../powertools/logging/PowertoolsLogging.java | 320 +++++++++++- .../logging/internal/LambdaLoggingAspect.java | 214 ++------ .../logging/internal/LoggingConstants.java | 11 +- .../internal/PowertoolsLoggedFields.java | 2 +- .../logging/PowertoolsLoggingTest.java | 466 +++++++++++++++++- .../internal/LambdaLoggingAspectTest.java | 156 +----- spotbugs-exclude.xml | 3 +- 29 files changed, 1232 insertions(+), 349 deletions(-) create mode 100644 powertools-e2e-tests/handlers/logging-functional/pom.xml create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/java/software/amazon/lambda/powertools/e2e/Input.java create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json create mode 100644 powertools-e2e-tests/handlers/logging-functional/src/main/resources/log4j2.xml diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java index e36810e08..13d8905f2 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.32.1 +// Protobuf Java Version: 4.33.0 package org.demo.kafka.protobuf; @@ -18,10 +18,10 @@ public final class ProtobufProduct extends com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, - /* minor= */ 32, - /* patch= */ 1, + /* minor= */ 33, + /* patch= */ 0, /* suffix= */ "", - ProtobufProduct.class.getName()); + "ProtobufProduct"); } // Use ProtobufProduct.newBuilder() to construct. private ProtobufProduct(com.google.protobuf.GeneratedMessage.Builder<?> builder) { diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java index 951644b2f..ae7cb2182 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.32.1 +// Protobuf Java Version: 4.33.0 package org.demo.kafka.protobuf; diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java index 0da2eec57..4fcac7bd7 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.32.1 +// Protobuf Java Version: 4.33.0 package org.demo.kafka.protobuf; @@ -12,10 +12,10 @@ private ProtobufProductOuterClass() {} com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, - /* minor= */ 32, - /* patch= */ 1, + /* minor= */ 33, + /* patch= */ 0, /* suffix= */ "", - ProtobufProductOuterClass.class.getName()); + "ProtobufProductOuterClass"); } public static void registerAllExtensions( com.google.protobuf.ExtensionRegistryLite registry) { @@ -51,7 +51,7 @@ public static void registerAllExtensions( new com.google.protobuf.Descriptors.FileDescriptor[] { }); internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor = - getDescriptor().getMessageTypes().get(0); + getDescriptor().getMessageType(0); internal_static_org_demo_kafka_protobuf_ProtobufProduct_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_org_demo_kafka_protobuf_ProtobufProduct_descriptor, diff --git a/powertools-e2e-tests/handlers/logging-functional/pom.xml b/powertools-e2e-tests/handlers/logging-functional/pom.xml new file mode 100644 index 000000000..5d774fe21 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/pom.xml @@ -0,0 +1,60 @@ +<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 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>software.amazon.lambda</groupId> + <artifactId>e2e-test-handlers-parent</artifactId> + <version>2.5.0</version> + </parent> + + <artifactId>e2e-test-handler-logging-functional</artifactId> + <packaging>jar</packaging> + <name>E2E test handler – Logging Functional</name> + + <dependencies> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging-log4j</artifactId> + </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-events</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/logging-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java new file mode 100644 index 000000000..78ab9ba4b --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -0,0 +1,40 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.logging.PowertoolsLogging; + +public class Function implements RequestHandler<Input, String> { + private static final Logger LOG = LoggerFactory.getLogger(Function.class); + + public String handleRequest(Input input, Context context) { + return PowertoolsLogging.withLogging(context, () -> { + input.getKeys().forEach(MDC::put); + LOG.info(input.getMessage()); + + // Flush buffer manually since we buffer at INFO level to test log buffering + PowertoolsLogging.flushBuffer(); + + return "OK"; + }); + } +} diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/logging-functional/src/main/java/software/amazon/lambda/powertools/e2e/Input.java new file mode 100644 index 000000000..66fd49ddc --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/java/software/amazon/lambda/powertools/e2e/Input.java @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +import java.util.Map; + +public class Input { + private String message; + private Map<String, String> keys; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Map<String, String> getKeys() { + return keys; + } + + public void setKeys(Map<String, String> keys) { + this.keys = keys; + } +} diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/log4j2.xml b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/log4j2.xml new file mode 100644 index 000000000..28e03a9e0 --- /dev/null +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/log4j2.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + <!-- We buffer everything to implicitly test buffer flushing --> + <BufferingAppender name="BufferedAppender" bufferAtVerbosity="INFO"> + <AppenderRef ref="JsonAppender" /> + </BufferingAppender> + </Appenders> + <Loggers> + <Root level="INFO"> + <AppenderRef ref="BufferedAppender" /> + </Root> + </Loggers> +</Configuration> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index fd2a3bae1..752492d6d 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -30,6 +30,7 @@ <module>largemessage_idempotent</module> <module>logging-log4j</module> <module>logging-logback</module> + <module>logging-functional</module> <module>tracing</module> <module>metrics</module> <module>idempotency</module> @@ -62,6 +63,11 @@ <artifactId>powertools-logging-logback</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java index f5d2cea84..20bc5394d 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LoggingE2ET.java @@ -70,7 +70,7 @@ void tearDown() { } @ParameterizedTest - @ValueSource(strings = { "logging-log4j", "logging-logback" }) + @ValueSource(strings = { "logging-log4j", "logging-logback", "logging-functional" }) @Timeout(value = 15, unit = TimeUnit.MINUTES) void test_logInfoWithAdditionalKeys(String pathToFunction) throws JsonProcessingException { setupInfrastructure(pathToFunction); diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index b08a4b695..2fa4680fb 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -186,6 +186,7 @@ <configuration> <environmentVariables> <AWS_LAMBDA_LOG_FORMAT>JSON</AWS_LAMBDA_LOG_FORMAT> + <POWERTOOLS_SERVICE_NAME>testService</POWERTOOLS_SERVICE_NAME> </environmentVariables> </configuration> </plugin> diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java index 7eeffc78f..46b5b65d4 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowerToolsResolverFactoryTest.java @@ -24,6 +24,7 @@ import java.nio.file.NoSuchFileException; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -35,6 +36,7 @@ import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; +import software.amazon.lambda.powertools.logging.PowertoolsLogging; import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled; @Order(1) @@ -45,7 +47,10 @@ class PowerToolsResolverFactoryTest { @BeforeEach void setUp() throws IllegalAccessException, IOException { MDC.clear(); + // Reset cold start state writeStaticField(LambdaHandlerProcessor.class, "isColdStart", null, true); + writeStaticField(PowertoolsLogging.class, "hasBeenInitialized", new AtomicBoolean(false), true); + context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java index 898abec2e..74a11813b 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java @@ -18,11 +18,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.contentOf; -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.pattern.RootCauseFirstThrowableProxyConverter; -import ch.qos.logback.classic.spi.LoggingEvent; -import com.amazonaws.services.lambda.runtime.Context; import java.io.File; import java.io.IOException; import java.nio.channels.FileChannel; @@ -30,16 +25,26 @@ import java.nio.file.NoSuchFileException; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; +import java.util.concurrent.atomic.AtomicBoolean; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; -import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import org.slf4j.LoggerFactory; import org.slf4j.MDC; + +import com.amazonaws.services.lambda.runtime.Context; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.pattern.RootCauseFirstThrowableProxyConverter; +import ch.qos.logback.classic.spi.LoggingEvent; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; -import software.amazon.lambda.powertools.logging.logback.LambdaEcsEncoder; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; +import software.amazon.lambda.powertools.logging.PowertoolsLogging; import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsLogEnabled; +import software.amazon.lambda.powertools.logging.logback.LambdaEcsEncoder; @Order(3) class LambdaEcsEncoderTest { @@ -51,7 +56,10 @@ class LambdaEcsEncoderTest { @BeforeEach void setUp() throws IllegalAccessException, IOException { MDC.clear(); + // Reset cold start state writeStaticField(LambdaHandlerProcessor.class, "isColdStart", null, true); + writeStaticField(PowertoolsLogging.class, "hasBeenInitialized", new AtomicBoolean(false), true); + context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 326fa4b19..97770d3d0 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -43,6 +43,8 @@ import java.util.Collections; import java.util.Date; import java.util.TimeZone; +import java.util.concurrent.atomic.AtomicBoolean; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -52,6 +54,7 @@ import org.slf4j.LoggerFactory; import org.slf4j.MDC; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.logging.PowertoolsLogging; import software.amazon.lambda.powertools.logging.argument.StructuredArgument; import software.amazon.lambda.powertools.logging.argument.StructuredArguments; import software.amazon.lambda.powertools.logging.internal.handler.PowertoolsArguments; @@ -73,7 +76,10 @@ class LambdaJsonEncoderTest { @BeforeEach void setUp() throws IllegalAccessException, IOException { MDC.clear(); + // Reset cold start state writeStaticField(LambdaHandlerProcessor.class, "isColdStart", null, true); + writeStaticField(PowertoolsLogging.class, "hasBeenInitialized", new AtomicBoolean(false), true); + context = new TestLambdaContext(); // Make sure file is cleaned up before running tests try { diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/PowertoolsLogging.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/PowertoolsLogging.java index 1276c2a87..f4c18af64 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/PowertoolsLogging.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/PowertoolsLogging.java @@ -14,21 +14,104 @@ package software.amazon.lambda.powertools.logging; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.coldStartDone; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isColdStart; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.serviceName; +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.LAMBDA_LOG_LEVEL; +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_LEVEL; +import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_SAMPLING_RATE; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SAMPLING_RATE; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SERVICE; + +import java.util.Arrays; +import java.util.Locale; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.slf4j.event.Level; + +import com.amazonaws.services.lambda.runtime.Context; +import com.fasterxml.jackson.databind.JsonNode; + +import io.burt.jmespath.Expression; import software.amazon.lambda.powertools.logging.internal.BufferManager; import software.amazon.lambda.powertools.logging.internal.LoggingManager; import software.amazon.lambda.powertools.logging.internal.LoggingManagerRegistry; +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; +import software.amazon.lambda.powertools.utilities.JsonConfig; /** - * PowertoolsLogging provides a backend-independent API for log buffering operations. - * This class abstracts away the underlying logging framework (Log4j2, Logback) and - * provides a unified interface for buffer management. + * PowertoolsLogging provides a logging backend-agnostic API for managing Powertools logging functionality. + * This class abstracts away the underlying logging framework (Log4j2, Logback) and provides a unified + * interface for Lambda context extraction, correlation ID handling, sampling rate configuration, + * log buffering operations, and other Lambda-specific logging features. + * + * <p>This class serves as a programmatic alternative to AspectJ-based {@code @Logging} annotation, + * allowing developers to integrate Powertools logging capabilities without AspectJ dependencies.</p> + * + * Key features: + * <ul> + * <li>Lambda context initialization with function metadata, trace ID, and service name</li> + * <li>Sampling rate configuration for DEBUG logging</li> + * <li>Backend-independent log buffer management (flush/clear operations)</li> + * <li>MDC state management for structured logging</li> + * </ul> */ public final class PowertoolsLogging { + private static final Logger LOG = LoggerFactory.getLogger(PowertoolsLogging.class); + private static final ThreadLocal<Random> SAMPLER = ThreadLocal.withInitial(Random::new); + private static AtomicBoolean hasBeenInitialized = new AtomicBoolean(false); + + static { + initializeLogLevel(); + } private PowertoolsLogging() { // Utility class } + private static void initializeLogLevel() { + if (POWERTOOLS_LOG_LEVEL != null) { + Level powertoolsLevel = getLevelFromString(POWERTOOLS_LOG_LEVEL); + if (LAMBDA_LOG_LEVEL != null) { + Level lambdaLevel = getLevelFromString(LAMBDA_LOG_LEVEL); + if (powertoolsLevel.toInt() < lambdaLevel.toInt()) { + LOG.warn( + "Current log level ({}) does not match AWS Lambda Advanced Logging Controls minimum log level ({}). This can lead to data loss, consider adjusting them.", + POWERTOOLS_LOG_LEVEL, LAMBDA_LOG_LEVEL); + } + } + setLogLevel(powertoolsLevel); + } else if (LAMBDA_LOG_LEVEL != null) { + setLogLevel(getLevelFromString(LAMBDA_LOG_LEVEL)); + } + } + + private static Level getLevelFromString(String level) { + if (Arrays.stream(Level.values()).anyMatch(slf4jLevel -> slf4jLevel.name().equalsIgnoreCase(level))) { + return Level.valueOf(level.toUpperCase(Locale.ROOT)); + } else { + // FATAL does not exist in slf4j + if ("FATAL".equalsIgnoreCase(level)) { + return Level.ERROR; + } + } + // default to INFO if incorrect value + return Level.INFO; + } + + private static void setLogLevel(Level logLevel) { + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + loggingManager.setLogLevel(logLevel); + } + /** * Flushes the log buffer for the current Lambda execution. * This method will flush any buffered logs to the output stream. @@ -52,4 +135,235 @@ public static void clearBuffer() { ((BufferManager) loggingManager).clearBuffer(); } } + + /** + * Initializes Lambda logging context with standard Powertools fields. + * This method should be called at the beginning of your Lambda handler to set up + * logging context with Lambda function information, trace ID, and service name. + * + * <p>Important: Call {@link #clearState(boolean)} at the end of your handler or use + * {@link #withLogging(Context, Supplier)} to handle cleanup automatically.</p> + * + * @param context the Lambda context provided by AWS Lambda runtime + */ + public static void initializeLogging(Context context) { + initializeLogging(context, 0.0, null, null); + } + + /** + * Initializes Lambda logging context with sampling rate configuration. + * This method sets up logging context and optionally enables DEBUG logging + * based on the provided sampling rate. + * + * <p>Important: Call {@link #clearState(boolean)} at the end of your handler or use + * {@link #withLogging(Context, double, Supplier)} to handle cleanup automatically.</p> + * + * @param context the Lambda context provided by AWS Lambda runtime + * @param samplingRate sampling rate for DEBUG logging (0.0 to 1.0) + */ + public static void initializeLogging(Context context, double samplingRate) { + initializeLogging(context, samplingRate, null, null); + } + + /** + * Initializes Lambda logging context with correlation ID extraction. + * This method sets up logging context and extracts correlation ID from the event + * using the provided JSON path. + * + * <p>Important: Call {@link #clearState(boolean)} at the end of your handler or use + * {@link #withLogging(Context, String, Object, Supplier)} to handle cleanup automatically.</p> + * + * @param context the Lambda context provided by AWS Lambda runtime + * @param correlationIdPath JSON path to extract correlation ID from event + * @param event the Lambda event object + */ + public static void initializeLogging(Context context, String correlationIdPath, Object event) { + initializeLogging(context, 0.0, correlationIdPath, event); + } + + /** + * Initializes Lambda logging context with full configuration. + * This method sets up logging context with Lambda function information, + * configures sampling rate for DEBUG logging, and optionally extracts + * correlation ID from the event. + * + * <p>Important: Call {@link #clearState(boolean)} at the end of your handler or use + * {@link #withLogging(Context, double, String, Object, Supplier)} to handle cleanup automatically.</p> + * + * <p>This method is thread-safe.</p> + * + * @param context the Lambda context provided by AWS Lambda runtime + * @param samplingRate sampling rate for DEBUG logging (0.0 to 1.0) + * @param correlationIdPath JSON path to extract correlation ID from event (can be null) + * @param event the Lambda event object (required if correlationIdPath is provided) + */ + public static void initializeLogging(Context context, double samplingRate, String correlationIdPath, Object event) { + + addLambdaContextToLoggingContext(context); + setLogLevelBasedOnSamplingRate(samplingRate); + getXrayTraceId().ifPresent(xRayTraceId -> MDC.put(FUNCTION_TRACE_ID.getName(), xRayTraceId)); + + if (correlationIdPath != null && !correlationIdPath.isEmpty() && event != null) { + captureCorrelationId(correlationIdPath, event); + } + } + + // Synchronized since isColdStart() is a globally managed constant in LambdaHandlerProcessor + private static synchronized void addLambdaContextToLoggingContext(Context context) { + if (context != null) { + PowertoolsLoggedFields.setValuesFromLambdaContext(context).forEach(MDC::put); + } + + MDC.put(FUNCTION_COLD_START.getName(), isColdStart() ? "true" : "false"); + if (hasBeenInitialized.compareAndSet(false, true)) { + coldStartDone(); + } + MDC.put(SERVICE.getName(), serviceName()); + } + + private static void setLogLevelBasedOnSamplingRate(double samplingRate) { + double effectiveSamplingRate = getEffectiveSamplingRate(samplingRate); + + if (effectiveSamplingRate < 0 || effectiveSamplingRate > 1) { + LOG.warn("Skipping sampling rate configuration because of invalid value. Sampling rate: {}", + effectiveSamplingRate); + return; + } + + MDC.put(SAMPLING_RATE.getName(), String.valueOf(effectiveSamplingRate)); + + if (effectiveSamplingRate == 0) { + return; + } + + float sample = SAMPLER.get().nextFloat(); + if (effectiveSamplingRate > sample) { + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + loggingManager.setLogLevel(Level.DEBUG); + LOG.debug( + "Changed log level to DEBUG based on Sampling configuration. Sampling Rate: {}, Sampler Value: {}.", + effectiveSamplingRate, sample); + } + } + + // The environment variable takes precedence over manually set sampling rate + private static double getEffectiveSamplingRate(double samplingRate) { + String envSampleRate = POWERTOOLS_SAMPLING_RATE; + if (envSampleRate != null) { + try { + return Double.parseDouble(envSampleRate); + } catch (NumberFormatException e) { + LOG.warn( + "Skipping sampling rate on environment variable configuration because of invalid value. Sampling rate: {}", + envSampleRate); + } + } + + return samplingRate; + } + + private static void captureCorrelationId(String correlationIdPath, Object event) { + try { + JsonNode jsonNode = JsonConfig.get().getObjectMapper().valueToTree(event); + Expression<JsonNode> jmesExpression = JsonConfig.get().getJmesPath().compile(correlationIdPath); + JsonNode node = jmesExpression.search(jsonNode); + + String asText = node.asText(); + if (asText != null && !asText.isEmpty()) { + MDC.put(PowertoolsLoggedFields.CORRELATION_ID.getName(), asText); + } else { + LOG.warn("Unable to extract any correlation id. Is your function expecting supported event type?"); + } + } catch (Exception e) { + LOG.warn("Failed to capture correlation id from event.", e); + } + } + + /** + * Clears MDC state and log buffer. + * + * @param clearMdcState whether to clear MDC state + */ + public static void clearState(boolean clearMdcState) { + if (clearMdcState) { + MDC.clear(); + } + clearBuffer(); + SAMPLER.remove(); + } + + /** + * Executes code with logging context initialized and automatically clears state. + * + * @param context the Lambda context provided by AWS Lambda runtime + * @param supplier the code to execute with logging context + * @param <T> the return type + * @return the result of the supplier execution + */ + public static <T> T withLogging(Context context, Supplier<T> supplier) { + initializeLogging(context); + try { + return supplier.get(); + } finally { + clearState(true); + } + } + + /** + * Executes code with logging context initialized with sampling rate and automatically clears state. + * + * @param context the Lambda context provided by AWS Lambda runtime + * @param samplingRate sampling rate for DEBUG logging (0.0 to 1.0) + * @param supplier the code to execute with logging context + * @param <T> the return type + * @return the result of the supplier execution + */ + public static <T> T withLogging(Context context, double samplingRate, Supplier<T> supplier) { + initializeLogging(context, samplingRate); + try { + return supplier.get(); + } finally { + clearState(true); + } + } + + /** + * Executes code with logging context initialized with correlation ID extraction and automatically clears state. + * + * @param context the Lambda context provided by AWS Lambda runtime + * @param correlationIdPath JSON path to extract correlation ID from event + * @param event the Lambda event object + * @param supplier the code to execute with logging context + * @param <T> the return type + * @return the result of the supplier execution + */ + public static <T> T withLogging(Context context, String correlationIdPath, Object event, Supplier<T> supplier) { + initializeLogging(context, correlationIdPath, event); + try { + return supplier.get(); + } finally { + clearState(true); + } + } + + /** + * Executes code with logging context initialized with full configuration and automatically clears state. + * + * @param context the Lambda context provided by AWS Lambda runtime + * @param samplingRate sampling rate for DEBUG logging (0.0 to 1.0) + * @param correlationIdPath JSON path to extract correlation ID from event (can be null) + * @param event the Lambda event object (required if correlationIdPath is provided) + * @param supplier the code to execute with logging context + * @param <T> the return type + * @return the result of the supplier execution + */ + public static <T> T withLogging(Context context, double samplingRate, String correlationIdPath, Object event, + Supplier<T> supplier) { + initializeLogging(context, samplingRate, correlationIdPath, event); + try { + return supplier.get(); + } finally { + clearState(true); + } + } } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java index 591283996..272c4bff9 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspect.java @@ -15,25 +15,14 @@ package software.amazon.lambda.powertools.logging.internal; import static java.nio.charset.StandardCharsets.UTF_8; -import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.coldStartDone; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.extractContext; -import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.getXrayTraceId; -import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isColdStart; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.isHandlerMethod; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnRequestHandler; import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnStreamHandler; -import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.serviceName; import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; -import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.LAMBDA_LOG_LEVEL; import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_ERROR; import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_EVENT; -import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_LEVEL; import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_LOG_RESPONSE; -import static software.amazon.lambda.powertools.logging.internal.LoggingConstants.POWERTOOLS_SAMPLING_RATE; -import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID; -import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; -import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_TRACE_ID; -import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.SERVICE; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -42,9 +31,6 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.util.Arrays; -import java.util.Locale; -import java.util.Random; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -53,66 +39,22 @@ import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.slf4j.MDC; import org.slf4j.MarkerFactory; -import org.slf4j.event.Level; import com.amazonaws.services.lambda.runtime.Context; -import com.fasterxml.jackson.databind.JsonNode; -import io.burt.jmespath.Expression; import software.amazon.lambda.powertools.logging.Logging; +import software.amazon.lambda.powertools.logging.PowertoolsLogging; import software.amazon.lambda.powertools.utilities.JsonConfig; @Aspect @DeclarePrecedence("*, software.amazon.lambda.powertools.logging.internal.LambdaLoggingAspect") public final class LambdaLoggingAspect { private static final Logger LOG = LoggerFactory.getLogger(LambdaLoggingAspect.class); - private static final Random SAMPLER = new Random(); - private static Level LEVEL_AT_INITIALISATION; /* not final for test purpose */ - private static final LoggingManager LOGGING_MANAGER; static { LOGGING_MANAGER = LoggingManagerRegistry.getLoggingManager(); - - setLogLevel(); - - LEVEL_AT_INITIALISATION = LOGGING_MANAGER.getLogLevel(LOG); - } - - static void setLogLevel() { - if (POWERTOOLS_LOG_LEVEL != null) { - Level powertoolsLevel = getLevelFromString(POWERTOOLS_LOG_LEVEL); - if (LAMBDA_LOG_LEVEL != null) { - Level lambdaLevel = getLevelFromString(LAMBDA_LOG_LEVEL); - if (powertoolsLevel.toInt() < lambdaLevel.toInt()) { - LOG.warn( - "Current log level ({}) does not match AWS Lambda Advanced Logging Controls minimum log level ({}). This can lead to data loss, consider adjusting them.", - POWERTOOLS_LOG_LEVEL, LAMBDA_LOG_LEVEL); - } - } - setLogLevels(powertoolsLevel); - } else if (LAMBDA_LOG_LEVEL != null) { - setLogLevels(getLevelFromString(LAMBDA_LOG_LEVEL)); - } - } - - private static Level getLevelFromString(String level) { - if (Arrays.stream(Level.values()).anyMatch(slf4jLevel -> slf4jLevel.name().equalsIgnoreCase(level))) { - return Level.valueOf(level.toUpperCase(Locale.ROOT)); - } else { - // FATAL does not exist in slf4j - if ("FATAL".equalsIgnoreCase(level)) { - return Level.ERROR; - } - } - // default to INFO if incorrect value - return Level.INFO; - } - - private static void setLogLevels(Level logLevel) { - LOGGING_MANAGER.setLogLevel(logLevel); } @SuppressWarnings({ "EmptyMethod" }) @@ -131,17 +73,19 @@ public Object around(ProceedingJoinPoint pjp, boolean isOnRequestHandler = placedOnRequestHandler(pjp); boolean isOnRequestStreamHandler = placedOnStreamHandler(pjp); - setLogLevelBasedOnSamplingRate(pjp, logging); - addLambdaContextToLoggingContext(pjp); - getXrayTraceId().ifPresent(xRayTraceId -> MDC.put(FUNCTION_TRACE_ID.getName(), xRayTraceId)); - - Object[] proceedArgs = logEvent(pjp, logging, isOnRequestHandler, isOnRequestStreamHandler); + // Initialize logging using PowertoolsLogging + Context context = extractContext(pjp); + Object[] proceedArgs = pjp.getArgs(); - if (!logging.correlationIdPath().isEmpty()) { - captureCorrelationId(logging.correlationIdPath(), proceedArgs, isOnRequestHandler, - isOnRequestStreamHandler); + if (isHandlerMethod(pjp) && context != null) { + Object event = extractEventForCorrelationId(logging, isOnRequestHandler, isOnRequestStreamHandler, + proceedArgs); + PowertoolsLogging.initializeLogging(context, logging.samplingRate(), + logging.correlationIdPath().isEmpty() ? null : logging.correlationIdPath(), event); } + logEvent(pjp, logging, isOnRequestHandler, isOnRequestStreamHandler, proceedArgs); + @SuppressWarnings("PMD.CloseResource") // Lambda-owned stream, not ours to close OutputStream backupOutputStream = null; if (isOnRequestStreamHandler) { @@ -160,7 +104,7 @@ public Object around(ProceedingJoinPoint pjp, handleException(pjp, logging, t); throw t; } finally { - performCleanup(logging); + PowertoolsLogging.clearState(logging.clearState()); } logResponse(pjp, logging, lambdaFunctionResponse, isOnRequestHandler, isOnRequestStreamHandler, @@ -169,74 +113,18 @@ public Object around(ProceedingJoinPoint pjp, return lambdaFunctionResponse; } - private Object[] logEvent(ProceedingJoinPoint pjp, Logging logging, - boolean isOnRequestHandler, boolean isOnRequestStreamHandler) { - Object[] proceedArgs = pjp.getArgs(); + private void logEvent(ProceedingJoinPoint pjp, Logging logging, + boolean isOnRequestHandler, boolean isOnRequestStreamHandler, Object[] proceedArgs) { if (logging.logEvent() || POWERTOOLS_LOG_EVENT) { if (isOnRequestHandler) { - logRequestHandlerEvent(pjp, pjp.getArgs()[0]); + logRequestHandlerEvent(pjp, proceedArgs[0]); } else if (isOnRequestStreamHandler) { - proceedArgs = logRequestStreamHandlerEvent(pjp); - } - } - return proceedArgs; - } - - private void addLambdaContextToLoggingContext(ProceedingJoinPoint pjp) { - Context extractedContext = extractContext(pjp); - - if (extractedContext != null) { - PowertoolsLoggedFields.setValuesFromLambdaContext(extractedContext).forEach(MDC::put); - MDC.put(FUNCTION_COLD_START.getName(), isColdStart() ? "true" : "false"); - MDC.put(SERVICE.getName(), serviceName()); - } - } - - private void setLogLevelBasedOnSamplingRate(final ProceedingJoinPoint pjp, - final Logging logging) { - double samplingRate = samplingRate(logging); - - if (isHandlerMethod(pjp)) { - - if (samplingRate < 0 || samplingRate > 1) { - LOG.warn("Skipping sampling rate configuration because of invalid value. Sampling rate: {}", - samplingRate); - return; - } - - MDC.put(PowertoolsLoggedFields.SAMPLING_RATE.getName(), String.valueOf(samplingRate)); - - if (samplingRate == 0) { - return; - } - - float sample = SAMPLER.nextFloat(); - - if (samplingRate > sample) { - setLogLevels(Level.DEBUG); - - LOG.debug("Changed log level to DEBUG based on Sampling configuration. " - + "Sampling Rate: {}, Sampler Value: {}.", samplingRate, sample); - } else if (LEVEL_AT_INITIALISATION != LOGGING_MANAGER.getLogLevel(LOG)) { - setLogLevels(LEVEL_AT_INITIALISATION); + logRequestStreamHandlerEvent(pjp, proceedArgs); } } } - private double samplingRate(final Logging logging) { - String sampleRate = POWERTOOLS_SAMPLING_RATE; - if (null != sampleRate) { - try { - return Double.parseDouble(sampleRate); - } catch (NumberFormatException e) { - LOG.warn("Skipping sampling rate on environment variable configuration because of invalid " - + "value. Sampling rate: {}", sampleRate); - } - } - return logging.samplingRate(); - } - @SuppressWarnings("java:S3457") private void logRequestHandlerEvent(final ProceedingJoinPoint pjp, final Object event) { Logger log = logger(pjp); @@ -246,12 +134,11 @@ private void logRequestHandlerEvent(final ProceedingJoinPoint pjp, final Object } @SuppressWarnings("java:S3457") - private Object[] logRequestStreamHandlerEvent(final ProceedingJoinPoint pjp) { - Object[] args = pjp.getArgs(); + private void logRequestStreamHandlerEvent(final ProceedingJoinPoint pjp, Object[] args) { Logger log = logger(pjp); if (log.isInfoEnabled()) { try { - byte[] bytes = bytesFromInputStreamSafely((InputStream) pjp.getArgs()[0]); + byte[] bytes = bytesFromInputStreamSafely((InputStream) args[0]); args[0] = new ByteArrayInputStream(bytes); // do not log asJson as it can be something else (String, XML...) log.info("Handler Event", entry("event", new String(bytes, UTF_8))); @@ -259,7 +146,6 @@ private Object[] logRequestStreamHandlerEvent(final ProceedingJoinPoint pjp) { LOG.warn("Failed to log event from supplied input stream.", e); } } - return args; } @SuppressWarnings("java:S3457") @@ -279,38 +165,6 @@ private void logRequestStreamHandlerResponse(final ProceedingJoinPoint pjp, fina } } - private void captureCorrelationId(final String correlationIdPath, - Object[] proceedArgs, - final boolean isOnRequestHandler, - final boolean isOnRequestStreamHandler) { - if (isOnRequestHandler) { - JsonNode jsonNode = JsonConfig.get().getObjectMapper().valueToTree(proceedArgs[0]); - setCorrelationIdFromNode(correlationIdPath, jsonNode); - } else if (isOnRequestStreamHandler) { - try { - byte[] bytes = bytesFromInputStreamSafely((InputStream) proceedArgs[0]); - JsonNode jsonNode = JsonConfig.get().getObjectMapper().readTree(bytes); - proceedArgs[0] = new ByteArrayInputStream(bytes); - - setCorrelationIdFromNode(correlationIdPath, jsonNode); - } catch (IOException e) { - LOG.warn("Failed to capture correlation id on event from supplied input stream.", e); - } - } - } - - private void setCorrelationIdFromNode(String correlationIdPath, JsonNode jsonNode) { - Expression<JsonNode> jmesExpression = JsonConfig.get().getJmesPath().compile(correlationIdPath); - JsonNode node = jmesExpression.search(jsonNode); - - String asText = node.asText(); - if (null != asText && !asText.isEmpty()) { - MDC.put(CORRELATION_ID.getName(), asText); - } else { - LOG.warn("Unable to extract any correlation id. Is your function expecting supported event type?"); - } - } - private byte[] bytesFromInputStreamSafely(final InputStream inputStream) throws IOException { try (ByteArrayOutputStream out = new ByteArrayOutputStream(); InputStreamReader reader = new InputStreamReader(inputStream, UTF_8); @@ -348,16 +202,6 @@ private void handleException(ProceedingJoinPoint pjp, Logging logging, Throwable } } - private void performCleanup(Logging logging) { - if (logging.clearState()) { - MDC.clear(); - } - if (LOGGING_MANAGER instanceof BufferManager) { - ((BufferManager) LOGGING_MANAGER).clearBuffer(); - } - coldStartDone(); - } - private void logResponse(ProceedingJoinPoint pjp, Logging logging, Object lambdaFunctionResponse, boolean isOnRequestHandler, boolean isOnRequestStreamHandler, OutputStream backupOutputStream, Object[] proceedArgs) throws IOException { @@ -372,6 +216,28 @@ private void logResponse(ProceedingJoinPoint pjp, Logging logging, Object lambda } } + private Object extractEventForCorrelationId(Logging logging, boolean isOnRequestHandler, + boolean isOnRequestStreamHandler, Object[] proceedArgs) { + if (logging.correlationIdPath().isEmpty()) { + return null; + } + + if (isOnRequestHandler && proceedArgs.length > 0) { + return proceedArgs[0]; + } else if (isOnRequestStreamHandler && proceedArgs.length > 0) { + try { + byte[] bytes = bytesFromInputStreamSafely((InputStream) proceedArgs[0]); + // Parse JSON string to Object for correlation ID extraction + Object event = JsonConfig.get().getObjectMapper().readTree(bytes); + proceedArgs[0] = new ByteArrayInputStream(bytes); // Restore stream + return event; + } catch (IOException e) { + LOG.warn("Failed to read event from input stream for correlation ID extraction.", e); + } + } + return null; + } + private Logger logger(final ProceedingJoinPoint pjp) { return LoggerFactory.getLogger(pjp.getSignature().getDeclaringType()); } diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java index 989608a77..511b12ace 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/LoggingConstants.java @@ -14,12 +14,15 @@ package software.amazon.lambda.powertools.logging.internal; -class LoggingConstants { - static String LAMBDA_LOG_LEVEL = System.getenv("AWS_LAMBDA_LOG_LEVEL"); /* not final for test purpose */ +public final class LoggingConstants { + @SuppressWarnings({"java:S1104", "java:S1444", "java:S3008"}) + public static String LAMBDA_LOG_LEVEL = System.getenv("AWS_LAMBDA_LOG_LEVEL"); /* not final for test purpose */ - static String POWERTOOLS_LOG_LEVEL = System.getenv("POWERTOOLS_LOG_LEVEL"); /* not final for test purpose */ + @SuppressWarnings({"java:S1104", "java:S1444", "java:S3008"}) + public static String POWERTOOLS_LOG_LEVEL = System.getenv("POWERTOOLS_LOG_LEVEL"); /* not final for test purpose */ - static String POWERTOOLS_SAMPLING_RATE = System.getenv("POWERTOOLS_LOGGER_SAMPLE_RATE"); /* not final for test purpose */ + @SuppressWarnings({"java:S1104", "java:S1444", "java:S3008"}) + public static String POWERTOOLS_SAMPLING_RATE = System.getenv("POWERTOOLS_LOGGER_SAMPLE_RATE"); /* not final for test purpose */ static boolean POWERTOOLS_LOG_EVENT = "true".equals(System.getenv("POWERTOOLS_LOGGER_LOG_EVENT")); /* not final for test purpose */ diff --git a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java index 6e0047f4f..2545396d2 100644 --- a/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java +++ b/powertools-logging/src/main/java/software/amazon/lambda/powertools/logging/internal/PowertoolsLoggedFields.java @@ -47,7 +47,7 @@ public static List<String> stringValues() { return Stream.of(values()).map(PowertoolsLoggedFields::getName).collect(Collectors.toList()); } - static Map<String, String> setValuesFromLambdaContext(Context context) { + public static Map<String, String> setValuesFromLambdaContext(Context context) { Map<String, String> hashMap = new HashMap<>(); hashMap.put(FUNCTION_NAME.name, context.getFunctionName()); diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/PowertoolsLoggingTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/PowertoolsLoggingTest.java index ea3a2f3f6..9c68f687b 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/PowertoolsLoggingTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/PowertoolsLoggingTest.java @@ -14,23 +14,78 @@ package software.amazon.lambda.powertools.logging; +import static org.apache.commons.lang3.reflect.FieldUtils.writeStaticField; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.contentOf; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.nio.channels.FileChannel; +import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import com.amazonaws.services.lambda.runtime.Context; +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; +import software.amazon.lambda.powertools.logging.internal.LoggingConstants; import software.amazon.lambda.powertools.logging.internal.LoggingManagerRegistry; +import software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields; import software.amazon.lambda.powertools.logging.internal.TestLoggingManager; class PowertoolsLoggingTest { + private static final Logger LOG = LoggerFactory.getLogger(PowertoolsLoggingTest.class); private TestLoggingManager testManager; + private Context context; @BeforeEach - void setUp() { + void setUp() throws IllegalAccessException, IOException { // Get the TestLoggingManager instance from registry testManager = (TestLoggingManager) LoggingManagerRegistry.getLoggingManager(); testManager.resetBufferState(); + + context = new TestLambdaContext(); + + // Reset environment variables for clean test isolation + writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", null, true); + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", null, true); + writeStaticField(LoggingConstants.class, "POWERTOOLS_SAMPLING_RATE", null, true); + + // Clear MDC for clean test isolation + MDC.clear(); + + // Reset cold start state + writeStaticField(LambdaHandlerProcessor.class, "isColdStart", null, true); + writeStaticField(PowertoolsLogging.class, "hasBeenInitialized", new AtomicBoolean(false), true); + + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } + } + + @AfterEach + void cleanUp() throws IOException { + // Make sure file is cleaned up + try { + FileChannel.open(Paths.get("target/logfile.json"), StandardOpenOption.WRITE).truncate(0).close(); + } catch (NoSuchFileException e) { + // may not be there in the first run + } } @Test @@ -50,4 +105,413 @@ void testClearBuffer_shouldCallBufferManager() { // THEN assertThat(testManager.isBufferCleared()).isTrue(); } + + @Test + void shouldLogDebugWhenPowertoolsLevelEnvVarIsDebug() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "DEBUG", true); + + // WHEN + reinitializeLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isTrue(); + } + + @Test + void shouldLogInfoWhenPowertoolsLevelEnvVarIsInfo() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "INFO", true); + + // WHEN + reinitializeLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isTrue(); + } + + @Test + void shouldLogInfoWhenPowertoolsLevelEnvVarIsInvalid() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "INVALID", true); + + // WHEN + reinitializeLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isTrue(); + } + + @Test + void shouldLogWarnWhenPowertoolsLevelEnvVarIsWarn() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "WARN", true); + + // WHEN + reinitializeLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isFalse(); + assertThat(LOG.isWarnEnabled()).isTrue(); + } + + @Test + void shouldLogErrorWhenPowertoolsLevelEnvVarIsError() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "ERROR", true); + + // WHEN + reinitializeLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isFalse(); + assertThat(LOG.isWarnEnabled()).isFalse(); + assertThat(LOG.isErrorEnabled()).isTrue(); + } + + @Test + void shouldLogErrorWhenPowertoolsLevelEnvVarIsFatal() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "FATAL", true); + + // WHEN + reinitializeLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isFalse(); + assertThat(LOG.isWarnEnabled()).isFalse(); + assertThat(LOG.isErrorEnabled()).isTrue(); + } + + @Test + void shouldLogWarnWhenPowertoolsLevelEnvVarIsWarnAndLambdaLevelVarIsInfo() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "WARN", true); + writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", "INFO", true); + + // WHEN + reinitializeLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isFalse(); + assertThat(LOG.isWarnEnabled()).isTrue(); + File logFile = new File("target/logfile.json"); + assertThat(contentOf(logFile)) + .doesNotContain(" does not match AWS Lambda Advanced Logging Controls minimum log level"); + } + + @Test + void shouldLogInfoWhenPowertoolsLevelEnvVarIsInfoAndLambdaLevelVarIsWarn() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "INFO", true); + writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", "WARN", true); + + // WHEN + reinitializeLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isTrue(); + File logFile = new File("target/logfile.json"); + // should log a warning as powertools level is lower than lambda level + assertThat(contentOf(logFile)).contains( + "Current log level (INFO) does not match AWS Lambda Advanced Logging Controls minimum log level (WARN). This can lead to data loss, consider adjusting them."); + } + + @Test + void shouldLogWarnWhenPowertoolsLevelEnvVarINotSetAndLambdaLevelVarIsWarn() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", null, true); + writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", "WARN", true); + + // WHEN + reinitializeLogLevel(); + + // THEN + assertThat(LOG.isDebugEnabled()).isFalse(); + assertThat(LOG.isInfoEnabled()).isFalse(); + assertThat(LOG.isWarnEnabled()).isTrue(); + } + + @Test + void initializeLogging_withContextOnly_shouldSetLambdaFields() { + // WHEN + PowertoolsLogging.initializeLogging(context); + + // THEN + Map<String, String> mdcMap = MDC.getCopyOfContextMap(); + assertThat(mdcMap) + .containsEntry(PowertoolsLoggedFields.FUNCTION_NAME.getName(), "test-function") + .containsEntry(PowertoolsLoggedFields.FUNCTION_VERSION.getName(), "1") + .containsEntry(PowertoolsLoggedFields.FUNCTION_COLD_START.getName(), "true") + .containsEntry(PowertoolsLoggedFields.SERVICE.getName(), "testService"); + } + + @Test + void initializeLogging_withSamplingRate_shouldSetSamplingRateInMdc() { + // WHEN + PowertoolsLogging.initializeLogging(context, 0.5); + + // THEN + assertThat(MDC.get(PowertoolsLoggedFields.SAMPLING_RATE.getName())).isEqualTo("0.5"); + } + + @Test + void initializeLogging_withCorrelationId_shouldExtractFromEvent() { + // GIVEN + Map<String, Object> event = Map.of("requestContext", Map.of("requestId", "test-correlation-id")); + + // WHEN + PowertoolsLogging.initializeLogging(context, "requestContext.requestId", event); + + // THEN + assertThat(MDC.get(PowertoolsLoggedFields.CORRELATION_ID.getName())).isEqualTo("test-correlation-id"); + } + + @Test + void initializeLogging_withFullConfiguration_shouldSetAllFields() { + // GIVEN + Map<String, Object> event = Map.of("id", "correlation-123"); + + // WHEN + PowertoolsLogging.initializeLogging(context, 0.5, "id", event); + + // THEN + Map<String, String> mdcMap = MDC.getCopyOfContextMap(); + assertThat(mdcMap) + .containsEntry(PowertoolsLoggedFields.FUNCTION_NAME.getName(), "test-function") + .containsEntry(PowertoolsLoggedFields.CORRELATION_ID.getName(), "correlation-123") + .containsEntry(PowertoolsLoggedFields.SAMPLING_RATE.getName(), "0.5"); + } + + @Test + void initializeLogging_withInvalidSamplingRate_shouldSkipSampling() { + // WHEN + PowertoolsLogging.initializeLogging(context, 2.0); + + // THEN + assertThat(MDC.get(PowertoolsLoggedFields.SAMPLING_RATE.getName())).isNull(); + } + + @Test + void initializeLogging_withEnvVarAndParameter_shouldUseEnvVarPrecedence() throws IllegalAccessException { + // GIVEN + writeStaticField(LoggingConstants.class, "POWERTOOLS_SAMPLING_RATE", "0.8", true); + + // WHEN + PowertoolsLogging.initializeLogging(context, 0.3); + + // THEN + assertThat(MDC.get(PowertoolsLoggedFields.SAMPLING_RATE.getName())).isEqualTo("0.8"); + } + + @Test + void initializeLogging_calledTwice_shouldMarkColdStartDoneOnSecondCall() throws IllegalAccessException { + // GIVEN + writeStaticField(PowertoolsLogging.class, "hasBeenInitialized", new AtomicBoolean(false), true); + + // WHEN - First call + PowertoolsLogging.initializeLogging(context); + String firstCallColdStart = MDC.get(PowertoolsLoggedFields.FUNCTION_COLD_START.getName()); + + // WHEN - Second call + PowertoolsLogging.initializeLogging(context); + String secondCallColdStart = MDC.get(PowertoolsLoggedFields.FUNCTION_COLD_START.getName()); + + // THEN + assertThat(firstCallColdStart).isEqualTo("true"); + assertThat(secondCallColdStart).isEqualTo("false"); + } + + @Test + void initializeLogging_withNullContext_shouldNotThrow() { + // WHEN & THEN + assertThatNoException().isThrownBy(() -> { + PowertoolsLogging.initializeLogging(null); + PowertoolsLogging.initializeLogging(null, 0.5); + PowertoolsLogging.initializeLogging(null, "path", Map.of()); + PowertoolsLogging.initializeLogging(null, 0.5, "path", Map.of()); + }); + } + + @Test + void clearState_shouldClearMdcAndBuffer() { + // GIVEN + MDC.put("test", "value"); + + // WHEN + PowertoolsLogging.clearState(true); + + // THEN + assertThat(MDC.getCopyOfContextMap()).isNull(); + assertThat(testManager.isBufferCleared()).isTrue(); + } + + @Test + void clearState_withoutMdcClear_shouldOnlyClearBuffer() { + // GIVEN + MDC.put("test", "value"); + + // WHEN + PowertoolsLogging.clearState(false); + + // THEN + assertThat(MDC.get("test")).isEqualTo("value"); + assertThat(testManager.isBufferCleared()).isTrue(); + } + + @Test + void initializeLogging_concurrentCalls_shouldBeThreadSafe() throws InterruptedException { + // GIVEN + int threadCount = 10; + Thread[] threads = new Thread[threadCount]; + String[] samplingRates = new String[threadCount]; + boolean[] coldStarts = new boolean[threadCount]; + boolean[] success = new boolean[threadCount]; + + // WHEN - Multiple threads call initializeLogging with alternating sampling rates + for (int i = 0; i < threadCount; i++) { + final int threadIndex = i; + final double samplingRate = (i % 2 == 0) ? 1.0 : 0.0; // Alternate between 1.0 and 0.0 + + threads[i] = new Thread(() -> { + try { + PowertoolsLogging.initializeLogging(context, samplingRate); + + // Capture the sampling rate and cold start values set in MDC (thread-local) + samplingRates[threadIndex] = MDC.get(PowertoolsLoggedFields.SAMPLING_RATE.getName()); + coldStarts[threadIndex] = Boolean + .parseBoolean(MDC.get(PowertoolsLoggedFields.FUNCTION_COLD_START.getName())); + success[threadIndex] = true; + + // Clean up thread-local state + PowertoolsLogging.clearState(true); + } catch (Exception e) { + success[threadIndex] = false; + } + }); + } + + // Start all threads + for (Thread thread : threads) { + thread.start(); + } + + // Wait for all threads to complete + for (Thread thread : threads) { + thread.join(); + } + + // THEN - All threads should complete successfully + for (boolean result : success) { + assertThat(result).isTrue(); + } + + // THEN - Each thread should have its own sampling rate in MDC and exactly one invocation was a cold start + int coldStartCount = 0; + for (int i = 0; i < threadCount; i++) { + String expectedSamplingRate = (i % 2 == 0) ? "1.0" : "0.0"; + assertThat(samplingRates[i]).as("Thread %d should have sampling rate %s", i, expectedSamplingRate) + .isEqualTo(expectedSamplingRate); + + coldStartCount += coldStarts[i] ? 1 : 0; + } + assertThat(coldStartCount).isEqualTo(1); + } + + @Test + void withLogging_basicUsage_shouldInitializeAndCleanup() { + // WHEN + String result = PowertoolsLogging.withLogging(context, () -> { + assertThat(MDC.get(PowertoolsLoggedFields.FUNCTION_NAME.getName())).isEqualTo("test-function"); + return "test-result"; + }); + + // THEN + assertThat(result).isEqualTo("test-result"); + assertThat(MDC.getCopyOfContextMap()).isNull(); + assertThat(testManager.isBufferCleared()).isTrue(); + } + + @Test + void withLogging_withSamplingRate_shouldSetSamplingRateAndCleanup() { + // WHEN + String result = PowertoolsLogging.withLogging(context, 0.5, () -> { + assertThat(MDC.get(PowertoolsLoggedFields.SAMPLING_RATE.getName())).isEqualTo("0.5"); + return "sampled-result"; + }); + + // THEN + assertThat(result).isEqualTo("sampled-result"); + assertThat(MDC.getCopyOfContextMap()).isNull(); + } + + @Test + void withLogging_withCorrelationId_shouldExtractCorrelationIdAndCleanup() { + // GIVEN + Map<String, Object> event = Map.of("requestId", "correlation-123"); + + // WHEN + Integer result = PowertoolsLogging.withLogging(context, "requestId", event, () -> { + assertThat(MDC.get(PowertoolsLoggedFields.CORRELATION_ID.getName())).isEqualTo("correlation-123"); + return 42; + }); + + // THEN + assertThat(result).isEqualTo(42); + assertThat(MDC.getCopyOfContextMap()).isNull(); + } + + @Test + void withLogging_withFullConfiguration_shouldSetAllFieldsAndCleanup() { + // GIVEN + Map<String, Object> event = Map.of("id", "full-correlation"); + + // WHEN + Boolean result = PowertoolsLogging.withLogging(context, 0.8, "id", event, () -> { + Map<String, String> mdcMap = MDC.getCopyOfContextMap(); + assertThat(mdcMap) + .containsEntry(PowertoolsLoggedFields.FUNCTION_NAME.getName(), "test-function") + .containsEntry(PowertoolsLoggedFields.CORRELATION_ID.getName(), "full-correlation") + .containsEntry(PowertoolsLoggedFields.SAMPLING_RATE.getName(), "0.8"); + return true; + }); + + // THEN + assertThat(result).isTrue(); + assertThat(MDC.getCopyOfContextMap()).isNull(); + } + + @Test + void withLogging_whenSupplierThrowsException_shouldStillCleanup() { + // WHEN & THEN + try { + PowertoolsLogging.withLogging(context, () -> { + assertThat(MDC.get(PowertoolsLoggedFields.FUNCTION_NAME.getName())).isEqualTo("test-function"); + throw new RuntimeException("test exception"); + }); + } catch (RuntimeException e) { + assertThat(e.getMessage()).isEqualTo("test exception"); + } + + // THEN - cleanup should still happen + assertThat(MDC.getCopyOfContextMap()).isNull(); + assertThat(testManager.isBufferCleared()).isTrue(); + } + + private void reinitializeLogLevel() { + try { + Method initializeLogLevel = PowertoolsLogging.class.getDeclaredMethod("initializeLogLevel"); + initializeLogLevel.setAccessible(true); + initializeLogLevel.invoke(null); + } catch (Exception e) { + throw new RuntimeException("Failed to reinitialize log level", e); + } + } } diff --git a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java index f77997a77..ca47f9097 100644 --- a/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java +++ b/powertools-logging/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaLoggingAspectTest.java @@ -31,8 +31,6 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; import java.nio.file.NoSuchFileException; @@ -41,6 +39,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -49,8 +48,6 @@ import org.junitpioneer.jupiter.ClearEnvironmentVariable; import org.junitpioneer.jupiter.SetEnvironmentVariable; import org.junitpioneer.jupiter.SetSystemProperty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.slf4j.event.Level; import org.slf4j.test.TestLogger; @@ -67,6 +64,7 @@ import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; +import software.amazon.lambda.powertools.logging.PowertoolsLogging; import software.amazon.lambda.powertools.logging.argument.StructuredArgument; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogAlbCorrelationId; import software.amazon.lambda.powertools.logging.handlers.PowertoolsLogApiGatewayHttpApiCorrelationId; @@ -90,7 +88,6 @@ class LambdaLoggingAspectTest { - private static final Logger LOG = LoggerFactory.getLogger(LambdaLoggingAspectTest.class); private static final int EXPECTED_CONTEXT_SIZE = 8; private RequestStreamHandler requestStreamHandler; private RequestHandler<Object, Object> requestHandler; @@ -98,13 +95,16 @@ class LambdaLoggingAspectTest { private Context context; @BeforeEach - void setUp() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, IOException { + void setUp() throws IllegalAccessException, IOException { MDC.clear(); + + // Reset cold start state writeStaticField(LambdaHandlerProcessor.class, "isColdStart", null, true); + writeStaticField(PowertoolsLogging.class, "hasBeenInitialized", new AtomicBoolean(false), true); + context = new TestLambdaContext(); requestHandler = new PowertoolsLogEnabled(); requestStreamHandler = new PowertoolsLogEnabledForStream(); - resetLogLevel(Level.INFO); writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", null, true); writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", null, true); writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_EVENT", false, true); @@ -131,139 +131,10 @@ void cleanUp() throws IOException { } catch (NoSuchFileException e) { // may not be there in the first run } - } - - @Test - void shouldLogDebugWhenPowertoolsLevelEnvVarIsDebug() throws IllegalAccessException { - // GIVEN - writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "DEBUG", true); - - // WHEN - LambdaLoggingAspect.setLogLevel(); - - // THEN - assertThat(LOG.isDebugEnabled()).isTrue(); - } - - @Test - void shouldLogInfoWhenPowertoolsLevelEnvVarIsInfo() throws IllegalAccessException { - // GIVEN - writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "INFO", true); - - // WHEN - LambdaLoggingAspect.setLogLevel(); - - // THEN - assertThat(LOG.isDebugEnabled()).isFalse(); - assertThat(LOG.isInfoEnabled()).isTrue(); - } - - @Test - void shouldLogInfoWhenPowertoolsLevelEnvVarIsInvalid() throws IllegalAccessException { - // GIVEN - writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "INVALID", true); - - // WHEN - LambdaLoggingAspect.setLogLevel(); - - // THEN - assertThat(LOG.isDebugEnabled()).isFalse(); - assertThat(LOG.isInfoEnabled()).isTrue(); - } - - @Test - void shouldLogWarnWhenPowertoolsLevelEnvVarIsWarn() throws IllegalAccessException { - // GIVEN - writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "WARN", true); - - // WHEN - LambdaLoggingAspect.setLogLevel(); - - // THEN - assertThat(LOG.isDebugEnabled()).isFalse(); - assertThat(LOG.isInfoEnabled()).isFalse(); - assertThat(LOG.isWarnEnabled()).isTrue(); - } - - @Test - void shouldLogErrorWhenPowertoolsLevelEnvVarIsError() throws IllegalAccessException { - // GIVEN - writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "ERROR", true); - - // WHEN - LambdaLoggingAspect.setLogLevel(); - // THEN - assertThat(LOG.isDebugEnabled()).isFalse(); - assertThat(LOG.isInfoEnabled()).isFalse(); - assertThat(LOG.isWarnEnabled()).isFalse(); - assertThat(LOG.isErrorEnabled()).isTrue(); - } - - @Test - void shouldLogErrorWhenPowertoolsLevelEnvVarIsFatal() throws IllegalAccessException { - // GIVEN - writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "FATAL", true); - - // WHEN - LambdaLoggingAspect.setLogLevel(); - - // THEN - assertThat(LOG.isDebugEnabled()).isFalse(); - assertThat(LOG.isInfoEnabled()).isFalse(); - assertThat(LOG.isWarnEnabled()).isFalse(); - assertThat(LOG.isErrorEnabled()).isTrue(); - } - - @Test - void shouldLogWarnWhenPowertoolsLevelEnvVarIsWarnAndLambdaLevelVarIsInfo() throws IllegalAccessException { - // GIVEN - writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "WARN", true); - writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", "INFO", true); - - // WHEN - LambdaLoggingAspect.setLogLevel(); - - // THEN - assertThat(LOG.isDebugEnabled()).isFalse(); - assertThat(LOG.isInfoEnabled()).isFalse(); - assertThat(LOG.isWarnEnabled()).isTrue(); - File logFile = new File("target/logfile.json"); - assertThat(contentOf(logFile)) - .doesNotContain(" does not match AWS Lambda Advanced Logging Controls minimum log level"); - } - - @Test - void shouldLogInfoWhenPowertoolsLevelEnvVarIsInfoAndLambdaLevelVarIsWarn() throws IllegalAccessException { - // GIVEN - writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", "INFO", true); - writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", "WARN", true); - - // WHEN - LambdaLoggingAspect.setLogLevel(); - - // THEN - assertThat(LOG.isDebugEnabled()).isFalse(); - assertThat(LOG.isInfoEnabled()).isTrue(); - File logFile = new File("target/logfile.json"); - // should log a warning as powertools level is lower than lambda level - assertThat(contentOf(logFile)).contains( - "Current log level (INFO) does not match AWS Lambda Advanced Logging Controls minimum log level (WARN). This can lead to data loss, consider adjusting them."); - } - - @Test - void shouldLogWarnWhenPowertoolsLevelEnvVarINotSetAndLambdaLevelVarIsWarn() throws IllegalAccessException { - // GIVEN - writeStaticField(LoggingConstants.class, "POWERTOOLS_LOG_LEVEL", null, true); - writeStaticField(LoggingConstants.class, "LAMBDA_LOG_LEVEL", "WARN", true); - - // WHEN - LambdaLoggingAspect.setLogLevel(); - - // THEN - assertThat(LOG.isDebugEnabled()).isFalse(); - assertThat(LOG.isInfoEnabled()).isFalse(); - assertThat(LOG.isWarnEnabled()).isTrue(); + // Reset log level to INFO to ensure test isolation + LoggingManager loggingManager = LoggingManagerRegistry.getLoggingManager(); + loggingManager.setLogLevel(Level.INFO); } @Test @@ -855,11 +726,4 @@ void shouldClearBufferBeforeErrorLoggingWhenFlushBufferOnUncaughtErrorDisabled() } } - private void resetLogLevel(Level level) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - Method setLogLevels = LambdaLoggingAspect.class.getDeclaredMethod("setLogLevels", Level.class); - setLogLevels.setAccessible(true); - setLogLevels.invoke(null, level); - writeStaticField(LambdaLoggingAspect.class, "LEVEL_AT_INITIALISATION", level, true); - } } diff --git a/spotbugs-exclude.xml b/spotbugs-exclude.xml index 35aed5e26..53226e3c2 100644 --- a/spotbugs-exclude.xml +++ b/spotbugs-exclude.xml @@ -201,8 +201,7 @@ <Bug pattern="MS_SHOULD_BE_FINAL"/> <Or> <And> - <Class name="software.amazon.lambda.powertools.logging.internal.LambdaLoggingAspect"/> - <Field name="SAMPLING_RATE"/> + <Class name="software.amazon.lambda.powertools.logging.internal.LoggingConstants"/> </And> </Or> </Match> From 1a0e7cbce5461abc85e98ae2a938477f203d6203 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 14:05:05 +0100 Subject: [PATCH 495/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.220.0 to 2.221.0 (#2235) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.220.0 to 2.221.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.220.0...v2.221.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.221.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 31d5f7e99..42777cc96 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.5.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.220.0</cdk.version> + <cdk.version>2.221.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.14.0</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 0b11ce4e0..046592e1c 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.2</constructs.version> - <cdk.version>2.220.0</cdk.version> + <cdk.version>2.221.0</cdk.version> </properties> <dependencies> From 2240e5511c619a4809b0146feafba4c3ac926e02 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 14:06:15 +0100 Subject: [PATCH 496/577] chore: bump aws.sdk.version from 2.32.31 to 2.36.2 (#2237) Bumps `aws.sdk.version` from 2.32.31 to 2.36.2. Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.36.2 Updates `software.amazon.awssdk:sdk-core` from 2.32.31 to 2.36.2 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.36.2 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.36.2 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.36.2 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.32.31 to 2.36.2 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.36.2 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.36.2 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.36.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index eac85eafe..a5d14f0c1 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.32.31</sdk.version> + <sdk.version>2.36.2</sdk.version> </properties> <dependencies> From ec7f84e4da0b31f306f8784717ceccfa3125f3fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 14:06:36 +0100 Subject: [PATCH 497/577] chore: bump actions/upload-artifact from 4.6.2 to 5.0.0 (#2238) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 5.0.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/ea165f8d65b6e75b540449e92b4886f43607fa02...330a01c490aca151604b8cf639adc76d48f6c5d4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- .github/workflows/security-scorecard.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 13c7c34d2..2c7f65324 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -112,7 +112,7 @@ jobs: snapshot: ${{ inputs.snapshot}} - id: upload_source name: Upload artifacts - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: if-no-files-found: error name: source diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index d4df1e675..3b17b3700 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -46,7 +46,7 @@ jobs: publish_results: true repo_token: ${{ secrets.SCORECARD_TOKEN }} - name: Upload Results - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: name: SARIF file path: results.sarif From 7e4fa88a7efacdd5c505ac68533febb9ed04bb8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 14:06:49 +0100 Subject: [PATCH 498/577] chore: bump github/codeql-action from 4.30.9 to 4.31.0 (#2239) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.9 to 4.31.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/16140ae1a102900babc80a33c44059580f687047...4e94bd11f71e507f7f87df81788dff88d1dacbfb) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 3b17b3700..4ca976695 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # v3.29.5 + uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v3.29.5 with: sarif_file: results.sarif From b98910fa1fd1d5e54c1a82fbf1ab1d421228de29 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 14:07:12 +0100 Subject: [PATCH 499/577] chore: bump actions/download-artifact from 5.0.0 to 6.0.0 (#2234) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5.0.0 to 6.0.0. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/634f93cb2916e3fdff6788551b99b062d0335ce0...018cc2cf5baa6db3ef3c5f8a56943fffe632ef53) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2c7f65324..79cb5b04f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -133,7 +133,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4.6.1 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v4.6.1 with: name: source - name: Setup Java @@ -168,7 +168,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4.6.1 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v4.6.1 with: name: source - name: Setup Java @@ -191,7 +191,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4.6.1 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v4.6.1 with: name: source - name: Setup Java @@ -229,7 +229,7 @@ jobs: ref: ${{ env.RELEASE_COMMIT }} - id: download_source name: Download artifacts - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4.6.1 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v4.6.1 with: name: source - id: setup-git From 74dc8a0d287382d5647588d9f11844465b8476a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 14:07:33 +0100 Subject: [PATCH 500/577] chore: bump graalvm/setup-graalvm from 1.4.1 to 1.4.2 (#2236) Bumps [graalvm/setup-graalvm](https://github.com/graalvm/setup-graalvm) from 1.4.1 to 1.4.2. - [Release notes](https://github.com/graalvm/setup-graalvm/releases) - [Commits](https://github.com/graalvm/setup-graalvm/compare/2a2412009026a83f51d179f92dc2b3fd4c8142df...eec48106e0bf45f2976c2ff0c3e22395cced8243) --- updated-dependencies: - dependency-name: graalvm/setup-graalvm dependency-version: 1.4.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 8bc474c20..e1d949aad 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -103,7 +103,7 @@ jobs: powertools-*/** pom.xml - name: Setup GraalVM - uses: graalvm/setup-graalvm@2a2412009026a83f51d179f92dc2b3fd4c8142df # v1.4.1 + uses: graalvm/setup-graalvm@eec48106e0bf45f2976c2ff0c3e22395cced8243 # v1.4.2 with: java-version: "21" distribution: "graalvm" From 1abc57b70da838ee97ccf6f17096d37c2993b6e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Oct 2025 10:22:36 +0100 Subject: [PATCH 501/577] chore: bump aws.sdk.version from 2.36.1 to 2.36.2 (#2240) Bumps `aws.sdk.version` from 2.36.1 to 2.36.2. Updates `software.amazon.awssdk:bom` from 2.36.1 to 2.36.2 Updates `software.amazon.awssdk:http-client-spi` from 2.36.1 to 2.36.2 Updates `software.amazon.awssdk:url-connection-client` from 2.32.31 to 2.36.2 Updates `software.amazon.awssdk:s3` from 2.32.31 to 2.36.2 Updates `software.amazon.awssdk:dynamodb` from 2.36.1 to 2.36.2 Updates `software.amazon.awssdk:lambda` from 2.36.1 to 2.36.2 Updates `software.amazon.awssdk:kinesis` from 2.32.31 to 2.36.2 Updates `software.amazon.awssdk:cloudwatch` from 2.36.1 to 2.36.2 Updates `software.amazon.awssdk:xray` from 2.36.1 to 2.36.2 Updates `software.amazon.awssdk:sqs` from 2.32.31 to 2.36.2 Updates `software.amazon.awssdk:cloudformation` from 2.36.1 to 2.36.2 Updates `software.amazon.awssdk:sts` from 2.36.1 to 2.36.2 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.36.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.36.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.36.2 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.36.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index b37c468c0..3d9bb3c67 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.36.1</aws.sdk.version> + <aws.sdk.version>2.36.2</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 8a8474f0a..878826077 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.36.1</aws.sdk.version> + <aws.sdk.version>2.36.2</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 752492d6d..ae075b71d 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.36.1</aws.sdk.version> + <aws.sdk.version>2.36.2</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 2516b83f4924e786fa2d62fabfcd44c1f50965ce Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Wed, 29 Oct 2025 17:37:15 +0100 Subject: [PATCH 502/577] feat(idempotency): Add functional `Idempotency` API (#2244) * Decouple AspectJ dependencies on pjp from IdempotencyHandler. * Create PowertoolsIdempotency functional API with overloads for all use-cases. * Make IdempotencyConfig thread-safe to avoid Lamdba context leaks in config singleton. * Fix bug: We need to pass the return type explicitly to support deserialization to the return type of the method. * Address some pmd findings. * Make java doc consistent in PowertoolsIdempotency. * Hide checked exceptions (from AspectJ) from user-facing API in PowertoolsIdempotency. * Remove unncessary try catch Throwable in unit tests * Add E2E test for functional idempotency API. * Fix sonar issues. * Remove unncessary constructors for Input object. * Add support for generic types. * Merge PowertoolsIdempotency with Idempotency to offer a single entrypoint to idempotency. * Make ConfigHolder final. * Make ConfigHolder modifier order comply with java language spec. * Make Holder class final. --- .../handlers/idempotency-functional/pom.xml | 60 ++++ .../lambda/powertools/e2e/Function.java | 66 ++++ .../amazon/lambda/powertools/e2e/Input.java | 27 ++ .../aws-lambda-java-core/reflect-config.json | 13 + .../reflect-config.json | 35 ++ .../jni-config.json | 11 + .../native-image.properties | 1 + .../reflect-config.json | 61 ++++ .../resource-config.json | 19 ++ .../reflect-config.json | 25 ++ .../reflect-config.json | 20 ++ .../resource-config.json | 7 + .../src/main/resources/log4j2.xml | 16 + .../handlers/idempotency-generics/pom.xml | 60 ++++ .../lambda/powertools/e2e/Function.java | 78 +++++ .../amazon/lambda/powertools/e2e/Input.java | 27 ++ .../aws-lambda-java-core/reflect-config.json | 13 + .../reflect-config.json | 35 ++ .../jni-config.json | 11 + .../native-image.properties | 1 + .../reflect-config.json | 61 ++++ .../resource-config.json | 19 ++ .../reflect-config.json | 25 ++ .../reflect-config.json | 20 ++ .../resource-config.json | 7 + .../src/main/resources/log4j2.xml | 16 + powertools-e2e-tests/handlers/pom.xml | 2 + .../lambda/powertools/IdempotencyE2ET.java | 31 +- .../powertools/idempotency/Idempotency.java | 238 +++++++++++++- .../idempotency/IdempotencyConfig.java | 8 +- .../internal/IdempotencyHandler.java | 28 +- .../internal/IdempotentAspect.java | 28 +- .../internal/IdempotentFunction.java | 30 ++ .../idempotency/internal/cache/LRUCache.java | 4 +- .../idempotency/IdempotencyTest.java | 311 ++++++++++++++++++ .../IdempotencyFunctionalFunction.java | 48 +++ ...IdempotencyMultiArgFunctionalFunction.java | 54 +++ .../internal/IdempotencyAspectTest.java | 71 +++- .../testutils/InMemoryPersistenceStore.java | 58 ++++ .../powertools/utilities/JsonConfig.java | 28 +- 40 files changed, 1612 insertions(+), 61 deletions(-) create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/pom.xml create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/java/software/amazon/lambda/powertools/e2e/Input.java create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/log4j2.xml create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/pom.xml create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json create mode 100644 powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/log4j2.xml create mode 100644 powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentFunction.java create mode 100644 powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java create mode 100644 powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunctionalFunction.java create mode 100644 powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyMultiArgFunctionalFunction.java create mode 100644 powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/testutils/InMemoryPersistenceStore.java diff --git a/powertools-e2e-tests/handlers/idempotency-functional/pom.xml b/powertools-e2e-tests/handlers/idempotency-functional/pom.xml new file mode 100644 index 000000000..c8893c6e9 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/pom.xml @@ -0,0 +1,60 @@ +<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 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>software.amazon.lambda</groupId> + <artifactId>e2e-test-handlers-parent</artifactId> + <version>2.5.0</version> + </parent> + + <artifactId>e2e-test-handler-idempotency-functional</artifactId> + <packaging>jar</packaging> + <name>E2E test handler – Idempotency Functional</name> + + <dependencies> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-idempotency-dynamodb</artifactId> + </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging-log4j</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-events</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/idempotency-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java new file mode 100644 index 000000000..fec7459c1 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -0,0 +1,66 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +import java.time.Duration; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.TimeZone; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.lambda.powertools.idempotency.Idempotency; +import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; +import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; + +public class Function implements RequestHandler<Input, String> { + + public Function() { + this(DynamoDbClient + .builder() + .httpClient(UrlConnectionHttpClient.builder().build()) + .region(Region.of(System.getenv("AWS_REGION"))) + .build()); + } + + public Function(DynamoDbClient client) { + Idempotency.config().withConfig( + IdempotencyConfig.builder() + .withExpiration(Duration.of(10, ChronoUnit.SECONDS)) + .build()) + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withDynamoDbClient(client) + .withTableName(System.getenv("IDEMPOTENCY_TABLE")) + .build()) + .configure(); + } + + public String handleRequest(Input input, Context context) { + Idempotency.registerLambdaContext(context); + + return Idempotency.makeIdempotent(this::processRequest, input, String.class); + } + + private String processRequest(Input input) { + DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME.withZone(TimeZone.getTimeZone("UTC").toZoneId()); + return dtf.format(Instant.now()); + } +} diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/idempotency-functional/src/main/java/software/amazon/lambda/powertools/e2e/Input.java new file mode 100644 index 000000000..0d14b749e --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/java/software/amazon/lambda/powertools/e2e/Input.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +public class Input { + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/log4j2.xml b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/log4j2.xml new file mode 100644 index 000000000..8925f70b9 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + </Appenders> + <Loggers> + <Root level="INFO"> + <AppenderRef ref="JsonAppender"/> + </Root> + <Logger name="JsonLogger" level="INFO" additivity="false"> + <AppenderRef ref="JsonAppender"/> + </Logger> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-generics/pom.xml b/powertools-e2e-tests/handlers/idempotency-generics/pom.xml new file mode 100644 index 000000000..5387d4059 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/pom.xml @@ -0,0 +1,60 @@ +<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 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>software.amazon.lambda</groupId> + <artifactId>e2e-test-handlers-parent</artifactId> + <version>2.5.0</version> + </parent> + + <artifactId>e2e-test-handler-idempotency-generics</artifactId> + <packaging>jar</packaging> + <name>E2E test handler – Idempotency Generics</name> + + <dependencies> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-idempotency-dynamodb</artifactId> + </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging-log4j</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-events</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-core</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>native-image</id> + <build> + <plugins> + <plugin> + <groupId>org.graalvm.buildtools</groupId> + <artifactId>native-maven-plugin</artifactId> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/idempotency-generics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java new file mode 100644 index 000000000..09e39d1eb --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -0,0 +1,78 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +import java.time.Duration; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.HashMap; +import java.util.Map; +import java.util.TimeZone; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.fasterxml.jackson.core.type.TypeReference; + +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.lambda.powertools.idempotency.Idempotency; +import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; +import software.amazon.lambda.powertools.idempotency.persistence.dynamodb.DynamoDBPersistenceStore; + +public class Function implements RequestHandler<Input, String> { + + public Function() { + this(DynamoDbClient + .builder() + .httpClient(UrlConnectionHttpClient.builder().build()) + .region(Region.of(System.getenv("AWS_REGION"))) + .build()); + } + + public Function(DynamoDbClient client) { + Idempotency.config().withConfig( + IdempotencyConfig.builder() + .withExpiration(Duration.of(10, ChronoUnit.SECONDS)) + .build()) + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withDynamoDbClient(client) + .withTableName(System.getenv("IDEMPOTENCY_TABLE")) + .build()) + .configure(); + } + + public String handleRequest(Input input, Context context) { + Idempotency.registerLambdaContext(context); + + // This is just to test the generic type support using TypeReference. + // We return the same String to run the same assertions as other idempotency E2E handlers. + Map<String, String> result = Idempotency.makeIdempotent( + this::processRequest, + input, + new TypeReference<Map<String, String>>() {}); + + return result.get("timestamp"); + } + + private Map<String, String> processRequest(Input input) { + DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME.withZone(TimeZone.getTimeZone("UTC").toZoneId()); + Map<String, String> result = new HashMap<>(); + result.put("timestamp", dtf.format(Instant.now())); + return result; + } +} diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java b/powertools-e2e-tests/handlers/idempotency-generics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java new file mode 100644 index 000000000..0d14b749e --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/java/software/amazon/lambda/powertools/e2e/Input.java @@ -0,0 +1,27 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +public class Input { + private String message; + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } +} diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json new file mode 100644 index 000000000..2780aca09 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-core/reflect-config.json @@ -0,0 +1,13 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "methods":[{"name":"<init>","parameterTypes":[] }], + "fields":[{"name":"logger"}], + "allPublicMethods":true + }, + { + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntimeInternal", + "methods":[{"name":"<init>","parameterTypes":[] }], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json new file mode 100644 index 000000000..ddda5d5f1 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-events/reflect-config.json @@ -0,0 +1,35 @@ +[ + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$ProxyRequestContext", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent$RequestIdentity", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredFields": true, + "allDeclaredMethods": true, + "allDeclaredConstructors": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json new file mode 100644 index 000000000..91be72f7a --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json @@ -0,0 +1,11 @@ +[ + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"<init>","parameterTypes":["java.lang.String","int"] }] + }, + { + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], + "allPublicMethods":true + } +] \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 000000000..20f8b7801 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json new file mode 100644 index 000000000..e69fa735c --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -0,0 +1,61 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields": [{ "name": "logger" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogLevel", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "com.amazonaws.services.lambda.runtime.logging.LogFormat", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredFields": true, + "allPublicFields": true + }, + { + "name": "java.lang.Void", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "java.util.Collections$UnmodifiableMap", + "fields": [{ "name": "m" }] + }, + { + "name": "jdk.internal.module.IllegalAccessLogger", + "fields": [{ "name": "logger" }] + }, + { + "name": "sun.misc.Unsafe", + "fields": [{ "name": "theUnsafe" }] + }, + { + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true + } +] diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json new file mode 100644 index 000000000..1062b4249 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json @@ -0,0 +1,19 @@ +{ + "resources": { + "includes": [ + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux-x86_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-aarch_64.so\\E" + }, + { + "pattern": "\\Qjni/libaws-lambda-jni.linux_musl-x86_64.so\\E" + } + ] + }, + "bundles": [] +} \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json new file mode 100644 index 000000000..9890688f9 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-serialization/reflect-config.json @@ -0,0 +1,25 @@ +[ + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7HandlersImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods": [{ "name": "<init>", "parameterTypes": [] }] + }, + { + "name": "com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ser.Serializers[]" + }, + { + "name": "org.joda.time.DateTime", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json new file mode 100644 index 000000000..9ddd235e2 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/reflect-config.json @@ -0,0 +1,20 @@ +[ + { + "name": "software.amazon.lambda.powertools.e2e.Function", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + }, + { + "name": "software.amazon.lambda.powertools.e2e.Input", + "allDeclaredConstructors": true, + "allPublicConstructors": true, + "allDeclaredMethods": true, + "allPublicMethods": true, + "allDeclaredClasses": true, + "allPublicClasses": true + } +] diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json new file mode 100644 index 000000000..be6aac3f6 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/software.amazon.lambda.powertools.e2e/resource-config.json @@ -0,0 +1,7 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\Qlog4j2.xml\\E" + }]}, + "bundles":[] +} diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/log4j2.xml b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/log4j2.xml new file mode 100644 index 000000000..8925f70b9 --- /dev/null +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + </Appenders> + <Loggers> + <Root level="INFO"> + <AppenderRef ref="JsonAppender"/> + </Root> + <Logger name="JsonLogger" level="INFO" additivity="false"> + <AppenderRef ref="JsonAppender"/> + </Logger> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index ae075b71d..7a7da9e02 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -34,6 +34,8 @@ <module>tracing</module> <module>metrics</module> <module>idempotency</module> + <module>idempotency-functional</module> + <module>idempotency-generics</module> <module>parameters</module> <module>validation-alb-event</module> <module>validation-apigw-event</module> diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java index c73a6d761..9ced0e4fb 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/IdempotencyE2ET.java @@ -23,40 +23,43 @@ import java.util.concurrent.TimeUnit; import org.assertj.core.api.Assertions; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import software.amazon.lambda.powertools.testutils.Infrastructure; import software.amazon.lambda.powertools.testutils.lambda.InvocationResult; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class IdempotencyE2ET { - private static Infrastructure infrastructure; - private static String functionName; + private Infrastructure infrastructure; + private String functionName; - @BeforeAll - @Timeout(value = 15, unit = TimeUnit.MINUTES) - static void setup() { + private void setupInfrastructure(String pathToFunction) { String random = UUID.randomUUID().toString().substring(0, 6); infrastructure = Infrastructure.builder() - .testName(IdempotencyE2ET.class.getSimpleName()) - .pathToFunction("idempotency") + .testName(IdempotencyE2ET.class.getSimpleName() + "-" + pathToFunction) + .pathToFunction(pathToFunction) .idempotencyTable("idempo" + random) .build(); Map<String, String> outputs = infrastructure.deploy(); functionName = outputs.get(FUNCTION_NAME_OUTPUT); } - @AfterAll - static void tearDown() { + @AfterEach + void tearDown() { if (infrastructure != null) { infrastructure.destroy(); } } - @Test - void test_ttlNotExpired_sameResult_ttlExpired_differentResult() throws InterruptedException { + @ParameterizedTest + @ValueSource(strings = { "idempotency", "idempotency-functional", "idempotency-generics" }) + @Timeout(value = 15, unit = TimeUnit.MINUTES) + void test_ttlNotExpired_sameResult_ttlExpired_differentResult(String pathToFunction) throws InterruptedException { + setupInfrastructure(pathToFunction); // GIVEN String event = "{\"message\":\"TTL 10sec\"}"; diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java index bd564caf8..4f73edea0 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/Idempotency.java @@ -14,25 +14,87 @@ package software.amazon.lambda.powertools.idempotency; +import java.util.function.Function; +import java.util.function.Supplier; + import com.amazonaws.services.lambda.runtime.Context; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; + +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyConfigurationException; +import software.amazon.lambda.powertools.idempotency.internal.IdempotencyHandler; import software.amazon.lambda.powertools.idempotency.persistence.BasePersistenceStore; +import software.amazon.lambda.powertools.utilities.JsonConfig; /** - * Holds the configuration for idempotency: - * <ul> - * <li>The persistence layer to use for persisting the request and response of the function (mandatory).</li> - * <li>The general configuration for idempotency (optional, see {@link IdempotencyConfig.Builder} methods to see defaults values.</li> - * </ul> - * <br/> - * Use it before the function handler ({@link com.amazonaws.services.lambda.runtime.RequestHandler#handleRequest(Object, Context)}) - * get called. - * <br/> - * Example: - * <pre> - * Idempotency.config().withPersistenceStore(...).configure(); - * </pre> + * Idempotency provides both a configuration and a functional API for implementing idempotent workloads. + * + * <p>This class is thread-safe. All operations delegate to the underlying persistence store + * which handles concurrent access safely.</p> + * + * <h2>Configuration</h2> + * <p>Configure the persistence layer and idempotency settings before your handler executes (e.g. in constructor):</p> + * <pre>{@code + * Idempotency.config() + * .withPersistenceStore(persistenceStore) + * .withConfig(idempotencyConfig) + * .configure(); + * }</pre> + * + * <h2>Functional API</h2> + * <p>Make methods idempotent without AspectJ annotations. Generic return types (e.g., {@code Map<String, Object>}, + * {@code List<Product>}) are supported via Jackson {@link TypeReference}.</p> + * + * <p><strong>Important:</strong> Always call {@link #registerLambdaContext(Context)} + * at the start of your handler to enable proper timeout handling.</p> + * + * <p>Example usage with Function (single parameter):</p> + * <pre>{@code + * public Basket handleRequest(Product input, Context context) { + * Idempotency.registerLambdaContext(context); + * return Idempotency.makeIdempotent(this::processProduct, input, Basket.class); + * } + * + * private Basket processProduct(Product product) { + * // business logic + * } + * }</pre> + * + * <p>Example usage with Supplier (multi-parameter methods):</p> + * <pre>{@code + * public String handleRequest(SQSEvent event, Context context) { + * Idempotency.registerLambdaContext(context); + * return Idempotency.makeIdempotent( + * event.getRecords().get(0).getBody(), + * () -> processPayment(orderId, amount, currency), + * String.class + * ); + * } + * }</pre> + * + * <p>When different methods use the same payload as idempotency key, use explicit function names + * to differentiate between them:</p> + * <pre>{@code + * // Different methods, same payload + * Idempotency.makeIdempotent("processPayment", orderId, + * () -> processPayment(orderId), String.class); + * + * Idempotency.makeIdempotent("refundPayment", orderId, + * () -> refundPayment(orderId), String.class); + * }</pre> + * + * @see #config() + * @see #registerLambdaContext(Context) + * @see #makeIdempotent(Object, Supplier, Class) + * @see #makeIdempotent(String, Object, Supplier, Class) + * @see #makeIdempotent(Function, Object, Class) + * @see #makeIdempotent(Object, Supplier, TypeReference) + * @see #makeIdempotent(String, Object, Supplier, TypeReference) + * @see #makeIdempotent(Function, Object, TypeReference) */ -public class Idempotency { +public final class Idempotency { + private static final String DEFAULT_FUNCTION_NAME = "function"; + private IdempotencyConfig config; private BasePersistenceStore persistenceStore; @@ -81,7 +143,7 @@ private void setPersistenceStore(BasePersistenceStore persistenceStore) { this.persistenceStore = persistenceStore; } - private static class Holder { + private static final class Holder { private static final Idempotency instance = new Idempotency(); } @@ -116,5 +178,151 @@ public Config withConfig(IdempotencyConfig config) { } } + // Functional API methods + + /** + * Makes a function idempotent using the provided idempotency key. + * Uses a default function name for namespacing the idempotency key. + * + * <p>This method is thread-safe and can be used in parallel processing scenarios + * such as batch processors.</p> + * + * <p>This method is suitable for making methods idempotent that have more than one parameter. + * For simple single-parameter methods, {@link #makeIdempotent(Function, Object, Class)} is more intuitive.</p> + * + * <p><strong>Note:</strong> If you need to call different functions with the same payload, + * use {@link #makeIdempotent(String, Object, Supplier, Class)} to specify distinct function names. + * This ensures each function has its own idempotency scope.</p> + * + * @param idempotencyKey the key used for idempotency (will be converted to JSON) + * @param function the function to make idempotent + * @param returnType the class of the return type for deserialization + * @param <T> the return type of the function + * @return the result of the function execution (either fresh or cached) + */ + public static <T> T makeIdempotent(Object idempotencyKey, Supplier<T> function, Class<T> returnType) { + return makeIdempotent(DEFAULT_FUNCTION_NAME, idempotencyKey, function, returnType); + } + + /** + * Makes a function idempotent using the provided function name and idempotency key. + * + * <p>This method is thread-safe and can be used in parallel processing scenarios + * such as batch processors.</p> + * + * @param functionName the name of the function (used for persistence store configuration) + * @param idempotencyKey the key used for idempotency (will be converted to JSON) + * @param function the function to make idempotent + * @param returnType the class of the return type for deserialization + * @param <T> the return type of the function + * @return the result of the function execution (either fresh or cached) + */ + public static <T> T makeIdempotent(String functionName, Object idempotencyKey, Supplier<T> function, + Class<T> returnType) { + return makeIdempotent(functionName, idempotencyKey, function, JsonConfig.toTypeReference(returnType)); + } + + /** + * Makes a function with one parameter idempotent. + * The parameter is used as the idempotency key. + * + * <p>For functions with more than one parameter, use {@link #makeIdempotent(Object, Supplier, Class)} instead.</p> + * + * <p><strong>Note:</strong> If you need to call different functions with the same payload, + * use {@link #makeIdempotent(String, Object, Supplier, Class)} to specify distinct function names. + * This ensures each function has its own idempotency scope.</p> + * + * @param function the function to make idempotent (method reference) + * @param arg the argument to pass to the function (also used as idempotency key) + * @param returnType the class of the return type for deserialization + * @param <T> the argument type + * @param <R> the return type + * @return the result of the function execution (either fresh or cached) + */ + public static <T, R> R makeIdempotent(Function<T, R> function, T arg, Class<R> returnType) { + return makeIdempotent(DEFAULT_FUNCTION_NAME, arg, () -> function.apply(arg), returnType); + } + + /** + * Makes a function idempotent using the provided idempotency key with support for generic return types. + * Uses a default function name for namespacing the idempotency key. + * + * <p>Use this method when the return type contains generics (e.g., {@code Map<String, Basket>}).</p> + * + * <p>Example usage:</p> + * <pre>{@code + * Map<String, Basket> result = Idempotency.makeIdempotent( + * payload, + * () -> processBaskets(), + * new TypeReference<Map<String, Basket>>() {} + * ); + * }</pre> + * + * @param idempotencyKey the key used for idempotency (will be converted to JSON) + * @param function the function to make idempotent + * @param typeRef the TypeReference for deserialization of generic types + * @param <T> the return type of the function + * @return the result of the function execution (either fresh or cached) + */ + public static <T> T makeIdempotent(Object idempotencyKey, Supplier<T> function, TypeReference<T> typeRef) { + return makeIdempotent(DEFAULT_FUNCTION_NAME, idempotencyKey, function, typeRef); + } + + /** + * Makes a function idempotent using the provided function name and idempotency key with support for generic return types. + * + * @param functionName the name of the function (used for persistence store configuration) + * @param idempotencyKey the key used for idempotency (will be converted to JSON) + * @param function the function to make idempotent + * @param typeRef the TypeReference for deserialization of generic types + * @param <T> the return type of the function + * @return the result of the function execution (either fresh or cached) + */ + @SuppressWarnings("unchecked") + public static <T> T makeIdempotent(String functionName, Object idempotencyKey, Supplier<T> function, + TypeReference<T> typeRef) { + try { + JsonNode payload = JsonConfig.get().getObjectMapper().valueToTree(idempotencyKey); + Context lambdaContext = Idempotency.getInstance().getConfig().getLambdaContext(); + + IdempotencyHandler handler = new IdempotencyHandler( + function::get, + typeRef, + functionName, + payload, + lambdaContext); + + Object result = handler.handle(); + return (T) result; + } catch (RuntimeException e) { + throw e; + } catch (Throwable e) { + throw new IdempotencyConfigurationException("Idempotency operation failed: " + e.getMessage()); + } + } + + /** + * Makes a function with one parameter idempotent with support for generic return types. + * The parameter is used as the idempotency key. + * + * <p>Example usage:</p> + * <pre>{@code + * Map<String, Basket> result = Idempotency.makeIdempotent( + * this::processProduct, + * product, + * new TypeReference<Map<String, Basket>>() {} + * ); + * }</pre> + * + * @param function the function to make idempotent (method reference) + * @param arg the argument to pass to the function (also used as idempotency key) + * @param typeRef the TypeReference for deserialization of generic types + * @param <T> the argument type + * @param <R> the return type + * @return the result of the function execution (either fresh or cached) + */ + public static <T, R> R makeIdempotent(Function<T, R> function, T arg, TypeReference<R> typeRef) { + return makeIdempotent(DEFAULT_FUNCTION_NAME, arg, () -> function.apply(arg), typeRef); + } } diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java index 9d5c66cac..0d9504483 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/IdempotencyConfig.java @@ -25,7 +25,7 @@ /** * Configuration of the idempotency feature. Use the {@link Builder} to create an instance. */ -public class IdempotencyConfig { +public final class IdempotencyConfig { private final int localCacheMaxItems; private final boolean useLocalCache; private final long expirationInSeconds; @@ -34,7 +34,7 @@ public class IdempotencyConfig { private final boolean throwOnNoIdempotencyKey; private final String hashFunction; private final BiFunction<Object, DataRecord, Object> responseHook; - private Context lambdaContext; + private final InheritableThreadLocal<Context> lambdaContext = new InheritableThreadLocal<>(); private IdempotencyConfig(String eventKeyJMESPath, String payloadValidationJMESPath, boolean throwOnNoIdempotencyKey, boolean useLocalCache, int localCacheMaxItems, @@ -87,11 +87,11 @@ public String getHashFunction() { } public Context getLambdaContext() { - return lambdaContext; + return lambdaContext.get(); } public void setLambdaContext(Context lambdaContext) { - this.lambdaContext = lambdaContext; + this.lambdaContext.set(lambdaContext); } public BiFunction<Object, DataRecord, Object> getResponseHook() { diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java index 0466f244f..77d3d49b0 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java @@ -21,12 +21,11 @@ import java.util.OptionalInt; import java.util.function.BiFunction; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.amazonaws.services.lambda.runtime.Context; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import software.amazon.lambda.powertools.idempotency.Idempotency; @@ -50,13 +49,21 @@ public class IdempotencyHandler { private static final Logger LOG = LoggerFactory.getLogger(IdempotencyHandler.class); private static final int MAX_RETRIES = 2; - private final ProceedingJoinPoint pjp; + private final IdempotentFunction<?> function; + private final TypeReference<?> returnTypeRef; private final JsonNode data; private final BasePersistenceStore persistenceStore; private final Context lambdaContext; - public IdempotencyHandler(ProceedingJoinPoint pjp, String functionName, JsonNode payload, Context lambdaContext) { - this.pjp = pjp; + public IdempotencyHandler(IdempotentFunction<?> function, Class<?> returnType, String functionName, + JsonNode payload, Context lambdaContext) { + this(function, JsonConfig.toTypeReference(returnType), functionName, payload, lambdaContext); + } + + public IdempotencyHandler(IdempotentFunction<?> function, TypeReference<?> returnTypeRef, String functionName, + JsonNode payload, Context lambdaContext) { + this.function = function; + this.returnTypeRef = returnTypeRef; this.data = payload; this.lambdaContext = lambdaContext; persistenceStore = Idempotency.getInstance().getPersistenceStore(); @@ -171,7 +178,6 @@ private Object handleForStatus(DataRecord record) { "Execution already in progress with idempotency key: " + record.getIdempotencyKey()); } - Class<?> returnType = ((MethodSignature) pjp.getSignature()).getReturnType(); try { LOG.debug("Response for key '{}' retrieved from idempotency store, skipping the function", record.getIdempotencyKey()); @@ -180,12 +186,12 @@ private Object handleForStatus(DataRecord record) { .getResponseHook(); final Object responseData; - if (returnType.equals(String.class)) { + if (String.class.equals(returnTypeRef.getType())) { // Primitive String data will be returned raw and not de-serialized from JSON. responseData = record.getResponseData(); } else { - responseData = JsonConfig.get().getObjectMapper().reader().readValue(record.getResponseData(), - returnType); + responseData = JsonConfig.get().getObjectMapper().readValue(record.getResponseData(), + returnTypeRef); } if (responseHook != null) { @@ -196,14 +202,14 @@ private Object handleForStatus(DataRecord record) { return responseData; } catch (Exception e) { throw new IdempotencyPersistenceLayerException( - "Unable to get function response as " + returnType.getSimpleName(), e); + "Unable to get function response as " + returnTypeRef.getType().getTypeName(), e); } } private Object getFunctionResponse() throws Throwable { Object response; try { - response = pjp.proceed(pjp.getArgs()); + response = function.execute(); } catch (Throwable handlerException) { // We need these nested blocks to preserve function's exception in case the persistence store operation // also raises an exception diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java index ea6d743f0..35c6dee40 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentAspect.java @@ -14,14 +14,21 @@ package software.amazon.lambda.powertools.idempotency.internal; -import com.amazonaws.services.lambda.runtime.Context; -import com.fasterxml.jackson.databind.JsonNode; +import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnRequestHandler; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; + import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.DeclarePrecedence; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; + +import com.amazonaws.services.lambda.runtime.Context; +import com.fasterxml.jackson.databind.JsonNode; + import software.amazon.lambda.powertools.idempotency.Constants; import software.amazon.lambda.powertools.idempotency.Idempotency; import software.amazon.lambda.powertools.idempotency.IdempotencyKey; @@ -29,11 +36,6 @@ import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyConfigurationException; import software.amazon.lambda.powertools.utilities.JsonConfig; -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - -import static software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor.placedOnRequestHandler; - /** * Aspect that handles the {@link Idempotent} annotation. * It uses the {@link IdempotencyHandler} to actually do the job. @@ -42,14 +44,15 @@ // Idempotency annotation should come first before large message @DeclarePrecedence("software.amazon.lambda.powertools.idempotency.internal.IdempotentAspect, *") public class IdempotentAspect { - @SuppressWarnings({"EmptyMethod"}) + @SuppressWarnings({ "EmptyMethod" }) @Pointcut("@annotation(idempotent)") public void callAt(Idempotent idempotent) { + // Pointcut method - body intentionally empty } @Around(value = "callAt(idempotent) && execution(@Idempotent * *.*(..))", argNames = "pjp,idempotent") public Object around(ProceedingJoinPoint pjp, - Idempotent idempotent) throws Throwable { + Idempotent idempotent) throws Throwable { String idempotencyDisabledEnv = System.getenv().get(Constants.IDEMPOTENCY_DISABLED_ENV); if (idempotencyDisabledEnv != null && !"false".equalsIgnoreCase(idempotencyDisabledEnv)) { @@ -76,7 +79,12 @@ public Object around(ProceedingJoinPoint pjp, lambdaContext = Idempotency.getInstance().getConfig().getLambdaContext(); } - IdempotencyHandler idempotencyHandler = new IdempotencyHandler(pjp, method.getName(), payload, lambdaContext); + IdempotencyHandler idempotencyHandler = new IdempotencyHandler( + () -> pjp.proceed(pjp.getArgs()), + method.getReturnType(), + method.getName(), + payload, + lambdaContext); return idempotencyHandler.handle(); } diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentFunction.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentFunction.java new file mode 100644 index 000000000..2ff2071b0 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotentFunction.java @@ -0,0 +1,30 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.idempotency.internal; + +/** + * Functional interface for idempotent function execution. + * <p> + * This interface is similar to {@link java.util.concurrent.Callable} but throws {@link Throwable} + * instead of {@link Exception}. This is necessary to support AspectJ's {@code ProceedingJoinPoint.proceed()} + * which throws {@code Throwable}, allowing exceptions to bubble up naturally without wrapping. + * + * @param <T> the return type of the function + */ +@FunctionalInterface +public interface IdempotentFunction<T> { + @SuppressWarnings("java:S112") // Throwable is required for AspectJ compatibility + T execute() throws Throwable; +} diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java index b57ad2977..a3bf1c5ff 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/cache/LRUCache.java @@ -35,7 +35,7 @@ public LRUCache(int capacity) { } @Override - protected boolean removeEldestEntry(Map.Entry entry) { - return (size() > this.capacity); + protected boolean removeEldestEntry(Map.Entry<K, V> entry) { + return size() > this.capacity; } } diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java new file mode 100644 index 000000000..10664a25b --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/IdempotencyTest.java @@ -0,0 +1,311 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.idempotency; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import java.util.HashMap; +import java.util.Map; +import java.util.OptionalInt; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.amazonaws.services.lambda.runtime.Context; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; + +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; +import software.amazon.lambda.powertools.idempotency.handlers.IdempotencyFunctionalFunction; +import software.amazon.lambda.powertools.idempotency.handlers.IdempotencyMultiArgFunctionalFunction; +import software.amazon.lambda.powertools.idempotency.model.Basket; +import software.amazon.lambda.powertools.idempotency.model.Product; +import software.amazon.lambda.powertools.idempotency.persistence.BasePersistenceStore; +import software.amazon.lambda.powertools.idempotency.testutils.InMemoryPersistenceStore; + +@ExtendWith(MockitoExtension.class) +class IdempotencyTest { + + private Context context = new TestLambdaContext(); + + @Mock + private BasePersistenceStore store; + + @Test + void firstCall_shouldPutInStore() { + Idempotency.config() + .withPersistenceStore(store) + .withConfig(IdempotencyConfig.builder() + .withEventKeyJMESPath("id") + .build()) + .configure(); + + IdempotencyFunctionalFunction function = new IdempotencyFunctionalFunction(); + + Product p = new Product(42, "fake product", 12); + Basket basket = function.handleRequest(p, context); + + assertThat(function.processCalled()).isTrue(); + assertThat(basket.getProducts()).hasSize(1); + + ArgumentCaptor<JsonNode> nodeCaptor = ArgumentCaptor.forClass(JsonNode.class); + ArgumentCaptor<OptionalInt> expiryCaptor = ArgumentCaptor.forClass(OptionalInt.class); + verify(store).saveInProgress(nodeCaptor.capture(), any(), expiryCaptor.capture()); + assertThat(nodeCaptor.getValue().get("id").asLong()).isEqualTo(p.getId()); + assertThat(nodeCaptor.getValue().get("name").asText()).isEqualTo(p.getName()); + assertThat(nodeCaptor.getValue().get("price").asDouble()).isEqualTo(p.getPrice()); + assertThat(expiryCaptor.getValue().orElse(-1)).isEqualTo(30000); + + ArgumentCaptor<Basket> resultCaptor = ArgumentCaptor.forClass(Basket.class); + verify(store).saveSuccess(any(), resultCaptor.capture(), any()); + assertThat(resultCaptor.getValue()).isEqualTo(basket); + } + + @Test + void testMakeIdempotentWithFunctionName() throws Throwable { + BasePersistenceStore spyStore = spy(BasePersistenceStore.class); + Idempotency.config() + .withPersistenceStore(spyStore) + .configure(); + Idempotency.registerLambdaContext(context); + + String result = Idempotency.makeIdempotent("myFunction", "test-key", () -> "test-result", + String.class); + + assertThat(result).isEqualTo("test-result"); + + ArgumentCaptor<String> functionNameCaptor = ArgumentCaptor.forClass(String.class); + verify(spyStore).configure(any(), functionNameCaptor.capture()); + assertThat(functionNameCaptor.getValue()).isEqualTo("myFunction"); + } + + @Test + void testMakeIdempotentWithMethodReferenceUsesDefaultName() throws Throwable { + BasePersistenceStore spyStore = spy(BasePersistenceStore.class); + Idempotency.config() + .withPersistenceStore(spyStore) + .configure(); + Idempotency.registerLambdaContext(context); + + String result = Idempotency.makeIdempotent("test-key", this::helperMethod, String.class); + + assertThat(result).isEqualTo("helper-result"); + + ArgumentCaptor<String> functionNameCaptor = ArgumentCaptor.forClass(String.class); + verify(spyStore).configure(any(), functionNameCaptor.capture()); + assertThat(functionNameCaptor.getValue()).isEqualTo("function"); + } + + private String helperMethod() { + return "helper-result"; + } + + @Test + void testMakeIdempotentWithFunctionOverload() throws Throwable { + BasePersistenceStore spyStore = spy(BasePersistenceStore.class); + Idempotency.config() + .withPersistenceStore(spyStore) + .configure(); + Idempotency.registerLambdaContext(context); + + Product p = new Product(42, "test product", 10); + Basket result = Idempotency.makeIdempotent(this::processProduct, p, Basket.class); + + assertThat(result.getProducts()).hasSize(1); + assertThat(result.getProducts().get(0)).isEqualTo(p); + + ArgumentCaptor<String> functionNameCaptor = ArgumentCaptor.forClass(String.class); + verify(spyStore).configure(any(), functionNameCaptor.capture()); + assertThat(functionNameCaptor.getValue()).isEqualTo("function"); + + ArgumentCaptor<JsonNode> nodeCaptor = ArgumentCaptor.forClass(JsonNode.class); + verify(spyStore).saveInProgress(nodeCaptor.capture(), any(), any()); + assertThat(nodeCaptor.getValue().get("id").asLong()).isEqualTo(p.getId()); + } + + private Basket processProduct(Product product) { + Basket basket = new Basket(); + basket.add(product); + return basket; + } + + @Test + void firstCall_withExplicitIdempotencyKey_shouldPutInStore() { + Idempotency.config() + .withPersistenceStore(store) + .configure(); + + IdempotencyMultiArgFunctionalFunction function = new IdempotencyMultiArgFunctionalFunction(); + + Product p = new Product(42, "fake product", 12); + Basket basket = function.handleRequest(p, context); + + assertThat(function.processCalled()).isTrue(); + assertThat(function.getExtraData()).isEqualTo("extra-data"); + assertThat(basket.getProducts()).hasSize(1); + + ArgumentCaptor<JsonNode> nodeCaptor = ArgumentCaptor.forClass(JsonNode.class); + verify(store).saveInProgress(nodeCaptor.capture(), any(), any()); + assertThat(nodeCaptor.getValue().asLong()).isEqualTo(p.getId()); + + ArgumentCaptor<Basket> resultCaptor = ArgumentCaptor.forClass(Basket.class); + verify(store).saveSuccess(any(), resultCaptor.capture(), any()); + assertThat(resultCaptor.getValue()).isEqualTo(basket); + } + + @Test + void secondCall_shouldRetrieveFromCacheAndDeserialize() throws Throwable { + InMemoryPersistenceStore inMemoryStore = new InMemoryPersistenceStore(); + + Idempotency.config() + .withPersistenceStore(inMemoryStore) + .configure(); + Idempotency.registerLambdaContext(context); + + Product p = new Product(42, "test product", 10); + int[] callCount = { 0 }; + + // First call - executes function and stores result + Basket result1 = Idempotency.makeIdempotent(p, () -> { + callCount[0]++; + return processProduct(p); + }, Basket.class); + assertThat(result1.getProducts()).hasSize(1); + assertThat(callCount[0]).isEqualTo(1); + + // Second call - should retrieve from cache, deserialize, and NOT execute function + Basket result2 = Idempotency.makeIdempotent(p, () -> { + callCount[0]++; + return processProduct(p); + }, Basket.class); + assertThat(result2.getProducts()).hasSize(1); + assertThat(result2.getProducts().get(0).getId()).isEqualTo(42); + assertThat(result2.getProducts().get(0).getName()).isEqualTo("test product"); + assertThat(callCount[0]).isEqualTo(1); // Function should NOT be called again + } + + @Test + void concurrentInvocations_shouldNotLeakContext() throws Exception { + Idempotency.config() + .withPersistenceStore(store) + .configure(); + + IdempotencyMultiArgFunctionalFunction function = new IdempotencyMultiArgFunctionalFunction(); + + // GIVEN + int threadCount = 10; + Thread[] threads = new Thread[threadCount]; + Context[] capturedContexts = new Context[threadCount]; + int[] capturedRemainingTimes = new int[threadCount]; + boolean[] success = new boolean[threadCount]; + + // WHEN - Multiple threads call handleRequest with different contexts + for (int i = 0; i < threadCount; i++) { + final int threadIndex = i; + final int expectedTime = (i + 1) * 2000; // 2000, 4000, 6000, ..., 20000 + + final Context threadContext = new TestLambdaContext() { + @Override + public int getRemainingTimeInMillis() { + return expectedTime; + } + }; + + threads[i] = new Thread(() -> { + try { + Product p = new Product(threadIndex, "product" + threadIndex, 10); + function.handleRequest(p, threadContext); + + // Capture the context that was actually stored in ThreadLocal by this thread + Context captured = Idempotency.getInstance().getConfig().getLambdaContext(); + capturedContexts[threadIndex] = captured; + capturedRemainingTimes[threadIndex] = captured != null ? captured.getRemainingTimeInMillis() : -1; + success[threadIndex] = true; + } catch (Exception e) { + success[threadIndex] = false; + } + }); + } + + // Start all threads + for (Thread thread : threads) { + thread.start(); + } + + // Wait for all threads to complete + for (Thread thread : threads) { + thread.join(); + } + + // THEN - All threads should complete successfully + for (boolean result : success) { + assertThat(result).isTrue(); + } + + // THEN - Each thread should have captured its own context (no leakage) + for (int i = 0; i < threadCount; i++) { + int expectedTime = (i + 1) * 2000; + assertThat(capturedRemainingTimes[i]) + .as("Thread %d should have remaining time %d", i, expectedTime) + .isEqualTo(expectedTime); + assertThat(capturedContexts[i]).as("Thread %d should have non-null context", i).isNotNull(); + } + } + + @Test + void testMakeIdempotentWithGenericType() throws Throwable { + InMemoryPersistenceStore inMemoryStore = new InMemoryPersistenceStore(); + + Idempotency.config() + .withPersistenceStore(inMemoryStore) + .configure(); + Idempotency.registerLambdaContext(context); + + int[] callCount = { 0 }; + + // First call - executes function and stores result + Map<String, Basket> result1 = Idempotency.makeIdempotent("test-key", () -> { + callCount[0]++; + Map<String, Basket> map = new HashMap<>(); + Basket basket = new Basket(); + basket.add(new Product(1, "product1", 10)); + map.put("basket1", basket); + return map; + }, new TypeReference<Map<String, Basket>>() { + }); + + assertThat(result1).hasSize(1); + assertThat(result1.get("basket1").getProducts()).hasSize(1); + assertThat(callCount[0]).isEqualTo(1); + + // Second call - should retrieve from cache and deserialize correctly + Map<String, Basket> result2 = Idempotency.makeIdempotent("test-key", () -> { + callCount[0]++; + return new HashMap<>(); + }, new TypeReference<Map<String, Basket>>() { + }); + + assertThat(result2).hasSize(1); + assertThat(result2.get("basket1").getProducts()).hasSize(1); + assertThat(result2.get("basket1").getProducts().get(0).getName()).isEqualTo("product1"); + assertThat(callCount[0]).isEqualTo(1); // Function should NOT be called again + } +} diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunctionalFunction.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunctionalFunction.java new file mode 100644 index 000000000..c2a85d178 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyFunctionalFunction.java @@ -0,0 +1,48 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.idempotency.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.idempotency.Idempotency; +import software.amazon.lambda.powertools.idempotency.model.Basket; +import software.amazon.lambda.powertools.idempotency.model.Product; + +/** + * Lambda function using Idempotency functional API without AspectJ annotations + */ +public class IdempotencyFunctionalFunction implements RequestHandler<Product, Basket> { + + private boolean processCalled = false; + + public boolean processCalled() { + return processCalled; + } + + @Override + public Basket handleRequest(Product input, Context context) { + Idempotency.registerLambdaContext(context); + + return Idempotency.makeIdempotent(this::process, input, Basket.class); + } + + private Basket process(Product input) { + processCalled = true; + Basket b = new Basket(); + b.add(input); + return b; + } +} diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyMultiArgFunctionalFunction.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyMultiArgFunctionalFunction.java new file mode 100644 index 000000000..42e75fd55 --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/handlers/IdempotencyMultiArgFunctionalFunction.java @@ -0,0 +1,54 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.idempotency.handlers; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; + +import software.amazon.lambda.powertools.idempotency.Idempotency; +import software.amazon.lambda.powertools.idempotency.model.Basket; +import software.amazon.lambda.powertools.idempotency.model.Product; + +/** + * Lambda function using Idempotency functional API with explicit idempotency key + */ +public class IdempotencyMultiArgFunctionalFunction implements RequestHandler<Product, Basket> { + + private boolean processCalled = false; + private String extraData; + + public boolean processCalled() { + return processCalled; + } + + public String getExtraData() { + return extraData; + } + + @Override + public Basket handleRequest(Product input, Context context) { + Idempotency.registerLambdaContext(context); + + return Idempotency.makeIdempotent(input.getId(), () -> process(input, "extra-data"), Basket.class); + } + + private Basket process(Product input, String extraData) { + processCalled = true; + this.extraData = extraData; + Basket b = new Basket(); + b.add(input); + return b; + } +} diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java index 0ccb1e5aa..384a20b2a 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyAspectTest.java @@ -194,7 +194,7 @@ void secondCall_notExpired_shouldNotGetFromStoreIfPresentOnIdempotencyException( "Test message", new RuntimeException("Test Cause"), dr)) - .when(store).saveInProgress(any(), any(), any()); + .when(store).saveInProgress(any(), any(), any()); // WHEN IdempotencyEnabledFunction function = new IdempotencyEnabledFunction(); @@ -538,4 +538,73 @@ void idempotencyOnSubMethodVoid_shouldThrowException() { IdempotencyConfigurationException.class); } + @Test + void concurrentInvocations_shouldNotLeakContext() throws Exception { + Idempotency.config() + .withPersistenceStore(store) + .configure(); + + // Use IdempotencyInternalFunction which calls registerLambdaContext + IdempotencyInternalFunction function = new IdempotencyInternalFunction(true); + + // GIVEN + int threadCount = 10; + Thread[] threads = new Thread[threadCount]; + Context[] capturedContexts = new Context[threadCount]; + int[] capturedRemainingTimes = new int[threadCount]; + boolean[] success = new boolean[threadCount]; + + // WHEN - Multiple threads call handleRequest with different contexts + for (int i = 0; i < threadCount; i++) { + final int threadIndex = i; + final int expectedTime = (i + 1) * 1000; // 1000, 2000, 3000, ..., 10000 + + final Context threadContext = new TestLambdaContext() { + @Override + public int getRemainingTimeInMillis() { + return expectedTime; + } + }; + + threads[i] = new Thread(() -> { + try { + Product p = new Product(threadIndex, "product" + threadIndex, 10); + function.handleRequest(p, threadContext); + + // Capture the context that was actually stored in ThreadLocal by this thread + Context captured = Idempotency.getInstance().getConfig().getLambdaContext(); + capturedContexts[threadIndex] = captured; + capturedRemainingTimes[threadIndex] = captured != null ? captured.getRemainingTimeInMillis() : -1; + success[threadIndex] = true; + } catch (Exception e) { + success[threadIndex] = false; + } + }); + } + + // Start all threads + for (Thread thread : threads) { + thread.start(); + } + + // Wait for all threads to complete + for (Thread thread : threads) { + thread.join(); + } + + // THEN - All threads should complete successfully + for (boolean result : success) { + assertThat(result).isTrue(); + } + + // THEN - Each thread should have captured its own context (no leakage) + for (int i = 0; i < threadCount; i++) { + int expectedTime = (i + 1) * 1000; + assertThat(capturedRemainingTimes[i]) + .as("Thread %d should have remaining time %d", i, expectedTime) + .isEqualTo(expectedTime); + assertThat(capturedContexts[i]).as("Thread %d should have non-null context", i).isNotNull(); + } + } + } diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/testutils/InMemoryPersistenceStore.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/testutils/InMemoryPersistenceStore.java new file mode 100644 index 000000000..5fec80a3c --- /dev/null +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/testutils/InMemoryPersistenceStore.java @@ -0,0 +1,58 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.idempotency.testutils; + +import java.time.Instant; +import java.util.HashMap; +import java.util.Map; + +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; +import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; +import software.amazon.lambda.powertools.idempotency.persistence.BasePersistenceStore; +import software.amazon.lambda.powertools.idempotency.persistence.DataRecord; + +/** + * In-memory implementation of BasePersistenceStore for testing purposes. + */ +public class InMemoryPersistenceStore extends BasePersistenceStore { + private final Map<String, DataRecord> data = new HashMap<>(); + + @Override + public DataRecord getRecord(String idempotencyKey) throws IdempotencyItemNotFoundException { + DataRecord dr = data.get(idempotencyKey); + if (dr == null) { + throw new IdempotencyItemNotFoundException(idempotencyKey); + } + return dr; + } + + @Override + public void putRecord(DataRecord dr, Instant now) throws IdempotencyItemAlreadyExistsException { + if (data.containsKey(dr.getIdempotencyKey())) { + throw new IdempotencyItemAlreadyExistsException(); + } + data.put(dr.getIdempotencyKey(), dr); + } + + @Override + public void updateRecord(DataRecord dr) { + data.put(dr.getIdempotencyKey(), dr); + } + + @Override + public void deleteRecord(String idempotencyKey) { + data.remove(idempotencyKey); + } +} diff --git a/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java b/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java index fc0f083e5..c6a986564 100644 --- a/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java +++ b/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java @@ -14,19 +14,23 @@ package software.amazon.lambda.powertools.utilities; +import java.lang.reflect.Type; +import java.util.function.Supplier; + import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.json.JsonMapper; + import io.burt.jmespath.JmesPath; import io.burt.jmespath.RuntimeConfiguration; import io.burt.jmespath.function.BaseFunction; import io.burt.jmespath.function.FunctionRegistry; import io.burt.jmespath.jackson.JacksonRuntime; -import java.util.function.Supplier; import software.amazon.lambda.powertools.utilities.jmespath.Base64Function; import software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunction; import software.amazon.lambda.powertools.utilities.jmespath.JsonFunction; @@ -51,8 +55,7 @@ public final class JsonConfig { private final FunctionRegistry customFunctions = defaultFunctions.extend( new Base64Function(), new Base64GZipFunction(), - new JsonFunction() - ); + new JsonFunction()); private final RuntimeConfiguration configuration = new RuntimeConfiguration.Builder() .withSilentTypeErrors(true) @@ -77,6 +80,23 @@ public ObjectMapper getObjectMapper() { return om.get(); } + /** + * Creates a TypeReference from a Class for use with Jackson deserialization. + * This is useful when you need to convert a Class to a TypeReference for generic type handling. + * + * @param clazz the class to convert to TypeReference + * @param <T> the type parameter + * @return a TypeReference wrapping the provided class + */ + public static <T> TypeReference<T> toTypeReference(Class<T> clazz) { + return new TypeReference<T>() { + @Override + public Type getType() { + return clazz; + } + }; + } + /** * Return the JmesPath used to select sub node of Json * @@ -103,7 +123,7 @@ public <T extends BaseFunction> void addFunction(T function) { jmesPath = new JacksonRuntime(updatedConfig, getObjectMapper()); } - private static class ConfigHolder { + private static final class ConfigHolder { private static final JsonConfig instance = new JsonConfig(); } } From dcb2b605b13cfa9391ca79795fbf7955b6cf8e74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 14:23:48 +0100 Subject: [PATCH 503/577] chore: bump aws.sdk.version from 2.36.2 to 2.37.1 (#2246) Bumps `aws.sdk.version` from 2.36.2 to 2.37.1. Updates `software.amazon.awssdk:url-connection-client` from 2.36.2 to 2.37.1 Updates `software.amazon.awssdk:sdk-core` from 2.36.2 to 2.37.1 Updates `software.amazon.awssdk:s3` from 2.36.2 to 2.37.1 Updates `software.amazon.awssdk:kinesis` from 2.36.2 to 2.37.1 Updates `software.amazon.awssdk:sqs` from 2.36.2 to 2.37.1 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.36.2 to 2.37.1 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.37.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.37.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.37.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.37.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.37.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.37.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index a5d14f0c1..19b404c82 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.36.2</sdk.version> + <sdk.version>2.37.1</sdk.version> </properties> <dependencies> From 74ca992a317346bd991024ad8988a117e1466f0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 14:24:13 +0100 Subject: [PATCH 504/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.221.0 to 2.221.1 (#2248) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.221.0 to 2.221.1. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/v2.221.1/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.221.0...v2.221.1) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.221.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 42777cc96..ce887884c 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.5.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.221.0</cdk.version> + <cdk.version>2.221.1</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.14.0</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 046592e1c..557611a93 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.2</constructs.version> - <cdk.version>2.221.0</cdk.version> + <cdk.version>2.221.1</cdk.version> </properties> <dependencies> From 6f2f262acbe248b0a6e408386be82d8a85b6d393 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 14:24:46 +0100 Subject: [PATCH 505/577] chore: bump github/codeql-action from 4.31.0 to 4.31.1 (#2249) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.0 to 4.31.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4e94bd11f71e507f7f87df81788dff88d1dacbfb...5fe9434cd24fe243e33e7f3305f8a5b519b70280) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 4ca976695..632e4b0d9 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v3.29.5 + uses: github/codeql-action/upload-sarif@5fe9434cd24fe243e33e7f3305f8a5b519b70280 # v3.29.5 with: sarif_file: results.sarif From 6e4701c75da366465b25cac43ea7669aa96bf616 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 14:25:00 +0100 Subject: [PATCH 506/577] chore: bump aws.sdk.version from 2.36.2 to 2.36.3 (#2242) Bumps `aws.sdk.version` from 2.36.2 to 2.36.3. Updates `software.amazon.awssdk:bom` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:http-client-spi` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:url-connection-client` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:s3` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:dynamodb` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:lambda` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:kinesis` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:cloudwatch` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:xray` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:sqs` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:cloudformation` from 2.36.2 to 2.36.3 Updates `software.amazon.awssdk:sts` from 2.36.2 to 2.36.3 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.36.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.36.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.36.3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.36.3 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.36.3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.36.3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.36.3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.36.3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.36.3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.36.3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.36.3 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.36.3 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 3d9bb3c67..7f9bbc6fa 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.36.2</aws.sdk.version> + <aws.sdk.version>2.36.3</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 878826077..449baba05 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.0</jackson.version> - <aws.sdk.version>2.36.2</aws.sdk.version> + <aws.sdk.version>2.36.3</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 7a7da9e02..86e867548 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.36.2</aws.sdk.version> + <aws.sdk.version>2.36.3</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From e1dbd95997b00704cf509cf3fe04dd7b2d6c679b Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Fri, 31 Oct 2025 11:40:40 +0100 Subject: [PATCH 507/577] fix(serialization): Fix Joda time serialization for AWS events. (#2252) --- powertools-serialization/pom.xml | 4 + .../powertools/utilities/JsonConfig.java | 5 +- .../utilities/EventDeserializerTest.java | 198 ++++++++++++++---- .../jmespath/Base64FunctionTest.java | 19 +- .../jmespath/Base64GZipFunctionTest.java | 30 +-- .../utilities/jmespath/JsonFunctionTest.java | 13 +- 6 files changed, 204 insertions(+), 65 deletions(-) diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 89fb2056a..1ed2ee259 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -47,6 +47,10 @@ <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-joda</artifactId> + </dependency> <!-- Test dependencies --> <dependency> diff --git a/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java b/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java index c6a986564..ac10412fa 100644 --- a/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java +++ b/powertools-serialization/src/main/java/software/amazon/lambda/powertools/utilities/JsonConfig.java @@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.datatype.joda.JodaModule; import io.burt.jmespath.JmesPath; import io.burt.jmespath.RuntimeConfiguration; @@ -41,11 +42,13 @@ public final class JsonConfig { // Don't throw an exception when json has extra fields you are not serializing on. .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) // Ignore null values when writing json. - .serializationInclusion(JsonInclude.Include.NON_NULL) + .defaultPropertyInclusion( + JsonInclude.Value.construct(JsonInclude.Include.NON_NULL, JsonInclude.Include.USE_DEFAULTS)) // Write times as a String instead of a Long so its human-readable. .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) // Sort fields in alphabetical order .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true) + .addModule(new JodaModule()) .build(); private static final ThreadLocal<ObjectMapper> om = ThreadLocal.withInitial(objectMapperSupplier); diff --git a/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/EventDeserializerTest.java b/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/EventDeserializerTest.java index 2914bd286..14fc32231 100644 --- a/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/EventDeserializerTest.java +++ b/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/EventDeserializerTest.java @@ -18,6 +18,13 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static software.amazon.lambda.powertools.utilities.EventDeserializer.extractDataFrom; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayV2HTTPEvent; import com.amazonaws.services.lambda.runtime.events.ActiveMQEvent; @@ -34,41 +41,37 @@ import com.amazonaws.services.lambda.runtime.events.SQSEvent; import com.amazonaws.services.lambda.runtime.events.ScheduledEvent; import com.amazonaws.services.lambda.runtime.tests.annotations.Event; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; +import com.fasterxml.jackson.databind.JsonNode; + import software.amazon.lambda.powertools.utilities.model.Order; import software.amazon.lambda.powertools.utilities.model.Product; -public class EventDeserializerTest { +class EventDeserializerTest { @Test - public void testDeserializeStringAsString_shouldReturnString() { + void testDeserializeStringAsString_shouldReturnString() { String stringEvent = "Hello World"; String result = extractDataFrom(stringEvent).as(String.class); assertThat(result).isEqualTo(stringEvent); } @Test - public void testDeserializeStringAsObject_shouldReturnObject() { + void testDeserializeStringAsObject_shouldReturnObject() { String productStr = "{\"id\":1234, \"name\":\"product\", \"price\":42}"; Product product = extractDataFrom(productStr).as(Product.class); assertProduct(product); } @Test - public void testDeserializeStringArrayAsList_shouldReturnList() { - String productStr = - "[{\"id\":1234, \"name\":\"product\", \"price\":42}, {\"id\":2345, \"name\":\"product2\", \"price\":43}]"; + void testDeserializeStringArrayAsList_shouldReturnList() { + String productStr = "[{\"id\":1234, \"name\":\"product\", \"price\":42}, {\"id\":2345, \"name\":\"product2\", \"price\":43}]"; List<Product> products = extractDataFrom(productStr).asListOf(Product.class); assertThat(products).hasSize(2); assertProduct(products.get(0)); } @Test - public void testDeserializeStringAsList_shouldThrowException() { + void testDeserializeStringAsList_shouldThrowException() { String productStr = "{\"id\":1234, \"name\":\"product\", \"price\":42}"; assertThatThrownBy(() -> extractDataFrom(productStr).asListOf(Product.class)) .isInstanceOf(EventDeserializationException.class) @@ -76,7 +79,7 @@ public void testDeserializeStringAsList_shouldThrowException() { } @Test - public void testDeserializeMapAsObject_shouldReturnObject() { + void testDeserializeMapAsObject_shouldReturnObject() { Map<String, Object> map = new HashMap<>(); map.put("id", 1234); map.put("name", "product"); @@ -87,21 +90,21 @@ public void testDeserializeMapAsObject_shouldReturnObject() { @ParameterizedTest @Event(value = "apigw_event.json", type = APIGatewayProxyRequestEvent.class) - public void testDeserializeAPIGWEventBodyAsObject_shouldReturnObject(APIGatewayProxyRequestEvent event) { + void testDeserializeAPIGWEventBodyAsObject_shouldReturnObject(APIGatewayProxyRequestEvent event) { Product product = extractDataFrom(event).as(Product.class); assertProduct(product); } @ParameterizedTest @Event(value = "sns_event.json", type = SNSEvent.class) - public void testDeserializeSNSEventMessageAsObject_shouldReturnObject(SNSEvent event) { + void testDeserializeSNSEventMessageAsObject_shouldReturnObject(SNSEvent event) { Product product = extractDataFrom(event).as(Product.class); assertProduct(product); } @ParameterizedTest @Event(value = "sqs_event.json", type = SQSEvent.class) - public void testDeserializeSQSEventMessageAsList_shouldReturnList(SQSEvent event) { + void testDeserializeSQSEventMessageAsList_shouldReturnList(SQSEvent event) { List<Product> products = extractDataFrom(event).asListOf(Product.class); assertThat(products).hasSize(2); assertProduct(products.get(0)); @@ -109,7 +112,7 @@ public void testDeserializeSQSEventMessageAsList_shouldReturnList(SQSEvent event @ParameterizedTest @Event(value = "kinesis_event.json", type = KinesisEvent.class) - public void testDeserializeKinesisEventMessageAsList_shouldReturnList(KinesisEvent event) { + void testDeserializeKinesisEventMessageAsList_shouldReturnList(KinesisEvent event) { List<Product> products = extractDataFrom(event).asListOf(Product.class); assertThat(products).hasSize(2); assertProduct(products.get(0)); @@ -117,7 +120,7 @@ public void testDeserializeKinesisEventMessageAsList_shouldReturnList(KinesisEve @ParameterizedTest @Event(value = "kafka_event.json", type = KafkaEvent.class) - public void testDeserializeKafkaEventMessageAsList_shouldReturnList(KafkaEvent event) { + void testDeserializeKafkaEventMessageAsList_shouldReturnList(KafkaEvent event) { List<Product> products = extractDataFrom(event).asListOf(Product.class); assertThat(products).hasSize(2); assertProduct(products.get(0)); @@ -125,7 +128,7 @@ public void testDeserializeKafkaEventMessageAsList_shouldReturnList(KafkaEvent e @ParameterizedTest @Event(value = "sqs_event.json", type = SQSEvent.class) - public void testDeserializeSQSEventMessageAsObject_shouldThrowException(SQSEvent event) { + void testDeserializeSQSEventMessageAsObject_shouldThrowException(SQSEvent event) { assertThatThrownBy(() -> extractDataFrom(event).as(Product.class)) .isInstanceOf(EventDeserializationException.class) .hasMessageContaining("consider using 'asListOf' instead"); @@ -133,7 +136,7 @@ public void testDeserializeSQSEventMessageAsObject_shouldThrowException(SQSEvent @ParameterizedTest @Event(value = "apigw_event.json", type = APIGatewayProxyRequestEvent.class) - public void testDeserializeAPIGatewayEventAsList_shouldThrowException(APIGatewayProxyRequestEvent event) { + void testDeserializeAPIGatewayEventAsList_shouldThrowException(APIGatewayProxyRequestEvent event) { assertThatThrownBy(() -> extractDataFrom(event).asListOf(Product.class)) .isInstanceOf(EventDeserializationException.class) .hasMessageContaining("consider using 'as' instead") @@ -142,14 +145,14 @@ public void testDeserializeAPIGatewayEventAsList_shouldThrowException(APIGateway @ParameterizedTest @Event(value = "custom_event_map.json", type = HashMap.class) - public void testDeserializeAPIGatewayMapEventAsList_shouldThrowException(Map<String, Order> event) { + void testDeserializeAPIGatewayMapEventAsList_shouldThrowException(Map<String, Order> event) { assertThatThrownBy(() -> extractDataFrom(event).asListOf(Order.class)) .isInstanceOf(EventDeserializationException.class) .hasMessage("The content of this event is not a list, consider using 'as' instead"); } @Test - public void testDeserializeEmptyEventAsList_shouldThrowException() { + void testDeserializeEmptyEventAsList_shouldThrowException() { assertThatThrownBy(() -> extractDataFrom(null).asListOf(Product.class)) .isInstanceOf(IllegalStateException.class) .hasMessage("Event content is null: the event may be malformed (missing fields)"); @@ -157,14 +160,14 @@ public void testDeserializeEmptyEventAsList_shouldThrowException() { @ParameterizedTest @Event(value = "apigw_event_no_body.json", type = APIGatewayProxyRequestEvent.class) - public void testDeserializeAPIGatewayNoBody_shouldThrowException(APIGatewayProxyRequestEvent event) { + void testDeserializeAPIGatewayNoBody_shouldThrowException(APIGatewayProxyRequestEvent event) { assertThatThrownBy(() -> extractDataFrom(event).as(Product.class)) .isInstanceOf(IllegalStateException.class) .hasMessage("Event content is null: the event may be malformed (missing fields)"); } @Test - public void testDeserializeAPIGatewayNoBodyAsList_shouldThrowException() { + void testDeserializeAPIGatewayNoBodyAsList_shouldThrowException() { assertThatThrownBy(() -> extractDataFrom(new Object()).asListOf(Product.class)) .isInstanceOf(EventDeserializationException.class) .hasMessage("The content of this event is not a list, consider using 'as' instead"); @@ -172,19 +175,18 @@ public void testDeserializeAPIGatewayNoBodyAsList_shouldThrowException() { @ParameterizedTest @Event(value = "sqs_event_no_body.json", type = SQSEvent.class) - public void testDeserializeSQSEventNoBody_shouldThrowException(SQSEvent event) { + void testDeserializeSQSEventNoBody_shouldThrowException(SQSEvent event) { List<Product> products = extractDataFrom(event).asListOf(Product.class); assertThat(products.get(0)).isNull(); } @Test - public void testDeserializeProductAsProduct_shouldReturnProduct() { + void testDeserializeProductAsProduct_shouldReturnProduct() { Product myProduct = new Product(1234, "product", 42); Product product = extractDataFrom(myProduct).as(Product.class); assertProduct(product); } - private void assertProduct(Product product) { assertThat(product) .isEqualTo(new Product(1234, "product", 42)) @@ -193,28 +195,28 @@ private void assertProduct(Product product) { @ParameterizedTest @Event(value = "scheduled_event.json", type = ScheduledEvent.class) - public void testDeserializeScheduledEventMessageAsObject_shouldReturnObject(ScheduledEvent event) { + void testDeserializeScheduledEventMessageAsObject_shouldReturnObject(ScheduledEvent event) { Product product = extractDataFrom(event).as(Product.class); assertProduct(product); } @ParameterizedTest @Event(value = "alb_event.json", type = ApplicationLoadBalancerRequestEvent.class) - public void testDeserializeALBEventMessageAsObjectShouldReturnObject(ApplicationLoadBalancerRequestEvent event) { + void testDeserializeALBEventMessageAsObjectShouldReturnObject(ApplicationLoadBalancerRequestEvent event) { Product product = extractDataFrom(event).as(Product.class); assertProduct(product); } @ParameterizedTest @Event(value = "cwl_event.json", type = CloudWatchLogsEvent.class) - public void testDeserializeCWLEventMessageAsObjectShouldReturnObject(CloudWatchLogsEvent event) { + void testDeserializeCWLEventMessageAsObjectShouldReturnObject(CloudWatchLogsEvent event) { Product product = extractDataFrom(event).as(Product.class); assertProduct(product); } @ParameterizedTest @Event(value = "kf_event.json", type = KinesisFirehoseEvent.class) - public void testDeserializeKFEventMessageAsListShouldReturnList(KinesisFirehoseEvent event) { + void testDeserializeKFEventMessageAsListShouldReturnList(KinesisFirehoseEvent event) { List<Product> products = extractDataFrom(event).asListOf(Product.class); assertThat(products).hasSize(1); assertProduct(products.get(0)); @@ -222,7 +224,7 @@ public void testDeserializeKFEventMessageAsListShouldReturnList(KinesisFirehoseE @ParameterizedTest @Event(value = "amq_event.json", type = ActiveMQEvent.class) - public void testDeserializeAMQEventMessageAsListShouldReturnList(ActiveMQEvent event) { + void testDeserializeAMQEventMessageAsListShouldReturnList(ActiveMQEvent event) { List<Product> products = extractDataFrom(event).asListOf(Product.class); assertThat(products).hasSize(1); assertProduct(products.get(0)); @@ -230,7 +232,7 @@ public void testDeserializeAMQEventMessageAsListShouldReturnList(ActiveMQEvent e @ParameterizedTest @Event(value = "rabbitmq_event.json", type = RabbitMQEvent.class) - public void testDeserializeRabbitMQEventMessageAsListShouldReturnList(RabbitMQEvent event) { + void testDeserializeRabbitMQEventMessageAsListShouldReturnList(RabbitMQEvent event) { List<Product> products = extractDataFrom(event).asListOf(Product.class); assertThat(products).hasSize(1); assertProduct(products.get(0)); @@ -238,7 +240,7 @@ public void testDeserializeRabbitMQEventMessageAsListShouldReturnList(RabbitMQEv @ParameterizedTest @Event(value = "kasip_event.json", type = KinesisAnalyticsStreamsInputPreprocessingEvent.class) - public void testDeserializeKasipEventMessageAsListShouldReturnList( + void testDeserializeKasipEventMessageAsListShouldReturnList( KinesisAnalyticsStreamsInputPreprocessingEvent event) { List<Product> products = extractDataFrom(event).asListOf(Product.class); assertThat(products).hasSize(1); @@ -247,7 +249,7 @@ public void testDeserializeKasipEventMessageAsListShouldReturnList( @ParameterizedTest @Event(value = "kafip_event.json", type = KinesisAnalyticsFirehoseInputPreprocessingEvent.class) - public void testDeserializeKafipEventMessageAsListShouldReturnList( + void testDeserializeKafipEventMessageAsListShouldReturnList( KinesisAnalyticsFirehoseInputPreprocessingEvent event) { List<Product> products = extractDataFrom(event).asListOf(Product.class); assertThat(products).hasSize(1); @@ -256,16 +258,138 @@ public void testDeserializeKafipEventMessageAsListShouldReturnList( @ParameterizedTest @Event(value = "apigwv2_event.json", type = APIGatewayV2HTTPEvent.class) - public void testDeserializeApiGWV2EventMessageAsObjectShouldReturnObject(APIGatewayV2HTTPEvent event) { + void testDeserializeApiGWV2EventMessageAsObjectShouldReturnObject(APIGatewayV2HTTPEvent event) { Product product = extractDataFrom(event).as(Product.class); assertProduct(product); } @ParameterizedTest @Event(value = "cfcr_event.json", type = CloudFormationCustomResourceEvent.class) - public void testDeserializeCfcrEventMessageAsObjectShouldReturnObject(CloudFormationCustomResourceEvent event) { + void testDeserializeCfcrEventMessageAsObjectShouldReturnObject(CloudFormationCustomResourceEvent event) { Product product = extractDataFrom(event).as(Product.class); assertProduct(product); } + @ParameterizedTest + @Event(value = "scheduled_event.json", type = ScheduledEvent.class) + void testSerializeScheduledEvent_shouldReturnValidJson(ScheduledEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("detail")).isTrue(); + } + + @ParameterizedTest + @Event(value = "apigw_event.json", type = APIGatewayProxyRequestEvent.class) + void testSerializeAPIGatewayEvent_shouldReturnValidJson(APIGatewayProxyRequestEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("body")).isTrue(); + } + + @ParameterizedTest + @Event(value = "sqs_event.json", type = SQSEvent.class) + void testSerializeSQSEvent_shouldReturnValidJson(SQSEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("records")).isTrue(); + } + + @ParameterizedTest + @Event(value = "sns_event.json", type = SNSEvent.class) + void testSerializeSNSEvent_shouldReturnValidJson(SNSEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("records")).isTrue(); + } + + @ParameterizedTest + @Event(value = "kinesis_event.json", type = KinesisEvent.class) + void testSerializeKinesisEvent_shouldReturnValidJson(KinesisEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("records")).isTrue(); + } + + @ParameterizedTest + @Event(value = "kafka_event.json", type = KafkaEvent.class) + void testSerializeKafkaEvent_shouldReturnValidJson(KafkaEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("records")).isTrue(); + } + + @ParameterizedTest + @Event(value = "alb_event.json", type = ApplicationLoadBalancerRequestEvent.class) + void testSerializeALBEvent_shouldReturnValidJson(ApplicationLoadBalancerRequestEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("body")).isTrue(); + } + + @ParameterizedTest + @Event(value = "cwl_event.json", type = CloudWatchLogsEvent.class) + void testSerializeCWLEvent_shouldReturnValidJson(CloudWatchLogsEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("awsLogs")).isTrue(); + } + + @ParameterizedTest + @Event(value = "kf_event.json", type = KinesisFirehoseEvent.class) + void testSerializeKFEvent_shouldReturnValidJson(KinesisFirehoseEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("records")).isTrue(); + } + + @ParameterizedTest + @Event(value = "amq_event.json", type = ActiveMQEvent.class) + void testSerializeAMQEvent_shouldReturnValidJson(ActiveMQEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("messages")).isTrue(); + } + + @ParameterizedTest + @Event(value = "rabbitmq_event.json", type = RabbitMQEvent.class) + void testSerializeRabbitMQEvent_shouldReturnValidJson(RabbitMQEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("rmqMessagesByQueue")).isTrue(); + } + + @ParameterizedTest + @Event(value = "kasip_event.json", type = KinesisAnalyticsStreamsInputPreprocessingEvent.class) + void testSerializeKasipEvent_shouldReturnValidJson(KinesisAnalyticsStreamsInputPreprocessingEvent event) + throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("records")).isTrue(); + } + + @ParameterizedTest + @Event(value = "kafip_event.json", type = KinesisAnalyticsFirehoseInputPreprocessingEvent.class) + void testSerializeKafipEvent_shouldReturnValidJson(KinesisAnalyticsFirehoseInputPreprocessingEvent event) + throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("records")).isTrue(); + } + + @ParameterizedTest + @Event(value = "apigwv2_event.json", type = APIGatewayV2HTTPEvent.class) + void testSerializeApiGWV2Event_shouldReturnValidJson(APIGatewayV2HTTPEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("body")).isTrue(); + } + + @ParameterizedTest + @Event(value = "cfcr_event.json", type = CloudFormationCustomResourceEvent.class) + void testSerializeCfcrEvent_shouldReturnValidJson(CloudFormationCustomResourceEvent event) throws Exception { + String json = JsonConfig.get().getObjectMapper().valueToTree(event).toString(); + JsonNode parsed = JsonConfig.get().getObjectMapper().readTree(json); + assertThat(parsed.has("resourceProperties")).isTrue(); + } + } diff --git a/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/Base64FunctionTest.java b/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/Base64FunctionTest.java index d86af6671..478d3477c 100644 --- a/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/Base64FunctionTest.java +++ b/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/Base64FunctionTest.java @@ -16,21 +16,24 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.io.IOException; + +import org.junit.jupiter.api.Test; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeType; + import io.burt.jmespath.Expression; -import java.io.IOException; -import org.junit.jupiter.api.Test; import software.amazon.lambda.powertools.utilities.JsonConfig; -public class Base64FunctionTest { +class Base64FunctionTest { @Test - public void testPowertoolsBase64() throws IOException { - JsonNode event = - JsonConfig.get().getObjectMapper().readTree(this.getClass().getResourceAsStream("/custom_event.json")); - Expression<JsonNode> expression = - JsonConfig.get().getJmesPath().compile("basket.powertools_base64(hiddenProduct)"); + void testPowertoolsBase64() throws IOException { + JsonNode event = JsonConfig.get().getObjectMapper() + .readTree(this.getClass().getResourceAsStream("/custom_event.json")); + Expression<JsonNode> expression = JsonConfig.get().getJmesPath() + .compile("basket.powertools_base64(hiddenProduct)"); JsonNode result = expression.search(event); assertThat(result.getNodeType()).isEqualTo(JsonNodeType.STRING); assertThat(result.asText()).isEqualTo("{\n" + diff --git a/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/Base64GZipFunctionTest.java b/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/Base64GZipFunctionTest.java index eeb605076..6f9f9a592 100644 --- a/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/Base64GZipFunctionTest.java +++ b/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/Base64GZipFunctionTest.java @@ -16,18 +16,21 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.io.IOException; + +import org.junit.jupiter.api.Test; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeType; + import io.burt.jmespath.Expression; import io.burt.jmespath.JmesPathType; -import java.io.IOException; -import org.junit.jupiter.api.Test; import software.amazon.lambda.powertools.utilities.JsonConfig; -public class Base64GZipFunctionTest { +class Base64GZipFunctionTest { @Test - public void testConstructor() { + void testConstructor() { Base64GZipFunction base64GZipFunction = new Base64GZipFunction(); assertThat(base64GZipFunction.name()).isEqualTo("powertools_base64_gzip"); assertThat(base64GZipFunction.argumentConstraints().expectedType().toLowerCase()).isEqualTo( @@ -38,18 +41,18 @@ public void testConstructor() { } @Test - public void testPowertoolsGzip() throws IOException { + void testPowertoolsGzip() throws IOException { JsonNode event = JsonConfig.get().getObjectMapper() .readTree(this.getClass().getResourceAsStream("/custom_event_gzip.json")); - Expression<JsonNode> expression = - JsonConfig.get().getJmesPath().compile("basket.powertools_base64_gzip(hiddenProduct)"); + Expression<JsonNode> expression = JsonConfig.get().getJmesPath() + .compile("basket.powertools_base64_gzip(hiddenProduct)"); JsonNode result = expression.search(event); assertThat(result.getNodeType()).isEqualTo(JsonNodeType.STRING); assertThat(result.asText()).isEqualTo("{ \"id\": 43242, \"name\": \"FooBar XY\", \"price\": 258}"); } @Test - public void testPowertoolsGzipEmptyJsonAttribute() throws IOException { + void testPowertoolsGzipEmptyJsonAttribute() throws IOException { JsonNode event = JsonConfig.get().getObjectMapper() .readTree(this.getClass().getResourceAsStream("/custom_event_gzip.json")); Expression<JsonNode> expression = JsonConfig.get().getJmesPath().compile("basket.powertools_base64_gzip('')"); @@ -58,7 +61,7 @@ public void testPowertoolsGzipEmptyJsonAttribute() throws IOException { } @Test - public void testPowertoolsGzipWrongArgumentType() throws IOException { + void testPowertoolsGzipWrongArgumentType() throws IOException { JsonNode event = JsonConfig.get().getObjectMapper() .readTree(this.getClass().getResourceAsStream("/custom_event_gzip.json")); Expression<JsonNode> expression = JsonConfig.get().getJmesPath().compile("basket.powertools_base64_gzip(null)"); @@ -68,21 +71,20 @@ public void testPowertoolsGzipWrongArgumentType() throws IOException { } @Test - public void testBase64GzipDecompressNull() { + void testBase64GzipDecompressNull() { String result = Base64GZipFunction.decompress(null); assertThat(result).isNull(); } @Test - public void testPowertoolsGzipNotCompressedJsonAttribute() throws IOException { + void testPowertoolsGzipNotCompressedJsonAttribute() throws IOException { JsonNode event = JsonConfig.get().getObjectMapper() .readTree(this.getClass().getResourceAsStream("/custom_event_gzip.json")); - Expression<JsonNode> expression = - JsonConfig.get().getJmesPath().compile("basket.powertools_base64_gzip(encodedString)"); + Expression<JsonNode> expression = JsonConfig.get().getJmesPath() + .compile("basket.powertools_base64_gzip(encodedString)"); JsonNode result = expression.search(event); assertThat(result.getNodeType()).isEqualTo(JsonNodeType.STRING); assertThat(result.asText()).isEqualTo("test"); } - } diff --git a/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/JsonFunctionTest.java b/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/JsonFunctionTest.java index 0bfb635fa..028dba9ea 100644 --- a/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/JsonFunctionTest.java +++ b/powertools-serialization/src/test/java/software/amazon/lambda/powertools/utilities/jmespath/JsonFunctionTest.java @@ -16,17 +16,20 @@ import static org.assertj.core.api.Assertions.assertThat; +import java.io.IOException; + +import org.junit.jupiter.api.Test; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.JsonNodeType; + import io.burt.jmespath.Expression; -import java.io.IOException; -import org.junit.jupiter.api.Test; import software.amazon.lambda.powertools.utilities.JsonConfig; -public class JsonFunctionTest { +class JsonFunctionTest { @Test - public void testJsonFunction() throws IOException { + void testJsonFunction() throws IOException { JsonNode event = JsonConfig.get().getObjectMapper() .readTree(this.getClass().getResourceAsStream("/custom_event_json.json")); Expression<JsonNode> expression = JsonConfig.get().getJmesPath().compile("powertools_json(body)"); @@ -38,7 +41,7 @@ public void testJsonFunction() throws IOException { } @Test - public void testJsonFunctionChild() throws IOException { + void testJsonFunctionChild() throws IOException { JsonNode event = JsonConfig.get().getObjectMapper() .readTree(this.getClass().getResourceAsStream("/custom_event_json.json")); Expression<JsonNode> expression = JsonConfig.get().getJmesPath().compile("powertools_json(body).list[0].item"); From f543b68171cb38df9dde72b2839aeb673e3e2b3d Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Fri, 31 Oct 2025 12:47:29 +0100 Subject: [PATCH 508/577] fix(logging): Fix bug where correlation_id field was missing in JSON structured output (#2256) --- .../json/resolver/PowertoolsResolver.java | 20 ++++++++++++++++++- .../src/main/resources/LambdaEcsLayout.json | 14 ++++++++----- .../src/main/resources/LambdaJsonLayout.json | 4 ++++ .../PowertoolsResolverArgumentsTest.java | 6 ++++-- .../logging/logback/LambdaEcsEncoder.java | 7 +++++++ .../internal/LambdaEcsEncoderTest.java | 4 +++- .../internal/LambdaJsonEncoderTest.java | 6 ++++-- 7 files changed, 50 insertions(+), 11 deletions(-) diff --git a/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java index 8ada50f49..cef5b86ee 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java +++ b/powertools-logging/powertools-logging-log4j/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolver.java @@ -15,6 +15,7 @@ package org.apache.logging.log4j.layout.template.json.resolver; import static java.util.Arrays.stream; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; @@ -112,7 +113,7 @@ public boolean isResolvable(LogEvent logEvent) { final String samplingRate = logEvent.getContextData().getValue(PowertoolsLoggedFields.SAMPLING_RATE.getName()); try { - return (null != samplingRate && Float.parseFloat(samplingRate) > 0.f); + return null != samplingRate && Float.parseFloat(samplingRate) > 0.f; } catch (NumberFormatException nfe) { return false; } @@ -142,6 +143,22 @@ public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { } }; + private static final EventResolver CORRELATION_ID_RESOLVER = new EventResolver() { + @Override + public boolean isResolvable(LogEvent logEvent) { + final String correlationId = + logEvent.getContextData().getValue(PowertoolsLoggedFields.CORRELATION_ID.getName()); + return null != correlationId; + } + + @Override + public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { + final String correlationId = + logEvent.getContextData().getValue(PowertoolsLoggedFields.CORRELATION_ID.getName()); + jsonWriter.writeString(correlationId); + } + }; + private static final EventResolver SERVICE_RESOLVER = (final LogEvent logEvent, final JsonWriter jsonWriter) -> { final String service = logEvent.getContextData().getValue(PowertoolsLoggedFields.SERVICE.getName()); @@ -214,6 +231,7 @@ public void resolve(LogEvent logEvent, JsonWriter jsonWriter) { { FUNCTION_REQUEST_ID.getName(), FUNCTION_REQ_RESOLVER }, { FUNCTION_COLD_START.getName(), COLD_START_RESOLVER }, { FUNCTION_TRACE_ID.getName(), XRAY_TRACE_RESOLVER }, + { CORRELATION_ID.getName(), CORRELATION_ID_RESOLVER }, { SAMPLING_RATE.getName(), SAMPLING_RATE_RESOLVER }, { "region", REGION_RESOLVER }, { "account_id", ACCOUNT_ID_RESOLVER } diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json index 19f13f199..58b30f60e 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaEcsLayout.json @@ -45,13 +45,13 @@ "$resolver": "thread", "field": "name" }, - "cloud.provider" : "aws", - "cloud.service.name" : "lambda", - "cloud.region" : { + "cloud.provider": "aws", + "cloud.service.name": "lambda", + "cloud.region": { "$resolver": "powertools", "field": "region" }, - "cloud.account.id" : { + "cloud.account.id": { "$resolver": "powertools", "field": "account_id" }, @@ -83,7 +83,11 @@ "$resolver": "powertools", "field": "xray_trace_id" }, + "correlation.id": { + "$resolver": "powertools", + "field": "correlation_id" + }, "": { "$resolver": "powertools" } -} \ No newline at end of file +} diff --git a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json index 8b811ee5f..793006502 100644 --- a/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json +++ b/powertools-logging/powertools-logging-log4j/src/main/resources/LambdaJsonLayout.json @@ -65,6 +65,10 @@ "$resolver": "powertools", "field": "xray_trace_id" }, + "correlation_id": { + "$resolver": "powertools", + "field": "correlation_id" + }, "": { "$resolver": "powertools" } diff --git a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java index 546d54579..573eaddbf 100644 --- a/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java +++ b/powertools-logging/powertools-logging-log4j/src/test/java/org/apache/logging/log4j/layout/template/json/resolver/PowertoolsResolverArgumentsTest.java @@ -90,7 +90,8 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { .contains( "\"input\":{\"awsRegion\":\"us-east-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") - .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); + .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"") + .contains("\"correlation_id\":\"1212abcd\""); // Reserved keys should be ignored PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> { assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\""); @@ -122,7 +123,8 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { .contains( "\"input\":{\"awsRegion\":\"us-east-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") - .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); + .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"") + .contains("\"correlation_id\":\"1212abcd\""); // Reserved keys should be ignored PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> { diff --git a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java index a1a7daff1..6a82d8e67 100644 --- a/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java +++ b/powertools-logging/powertools-logging-logback/src/main/java/software/amazon/lambda/powertools/logging/logback/LambdaEcsEncoder.java @@ -15,6 +15,7 @@ package software.amazon.lambda.powertools.logging.logback; import static java.nio.charset.StandardCharsets.UTF_8; +import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.CORRELATION_ID; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_ARN; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_COLD_START; import static software.amazon.lambda.powertools.logging.internal.PowertoolsLoggedFields.FUNCTION_MEMORY_SIZE; @@ -72,6 +73,7 @@ public class LambdaEcsEncoder extends EncoderBase<ILoggingEvent> { protected static final String FUNCTION_VERSION_ATTR_NAME = "faas.version"; protected static final String FUNCTION_MEMORY_ATTR_NAME = "faas.memory"; protected static final String FUNCTION_TRACE_ID_ATTR_NAME = "trace.id"; + protected static final String CORRELATION_ID_ATTR_NAME = "correlation.id"; protected static final String ECS_VERSION = "1.2.0"; protected static final String CLOUD_PROVIDER = "aws"; @@ -156,6 +158,11 @@ private void serializeFunctionInfo(JsonSerializer serializer, String arn, Map<St serializer.writeStringField(FUNCTION_COLD_START_ATTR_NAME, mdcPropertyMap.get(FUNCTION_COLD_START.getName())); serializer.writeRaw(','); serializer.writeStringField(FUNCTION_TRACE_ID_ATTR_NAME, mdcPropertyMap.get(FUNCTION_TRACE_ID.getName())); + String correlationId = mdcPropertyMap.get(CORRELATION_ID.getName()); + if (correlationId != null) { + serializer.writeRaw(','); + serializer.writeStringField(CORRELATION_ID_ATTR_NAME, correlationId); + } } } diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java index 74a11813b..30ede8ba8 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaEcsEncoderTest.java @@ -102,7 +102,8 @@ void shouldNotLogFunctionInfo() { // THEN assertThat(result).contains( - "\"faas.id\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"faas.name\":\"test-function\",\"faas.version\":\"1\",\"faas.memory\":\"128\",\"faas.execution\":\"test-request-id\",\"faas.coldstart\":\"false\""); + "\"faas.id\":\"arn:aws:lambda:us-east-1:123456789012:function:test\",\"faas.name\":\"test-function\",\"faas.version\":\"1\",\"faas.memory\":\"128\",\"faas.execution\":\"test-request-id\",\"faas.coldstart\":\"false\"") + .contains("\"correlation.id\":\"test-correlation-id\""); // WHEN (includeFaasInfo = false) encoder.setIncludeFaasInfo(false); @@ -175,6 +176,7 @@ private void setMDC() { MDC.put(PowertoolsLoggedFields.FUNCTION_COLD_START.getName(), "false"); MDC.put(PowertoolsLoggedFields.SAMPLING_RATE.getName(), "0.2"); MDC.put(PowertoolsLoggedFields.SERVICE.getName(), "Service"); + MDC.put(PowertoolsLoggedFields.CORRELATION_ID.getName(), "test-correlation-id"); } } diff --git a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java index 97770d3d0..16bd9e92a 100644 --- a/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java +++ b/powertools-logging/powertools-logging-logback/src/test/java/software/amazon/lambda/powertools/logging/internal/LambdaJsonEncoderTest.java @@ -135,7 +135,8 @@ void shouldLogArgumentsAsJsonWhenUsingRawJson() { "\"input\":{\"awsRegion\":\"eu-central-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") // Should auto-escape double quotes around id - .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); + .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"") + .contains("\"correlation_id\":\"1212abcd\""); // Reserved keys should be ignored PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> { assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\""); @@ -168,7 +169,8 @@ void shouldLogArgumentsAsJsonWhenUsingKeyValue() { "\"input\":{\"awsRegion\":\"eu-central-1\",\"body\":\"plop\",\"eventSource\":\"eb\",\"messageAttributes\":{\"keyAttribute\":{\"stringListValues\":[\"val1\",\"val2\",\"val3\"]}},\"messageId\":\"1212abcd\"}") .contains("\"message\":\"1212abcd\"") // Should auto-escape double quotes around id - .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\""); + .contains("\"message\":\"Message body = plop and id = \\\"1212abcd\\\"\"") + .contains("\"correlation_id\":\"1212abcd\""); // Reserved keys should be ignored PowertoolsLoggedFields.stringValues().stream().forEach(reservedKey -> { assertThat(contentOf(logFile)).doesNotContain("\"" + reservedKey + "\":\"shouldBeIgnored\""); From 71c632b70a4d1ec3146102e4c2ab5e3fa0f793d0 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Mon, 3 Nov 2025 11:42:16 +0100 Subject: [PATCH 509/577] feat(large-messages): Add function interface for Large Messages Utility (#2257) * Add functional API for LargeMessages utility. * Add E2E tests for functional large messages. * Use format specifiers for logging in LargeMessageE2ET.java. --- .../handlers/largemessage-functional/pom.xml | 46 +++ .../lambda/powertools/e2e/Function.java | 85 ++++++ .../src/main/resources/log4j2.xml | 16 + powertools-e2e-tests/handlers/pom.xml | 1 + .../lambda/powertools/LargeMessageE2ET.java | 62 ++-- powertools-large-messages/pom.xml | 18 +- .../largemessages/LargeMessage.java | 12 +- .../largemessages/LargeMessages.java | 156 ++++++++++ .../internal/LargeMessageAspect.java | 13 +- .../internal/LargeMessageFunction.java | 35 +++ .../internal/LargeMessageProcessor.java | 68 +++-- .../LargeMessageProcessorFactory.java | 7 +- .../largemessages/LargeMessagesTest.java | 287 ++++++++++++++++++ .../internal/LargeMessageAspectTest.java | 102 ++++--- .../test/resources/simplelogger.properties | 7 + 15 files changed, 810 insertions(+), 105 deletions(-) create mode 100644 powertools-e2e-tests/handlers/largemessage-functional/pom.xml create mode 100644 powertools-e2e-tests/handlers/largemessage-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java create mode 100644 powertools-e2e-tests/handlers/largemessage-functional/src/main/resources/log4j2.xml create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessages.java create mode 100644 powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageFunction.java create mode 100644 powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/LargeMessagesTest.java create mode 100644 powertools-large-messages/src/test/resources/simplelogger.properties diff --git a/powertools-e2e-tests/handlers/largemessage-functional/pom.xml b/powertools-e2e-tests/handlers/largemessage-functional/pom.xml new file mode 100644 index 000000000..4afb633f2 --- /dev/null +++ b/powertools-e2e-tests/handlers/largemessage-functional/pom.xml @@ -0,0 +1,46 @@ +<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 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>software.amazon.lambda</groupId> + <artifactId>e2e-test-handlers-parent</artifactId> + <version>2.5.0</version> + </parent> + + <artifactId>e2e-test-handler-largemessage-functional</artifactId> + <packaging>jar</packaging> + <name>E2E test handler – Large message functional</name> + + <dependencies> + <dependency> + <groupId>software.amazon.awssdk</groupId> + <artifactId>dynamodb</artifactId> + </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-large-messages</artifactId> + </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging-log4j</artifactId> + </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging</artifactId> + </dependency> + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-lambda-java-events</artifactId> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + </plugin> + </plugins> + </build> +</project> diff --git a/powertools-e2e-tests/handlers/largemessage-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java b/powertools-e2e-tests/handlers/largemessage-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java new file mode 100644 index 000000000..05a336500 --- /dev/null +++ b/powertools-e2e-tests/handlers/largemessage-functional/src/main/java/software/amazon/lambda/powertools/e2e/Function.java @@ -0,0 +1,85 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.e2e; + +import static software.amazon.lambda.powertools.logging.PowertoolsLogging.withLogging; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; +import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; + +import software.amazon.awssdk.http.urlconnection.UrlConnectionHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.dynamodb.DynamoDbClient; +import software.amazon.awssdk.services.dynamodb.model.AttributeValue; +import software.amazon.awssdk.services.dynamodb.model.PutItemRequest; +import software.amazon.awssdk.utils.BinaryUtils; +import software.amazon.awssdk.utils.Md5Utils; +import software.amazon.lambda.powertools.largemessages.LargeMessages; + +public class Function implements RequestHandler<SQSEvent, SQSBatchResponse> { + + private static final String TABLE_FOR_ASYNC_TESTS = System.getenv("TABLE_FOR_ASYNC_TESTS"); + private DynamoDbClient client; + + public Function() { + if (client == null) { + client = DynamoDbClient.builder() + .httpClient(UrlConnectionHttpClient.builder().build()) + .region(Region.of(System.getenv("AWS_REGION"))) + .build(); + } + } + + public SQSBatchResponse handleRequest(SQSEvent event, Context context) { + return withLogging(context, () -> { + for (SQSMessage message : event.getRecords()) { + LargeMessages.processLargeMessage(message, msg -> processRawMessage(msg, context)); + } + return SQSBatchResponse.builder().build(); + }); + } + + private Void processRawMessage(SQSMessage sqsMessage, Context context) { + String bodyMD5 = md5(sqsMessage.getBody()); + if (!sqsMessage.getMd5OfBody().equals(bodyMD5)) { + throw new SecurityException( + String.format("message digest does not match, expected %s, got %s", sqsMessage.getMd5OfBody(), + bodyMD5)); + } + + Map<String, AttributeValue> item = new HashMap<>(); + item.put("functionName", AttributeValue.builder().s(context.getFunctionName()).build()); + item.put("id", AttributeValue.builder().s(sqsMessage.getMessageId()).build()); + item.put("bodyMD5", AttributeValue.builder().s(bodyMD5).build()); + item.put("bodySize", + AttributeValue.builder().n(String.valueOf(sqsMessage.getBody().getBytes(StandardCharsets.UTF_8).length)) + .build()); + + client.putItem(PutItemRequest.builder().tableName(TABLE_FOR_ASYNC_TESTS).item(item).build()); + + return null; + } + + private String md5(String message) { + return BinaryUtils.toHex(Md5Utils.computeMD5Hash(message.getBytes(StandardCharsets.UTF_8))); + } +} diff --git a/powertools-e2e-tests/handlers/largemessage-functional/src/main/resources/log4j2.xml b/powertools-e2e-tests/handlers/largemessage-functional/src/main/resources/log4j2.xml new file mode 100644 index 000000000..8925f70b9 --- /dev/null +++ b/powertools-e2e-tests/handlers/largemessage-functional/src/main/resources/log4j2.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <Console name="JsonAppender" target="SYSTEM_OUT"> + <JsonTemplateLayout eventTemplateUri="classpath:LambdaJsonLayout.json" /> + </Console> + </Appenders> + <Loggers> + <Root level="INFO"> + <AppenderRef ref="JsonAppender"/> + </Root> + <Logger name="JsonLogger" level="INFO" additivity="false"> + <AppenderRef ref="JsonAppender"/> + </Logger> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 86e867548..f171422c5 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -27,6 +27,7 @@ <modules> <module>batch</module> <module>largemessage</module> + <module>largemessage-functional</module> <module>largemessage_idempotent</module> <module>logging-log4j</module> <module>logging-logback</module> diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java index 74247ca2e..0de2dca60 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/LargeMessageE2ET.java @@ -16,9 +16,10 @@ import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.Timeout; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,6 +41,7 @@ import software.amazon.lambda.powertools.testutils.Infrastructure; import software.amazon.lambda.powertools.testutils.RetryUtils; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) class LargeMessageE2ET { private static final Logger LOG = LoggerFactory.getLogger(LargeMessageE2ET.class); @@ -55,25 +57,34 @@ class LargeMessageE2ET { .region(region) .build(); - private static Infrastructure infrastructure; - private static String functionName; - private static String bucketName; - private static String queueUrl; - private static String tableName; + private Infrastructure infrastructure; + private String functionName; + private String bucketName; + private String queueUrl; + private String tableName; private String messageId; + private String currentPathToFunction; + + private void setupInfrastructure(String pathToFunction) { + // Do not re-deploy the same function + if (pathToFunction.equals(currentPathToFunction)) { + return; + } + + // Destroy any existing infrastructure before re-deploying + if (infrastructure != null) { + infrastructure.destroy(); + } - @BeforeAll - @Timeout(value = 5, unit = TimeUnit.MINUTES) - static void setup() { String random = UUID.randomUUID().toString().substring(0, 6); bucketName = "largemessagebucket" + random; String queueName = "largemessagequeue" + random; infrastructure = Infrastructure.builder() - .testName(LargeMessageE2ET.class.getSimpleName()) + .testName(LargeMessageE2ET.class.getSimpleName() + "-" + pathToFunction) .queue(queueName) .largeMessagesBucket(bucketName) - .pathToFunction("largemessage") + .pathToFunction(pathToFunction) .timeoutInSeconds(60) .build(); @@ -81,19 +92,24 @@ static void setup() { functionName = outputs.get(FUNCTION_NAME_OUTPUT); queueUrl = outputs.get("QueueURL"); tableName = outputs.get("TableNameForAsyncTests"); + currentPathToFunction = pathToFunction; - LOG.info("Testing '" + LargeMessageE2ET.class.getSimpleName() + "'"); + LOG.info("Testing '{}' with {}", LargeMessageE2ET.class.getSimpleName(), pathToFunction); } @AfterAll - static void tearDown() { + void cleanup() { if (infrastructure != null) { infrastructure.destroy(); } } @AfterEach - void reset() { + void tearDown() { + reset(); + } + + private void reset() { if (messageId != null) { Map<String, AttributeValue> itemToDelete = new HashMap<>(); itemToDelete.put("functionName", AttributeValue.builder().s(functionName).build()); @@ -103,8 +119,12 @@ void reset() { } } - @Test - void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException { + @ParameterizedTest + @ValueSource(strings = { "largemessage", "largemessage-functional" }) + @Timeout(value = 5, unit = TimeUnit.MINUTES) + void bigSQSMessageOffloadedToS3_shouldLoadFromS3(String pathToFunction) throws IOException { + setupInfrastructure(pathToFunction); + // GIVEN final ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration() .withPayloadSupportEnabled(s3Client, bucketName); @@ -146,8 +166,12 @@ void bigSQSMessageOffloadedToS3_shouldLoadFromS3() throws IOException { assertThat(items.get(0).get("bodyMD5").s()).isEqualTo("22bde5e7b05fa80bc7be45bdd4bc6c75"); } - @Test - void smallSQSMessage_shouldNotReadFromS3() { + @ParameterizedTest + @ValueSource(strings = { "largemessage", "largemessage-functional" }) + @Timeout(value = 5, unit = TimeUnit.MINUTES) + void smallSQSMessage_shouldNotReadFromS3(String pathToFunction) { + setupInfrastructure(pathToFunction); + // GIVEN final ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration() .withPayloadSupportEnabled(s3Client, bucketName); diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index a405941d7..bc7bbf03a 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -14,11 +14,11 @@ --> <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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> -<description>A suite of utilities for AWS Lambda Functions that makes handling large messages in SQS and SNS easier.</description> + <description>A suite of utilities for AWS Lambda Functions that makes handling large messages in SQS and SNS easier.</description> <parent> <groupId>software.amazon.lambda</groupId> @@ -41,6 +41,13 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-common</artifactId> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-common</artifactId> + <version>${project.version}</version> + <type>test-jar</type> + <scope>test</scope> + </dependency> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-events</artifactId> @@ -102,6 +109,11 @@ <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <scope>test</scope> + </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessage.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessage.java index 4e556966c..eb5b368a5 100644 --- a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessage.java +++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessage.java @@ -20,15 +20,15 @@ import java.lang.annotation.Target; /** - * <p>Use this annotation to handle large messages (> 256 KB) from SQS or SNS. + * <p>Use this annotation to handle large messages (> 1 MB) from SQS or SNS. * When large messages are sent to an SQS Queue or SNS Topic, they are offloaded to S3 and only a reference is passed in the message/record.</p> * * <p>{@code @LargeMessage} automatically retrieves and deletes messages * which have been offloaded to S3 using the {@code amazon-sqs-java-extended-client-lib} or {@code amazon-sns-java-extended-client-lib} * client libraries.</p> * - * <p>This version of the {@code @LargeMessage} is compatible with version - * 1.1.0+ of {@code amazon-sqs-java-extended-client-lib} / {@code amazon-sns-java-extended-client-lib}.</p> + * <p>This version of the {@code @LargeMessage} is compatible with version 1.1.0+ and 2.0.0+ + * of {@code amazon-sqs-java-extended-client-lib} / {@code amazon-sns-java-extended-client-lib}.</p> * <br/> * <p>Put this annotation on a method where the first parameter is either a {@link com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage} or {@link com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord}. * <br/> @@ -54,9 +54,11 @@ * </pre> * </p> * - * <p><b>Note 1</b>: Retrieving payloads and deleting objects from S3 will increase the duration of the + * <p><b>Note 1</b>: The message object (SQSMessage or SNSRecord) is modified in-place to avoid duplicating + * the large blob in memory. The message body will be replaced with the S3 object content.</p> + * <p><b>Note 2</b>: Retrieving payloads and deleting objects from S3 will increase the duration of the * Lambda function.</p> - * <p><b>Note 2</b>: Make sure to configure your function with enough memory to be able to retrieve S3 objects.</p> + * <p><b>Note 3</b>: Make sure to configure your function with enough memory to be able to retrieve S3 objects.</p> */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessages.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessages.java new file mode 100644 index 000000000..52675d3eb --- /dev/null +++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/LargeMessages.java @@ -0,0 +1,156 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.largemessages; + +import java.util.Optional; +import java.util.function.Function; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import software.amazon.lambda.powertools.largemessages.internal.LargeMessageProcessor; +import software.amazon.lambda.powertools.largemessages.internal.LargeMessageProcessorFactory; + +/** + * Functional API for processing large messages without AspectJ. + * <p> + * Use this class to handle large messages (> 1 MB) from SQS or SNS. + * When large messages are sent to an SQS Queue or SNS Topic, they are offloaded to S3 and only a reference is passed in the message/record. + * <p> + * {@code LargeMessages} automatically retrieves and optionally deletes messages + * which have been offloaded to S3 using the {@code amazon-sqs-java-extended-client-lib} or {@code amazon-sns-java-extended-client-lib} + * client libraries. + * <p> + * This version is compatible with version 1.1.0+ and 2.0.0+ of {@code amazon-sqs-java-extended-client-lib} / {@code amazon-sns-java-extended-client-lib}. + * <p> + * <u>SQS Example</u>: + * <pre> + * public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { + * private final BatchMessageHandler<SQSEvent, SQSBatchResponse> handler; + * + * public SqsBatchHandler() { + * handler = new BatchMessageHandlerBuilder() + * .withSqsBatchHandler() + * .buildWithRawMessageHandler(this::processMessage); + * } + * + * @Override + * public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + * return handler.processBatch(sqsEvent, context); + * } + * + * private void processMessage(SQSEvent.SQSMessage sqsMessage) { + * LargeMessages.processLargeMessage(sqsMessage, this::handleProcessedMessage); + * } + * + * private void handleProcessedMessage(SQSEvent.SQSMessage processedMessage) { + * // processedMessage.getBody() will contain the content of the S3 Object + * } + * } + * </pre> + * <p> + * To disable the deletion of S3 objects: + * <pre> + * LargeMessages.processLargeMessage(sqsMessage, this::handleProcessedMessage, false); + * </pre> + * <p> + * For multi-argument methods, use a lambda to pass additional parameters: + * <pre> + * public void handleRequest(SQSEvent event, Context context) { + * event.getRecords().forEach(message -> + * LargeMessages.processLargeMessage(message, processedMsg -> processMessage(processedMsg, context)) + * ); + * } + * + * private void processMessage(SQSMessage processedMessage, Context context) { + * // processedMessage.getBody() will contain the content of the S3 Object + * } + * </pre> + * <p> + * <b>Note 1</b>: The message object (SQSMessage or SNSRecord) is modified in-place to avoid duplicating + * the large blob in memory. The message body will be replaced with the S3 object content. + * <p> + * <b>Note 2</b>: Retrieving payloads and deleting objects from S3 will increase the duration of the Lambda function. + * <p> + * <b>Note 3</b>: Make sure to configure your function with enough memory to be able to retrieve S3 objects. + * + * @see LargeMessage + */ +public final class LargeMessages { + + private static final Logger LOG = LoggerFactory.getLogger(LargeMessages.class); + + private LargeMessages() { + // Utility class + } + + /** + * Process a large message and execute the function with the processed message. + * <p> + * The S3 object will be deleted after processing (default behavior). + * To disable S3 object deletion, use {@link #processLargeMessage(Object, Function, boolean)}. + * <p> + * Example usage: + * <pre> + * String returnValueOfFunction = LargeMessages.processLargeMessage(sqsMessage, this::handleMessage); + * String returnValueOfFunction = LargeMessages.processLargeMessage(sqsMessage, processedMsg -> processOrder(processedMsg, orderId, amount)); + * </pre> + * + * @param message the message to process (SQSMessage or SNSRecord) + * @param function the function to execute with the processed message + * @param <T> the message type + * @param <R> the return type of the function + * @return the result of the function execution + */ + public static <T, R> R processLargeMessage(T message, Function<T, R> function) { + return processLargeMessage(message, function, true); + } + + /** + * Process a large message and execute the function with the processed message. + * <p> + * Example usage: + * <pre> + * String returnValueOfFunction = LargeMessages.processLargeMessage(sqsMessage, this::handleMessage, false); + * String returnValueOfFunction = LargeMessages.processLargeMessage(sqsMessage, processedMsg -> processOrder(processedMsg, orderId, amount), false); + * </pre> + * + * @param message the message to process (SQSMessage or SNSRecord) + * @param function the function to execute with the processed message + * @param deleteS3Object whether to delete the S3 object after processing + * @param <T> the message type + * @param <R> the return type of the function + * @return the result of the function execution + */ + public static <T, R> R processLargeMessage(T message, Function<T, R> function, boolean deleteS3Object) { + Optional<LargeMessageProcessor<?>> processor = LargeMessageProcessorFactory.get(message); + + if (!processor.isPresent()) { + LOG.warn("Unsupported message type [{}], proceeding without large message processing", + message.getClass()); + return function.apply(message); + } + + try { + @SuppressWarnings("unchecked") + LargeMessageProcessor<T> typedProcessor = (LargeMessageProcessor<T>) processor.get(); + return typedProcessor.process(message, function::apply, deleteS3Object); + } catch (RuntimeException e) { + throw e; + } catch (Throwable t) { + throw new LargeMessageProcessingException("Failed to process large message", t); + } + } +} diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspect.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspect.java index 2aa81691f..0a8b93095 100644 --- a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspect.java +++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspect.java @@ -15,12 +15,14 @@ package software.amazon.lambda.powertools.largemessages.internal; import java.util.Optional; + import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.largemessages.LargeMessage; /** @@ -31,17 +33,17 @@ public class LargeMessageAspect { private static final Logger LOG = LoggerFactory.getLogger(LargeMessageAspect.class); - @SuppressWarnings({"EmptyMethod"}) + @SuppressWarnings({ "EmptyMethod" }) @Pointcut("@annotation(largeMessage)") public void callAt(LargeMessage largeMessage) { + // Pointcut method - body intentionally empty } + @SuppressWarnings("unchecked") @Around(value = "callAt(largeMessage) && execution(@LargeMessage * *.*(..))", argNames = "pjp,largeMessage") - public Object around(ProceedingJoinPoint pjp, - LargeMessage largeMessage) throws Throwable { + public Object around(ProceedingJoinPoint pjp, LargeMessage largeMessage) throws Throwable { Object[] proceedArgs = pjp.getArgs(); - // we need a message to process if (proceedArgs.length == 0) { LOG.warn("@LargeMessage annotation is placed on a method without any message to process, proceeding"); return pjp.proceed(proceedArgs); @@ -56,7 +58,8 @@ public Object around(ProceedingJoinPoint pjp, return pjp.proceed(proceedArgs); } - return largeMessageProcessor.get().process(pjp, largeMessage.deleteS3Object()); + return ((LargeMessageProcessor<Object>) largeMessageProcessor.get()).process(message, + msg -> pjp.proceed(proceedArgs), largeMessage.deleteS3Object()); } } diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageFunction.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageFunction.java new file mode 100644 index 000000000..1690eedac --- /dev/null +++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageFunction.java @@ -0,0 +1,35 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.largemessages.internal; + +/** + * Functional interface for large message processing. + * <p> + * This interface is similar to {@link java.util.function.Function} but throws {@link Throwable} + * instead of no exceptions. This is necessary to support AspectJ's {@code ProceedingJoinPoint.proceed()} + * which throws {@code Throwable}, allowing exceptions to bubble up naturally without wrapping. + * <p> + * This interface should not be exposed to user-facing APIs such as + * {@link software.amazon.lambda.powertools.largemessages.LargeMessages}. These should use plain + * {@link java.util.function.Function}. + * + * @param <T> the input type (message type) + * @param <R> the return type of the function + */ +@FunctionalInterface +public interface LargeMessageFunction<T, R> { + @SuppressWarnings("java:S112") // Throwable is required for AspectJ compatibility + R apply(T processedMessage) throws Throwable; +} diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java index 5478931f1..c41af0cea 100644 --- a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java +++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessor.java @@ -17,9 +17,10 @@ import static java.lang.String.format; import java.nio.charset.StandardCharsets; -import org.aspectj.lang.ProceedingJoinPoint; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import software.amazon.awssdk.core.exception.SdkException; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.lambda.powertools.largemessages.LargeMessageConfig; @@ -28,33 +29,44 @@ import software.amazon.payloadoffloading.S3Dao; /** - * Abstract processor for Large Messages. Handle the download from S3 and replace the actual S3 pointer with the content - * of the S3 Object leveraging the payloadoffloading library. + * Abstract processor for Large Messages. + * <p> + * Handles the download from S3 and replaces the S3 pointer with the actual content + * of the S3 Object, leveraging the payloadoffloading library. * - * @param <T> any message type that support Large Messages with S3 pointers - * ({@link com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage} and {@link com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord} at the moment) + * @param <T> any message type that supports Large Messages with S3 pointers + * ({@link com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage} + * and {@link com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord}) */ -abstract class LargeMessageProcessor<T> { +public abstract class LargeMessageProcessor<T> { protected static final String RESERVED_ATTRIBUTE_NAME = "ExtendedPayloadSize"; private static final Logger LOG = LoggerFactory.getLogger(LargeMessageProcessor.class); private final S3Client s3Client = LargeMessageConfig.get().getS3Client(); private final S3BackedPayloadStore payloadStore = new S3BackedPayloadStore(new S3Dao(s3Client), "DUMMY"); - public Object process(ProceedingJoinPoint pjp, boolean deleteS3Object) throws Throwable { - Object[] proceedArgs = pjp.getArgs(); - T message = (T) proceedArgs[0]; - + /** + * Process a large message using a functional interface. + * + * @param message the message to process + * @param function the function to execute with the processed message + * @param deleteS3Object whether to delete the S3 object after processing + * @param <R> the return type of the wrapped function + * @return the result of the function execution + * @throws Throwable if an error occurs during processing + */ + public <R> R process(T message, LargeMessageFunction<T, R> function, boolean deleteS3Object) throws Throwable { if (!isLargeMessage(message)) { LOG.warn("Not a large message, proceeding"); - return pjp.proceed(proceedArgs); + return function.apply(message); } String payloadPointer = getMessageContent(message); if (payloadPointer == null) { LOG.warn("No content in the message, proceeding"); - return pjp.proceed(proceedArgs); + return function.apply(message); } + // legacy attribute (sqs only) payloadPointer = payloadPointer.replace("com.amazon.sqs.javamessaging.MessageS3Pointer", "software.amazon.payloadoffloading.PayloadS3Pointer"); @@ -73,7 +85,7 @@ public Object process(ProceedingJoinPoint pjp, boolean deleteS3Object) throws Th updateMessageContent(message, s3ObjectContent); removeLargeMessageAttributes(message); - Object response = pjp.proceed(proceedArgs); + R result = function.apply(message); if (deleteS3Object) { if (LOG.isInfoEnabled()) { @@ -82,45 +94,45 @@ public Object process(ProceedingJoinPoint pjp, boolean deleteS3Object) throws Th deleteS3Object(payloadPointer); } - return response; + return result; } /** - * Retrieve the message id + * Retrieve the message ID. * - * @param message the message itself - * @return the id of the message (String format) + * @param message the message + * @return the message ID */ protected abstract String getMessageId(T message); /** - * Retrieve the content of the message (ex: body of an SQSMessage) + * Retrieve the content of the message (e.g., body of an SQSMessage). * - * @param message the message itself - * @return the content of the message (String format) + * @param message the message + * @return the message content */ protected abstract String getMessageContent(T message); /** - * Update the message content of the message (ex: body of an SQSMessage) + * Update the message content (e.g., body of an SQSMessage). * - * @param message the message itself - * @param messageContent the new content of the message (String format) + * @param message the message + * @param messageContent the new message content */ protected abstract void updateMessageContent(T message, String messageContent); /** - * Check if the message is actually a large message (indicator in message attributes) + * Check if the message is a large message (based on message attributes). * - * @param message the message itself - * @return true if the message is a large message + * @param message the message + * @return true if the message is a large message, false otherwise */ protected abstract boolean isLargeMessage(T message); /** - * Remove the large message indicator (in message attributes) + * Remove the large message indicator from message attributes. * - * @param message the message itself + * @param message the message */ protected abstract void removeLargeMessageAttributes(T message); diff --git a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactory.java b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactory.java index 26c33738a..06ee92968 100644 --- a/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactory.java +++ b/powertools-large-messages/src/main/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageProcessorFactory.java @@ -14,14 +14,15 @@ package software.amazon.lambda.powertools.largemessages.internal; +import java.util.Optional; + import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord; import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; -import java.util.Optional; -class LargeMessageProcessorFactory { +public final class LargeMessageProcessorFactory { private LargeMessageProcessorFactory() { - // not intended to be instantiated + // Utility class } public static Optional<LargeMessageProcessor<?>> get(Object message) { diff --git a/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/LargeMessagesTest.java b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/LargeMessagesTest.java new file mode 100644 index 000000000..7bd3e80e2 --- /dev/null +++ b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/LargeMessagesTest.java @@ -0,0 +1,287 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.largemessages; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.amazonaws.services.lambda.runtime.events.KinesisEvent.KinesisEventRecord; +import com.amazonaws.services.lambda.runtime.events.SNSEvent; +import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNS; +import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord; +import com.amazonaws.services.lambda.runtime.events.SQSEvent.MessageAttribute; +import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; + +import software.amazon.awssdk.core.ResponseInputStream; +import software.amazon.awssdk.http.AbortableInputStream; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.S3Exception; + +@ExtendWith(MockitoExtension.class) +class LargeMessagesTest { + + private static final String BIG_MSG = "A biiiiiiiig message"; + private static final String BUCKET_NAME = "bucketname"; + private static final String BUCKET_KEY = "c71eb2ae-37e0-4265-8909-32f4153faddf"; + private static final String BIG_MESSAGE_BODY = "[\"software.amazon.payloadoffloading.PayloadS3Pointer\", {\"s3BucketName\":\"" + + BUCKET_NAME + + "\", \"s3Key\":\"" + BUCKET_KEY + "\"}]"; + + @Mock + private S3Client s3Client; + + @BeforeEach + void init() throws NoSuchFieldException, IllegalAccessException { + // need to clean the s3Client with introspection (singleton) + Field client = LargeMessageConfig.class.getDeclaredField("s3Client"); + client.setAccessible(true); + client.set(LargeMessageConfig.get(), null); + LargeMessageConfig.init().withS3Client(s3Client); + } + + @Test + void testProcessLargeSQSMessage_shouldRetrieveFromS3AndDelete() { + // given + when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); + SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); + + // when + String result = LargeMessages.processLargeMessage(sqsMessage, SQSMessage::getBody); + + // then + assertThat(result).isEqualTo(BIG_MSG); + ArgumentCaptor<DeleteObjectRequest> delete = ArgumentCaptor.forClass(DeleteObjectRequest.class); + verify(s3Client).deleteObject(delete.capture()); + assertThat(delete.getValue().bucket()).isEqualTo(BUCKET_NAME); + assertThat(delete.getValue().key()).isEqualTo(BUCKET_KEY); + } + + @Test + void testProcessLargeSQSMessage_withDeleteDisabled_shouldNotDelete() { + // given + when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); + SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); + + // when + String result = LargeMessages.processLargeMessage(sqsMessage, SQSMessage::getBody, false); + + // then + assertThat(result).isEqualTo(BIG_MSG); + verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class)); + } + + @Test + void testProcessLargeSNSMessage_shouldRetrieveFromS3AndDelete() { + // given + when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); + SNSRecord snsRecord = snsRecordWithMessage(BIG_MESSAGE_BODY, true); + + // when + String result = LargeMessages.processLargeMessage(snsRecord, msg -> msg.getSNS().getMessage()); + + // then + assertThat(result).isEqualTo(BIG_MSG); + verify(s3Client).deleteObject(any(DeleteObjectRequest.class)); + } + + @Test + void testProcessSmallMessage_shouldNotInteractWithS3() { + // given + SQSMessage sqsMessage = sqsMessageWithBody("Small message", false); + + // when + String result = LargeMessages.processLargeMessage(sqsMessage, SQSMessage::getBody); + + // then + assertThat(result).isEqualTo("Small message"); + verifyNoInteractions(s3Client); + } + + @Test + void testProcessUnsupportedMessageType_shouldCallHandlerDirectly() { + // given + KinesisEventRecord kinesisRecord = new KinesisEventRecord(); + kinesisRecord.setEventID("kinesis-123"); + + // when + String result = LargeMessages.processLargeMessage(kinesisRecord, KinesisEventRecord::getEventID); + + // then + assertThat(result).isEqualTo("kinesis-123"); + verifyNoInteractions(s3Client); + } + + @Test + void testProcessMessageWithNullBody_shouldCallHandler() { + // given + SQSMessage sqsMessage = sqsMessageWithBody(null, true); + + // when + String result = LargeMessages.processLargeMessage(sqsMessage, SQSMessage::getBody); + + // then + assertThat(result).isNull(); + verifyNoInteractions(s3Client); + } + + @Test + void testProcessMessage_whenS3GetFails_shouldThrowException() { + // given + when(s3Client.getObject(any(GetObjectRequest.class))) + .thenThrow(S3Exception.create("Access denied", new Exception("Permission denied"))); + SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); + + // when / then + assertThatThrownBy(() -> LargeMessages.processLargeMessage(sqsMessage, SQSMessage::getBody)) + .isInstanceOf(LargeMessageProcessingException.class) + .hasMessageContaining("Failed processing S3 record"); + } + + @Test + void testProcessMessage_whenS3DeleteFails_shouldThrowException() { + // given + when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); + when(s3Client.deleteObject(any(DeleteObjectRequest.class))) + .thenThrow(S3Exception.create("Access denied", new Exception("Permission denied"))); + SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); + + // when / then + assertThatThrownBy(() -> LargeMessages.processLargeMessage(sqsMessage, SQSMessage::getBody)) + .isInstanceOf(LargeMessageProcessingException.class) + .hasMessageContaining("Failed deleting S3 record"); + } + + @Test + void testProcessMessage_whenHandlerThrowsRuntimeException_shouldPropagate() { + // given + when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); + SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); + + // when / then + assertThatThrownBy(() -> LargeMessages.processLargeMessage(sqsMessage, msg -> { + throw new IllegalStateException("Handler error"); + })) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Handler error"); + } + + @Test + void testProcessLargeMessage_withMultiParam_shouldRetrieveFromS3AndDelete() { + // given + when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); + SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); + String orderId = "order-123"; + + // when + String result = LargeMessages.processLargeMessage(sqsMessage, msg -> processOrderSimple(msg, orderId)); + + // then + assertThat(result).isEqualTo("order-123-processed"); + verify(s3Client).deleteObject(any(DeleteObjectRequest.class)); + } + + @Test + void testProcessLargeMessage_withMultiParamAndDeleteDisabled_shouldNotDelete() { + // given + when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); + SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); + String orderId = "order-456"; + + // when + String result = LargeMessages.processLargeMessage(sqsMessage, msg -> processOrderSimple(msg, orderId), false); + + // then + assertThat(result).isEqualTo("order-456-processed"); + verify(s3Client, never()).deleteObject(any(DeleteObjectRequest.class)); + } + + @Test + void testProcessLargeMessage_shouldModifyMessageInPlace() { + // given + when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); + SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); + String originalBody = sqsMessage.getBody(); + + // when + LargeMessages.processLargeMessage(sqsMessage, msg -> { + assertThat(msg.getBody()).isEqualTo(BIG_MSG); + return null; + }); + + // then - verify the original message object was modified + assertThat(sqsMessage.getBody()).isEqualTo(BIG_MSG); + assertThat(sqsMessage.getBody()).isNotEqualTo(originalBody); + } + + private String processOrderSimple(SQSMessage message, String orderId) { + assertThat(message.getBody()).isEqualTo(BIG_MSG); + return orderId + "-processed"; + } + + private ResponseInputStream<GetObjectResponse> s3ObjectWithLargeMessage() { + return new ResponseInputStream<>(GetObjectResponse.builder().build(), + AbortableInputStream.create(new ByteArrayInputStream(BIG_MSG.getBytes()))); + } + + private SQSMessage sqsMessageWithBody(String messageBody, boolean largeMessage) { + SQSMessage sqsMessage = new SQSMessage(); + sqsMessage.setBody(messageBody); + if (messageBody != null) { + sqsMessage.setMd5OfBody("dummy-md5"); + } + + if (largeMessage) { + Map<String, MessageAttribute> attributeMap = new HashMap<>(); + MessageAttribute payloadAttribute = new MessageAttribute(); + payloadAttribute.setStringValue("300450"); + payloadAttribute.setDataType("Number"); + attributeMap.put("ExtendedPayloadSize", payloadAttribute); + + sqsMessage.setMessageAttributes(attributeMap); + sqsMessage.setMd5OfMessageAttributes("dummy-md5"); + } + return sqsMessage; + } + + private SNSRecord snsRecordWithMessage(String messageBody, boolean largeMessage) { + SNS sns = new SNS().withMessage(messageBody); + if (largeMessage) { + sns.setMessageAttributes(Collections.singletonMap("ExtendedPayloadSize", + new SNSEvent.MessageAttribute())); + } + return new SNSRecord().withSns(sns); + } +} diff --git a/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspectTest.java b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspectTest.java index c364a89d9..b84709ddc 100644 --- a/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspectTest.java +++ b/powertools-large-messages/src/test/java/software/amazon/lambda/powertools/largemessages/internal/LargeMessageAspectTest.java @@ -22,17 +22,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -import static org.mockito.MockitoAnnotations.openMocks; import static software.amazon.lambda.powertools.largemessages.internal.LargeSQSMessageProcessor.calculateMessageAttributesMd5; import static software.amazon.lambda.powertools.largemessages.internal.LargeSQSMessageProcessor.calculateMessageBodyMd5; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.KinesisEvent.KinesisEventRecord; -import com.amazonaws.services.lambda.runtime.events.SNSEvent; -import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNS; -import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord; -import com.amazonaws.services.lambda.runtime.events.SQSEvent.MessageAttribute; -import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; import java.io.ByteArrayInputStream; import java.lang.reflect.Field; import java.nio.ByteBuffer; @@ -41,11 +33,22 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Consumer; + import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import com.amazonaws.services.lambda.runtime.events.KinesisEvent.KinesisEventRecord; +import com.amazonaws.services.lambda.runtime.events.SNSEvent; +import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNS; +import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord; +import com.amazonaws.services.lambda.runtime.events.SQSEvent.MessageAttribute; +import com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage; + import software.amazon.awssdk.core.ResponseInputStream; import software.amazon.awssdk.http.AbortableInputStream; import software.amazon.awssdk.services.s3.S3Client; @@ -53,11 +56,13 @@ import software.amazon.awssdk.services.s3.model.GetObjectRequest; import software.amazon.awssdk.services.s3.model.GetObjectResponse; import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.largemessages.LargeMessage; import software.amazon.lambda.powertools.largemessages.LargeMessageConfig; import software.amazon.lambda.powertools.largemessages.LargeMessageProcessingException; -public class LargeMessageAspectTest { +@ExtendWith(MockitoExtension.class) +class LargeMessageAspectTest { private static final String BIG_MSG = "A biiiiiiiig message"; private static final String BIG_MSG_MD5 = "919ebd392d8cb7161f95cb612a903d42"; @@ -65,19 +70,17 @@ public class LargeMessageAspectTest { private static final String BUCKET_NAME = "bucketname"; private static final String BUCKET_KEY = "c71eb2ae-37e0-4265-8909-32f4153faddf"; - private static final String BIG_MESSAGE_BODY = - "[\"software.amazon.payloadoffloading.PayloadS3Pointer\", {\"s3BucketName\":\"" + BUCKET_NAME + - "\", \"s3Key\":\"" + BUCKET_KEY + "\"}]"; + private static final String BIG_MESSAGE_BODY = "[\"software.amazon.payloadoffloading.PayloadS3Pointer\", {\"s3BucketName\":\"" + + BUCKET_NAME + + "\", \"s3Key\":\"" + BUCKET_KEY + "\"}]"; @Mock private S3Client s3Client; - @Mock - private Context context; + + private final TestLambdaContext context = new TestLambdaContext(); @BeforeEach - public void init() throws NoSuchFieldException, IllegalAccessException { - openMocks(this); - setupContext(); + void init() throws NoSuchFieldException, IllegalAccessException { // need to clean the s3Client with introspection (singleton) Field client = LargeMessageConfig.class.getDeclaredField("s3Client"); client.setAccessible(true); @@ -86,13 +89,13 @@ public void init() throws NoSuchFieldException, IllegalAccessException { } @LargeMessage - private String processSQSMessage(SQSMessage sqsMessage, Context context) { + private String processSQSMessage(SQSMessage sqsMessage, TestLambdaContext context) { return sqsMessage.getBody(); } @LargeMessage private String processSQSMessageWithMd5Checks(SQSMessage transformedMessage, String initialBodyMD5, - String initialAttributesMD5) { + String initialAttributesMD5) { assertThat(transformedMessage.getMd5OfBody()).isNotEqualTo(initialBodyMD5); assertThat(transformedMessage.getMd5OfBody()).isEqualTo(BIG_MSG_MD5); @@ -108,7 +111,7 @@ private String processSNSMessageWithoutContext(SNSRecord snsRecord) { } @LargeMessage(deleteS3Object = false) - private String processSQSMessageNoDelete(SQSMessage sqsMessage, Context context) { + private String processSQSMessageNoDelete(SQSMessage sqsMessage, TestLambdaContext context) { return sqsMessage.getBody(); } @@ -122,8 +125,15 @@ private String processNoMessage() { return "Hello World"; } + @LargeMessage + private void verifyMessageObjectIsModified(SQSMessage sqsMessage) { + // This test verifies the message object itself is modified, not a copy + assertThat(sqsMessage.getBody()).isEqualTo(BIG_MSG); + assertThat(sqsMessage.getMd5OfBody()).isEqualTo(BIG_MSG_MD5); + } + @Test - public void testLargeSQSMessageWithDefaultDeletion() { + void testLargeSQSMessageWithDefaultDeletion() { // given when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); @@ -136,8 +146,7 @@ public void testLargeSQSMessageWithDefaultDeletion() { ArgumentCaptor<DeleteObjectRequest> delete = ArgumentCaptor.forClass(DeleteObjectRequest.class); verify(s3Client).deleteObject(delete.capture()); Assertions.assertThat(delete.getValue()) - .satisfies((Consumer<DeleteObjectRequest>) deleteObjectRequest -> - { + .satisfies((Consumer<DeleteObjectRequest>) deleteObjectRequest -> { assertThat(deleteObjectRequest.bucket()) .isEqualTo(BUCKET_NAME); @@ -147,7 +156,7 @@ public void testLargeSQSMessageWithDefaultDeletion() { } @Test - public void testLargeSQSMessage_shouldChangeMd5OfBodyAndAttributes() { + void testLargeSQSMessage_shouldChangeMd5OfBodyAndAttributes() { // given when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); @@ -179,12 +188,12 @@ public void testLargeSQSMessage_shouldChangeMd5OfBodyAndAttributes() { } @Test - public void testLargeSNSMessageWithDefaultDeletion() { + void testLargeSNSMessageWithDefaultDeletion() { // given when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); SNSRecord snsRecord = snsRecordWithMessage(BIG_MESSAGE_BODY, true); - //when + // when String message = processSNSMessageWithoutContext(snsRecord); // then @@ -192,8 +201,7 @@ public void testLargeSNSMessageWithDefaultDeletion() { ArgumentCaptor<DeleteObjectRequest> delete = ArgumentCaptor.forClass(DeleteObjectRequest.class); verify(s3Client).deleteObject(delete.capture()); Assertions.assertThat(delete.getValue()) - .satisfies((Consumer<DeleteObjectRequest>) deleteObjectRequest -> - { + .satisfies((Consumer<DeleteObjectRequest>) deleteObjectRequest -> { assertThat(deleteObjectRequest.bucket()) .isEqualTo(BUCKET_NAME); @@ -203,7 +211,7 @@ public void testLargeSNSMessageWithDefaultDeletion() { } @Test - public void testLargeSQSMessageWithNoDeletion_shouldNotDelete() { + void testLargeSQSMessageWithNoDeletion_shouldNotDelete() { // given when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); @@ -217,7 +225,7 @@ public void testLargeSQSMessageWithNoDeletion_shouldNotDelete() { } @Test - public void testKinesisMessage_shouldProceedWithoutS3() { + void testKinesisMessage_shouldProceedWithoutS3() { // given KinesisEventRecord kinesisEventRecord = new KinesisEventRecord(); kinesisEventRecord.setEventID("kinesis_id1234567890"); @@ -231,7 +239,7 @@ public void testKinesisMessage_shouldProceedWithoutS3() { } @Test - public void testNoMessage_shouldProceedWithoutS3() { + void testNoMessage_shouldProceedWithoutS3() { // when String message = processNoMessage(); @@ -241,7 +249,7 @@ public void testNoMessage_shouldProceedWithoutS3() { } @Test - public void testSmallMessage_shouldProceedWithoutS3() { + void testSmallMessage_shouldProceedWithoutS3() { // given SQSMessage sqsMessage = sqsMessageWithBody("This is small message", false); @@ -255,7 +263,7 @@ public void testSmallMessage_shouldProceedWithoutS3() { } @Test - public void testNullMessage_shouldProceedWithoutS3() { + void testNullMessage_shouldProceedWithoutS3() { // given SQSMessage sqsMessage = sqsMessageWithBody(null, true); @@ -268,7 +276,7 @@ public void testNullMessage_shouldProceedWithoutS3() { } @Test - public void testGetS3ObjectException_shouldThrowLargeMessageProcessingException() { + void testGetS3ObjectException_shouldThrowLargeMessageProcessingException() { // given when(s3Client.getObject(any(GetObjectRequest.class))).thenThrow(S3Exception.create("Permission denied", new Exception("User is not allowed to access bucket " + BUCKET_NAME))); @@ -281,7 +289,7 @@ public void testGetS3ObjectException_shouldThrowLargeMessageProcessingException( } @Test - public void testDeleteS3ObjectException_shouldThrowLargeMessageProcessingException() { + void testDeleteS3ObjectException_shouldThrowLargeMessageProcessingException() { // given when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); when(s3Client.deleteObject(any(DeleteObjectRequest.class))).thenThrow(S3Exception.create("Permission denied", @@ -294,6 +302,22 @@ public void testDeleteS3ObjectException_shouldThrowLargeMessageProcessingExcepti .hasMessage(format("Failed deleting S3 record [%s]", BIG_MESSAGE_BODY)); } + @Test + void testMessageObjectIsModifiedInPlace() { + // given + when(s3Client.getObject(any(GetObjectRequest.class))).thenReturn(s3ObjectWithLargeMessage()); + SQSMessage sqsMessage = sqsMessageWithBody(BIG_MESSAGE_BODY, true); + String originalBody = sqsMessage.getBody(); + + // when + verifyMessageObjectIsModified(sqsMessage); + + // then - verify the original message object was modified + assertThat(sqsMessage.getBody()).isEqualTo(BIG_MSG); + assertThat(sqsMessage.getBody()).isNotEqualTo(originalBody); + assertThat(sqsMessage.getMd5OfBody()).isEqualTo(BIG_MSG_MD5); + } + private ResponseInputStream<GetObjectResponse> s3ObjectWithLargeMessage() { return new ResponseInputStream<>(GetObjectResponse.builder().build(), AbortableInputStream.create(new ByteArrayInputStream(BIG_MSG.getBytes()))); @@ -304,7 +328,7 @@ private SQSMessage sqsMessageWithBody(String messageBody, boolean largeMessage) } private SQSMessage sqsMessageWithBody(String messageBody, boolean largeMessage, - Map<String, MessageAttribute> optionalAttributes) { + Map<String, MessageAttribute> optionalAttributes) { SQSMessage sqsMessage = new SQSMessage(); sqsMessage.setBody(messageBody); if (messageBody != null) { @@ -338,10 +362,4 @@ private SNSRecord snsRecordWithMessage(String messageBody, boolean largeMessage) return new SNSRecord().withSns(sns); } - private void setupContext() { - when(context.getFunctionName()).thenReturn("testFunction"); - when(context.getInvokedFunctionArn()).thenReturn("testArn"); - when(context.getFunctionVersion()).thenReturn("1"); - when(context.getMemoryLimitInMB()).thenReturn(1024); - } } diff --git a/powertools-large-messages/src/test/resources/simplelogger.properties b/powertools-large-messages/src/test/resources/simplelogger.properties new file mode 100644 index 000000000..559c22385 --- /dev/null +++ b/powertools-large-messages/src/test/resources/simplelogger.properties @@ -0,0 +1,7 @@ +org.slf4j.simpleLogger.logFile=target/large-messages-test.log +org.slf4j.simpleLogger.defaultLogLevel=warn +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS +org.slf4j.simpleLogger.showThreadName=false +org.slf4j.simpleLogger.showLogName=true +org.slf4j.simpleLogger.showShortLogName=false From f106143a2beafd24e0258fb8318cbcacdebb6e7e Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Mon, 3 Nov 2025 17:56:19 +0100 Subject: [PATCH 510/577] fix(idempotency): Validate payload for optimistic idempotent writes. (#2261) * Validate payload for optimistic idempotent writes. * Re-throw IdempotencyValidationException instead of wrapping in a persistence layer exception. --- .../internal/IdempotencyHandler.java | 2 + .../persistence/BasePersistenceStore.java | 45 ++++++++++----- .../persistence/BasePersistenceStoreTest.java | 56 +++++++++++++++++-- 3 files changed, 84 insertions(+), 19 deletions(-) diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java index 77d3d49b0..d4e0d2222 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/internal/IdempotencyHandler.java @@ -109,6 +109,8 @@ private Object processIdempotency() throws Throwable { } } catch (IdempotencyKeyException ike) { throw ike; + } catch (IdempotencyValidationException ive) { + throw ive; } catch (Exception e) { throw new IdempotencyPersistenceLayerException( "Failed to save in progress record to idempotency store. If you believe this is a Powertools for AWS Lambda (Java) bug, please open an issue.", diff --git a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java index 7e93dc00c..00ddc4336 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java +++ b/powertools-idempotency/powertools-idempotency-core/src/main/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStore.java @@ -16,10 +16,6 @@ import static software.amazon.lambda.powertools.common.internal.LambdaConstants.LAMBDA_FUNCTION_NAME_ENV; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectWriter; -import io.burt.jmespath.Expression; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -33,8 +29,15 @@ import java.util.Spliterators; import java.util.stream.Stream; import java.util.stream.StreamSupport; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectWriter; + +import io.burt.jmespath.Expression; import software.amazon.lambda.powertools.idempotency.IdempotencyConfig; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemAlreadyExistsException; import software.amazon.lambda.powertools.idempotency.exceptions.IdempotencyItemNotFoundException; @@ -125,8 +128,7 @@ public void saveSuccess(JsonNode data, Object result, Instant now) { DataRecord.Status.COMPLETED, getExpiryEpochSecond(now), responseJson, - getHashedPayload(data) - ); + getHashedPayload(data)); LOG.debug("Function successfully executed. Saving record to persistence store with idempotency key: {}", dataRecord.getIdempotencyKey()); updateRecord(dataRecord); @@ -157,8 +159,8 @@ public void saveInProgress(JsonNode data, Instant now, OptionalInt remainingTime OptionalLong inProgressExpirationMsTimestamp = OptionalLong.empty(); if (remainingTimeInMs.isPresent()) { - inProgressExpirationMsTimestamp = - OptionalLong.of(now.plus(remainingTimeInMs.getAsInt(), ChronoUnit.MILLIS).toEpochMilli()); + inProgressExpirationMsTimestamp = OptionalLong + .of(now.plus(remainingTimeInMs.getAsInt(), ChronoUnit.MILLIS).toEpochMilli()); } DataRecord dataRecord = new DataRecord( @@ -167,10 +169,23 @@ public void saveInProgress(JsonNode data, Instant now, OptionalInt remainingTime getExpiryEpochSecond(now), null, getHashedPayload(data), - inProgressExpirationMsTimestamp - ); + inProgressExpirationMsTimestamp); LOG.debug("saving in progress record for idempotency key: {}", dataRecord.getIdempotencyKey()); - putRecord(dataRecord, now); + + try { + putRecord(dataRecord, now); + } catch (IdempotencyItemAlreadyExistsException iaee) { + // Similar to getRecord, we need to call validatePayload before returning a data record. + // PR https://github.com/aws-powertools/powertools-lambda-java/pull/1821 introduced returning a data record + // through IdempotencyItemAlreadyExistsException to save DynamoDB calls when using DDB as store. + Optional<DataRecord> dr = iaee.getDataRecord(); + if (dr.isPresent()) { + // throws IdempotencyValidationException if payload validation is enabled and failing + validatePayload(data, dr.get()); + } + + throw iaee; + } } /** @@ -188,7 +203,7 @@ public void deleteRecord(JsonNode data, Throwable throwable) { String idemPotencyKey = hashedIdempotencyKey.get(); LOG.debug("Function raised an exception {}. " + - "Clearing in progress record in persistence store for idempotency key: {}", + "Clearing in progress record in persistence store for idempotency key: {}", throwable.getClass(), idemPotencyKey); @@ -255,9 +270,9 @@ private Optional<String> getHashedIdempotencyKey(JsonNode data) { private boolean isMissingIdemPotencyKey(JsonNode data) { if (data.isContainerNode()) { - Stream<JsonNode> stream = - StreamSupport.stream(Spliterators.spliteratorUnknownSize(data.elements(), Spliterator.ORDERED), - false); + Stream<JsonNode> stream = StreamSupport.stream( + Spliterators.spliteratorUnknownSize(data.elements(), Spliterator.ORDERED), + false); return stream.allMatch(JsonNode::isNull); } return data.isNull(); diff --git a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java index d5d45c78f..8e46de1cc 100644 --- a/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java +++ b/powertools-idempotency/powertools-idempotency-core/src/test/java/software/amazon/lambda/powertools/idempotency/persistence/BasePersistenceStoreTest.java @@ -28,6 +28,7 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.tests.EventLoader; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.DoubleNode; import com.fasterxml.jackson.databind.node.TextNode; @@ -145,8 +146,8 @@ void saveInProgress_jmespath_NotFound_shouldThrowException() { assertThatThrownBy( () -> persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty())) - .isInstanceOf(IdempotencyKeyException.class) - .hasMessageContaining("No data found to create a hashed idempotency key"); + .isInstanceOf(IdempotencyKeyException.class) + .hasMessageContaining("No data found to create a hashed idempotency key"); assertThat(status).isEqualTo(-1); } @@ -181,7 +182,7 @@ void saveInProgress_withLocalCache_NotExpired_ShouldThrowException() { assertThatThrownBy( () -> persistenceStore.saveInProgress(JsonConfig.get().getObjectMapper().valueToTree(event), now, OptionalInt.empty())) - .isInstanceOf(IdempotencyItemAlreadyExistsException.class); + .isInstanceOf(IdempotencyItemAlreadyExistsException.class); assertThat(status).isEqualTo(-1); } @@ -243,7 +244,8 @@ void saveSuccess_withCacheEnabled_shouldSaveInCache() throws JsonProcessingExcep DataRecord cachedDr = cache.get("testFunction#8d6a8f173b46479eff55e0997864a514"); assertThat(cachedDr.getStatus()).isEqualTo(DataRecord.Status.COMPLETED); assertThat(cachedDr.getExpiryTimestamp()).isEqualTo(now.plus(3600, ChronoUnit.SECONDS).getEpochSecond()); - assertThat(cachedDr.getResponseData()).isEqualTo(JsonConfig.get().getObjectMapper().writeValueAsString(product)); + assertThat(cachedDr.getResponseData()) + .isEqualTo(JsonConfig.get().getObjectMapper().writeValueAsString(product)); assertThat(cachedDr.getIdempotencyKey()).isEqualTo("testFunction#8d6a8f173b46479eff55e0997864a514"); assertThat(cachedDr.getPayloadHash()).isEmpty(); } @@ -325,6 +327,52 @@ void getRecord_invalidPayload_shouldThrowValidationException() { assertThatThrownBy( () -> persistenceStore.getRecord(JsonConfig.get().getObjectMapper().valueToTree(event), Instant.now())) + .isInstanceOf(IdempotencyValidationException.class); + } + + @Test + void saveInProgress_invalidPayload_shouldThrowValidationException() { + APIGatewayProxyRequestEvent event = EventLoader.loadApiGatewayRestEvent("apigw_event.json"); + persistenceStore = new BasePersistenceStore() { + @Override + public DataRecord getRecord(String idempotencyKey) throws IdempotencyItemNotFoundException { + return new DataRecord(idempotencyKey, DataRecord.Status.INPROGRESS, + Instant.now().plus(3600, ChronoUnit.SECONDS).getEpochSecond(), "Response", "different hash"); + } + + @Override + public void putRecord(DataRecord dataRecord, Instant now) throws IdempotencyItemAlreadyExistsException { + DataRecord existingRecord = new DataRecord( + dataRecord.getIdempotencyKey(), + DataRecord.Status.INPROGRESS, + Instant.now().plus(3600, ChronoUnit.SECONDS).getEpochSecond(), + null, + "different hash"); + throw new IdempotencyItemAlreadyExistsException("Item already exists", new Exception(), existingRecord); + } + + @Override + public void updateRecord(DataRecord dataRecord) { + // Not needed for this test. + } + + @Override + public void deleteRecord(String idempotencyKey) { + // Not needed for this test. + + } + }; + + persistenceStore.configure(IdempotencyConfig.builder() + .withEventKeyJMESPath("powertools_json(body).id") + .withPayloadValidationJMESPath("powertools_json(body).message") + .build(), + "myfunc"); + + Instant now = Instant.now(); + OptionalInt remainingTime = OptionalInt.empty(); + JsonNode eventJson = JsonConfig.get().getObjectMapper().valueToTree(event); + assertThatThrownBy(() -> persistenceStore.saveInProgress(eventJson, now, remainingTime)) .isInstanceOf(IdempotencyValidationException.class); } From 68b6c026cb62785c23e88ca88f601ff4833e3f63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:08:56 +0100 Subject: [PATCH 511/577] chore: bump aws.sdk.version from 2.36.3 to 2.37.2 (#2253) Bumps `aws.sdk.version` from 2.36.3 to 2.37.2. Updates `software.amazon.awssdk:url-connection-client` from 2.36.3 to 2.37.2 Updates `software.amazon.awssdk:sdk-core` from 2.37.1 to 2.37.2 Updates `software.amazon.awssdk:s3` from 2.36.3 to 2.37.2 Updates `software.amazon.awssdk:kinesis` from 2.36.3 to 2.37.2 Updates `software.amazon.awssdk:sqs` from 2.36.3 to 2.37.2 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.37.1 to 2.37.2 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.37.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.37.2 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.37.2 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.37.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.37.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.37.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 19b404c82..75b283d3d 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.37.1</sdk.version> + <sdk.version>2.37.2</sdk.version> </properties> <dependencies> From 93d9ee60b69d4de6caab6c41d1f8a7ee15b0dd7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:09:08 +0100 Subject: [PATCH 512/577] chore: bump com.fasterxml.jackson:jackson-bom from 2.20.0 to 2.20.1 (#2254) Bumps [com.fasterxml.jackson:jackson-bom](https://github.com/FasterXML/jackson-bom) from 2.20.0 to 2.20.1. - [Commits](https://github.com/FasterXML/jackson-bom/compare/jackson-bom-2.20.0...jackson-bom-2.20.1) --- updated-dependencies: - dependency-name: com.fasterxml.jackson:jackson-bom dependency-version: 2.20.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 449baba05..a790145c1 100644 --- a/pom.xml +++ b/pom.xml @@ -84,7 +84,7 @@ <maven.deploy.plugin.version>3.1.2</maven.deploy.plugin.version> <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> - <jackson.version>2.20.0</jackson.version> + <jackson.version>2.20.1</jackson.version> <aws.sdk.version>2.36.3</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> From 25f02a9c2cd022729a0751f7bdbf4a38f8e8410d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:09:24 +0100 Subject: [PATCH 513/577] chore: bump github/codeql-action from 4.31.1 to 4.31.2 (#2255) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.1 to 4.31.2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5fe9434cd24fe243e33e7f3305f8a5b519b70280...0499de31b99561a6d14a36a5f662c2a54f91beee) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 632e4b0d9..996135fa9 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@5fe9434cd24fe243e33e7f3305f8a5b519b70280 # v3.29.5 + uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5 with: sarif_file: results.sarif From 357f1206801ce8ada3784ecf398ecc8015a722ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:10:31 +0100 Subject: [PATCH 514/577] chore: bump squidfunk/mkdocs-material in /docs (#2259) Bumps squidfunk/mkdocs-material from `f5c556a` to `58dee36`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: 58dee36ad85b0ae4836522ee6d3f0150d828bca9a1f7d3bfbf430bca771c1441 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 9b8bde4c5..88d6ca284 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -FROM squidfunk/mkdocs-material@sha256:f5c556a6d30ce0c1c0df10e3c38c79bbcafdaea4b1c1be366809d0d4f6f9d57f +FROM squidfunk/mkdocs-material@sha256:58dee36ad85b0ae4836522ee6d3f0150d828bca9a1f7d3bfbf430bca771c1441 COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From 41f3ef517db2561e596963590b9beb47a2bd6b0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 11:12:25 +0100 Subject: [PATCH 515/577] chore: bump aws.sdk.version from 2.36.3 to 2.37.3 (#2258) Bumps `aws.sdk.version` from 2.36.3 to 2.37.3. Updates `software.amazon.awssdk:bom` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:http-client-spi` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:url-connection-client` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:s3` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:dynamodb` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:lambda` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:kinesis` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:cloudwatch` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:xray` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:sqs` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:cloudformation` from 2.36.3 to 2.37.3 Updates `software.amazon.awssdk:sts` from 2.36.3 to 2.37.3 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.37.3 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.37.3 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.37.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.37.3 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.37.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.37.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.37.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.37.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-version: 2.37.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.37.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.37.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-version: 2.37.3 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 7f9bbc6fa..a164315fe 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.36.3</aws.sdk.version> + <aws.sdk.version>2.37.3</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index a790145c1..dbf1ac898 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.1</jackson.version> - <aws.sdk.version>2.36.3</aws.sdk.version> + <aws.sdk.version>2.37.3</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index f171422c5..82b7a1de3 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.36.3</aws.sdk.version> + <aws.sdk.version>2.37.3</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 93582c5a895252b7c81ab1757f6048e60e44d596 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 4 Nov 2025 15:31:35 +0100 Subject: [PATCH 516/577] Update UA configurator to comply with 50 chars limit. (#2268) --- .../internal/UserAgentConfigurator.java | 35 +++++++- .../internal/UserAgentConfiguratorTest.java | 81 ++++++++++++++++++- 2 files changed, 111 insertions(+), 5 deletions(-) diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java index 7deca89f1..27b69d5ad 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/UserAgentConfigurator.java @@ -82,18 +82,29 @@ static String getVersionFromProperties(String propertyFileName, String versionKe /** * Configures the AWS SDK to use Powertools user agent by setting the sdk.ua.appId system property. - * If the property is already set and not empty, appends the Powertools user agent with a "/" separator. + * Preserves any user-provided value and replaces any existing Powertools user agent. + * Enforces a 50 character limit to comply with AWS SDK recommendations. * This should be called during library initialization to ensure the user agent is properly configured. */ public static void configureUserAgent(String ptFeature) { try { String existingValue = System.getProperty(SDK_USER_AGENT_APP_ID); String powertoolsUserAgent = getUserAgent(ptFeature); + String newValue; - if (existingValue != null && !existingValue.isEmpty()) { - System.setProperty(SDK_USER_AGENT_APP_ID, existingValue + "/" + powertoolsUserAgent); + if (existingValue == null || existingValue.isEmpty()) { + newValue = powertoolsUserAgent; } else { - System.setProperty(SDK_USER_AGENT_APP_ID, powertoolsUserAgent); + String userValue = extractUserValue(existingValue); + if (userValue.isEmpty()) { + newValue = powertoolsUserAgent; + } else { + newValue = userValue + "/" + powertoolsUserAgent; + } + } + + if (newValue.length() <= 50) { + System.setProperty(SDK_USER_AGENT_APP_ID, newValue); } } catch (Exception e) { // We don't re-raise since we don't want to break the user if something in this logic doesn't work @@ -101,6 +112,22 @@ public static void configureUserAgent(String ptFeature) { } } + /** + * Extracts the user-provided value from the existing user agent string by removing any Powertools user agent. + * A Powertools user agent follows the pattern "PT/{FEATURE}/{VERSION} PTENV/{ENV}". + * + * @param existingValue the existing user agent string + * @return the user-provided value without Powertools user agent, or empty string if none exists + */ + static String extractUserValue(String existingValue) { + if (existingValue == null || existingValue.isEmpty()) { + return ""; + } + // Remove Powertools user agent pattern: PT/{FEATURE}/{VERSION} PTENV/{ENV} + String result = existingValue.replaceAll("/?PT/[^/]+/[^ ]+ PTENV/[^ ]+", ""); + return result.trim(); + } + /** * Retrieves the user agent string for the Powertools for AWS Lambda. * It follows the pattern PT/{PT_FEATURE}/{PT_VERSION} PTENV/{PT_EXEC_ENV} diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java index fbe4529d8..33050d8b4 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/UserAgentConfiguratorTest.java @@ -131,7 +131,7 @@ void testConfigureUserAgent() { } @Test - void testConfigureUserAgent_WithExistingValue() { + void testConfigureUserAgent_WithExistingUserValue() { System.setProperty("sdk.ua.appId", "UserValueABC123"); UserAgentConfigurator.configureUserAgent("test-feature"); @@ -139,6 +139,64 @@ void testConfigureUserAgent_WithExistingValue() { .isEqualTo("UserValueABC123/PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); } + @Test + void testConfigureUserAgent_ReplacePowertoolsUserAgent() { + System.setProperty("sdk.ua.appId", "PT/BATCH/" + VERSION + " PTENV/NA"); + UserAgentConfigurator.configureUserAgent("logging-log4j"); + + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("PT/LOGGING-LOG4J/" + VERSION + " PTENV/NA"); + } + + @Test + void testConfigureUserAgent_PreserveUserValueAndReplacePowertools() { + System.setProperty("sdk.ua.appId", "UserValue/PT/BATCH/" + VERSION + " PTENV/NA"); + UserAgentConfigurator.configureUserAgent("tracing"); + + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("UserValue/PT/TRACING/" + VERSION + " PTENV/NA"); + } + + @Test + void testConfigureUserAgent_ExceedsLimit() { + System.setProperty("sdk.ua.appId", "VeryLongUserValueThatExceedsTheLimitWhenCombined"); + UserAgentConfigurator.configureUserAgent("test-feature"); + + // Should not update if it would exceed 50 characters + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("VeryLongUserValueThatExceedsTheLimitWhenCombined"); + } + + @Test + void testExtractUserValue_NoUserValue() { + String result = UserAgentConfigurator.extractUserValue("PT/BATCH/" + VERSION + " PTENV/NA"); + assertThat(result).isEmpty(); + } + + @Test + void testExtractUserValue_WithUserValue() { + String result = UserAgentConfigurator.extractUserValue("UserValue/PT/BATCH/" + VERSION + " PTENV/NA"); + assertThat(result).isEqualTo("UserValue"); + } + + @Test + void testExtractUserValue_EmptyString() { + String result = UserAgentConfigurator.extractUserValue(""); + assertThat(result).isEmpty(); + } + + @Test + void testExtractUserValue_NullString() { + String result = UserAgentConfigurator.extractUserValue(null); + assertThat(result).isEmpty(); + } + + @Test + void testExtractUserValue_OnlyUserValue() { + String result = UserAgentConfigurator.extractUserValue("MyCustomValue"); + assertThat(result).isEqualTo("MyCustomValue"); + } + @Test void testConfigureUserAgent_WithEmptyExistingValue() { System.setProperty("sdk.ua.appId", ""); @@ -148,4 +206,25 @@ void testConfigureUserAgent_WithEmptyExistingValue() { .isEqualTo("PT/TEST-FEATURE/" + VERSION + " PTENV/NA"); } + @Test + @SetEnvironmentVariable(key = AWS_EXECUTION_ENV, value = "AWS_Lambda_java11") + void testConfigureUserAgent_MultipleUtilities() { + System.clearProperty("sdk.ua.appId"); + + // First utility + UserAgentConfigurator.configureUserAgent("batch"); + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("PT/BATCH/" + VERSION + " PTENV/AWS_Lambda_java11"); + + // Second utility - should replace, not append + UserAgentConfigurator.configureUserAgent("logging-log4j"); + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("PT/LOGGING-LOG4J/" + VERSION + " PTENV/AWS_Lambda_java11"); + + // Third utility - should replace again + UserAgentConfigurator.configureUserAgent("tracing"); + assertThat(System.getProperty("sdk.ua.appId")) + .isEqualTo("PT/TRACING/" + VERSION + " PTENV/AWS_Lambda_java11"); + } + } From d1c5b46ea263ebafabecf64a0b72a2652806be35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:33:36 +0100 Subject: [PATCH 517/577] chore: bump org.junit.jupiter:junit-jupiter from 5.14.0 to 5.14.1 (#2265) Bumps [org.junit.jupiter:junit-jupiter](https://github.com/junit-team/junit-framework) from 5.14.0 to 5.14.1. - [Release notes](https://github.com/junit-team/junit-framework/releases) - [Commits](https://github.com/junit-team/junit-framework/compare/r5.14.0...r5.14.1) --- updated-dependencies: - dependency-name: org.junit.jupiter:junit-jupiter dependency-version: 5.14.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index ce887884c..3a07e6e6c 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -9,7 +9,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.221.1</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> - <junit.version>5.14.0</junit.version> + <junit.version>5.14.1</junit.version> </properties> <build> <plugins> From 578cb8616a3a76c921ef01a319bcb601e153fb31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 15:34:09 +0100 Subject: [PATCH 518/577] chore: bump aws.sdk.version from 2.37.3 to 2.37.4 (#2264) Bumps `aws.sdk.version` from 2.37.3 to 2.37.4. Updates `software.amazon.awssdk:bom` from 2.37.3 to 2.37.4 Updates `software.amazon.awssdk:http-client-spi` from 2.37.3 to 2.37.4 Updates `software.amazon.awssdk:url-connection-client` from 2.37.2 to 2.37.4 Updates `software.amazon.awssdk:s3` from 2.37.2 to 2.37.4 Updates `software.amazon.awssdk:dynamodb` from 2.37.3 to 2.37.4 Updates `software.amazon.awssdk:lambda` from 2.37.3 to 2.37.4 Updates `software.amazon.awssdk:kinesis` from 2.37.2 to 2.37.4 Updates `software.amazon.awssdk:cloudwatch` from 2.37.3 to 2.37.4 Updates `software.amazon.awssdk:xray` from 2.37.3 to 2.37.4 Updates `software.amazon.awssdk:sqs` from 2.37.2 to 2.37.4 Updates `software.amazon.awssdk:cloudformation` from 2.37.3 to 2.37.4 Updates `software.amazon.awssdk:sts` from 2.37.3 to 2.37.4 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.37.4 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.37.4 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.37.4 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.37.4 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.37.4 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.37.4 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.37.4 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.37.4 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.37.4 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.37.4 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.37.4 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.37.4 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index a164315fe..edd774e74 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.37.3</aws.sdk.version> + <aws.sdk.version>2.37.4</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index dbf1ac898..bc5389841 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.1</jackson.version> - <aws.sdk.version>2.37.3</aws.sdk.version> + <aws.sdk.version>2.37.4</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 82b7a1de3..827feccea 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.37.3</aws.sdk.version> + <aws.sdk.version>2.37.4</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 9251e18ab11eb647d9d040c6a6822c73fbe5822f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 17:00:10 +0100 Subject: [PATCH 519/577] chore: bump io.github.ascopes:protobuf-maven-plugin (#2269) Bumps [io.github.ascopes:protobuf-maven-plugin](https://github.com/ascopes/protobuf-maven-plugin) from 3.3.0 to 3.10.2. - [Release notes](https://github.com/ascopes/protobuf-maven-plugin/releases) - [Commits](https://github.com/ascopes/protobuf-maven-plugin/compare/v3.3.0...v3.10.2) --- updated-dependencies: - dependency-name: io.github.ascopes:protobuf-maven-plugin dependency-version: 3.10.2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/tools/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-kafka/tools/pom.xml b/examples/powertools-examples-kafka/tools/pom.xml index 80ed6c264..e6f2654d1 100644 --- a/examples/powertools-examples-kafka/tools/pom.xml +++ b/examples/powertools-examples-kafka/tools/pom.xml @@ -62,7 +62,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.3.0</version> + <version>3.10.2</version> <executions> <execution> <goals> From 9ca99332edc2732cce3a7eeb9b2acf79aa489abf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:53:05 +0100 Subject: [PATCH 520/577] chore(ci): bump version to 2.6.0 (#2270) * chore(ci): bump version to 2.6.0 * Restore CHANGELOG.md from main. --------- Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Philipp Page <pagejep@amazon.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/README.md | 4 ++-- .../infra/sam-graalvm/README.md | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- .../powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- .../powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/handlers/batch/pom.xml | 2 +- .../handlers/idempotency-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency-generics/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency/pom.xml | 2 +- .../handlers/largemessage-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/largemessage/pom.xml | 2 +- .../handlers/largemessage_idempotent/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-log4j/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-logback/pom.xml | 2 +- powertools-e2e-tests/handlers/metrics/pom.xml | 2 +- powertools-e2e-tests/handlers/parameters/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/handlers/tracing/pom.xml | 2 +- powertools-e2e-tests/handlers/validation-alb-event/pom.xml | 2 +- .../handlers/validation-apigw-event/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 62 files changed, 69 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index b53d5aeb1..58d3901dc 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-metrics</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </dependency> ... </dependencies> diff --git a/examples/pom.xml b/examples/pom.xml index 71d924c26..9ce451a33 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-examples</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Examples</name> diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 75b283d3d..707b9bcfb 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-batch</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Batch</name> diff --git a/examples/powertools-examples-cloudformation/README.md b/examples/powertools-examples-cloudformation/README.md index b26007d44..35184b6d2 100644 --- a/examples/powertools-examples-cloudformation/README.md +++ b/examples/powertools-examples-cloudformation/README.md @@ -15,7 +15,7 @@ Run the following in your shell: ```bash cd infra/sam sam build -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.5.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.6.0718 ``` ### Deploy with CDK @@ -32,5 +32,5 @@ To build and deploy this application for the first time, run the following in yo cd infra/cdk mvn package cdk synth -cdk deploy -c BucketNameParam=my-unique-bucket-2.5.0718 +cdk deploy -c BucketNameParam=my-unique-bucket-2.6.0718 ``` \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md index b577855ce..01365932e 100644 --- a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md +++ b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md @@ -40,7 +40,7 @@ sam build ## Deploy the sample application ```shell -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.5.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.6.0718 ``` This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting started with SAM in [the examples directory](../../../README.md) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index edd774e74..389245bbc 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-cloudformation</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 8a5ac6601..756c082b8 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ <groupId>software.amazon.lambda.examples</groupId> <!-- TODO TODO TODO this should build from SNAPSHOT, but it doesn't, because the snapshots don't appear in the docker environment CDK builds it in in our CDK tests. How to procede? V2 blocker --> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-core-utilities-cdk</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 3a07e6e6c..4d3414c63 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <artifactId>cdk</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.221.1</cdk.version> diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 9b89d923a..36524f0b1 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.5.0' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.5.0' - aspect 'software.amazon.lambda:powertools-metrics:2.5.0' + aspect 'software.amazon.lambda:powertools-tracing:2.6.0' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.6.0' + aspect 'software.amazon.lambda:powertools-metrics:2.6.0' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 85ec540a9..c3713c344 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.5.0") - aspect("software.amazon.lambda:powertools-logging-log4j:2.5.0") - aspect("software.amazon.lambda:powertools-metrics:2.5.0") + aspect("software.amazon.lambda:powertools-tracing:2.6.0") + aspect("software.amazon.lambda:powertools-logging-log4j:2.6.0") + aspect("software.amazon.lambda:powertools-metrics:2.6.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 71b93be66..b879ae49d 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-core-utilities-sam-graalvm</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index 60d6b796f..a5e3881b2 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-core-utilities-sam</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 01e734f6f..8ef3b556d 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-core-utilities-serverless</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 4b7d19fe4..d320a1d40 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-core-utilities-terraform</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index 6ee70def3..3fa68c7e0 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-idempotency-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency GraalVM</name> diff --git a/examples/powertools-examples-idempotency/sam/pom.xml b/examples/powertools-examples-idempotency/sam/pom.xml index d84651e15..0654867f9 100644 --- a/examples/powertools-examples-idempotency/sam/pom.xml +++ b/examples/powertools-examples-idempotency/sam/pom.xml @@ -17,7 +17,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-idempotency</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency</name> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index fe56c6b1e..5428655bd 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-kafka</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Kafka</name> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index e72df3086..bfebbe57d 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-parameters-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index e2ee15f26..17a1efa79 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-parameters-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters</name> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index cdf131482..9b03e3046 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-serialization-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 683faf783..7120d3a91 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-serialization-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization</name> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index b84fac5bb..5826e7456 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <artifactId>powertools-examples-validation</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Validation</name> diff --git a/mkdocs.yml b/mkdocs.yml index 62e211728..da4303c38 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -127,7 +127,7 @@ extra_javascript: extra: powertools: - version: 2.5.0 + version: 2.6.0 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index bc5389841..66d15731b 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Parent</name> diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index edb849cea..ccf926d39 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <description>A suite of utilities that makes batch message processing using AWS Lambda easier.</description> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index f6d8ad33f..015179833 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Cloudformation</name> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 3583a4dc0..2610a8c4f 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Common Internal Utilities</name> diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index 21161f9e7..a630ba09b 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-batch</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency-functional/pom.xml b/powertools-e2e-tests/handlers/idempotency-functional/pom.xml index c8893c6e9..73c8780d3 100644 --- a/powertools-e2e-tests/handlers/idempotency-functional/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-idempotency-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency-generics/pom.xml b/powertools-e2e-tests/handlers/idempotency-generics/pom.xml index 5387d4059..d89aa33e2 100644 --- a/powertools-e2e-tests/handlers/idempotency-generics/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency-generics/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-idempotency-generics</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index 7c0e957fe..ea84e7b26 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-idempotency</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage-functional/pom.xml b/powertools-e2e-tests/handlers/largemessage-functional/pom.xml index 4afb633f2..094c54841 100644 --- a/powertools-e2e-tests/handlers/largemessage-functional/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-largemessage-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index 469a9a48a..3004a884c 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-largemessage</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index 1e89edd67..74a7b2999 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-large-msg-idempotent</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-functional/pom.xml b/powertools-e2e-tests/handlers/logging-functional/pom.xml index 5d774fe21..a8f79df30 100644 --- a/powertools-e2e-tests/handlers/logging-functional/pom.xml +++ b/powertools-e2e-tests/handlers/logging-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-logging-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-log4j/pom.xml b/powertools-e2e-tests/handlers/logging-log4j/pom.xml index dddc84152..0ed761274 100644 --- a/powertools-e2e-tests/handlers/logging-log4j/pom.xml +++ b/powertools-e2e-tests/handlers/logging-log4j/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-logging-log4j</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-logback/pom.xml b/powertools-e2e-tests/handlers/logging-logback/pom.xml index 4f3a28c72..d8523f721 100644 --- a/powertools-e2e-tests/handlers/logging-logback/pom.xml +++ b/powertools-e2e-tests/handlers/logging-logback/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-logging-logback</artifactId> diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 84006df9a..3b60d2aba 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-metrics</artifactId> diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index e0a58f9bd..495b51311 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-parameters</artifactId> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 827feccea..2e024375c 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -4,7 +4,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> <packaging>pom</packaging> <name>Handlers for End-to-End tests</name> <description>Fake handlers that use Powertools for AWS Lambda (Java).</description> diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index 5f6943ca6..2aaae55f5 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-tracing</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml index e9e8f5c47..c966194b1 100644 --- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-validation-alb-event</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml index 21e80c20e..85b8f47dc 100644 --- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>e2e-test-handler-validation-apigw-event</artifactId> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 557611a93..1898e309f 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>powertools-e2e-tests</artifactId> diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 8961701d3..7bfe38ef4 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>powertools-idempotency</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 64907072f..0e784c0f5 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>powertools-idempotency-core</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index a55947d4b..ea562ea89 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>powertools-idempotency-dynamodb</artifactId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index fd001f575..ac8c95f05 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>powertools-kafka</artifactId> diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index bc7bbf03a..e29327c7d 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>powertools-large-messages</artifactId> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 2fa4680fb..bcc28c6c2 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Logging</name> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index b4800ab54..fc47ac84d 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 0cfbb6104..2269303f5 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 74b4ca7c4..ae2871b41 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Metrics</name> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index f1e4eae57..72d3133d3 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>powertools-parameters</artifactId> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index eefc46ac5..454102ede 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index cfc8f64d3..594761bee 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 9d3ca0500..4b4616cb2 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index a277337a7..0e31ed729 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 61fb4c3b9..b1b655fe8 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.5.0</version> + <version>2.6.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 1ed2ee259..79b6653fa 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <artifactId>powertools-serialization</artifactId> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index c1f1433a1..3b1e58ccd 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Tracing</name> diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 57f8f25fb..2c119972d 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.5.0</version> + <version>2.6.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Validation</name> From e928caedcf5fbbb0e43fbffd38b7d9a617fd3fef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Nov 2025 16:39:04 +0100 Subject: [PATCH 521/577] chore: bump com.amazonaws:aws-lambda-java-runtime-interface-client (#2272) Bumps [com.amazonaws:aws-lambda-java-runtime-interface-client](https://github.com/aws/aws-lambda-java-libs) from 2.8.6 to 2.8.7. - [Commits](https://github.com/aws/aws-lambda-java-libs/commits) --- updated-dependencies: - dependency-name: com.amazonaws:aws-lambda-java-runtime-interface-client dependency-version: 2.8.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 389245bbc..e04a8dc43 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -77,7 +77,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.6</version> + <version>2.8.7</version> </dependency> </dependencies> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index b879ae49d..cfd640aa1 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -49,7 +49,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.6</version> + <version>2.8.7</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index 3fa68c7e0..dff0082f1 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -43,7 +43,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.6</version> + <version>2.8.7</version> </dependency> <dependency> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index bfebbe57d..9c62498d5 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -49,7 +49,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.6</version> + <version>2.8.7</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index 9b03e3046..7df5805ce 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -36,7 +36,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.6</version> + <version>2.8.7</version> </dependency> </dependencies> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 2e024375c..95a09d1d9 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -129,7 +129,7 @@ <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-runtime-interface-client</artifactId> - <version>2.8.6</version> + <version>2.8.7</version> </dependency> </dependencies> </dependencyManagement> From f08e8731aaac85014d752c58294c9e11e89b5d03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Nov 2025 16:39:08 +0100 Subject: [PATCH 522/577] chore: bump aws.sdk.version from 2.37.4 to 2.37.5 (#2271) Bumps `aws.sdk.version` from 2.37.4 to 2.37.5. Updates `software.amazon.awssdk:bom` from 2.37.4 to 2.37.5 Updates `software.amazon.awssdk:http-client-spi` from 2.37.4 to 2.37.5 Updates `software.amazon.awssdk:url-connection-client` from 2.37.2 to 2.37.5 Updates `software.amazon.awssdk:s3` from 2.37.2 to 2.37.5 Updates `software.amazon.awssdk:dynamodb` from 2.37.4 to 2.37.5 Updates `software.amazon.awssdk:lambda` from 2.37.4 to 2.37.5 Updates `software.amazon.awssdk:kinesis` from 2.37.2 to 2.37.5 Updates `software.amazon.awssdk:cloudwatch` from 2.37.4 to 2.37.5 Updates `software.amazon.awssdk:xray` from 2.37.4 to 2.37.5 Updates `software.amazon.awssdk:sqs` from 2.37.2 to 2.37.5 Updates `software.amazon.awssdk:cloudformation` from 2.37.4 to 2.37.5 Updates `software.amazon.awssdk:sts` from 2.37.4 to 2.37.5 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.37.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.37.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.37.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index e04a8dc43..a88339746 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.37.4</aws.sdk.version> + <aws.sdk.version>2.37.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 66d15731b..d262fbc6b 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.1</jackson.version> - <aws.sdk.version>2.37.4</aws.sdk.version> + <aws.sdk.version>2.37.5</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 95a09d1d9..599588c1d 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.37.4</aws.sdk.version> + <aws.sdk.version>2.37.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 1ed3daeba384f12ec5df3ea11d42ef038c791246 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 11:08:51 +0100 Subject: [PATCH 523/577] chore: bump aws.sdk.version from 2.37.2 to 2.37.5 (#2273) Bumps `aws.sdk.version` from 2.37.2 to 2.37.5. Updates `software.amazon.awssdk:url-connection-client` from 2.37.2 to 2.37.5 Updates `software.amazon.awssdk:sdk-core` from 2.37.2 to 2.37.5 Updates `software.amazon.awssdk:s3` from 2.37.2 to 2.37.5 Updates `software.amazon.awssdk:kinesis` from 2.37.2 to 2.37.5 Updates `software.amazon.awssdk:sqs` from 2.37.2 to 2.37.5 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.37.2 to 2.37.5 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.37.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.37.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.37.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.37.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 707b9bcfb..103a8a4b4 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.37.2</sdk.version> + <sdk.version>2.37.5</sdk.version> </properties> <dependencies> From 6b032bbaaf019283931ec9fc83d147e9b271cd65 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 11:09:06 +0100 Subject: [PATCH 524/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.221.1 to 2.222.0 (#2274) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.221.1 to 2.222.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.221.1...v2.222.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.222.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 4d3414c63..9348d52d9 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.6.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.221.1</cdk.version> + <cdk.version>2.222.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.14.1</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 1898e309f..09bfe8271 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.2</constructs.version> - <cdk.version>2.221.1</cdk.version> + <cdk.version>2.222.0</cdk.version> </properties> <dependencies> From e39cc6041417eb13896bc2a0b41a3c4eafd84b11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 11:09:18 +0100 Subject: [PATCH 525/577] chore: bump sam/build-java21 (#2275) Bumps sam/build-java21 from `72709a0` to `51709ae`. --- updated-dependencies: - dependency-name: sam/build-java21 dependency-version: 51709ae612478654f833998a3455519d0524157230757cf6327e402213811e38 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index 8d26b4770..1abb53643 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:72709a010ebfc993fb402c1bce599a0b754110b873d1a58e60c52136e8c8f3f1 +FROM public.ecr.aws/sam/build-java21@sha256:51709ae612478654f833998a3455519d0524157230757cf6327e402213811e38 # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From 691aeea73b55126072065237b8bed41b58d497ee Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:01:37 +0100 Subject: [PATCH 526/577] chore: bump aws.sdk.version from 2.37.5 to 2.38.2 (#2276) Bumps `aws.sdk.version` from 2.37.5 to 2.38.2. Updates `software.amazon.awssdk:url-connection-client` from 2.37.5 to 2.38.2 Updates `software.amazon.awssdk:sdk-core` from 2.37.5 to 2.38.2 Updates `software.amazon.awssdk:s3` from 2.37.5 to 2.38.2 Updates `software.amazon.awssdk:kinesis` from 2.37.5 to 2.38.2 Updates `software.amazon.awssdk:sqs` from 2.37.5 to 2.38.2 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.37.5 to 2.38.2 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.38.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.38.2 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.38.2 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.38.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.38.2 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.38.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 103a8a4b4..518cdbdd4 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.37.5</sdk.version> + <sdk.version>2.38.2</sdk.version> </properties> <dependencies> From 7c6d6ea17aad11987a276aa06ac4fc63c38e58f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 Nov 2025 11:01:45 +0100 Subject: [PATCH 527/577] chore: bump software.constructs:constructs from 10.4.2 to 10.4.3 (#2277) Bumps [software.constructs:constructs](https://github.com/aws/constructs) from 10.4.2 to 10.4.3. - [Release notes](https://github.com/aws/constructs/releases) - [Commits](https://github.com/aws/constructs/compare/v10.4.2...v10.4.3) --- updated-dependencies: - dependency-name: software.constructs:constructs dependency-version: 10.4.3 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 09bfe8271..ddf1a360a 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -30,7 +30,7 @@ <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> - <constructs.version>10.4.2</constructs.version> + <constructs.version>10.4.3</constructs.version> <cdk.version>2.222.0</cdk.version> </properties> From 598f004a0f56fad3e0e4f70594ff28fe1de4f616 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 09:56:26 +0100 Subject: [PATCH 528/577] chore: bump aws.sdk.version from 2.37.5 to 2.38.3 (#2278) Bumps `aws.sdk.version` from 2.37.5 to 2.38.3. Updates `software.amazon.awssdk:bom` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:http-client-spi` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:url-connection-client` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:s3` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:dynamodb` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:lambda` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:kinesis` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:cloudwatch` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:xray` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:sqs` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:cloudformation` from 2.37.5 to 2.38.3 Updates `software.amazon.awssdk:sts` from 2.37.5 to 2.38.3 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.38.3 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.38.3 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.38.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.38.3 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.38.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.38.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.38.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.38.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-version: 2.38.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.38.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.38.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-version: 2.38.3 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index a88339746..392d08b4b 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.37.5</aws.sdk.version> + <aws.sdk.version>2.38.3</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index d262fbc6b..4d5ff7248 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.1</jackson.version> - <aws.sdk.version>2.37.5</aws.sdk.version> + <aws.sdk.version>2.38.3</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 599588c1d..bf2e78f8c 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.37.5</aws.sdk.version> + <aws.sdk.version>2.38.3</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 7cdac1d58edf24648bd0e9875f01748e43391f0f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 09:56:40 +0100 Subject: [PATCH 529/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.222.0 to 2.223.0 (#2279) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.222.0 to 2.223.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.222.0...v2.223.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.223.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 9348d52d9..4ca38877d 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.6.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.222.0</cdk.version> + <cdk.version>2.223.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.14.1</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index ddf1a360a..860593819 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.3</constructs.version> - <cdk.version>2.222.0</cdk.version> + <cdk.version>2.223.0</cdk.version> </properties> <dependencies> From d550de02ffe2ef6901db9cb35b8338f61097bfb4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 09:57:42 +0100 Subject: [PATCH 530/577] chore: bump squidfunk/mkdocs-material in /docs (#2280) Bumps squidfunk/mkdocs-material from `58dee36` to `980e11f`. --- updated-dependencies: - dependency-name: squidfunk/mkdocs-material dependency-version: 980e11fed03b8e7851e579be9f34b1210f516c9f0b4da1a1457f21a460bd6628 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 88d6ca284..56c4c19ea 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -FROM squidfunk/mkdocs-material@sha256:58dee36ad85b0ae4836522ee6d3f0150d828bca9a1f7d3bfbf430bca771c1441 +FROM squidfunk/mkdocs-material@sha256:980e11fed03b8e7851e579be9f34b1210f516c9f0b4da1a1457f21a460bd6628 COPY requirements.txt /tmp/ RUN pip install --require-hashes -r /tmp/requirements.txt From addad65980bd89fd992f6fe91de7b70af68b5135 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 09:57:55 +0100 Subject: [PATCH 531/577] chore: bump actions/dependency-review-action from 4.8.1 to 4.8.2 (#2281) Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.8.1 to 4.8.2. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/40c09b7dc99638e5ddb0bfd91c1673effc064d8a...3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.8.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-dependencies-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml index 692acd64d..c6e06950f 100644 --- a/.github/workflows/security-dependencies-check.yml +++ b/.github/workflows/security-dependencies-check.yml @@ -26,6 +26,6 @@ jobs: - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Verify Contents - uses: actions/dependency-review-action@40c09b7dc99638e5ddb0bfd91c1673effc064d8a # v4.8.1 + uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 with: config-file: './.github/dependency-review-config.yml' From f9f227cf5a289da7c701057c9228296811ebfb3a Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 13 Nov 2025 10:19:29 +0100 Subject: [PATCH 532/577] docs: Document new functional API (#2282) * Initial version of documentation revamp adding functional API and usage patterns. * Update tracing docs highlighting functional API. * Update metrics docs highlighting functional API. * Update parameters docs highlithing functional approach. * Update validation docs highlithing functional API. * Update README.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/core/logging.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/core/logging.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/core/logging.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/core/logging.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/core/metrics.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/core/tracing.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/index.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/core/logging.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/utilities/idempotency.md Co-authored-by: Stefano Vozza <svozza@gmail.com> * Update docs/utilities/idempotency.md Co-authored-by: Stefano Vozza <svozza@gmail.com> --------- Co-authored-by: Stefano Vozza <svozza@gmail.com> --- README.md | 14 +- docs/FAQs.md | 4 + docs/core/logging.md | 264 ++++++++++++++++--- docs/core/metrics.md | 82 +++--- docs/core/tracing.md | 142 +++++----- docs/index.md | 39 ++- docs/processes/maintainers.md | 2 +- docs/usage-patterns.md | 183 +++++++++++++ docs/utilities/idempotency.md | 427 +++++++++++++++++++++++++------ docs/utilities/large_messages.md | 271 +++++++++++++++----- docs/utilities/parameters.md | 44 ++-- docs/utilities/validation.md | 23 +- mkdocs.yml | 4 +- 13 files changed, 1167 insertions(+), 332 deletions(-) create mode 100644 docs/usage-patterns.md diff --git a/README.md b/README.md index 58d3901dc..e771db05c 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your </dependency> <dependency> <groupId>software.amazon.lambda</groupId> - <artifactId>powertools-logging</artifactId> + <artifactId>powertools-logging-log4j</artifactId> <version>2.6.0</version> </dependency> <dependency> @@ -116,6 +116,7 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' aspect 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' + implementation 'software.amazon.lambda:powertools-logging-log4j:{{ powertools.version }}' implementation "org.aspectj:aspectjrt:1.9.22" } @@ -126,10 +127,10 @@ Next, configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lam ### Java Compatibility -Powertools for AWS Lambda (Java) supports all Java version from 11 up to 21 as well as the -[corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). +Powertools for AWS Lambda (Java) supports all Java versions from 11 to 25 in line with the [corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). + For the modules that provide annotations, Powertools for AWS Lambda (Java) leverages the **aspectj** library. -You may need to add the good version of `aspectjrt` to your dependencies based on the JDK used for building your function: +You may need to add the appropriate version of `aspectjrt` to your dependencies based on the JDK used for building your function: ```xml <dependency> @@ -142,12 +143,13 @@ You may need to add the good version of `aspectjrt` to your dependencies based o <details> <summary><b>JDK - aspectj dependency matrix</b></summary> +Use the following [dependency matrix](https://github.com/eclipse-aspectj/aspectj/blob/master/docs/release/JavaVersionCompatibility.adoc) to understand which AspectJ version to use based on your JDK version: + | JDK version | aspectj version | |-------------|------------------------| | `11-17` | `1.9.20.1` (or higher) | | `21` | `1.9.21` (or higher) | - -More info [here](https://github.com/aws-powertools/powertools-lambda-java/pull/1519/files#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5R191). +| `25` | `1.9.25` (or higher) | </details> diff --git a/docs/FAQs.md b/docs/FAQs.md index 75f699c91..cea4b774f 100644 --- a/docs/FAQs.md +++ b/docs/FAQs.md @@ -7,6 +7,8 @@ description: Frequently Asked Questions Many utilities in this library use `aspectj-maven-plugin` to compile-time weave (CTW) aspects into the project. In case you want to use `Lombok` or other compile-time preprocessor for your project, it is required to change `aspectj-maven-plugin` configuration to enable in-place weaving feature. Otherwise the plugin will ignore changes introduced by `Lombok` and will use `.java` files as a source. +Alternatively, you can use the [functional approach](./usage-patterns.md#functional-approach) which does not require AspectJ configuration. + To enable in-place weaving feature you need to use following `aspectj-maven-plugin` configuration: ```xml hl_lines="2-6" @@ -31,6 +33,8 @@ To enable in-place weaving feature you need to use following `aspectj-maven-plug Many utilities use `aspectj-maven-plugin` to compile-time weave (CTW) aspects into the project. When using it with Kotlin projects, it is required to `forceAjcCompile`. No explicit configuration should be required for gradle projects. +Alternatively, you can use the [functional approach](./usage-patterns.md#functional-approach) which does not require AspectJ configuration. + To enable `forceAjcCompile` you need to use following `aspectj-maven-plugin` configuration: ```xml hl_lines="2" diff --git a/docs/core/logging.md b/docs/core/logging.md index db01a3ec0..8358087d2 100644 --- a/docs/core/logging.md +++ b/docs/core/logging.md @@ -23,13 +23,12 @@ Logging provides an opinionated logger with output structured as JSON. You can find complete examples in the [project repository](https://github.com/aws-powertools/powertools-lambda-java/tree/v2/examples/powertools-examples-core-utilities){target="_blank"}. ### Installation -Depending on preference, you must choose to use either _log4j2_ or _logback_ as your log provider. In both cases you need to configure _aspectj_ -to weave the code and make sure the annotation is processed. +Depending on preference, you must choose to use either _log4j2_ or _logback_ as your log provider. If you use the AspectJ annotation approach, you must configure _aspectj_ to weave the code and make sure the annotation is processed. If you prefer the [functional approach](../usage-patterns.md#functional-approach), AspectJ configuration is not required. #### Maven === "log4j2" - ```xml hl_lines="3-7 24-27" + ```xml hl_lines="3-12 30-33" <dependencies> ... <dependency> @@ -37,10 +36,16 @@ to weave the code and make sure the annotation is processed. <artifactId>powertools-logging-log4j</artifactId> <version>{{ powertools.version }}</version> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging</artifactId> + <version>{{ powertools.version }}</version> + </dependency> ... </dependencies> ... <!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project --> + <!-- Note: This AspectJ configuration is not needed when using the functional approach --> <build> <plugins> ... @@ -82,7 +87,7 @@ to weave the code and make sure the annotation is processed. === "logback" - ```xml hl_lines="3-7 24-27" + ```xml hl_lines="3-12 30-33" <dependencies> ... <dependency> @@ -90,10 +95,16 @@ to weave the code and make sure the annotation is processed. <artifactId>powertools-logging-logback</artifactId> <version>{{ powertools.version }}</version> </dependency> + <dependency> + <groupId>software.amazon.lambda</groupId> + <artifactId>powertools-logging</artifactId> + <version>{{ powertools.version }}</version> + </dependency> ... </dependencies> ... <!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project --> + <!-- Note: This AspectJ configuration is not needed when using the functional approach --> <build> <plugins> ... @@ -137,10 +148,10 @@ to weave the code and make sure the annotation is processed. === "log4j2" - ```groovy hl_lines="3 11" + ```groovy hl_lines="3 11-12" plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' // Not needed when using the functional approach } repositories { @@ -148,7 +159,8 @@ to weave the code and make sure the annotation is processed. } dependencies { - aspect 'software.amazon.lambda:powertools-logging-log4j:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' // Not needed when using the functional approach + implementation 'software.amazon.lambda:powertools-logging-log4j:{{ powertools.version }}' } sourceCompatibility = 11 @@ -157,10 +169,10 @@ to weave the code and make sure the annotation is processed. === "logback" - ```groovy hl_lines="3 11" + ```groovy hl_lines="3 11-12" plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' // Not needed when using the functional approach } repositories { @@ -168,7 +180,8 @@ to weave the code and make sure the annotation is processed. } dependencies { - aspect 'software.amazon.lambda:powertools-logging-logback:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' // Not needed when using the functional approach + implementation 'software.amazon.lambda:powertools-logging-logback:{{ powertools.version }}' } sourceCompatibility = 11 @@ -317,9 +330,9 @@ If you set `POWERTOOLS_LOG_LEVEL` lower than ALC, we will emit a warning informi ## Basic Usage -To use Lambda Powertools for AWS Lambda Logging, use the `@Logging` annotation in your code and the standard _SLF4J_ logger: +You can use Powertools for AWS Lambda Logging with either the `@Logging` annotation or the functional API: -=== "PaymentFunction.java" +=== "@Logging annotation" ```java hl_lines="8 10 12 14" import org.slf4j.Logger; @@ -341,6 +354,30 @@ To use Lambda Powertools for AWS Lambda Logging, use the `@Logging` annotation i } ``` +=== "Functional API" + + ```java hl_lines="8 11 12 14 17" + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.logging.PowertoolsLogging; + // ... other imports + + public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); + + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + return PowertoolsLogging.withLogging(context, () -> { + LOGGER.info("Collecting payment"); + // ... + LOGGER.debug("order={}, amount={}", order.getId(), order.getAmount()); + // ... + return new APIGatewayProxyResponseEvent().withStatusCode(200); + }); + } + } + ``` + ## Standard structured keys Your logs will always include the following keys in your structured logging: @@ -376,11 +413,10 @@ The following keys will also be added to all your structured logs (unless [confi #### Logging a correlation ID -You can set a correlation ID using the `correlationIdPath` attribute of the `@Logging`annotation, -by passing a [JMESPath expression](https://jmespath.org/tutorial.html){target="_blank"}, +You can set a correlation ID using the `correlationIdPath` parameter by passing a [JMESPath expression](https://jmespath.org/tutorial.html){target="_blank"}, including our custom [JMESPath Functions](../utilities/serialization.md#built-in-functions). -=== "AppCorrelationIdPath.java" +=== "@Logging annotation" ```java hl_lines="5" public class AppCorrelationIdPath implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @@ -395,6 +431,24 @@ including our custom [JMESPath Functions](../utilities/serialization.md#built-in } } ``` + +=== "Functional API" + + ```java hl_lines="6" + public class AppCorrelationIdPath implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppCorrelationIdPath.class); + + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + return PowertoolsLogging.withLogging(context, "headers.my_request_id_header", input, () -> { + // ... + LOGGER.info("Collecting payment"); + // ... + return new APIGatewayProxyResponseEvent().withStatusCode(200); + }); + } + } + ``` === "Example HTTP Event" ```json hl_lines="3" @@ -422,7 +476,7 @@ including our custom [JMESPath Functions](../utilities/serialization.md#built-in To ease routine tasks like extracting correlation ID from popular event sources, we provide [built-in JMESPath expressions](#built-in-correlation-id-expressions). -=== "AppCorrelationId.java" +=== "@Logging annotation" ```java hl_lines="1 7" import software.amazon.lambda.powertools.logging.CorrelationIdPaths; @@ -440,6 +494,26 @@ we provide [built-in JMESPath expressions](#built-in-correlation-id-expressions) } ``` +=== "Functional API" + + ```java hl_lines="1 8" + import software.amazon.lambda.powertools.logging.CorrelationIdPaths; + + public class AppCorrelationId implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppCorrelationId.class); + + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + return PowertoolsLogging.withLogging(context, CorrelationIdPaths.API_GATEWAY_REST, input, () -> { + // ... + LOGGER.info("Collecting payment"); + // ... + return new APIGatewayProxyResponseEvent().withStatusCode(200); + }); + } + } + ``` + === "Example Event" ```json hl_lines="3" @@ -668,10 +742,9 @@ You can remove additional keys added with the MDC using `MDC.remove("key")`. #### Clearing state Logger is commonly initialized in the global scope. Due to [Lambda Execution Context reuse](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html){target="_blank"}, -this means that custom keys, added with the MDC can be persisted across invocations. If you want all custom keys to be deleted, you can use -`clearState=true` attribute on the `@Logging` annotation. +this means that custom keys, added with the MDC can be persisted across invocations. You can clear state using `clearState=true` on the `@Logging` annotation, or use the functional API which handles cleanup automatically. -=== "CreditCardFunction.java" +=== "@Logging annotation" ```java hl_lines="5 8" public class CreditCardFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @@ -716,15 +789,18 @@ this means that custom keys, added with the MDC can be persisted across invocati `clearState` is based on `MDC.clear()`. State clearing is automatically done at the end of the execution of the handler if set to `true`. +???+ tip + When using the functional API with `PowertoolsLogging.withLogging()`, state is automatically cleared at the end of execution, so you don't need to manage it manually. + ## Logging incoming event -When debugging in non-production environments, you can instruct the `@Logging` annotation to log the incoming event with `logEvent` param or via `POWERTOOLS_LOGGER_LOG_EVENT` env var. +When debugging in non-production environments, you can log the incoming event using the `@Logging` annotation with the `logEvent` parameter, via the `POWERTOOLS_LOGGER_LOG_EVENT` environment variable, or manually with the functional API. ???+ warning - This is disabled by default to prevent sensitive info being logged + This is disabled by default to prevent sensitive info being logged. -=== "AppLogEvent.java" +=== "@Logging annotation" ```java hl_lines="5" public class AppLogEvent implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @@ -738,17 +814,36 @@ When debugging in non-production environments, you can instruct the `@Logging` a } ``` +=== "Functional API" + + ```java hl_lines="1 9" + import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; + + public class AppLogEvent implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppLogEvent.class); + + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + return PowertoolsLogging.withLogging(context, () -> { + LOGGER.info("Handler Event", entry("event", input)); + // ... + return new APIGatewayProxyResponseEvent().withStatusCode(200); + }); + } + } + ``` + ???+ note - If you use this on a RequestStreamHandler, the SDK must duplicate input streams in order to log them. + If you use this on a RequestStreamHandler, the SDK must duplicate input streams in order to log them when used together with the `@Logging` annotation. ## Logging handler response -When debugging in non-production environments, you can instruct the `@Logging` annotation to log the response with `logResponse` param or via `POWERTOOLS_LOGGER_LOG_RESPONSE` env var. +When debugging in non-production environments, you can log the response using the `@Logging` annotation with the `logResponse` parameter, via the `POWERTOOLS_LOGGER_LOG_RESPONSE` environment variable, or manually with the functional API. ???+ warning - This is disabled by default to prevent sensitive info being logged + This is disabled by default to prevent sensitive info being logged. -=== "AppLogResponse.java" +=== "@Logging annotation" ```java hl_lines="5" public class AppLogResponse implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @@ -762,18 +857,41 @@ When debugging in non-production environments, you can instruct the `@Logging` a } ``` +=== "Functional API" + + ```java hl_lines="1 11" + import static software.amazon.lambda.powertools.logging.argument.StructuredArguments.entry; + + public class AppLogResponse implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppLogResponse.class); + + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + return PowertoolsLogging.withLogging(context, () -> { + // ... + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent().withStatusCode(200); + LOGGER.info("Handler Response", entry("response", response)); + return response; + }); + } + } + ``` + ???+ note - If you use this on a RequestStreamHandler, Powertools must duplicate output streams in order to log them. + If you use this on a RequestStreamHandler, Powertools must duplicate output streams in order to log them when used together with the `@Logging` annotation. ## Logging handler uncaught exception By default, AWS Lambda logs any uncaught exception that might happen in the handler. However, this log is not structured -and does not contain any additional context. You can instruct the `@Logging` annotation to log this kind of exception +and does not contain any additional context. When using the `@Logging` annotation, you can enable structured exception logging with `logError` param or via `POWERTOOLS_LOGGER_LOG_ERROR` env var. ???+ warning - This is disabled by default to prevent double logging + This is disabled by default to prevent double logging. -=== "AppLogResponse.java" +???+ note + This feature is only available when using the `@Logging` annotation. When using the functional API, you must catch and log exceptions manually using try-catch blocks. + +=== "@Logging annotation" ```java hl_lines="5" public class AppLogError implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @@ -787,6 +905,29 @@ with `logError` param or via `POWERTOOLS_LOGGER_LOG_ERROR` env var. } ``` +=== "Functional API" + + ```java hl_lines="1 9 12-13" + import org.slf4j.MarkerFactory; + + public class AppLogError implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppLogError.class); + + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + return PowertoolsLogging.withLogging(context, () -> { + try { + // ... + return new APIGatewayProxyResponseEvent().withStatusCode(200); + } catch (Exception e) { + LOGGER.error(MarkerFactory.getMarker("FATAL"), "Exception in Lambda Handler", e); + throw e; + } + }); + } + } + ``` + ## Advanced ### Buffering logs @@ -1050,7 +1191,10 @@ You can manually control the log buffer using the `PowertoolsLogging` utility cl Use the `@Logging` annotation to automatically flush buffered logs when an uncaught exception is raised in your Lambda function. This is enabled by default (`flushBufferOnUncaughtError = true`), but you can explicitly configure it if needed. -=== "PaymentFunction.java" +???+ warning + This feature is only available when using the `@Logging` annotation. When using the functional API, you must manually flush the buffer in exception handlers. + +=== "@Logging annotation" ```java hl_lines="5 11" public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @@ -1068,6 +1212,30 @@ Use the `@Logging` annotation to automatically flush buffered logs when an uncau } ``` +=== "Functional API" + + ```java hl_lines="14" + import software.amazon.lambda.powertools.logging.PowertoolsLogging; + + public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(PaymentFunction.class); + + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + return PowertoolsLogging.withLogging(context, () -> { + try { + LOGGER.debug("a debug log"); // this is buffered + // do stuff + throw new RuntimeException("Something went wrong"); + } catch (Exception e) { + PowertoolsLogging.flushBuffer(); // Manually flush buffered logs + throw e; + } + }); + } + } + ``` + #### Buffering workflows ##### Manual flush @@ -1161,13 +1329,13 @@ sequenceDiagram ## Sampling debug logs -You can dynamically set a percentage of your logs to`DEBUG` level to be included in the logger output, regardless of configured log leve, using the`POWERTOOLS_LOGGER_SAMPLE_RATE` environment variable or -via `samplingRate` attribute on the `@Logging` annotation. +You can dynamically set a percentage of your logs to`DEBUG` level to be included in the logger output, regardless of configured log level, using the`POWERTOOLS_LOGGER_SAMPLE_RATE` environment variable, +via the `samplingRate` attribute on the `@Logging` annotation, or as a parameter in the functional API. !!! info - Configuration on environment variable is given precedence over sampling rate configuration on annotation, provided it's in valid value range. + Configuration via environment variable is given precedence over sampling rate configuration, provided it's in valid value range. -=== "Sampling via annotation attribute" +=== "@Logging annotation" ```java hl_lines="5" public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @@ -1182,6 +1350,23 @@ via `samplingRate` attribute on the `@Logging` annotation. } ``` +=== "Functional API" + + ```java hl_lines="6" + public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + private static final Logger LOGGER = LoggerFactory.getLogger(App.class); + + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent input, final Context context) { + return PowertoolsLogging.withLogging(context, 0.5, () -> { + // will eventually be logged based on the sampling rate + LOGGER.debug("Handle payment"); + return new APIGatewayProxyResponseEvent().withStatusCode(200); + }); + } + } + ``` + === "Sampling via environment variable" ```yaml hl_lines="8" @@ -1198,7 +1383,7 @@ via `samplingRate` attribute on the `@Logging` annotation. ## Built-in Correlation ID expressions -You can use any of the following built-in JMESPath expressions as part of `@Logging(correlationIdPath = ...)`: +You can use any of the following built-in JMESPath expressions with the `@Logging` annotation or the functional API: ???+ note "Note: Any object key named with `-` must be escaped" For example, **`request.headers."x-amzn-trace-id"`**. @@ -1237,8 +1422,7 @@ The `JsonTemplateLayout` is automatically configured with the provided template: "field": "name" }, "message": { - "$resolver": "powertools", - "field": "message" + "$resolver": "message" }, "error": { "message": { @@ -1299,6 +1483,10 @@ The `JsonTemplateLayout` is automatically configured with the provided template: "$resolver": "powertools", "field": "xray_trace_id" }, + "correlation_id": { + "$resolver": "powertools", + "field": "correlation_id" + }, "": { "$resolver": "powertools" } diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 71c56bb8b..e7f7bd87f 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -48,6 +48,7 @@ Visit the AWS documentation for a complete explanation for [Amazon CloudWatch co </dependencies> ... <!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project --> + <!-- Note: This AspectJ configuration is not needed when using the functional approach --> <build> <plugins> ... @@ -89,10 +90,10 @@ Visit the AWS documentation for a complete explanation for [Amazon CloudWatch co === "Gradle" - ```groovy hl_lines="3 11" + ```groovy hl_lines="3 11 12" plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' // Not needed when using the functional approach } repositories { @@ -100,7 +101,8 @@ Visit the AWS documentation for a complete explanation for [Amazon CloudWatch co } dependencies { - aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' // Not needed when using the functional approach + implementation 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' // Use this instead of 'aspect' when using the functional approach } sourceCompatibility = 11 @@ -127,27 +129,12 @@ Metrics has three global settings that will be used across all metrics emitted. The `Metrics` Singleton can be configured by three different interfaces. The following order of precedence applies: 1. `@FlushMetrics` annotation -2. `MetricsBuilder` using Builder pattern (see [Advanced section](#usage-without-metrics-annotation)) +2. `MetricsBuilder` using Builder pattern (see [Advanced section](#usage-without-flushmetrics-annotation)) 3. Environment variables (recommended) For most use-cases, we recommend using Environment variables and only overwrite settings in code where needed using either the `@FlushMetrics` annotation or `MetricsBuilder` if the annotation cannot be used. -=== "template.yaml" - - ```yaml hl_lines="9 10" - Resources: - HelloWorldFunction: - Type: AWS::Serverless::Function - Properties: - ... - Runtime: java11 - Environment: - Variables: - POWERTOOLS_SERVICE_NAME: payment - POWERTOOLS_METRICS_NAMESPACE: ServerlessAirline - ``` - -=== "MetricsEnabledHandler.java" +=== "@FlushMetrics annotation" ```java hl_lines="9" import software.amazon.lambda.powertools.metrics.FlushMetrics; @@ -165,9 +152,45 @@ For most use-cases, we recommend using Environment variables and only overwrite } ``` -`Metrics` is implemented as a Singleton to keep track of your aggregate metrics in memory and make them accessible anywhere in your code. To guarantee that metrics are flushed properly the `@FlushMetrics` annotation must be added on the lambda handler. +=== "MetricsBuilder" + + ```java hl_lines="7-8" + import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.MetricsBuilder; + + public class MetricsEnabledHandler implements RequestHandler<Object, Object> { + + private static final Metrics metrics = MetricsBuilder.builder() + .withNamespace("ServerlessAirline") + .withService("payment") + .build(); + + @Override + public Object handleRequest(Object input, Context context) { + // ... + metrics.flush(); + } + } + ``` + +=== "Environment variables" + + ```yaml hl_lines="9 10" + Resources: + HelloWorldFunction: + Type: AWS::Serverless::Function + Properties: + ... + Runtime: java11 + Environment: + Variables: + POWERTOOLS_SERVICE_NAME: payment + POWERTOOLS_METRICS_NAMESPACE: ServerlessAirline + ``` + +`Metrics` is implemented as a Singleton to keep track of your aggregate metrics in memory and make them accessible anywhere in your code. The `@FlushMetrics` annotation automatically flushes metrics at the end of the Lambda handler execution. Alternatively, you can use the functional approach and manually flush metrics using `metrics.flush()`. -!!!info "You can use the Metrics utility without the `@FlushMetrics` annotation and flush manually. Read more in the [advanced section below](#usage-without-metrics-annotation)." +!!!info "Read more about the functional approach in the [advanced section below](#usage-without-flushmetrics-annotation)." ## Creating metrics @@ -381,7 +404,7 @@ You can use `addMetadata` for advanced use cases, where you want to add metadata This will not be available during metrics visualization, use Dimensions for this purpose. !!! info - Adding metadata with a key that is the same as an existing metric will be ignored + Adding metadata with a key that is the same as an existing metric will be ignored. <!-- prettier-ignore-end --> === "App.java" @@ -468,7 +491,7 @@ You can create metrics with different configurations e.g. different namespace an === "App.java" - ```java hl_lines="12-18" + ```java hl_lines="12-22" import software.amazon.lambda.powertools.metrics.Metrics; import software.amazon.lambda.powertools.metrics.MetricsFactory; import software.amazon.lambda.powertools.metrics.model.DimensionSet; @@ -504,22 +527,22 @@ You can create metrics with different configurations e.g. different namespace an ### Usage without `@FlushMetrics` annotation -The `Metrics` Singleton provides all configuration options via `MetricsBuilder` in addition to the `@FlushMetrics` annotation. This can be useful if work in an environment or framework that does not leverage the vanilla Lambda `handleRequest` method. +You can use the **functional API** approach (see [usage patterns](../usage-patterns.md#functional-approach)) to work with Metrics without the `@FlushMetrics` annotation. The `Metrics` Singleton provides all configuration options via `MetricsBuilder`. This approach eliminates the AspectJ runtime dependency and is useful if you work in an environment or with a framework that does not leverage the vanilla Lambda `handleRequest` method. !!!info "The environment variables for Service and Namespace configuration still apply but can be overwritten with `MetricsBuilder` if needed." -The following example shows how to configure a custom `Metrics` Singleton using the Builder pattern. Note that it is necessary to manually flush metrics now. +The following example shows how to configure a custom `Metrics` Singleton using the Builder pattern. With the functional approach, you must manually flush metrics using `metrics.flush()`. === "App.java" - ```java hl_lines="7-12 19 23" + ```java hl_lines="7-12 19 24" import software.amazon.lambda.powertools.metrics.Metrics; import software.amazon.lambda.powertools.metrics.MetricsBuilder; import software.amazon.lambda.powertools.metrics.model.DimensionSet; import software.amazon.lambda.powertools.metrics.model.MetricUnit; public class App implements RequestHandler<Object, Object> { - // Create and configure a Metrics singleton without annotation + // Create and configure a Metrics singleton using the functional approach private static final Metrics metrics = MetricsBuilder.builder() .withNamespace("ServerlessAirline") .withRaiseOnEmptyMetrics(true) @@ -533,8 +556,9 @@ The following example shows how to configure a custom `Metrics` Singleton using // Dimensions are also optional. metrics.captureColdStartMetric(context, DimensionSet.of("FunctionName", "MyFunction", "Service", "payment")); - // Add metrics to the custom metrics singleton + // Add metrics metrics.addMetric("CustomMetric", 1, MetricUnit.COUNT); + // Manually flush metrics metrics.flush(); } } diff --git a/docs/core/tracing.md b/docs/core/tracing.md index 8129d45ba..95fbe6d06 100644 --- a/docs/core/tracing.md +++ b/docs/core/tracing.md @@ -20,7 +20,7 @@ a provides functionality to reduce the overhead of performing common tracing tas === "Maven" - ```xml hl_lines="3-7 16 18 24-27" + ```xml hl_lines="3-7 25-28" <dependencies> ... <dependency> @@ -32,6 +32,7 @@ a provides functionality to reduce the overhead of performing common tracing tas </dependencies> ... <!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project --> + <!-- Note: This AspectJ configuration is not needed when using the functional approach --> <build> <plugins> ... @@ -73,10 +74,10 @@ a provides functionality to reduce the overhead of performing common tracing tas === "Gradle" - ```groovy hl_lines="3 11" + ```groovy hl_lines="3 11 12" plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' // Not needed when using the functional approach } repositories { @@ -84,11 +85,12 @@ a provides functionality to reduce the overhead of performing common tracing tas } dependencies { - aspect 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' // Not needed when using the functional approach + implementation 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' // Use this instead of 'aspect' when using the functional approach } - sourceCompatibility = 11 - targetCompatibility = 11 + sourceCompatibility = 11 // or higher + targetCompatibility = 11 // or higher ``` ## Initialization @@ -118,11 +120,13 @@ The Powertools for AWS Lambda (Java) service name is used as the X-Ray namespace ### Lambda handler -To enable Powertools for AWS Lambda (Java) tracing to your function add the `@Tracing` annotation to your `handleRequest` method or on -any method will capture the method as a separate subsegment automatically. You can optionally choose to customize -segment name that appears in traces. +You can enable tracing using either the `@Tracing` annotation or the functional API. -=== "Tracing annotation" +**With the `@Tracing` annotation**, add it to your `handleRequest` method or any method to capture it as a separate subsegment automatically. You can optionally customize the segment name that appears in traces. + +**With the functional API**, use `TracingUtils.withSubsegment()` to manually create subsegments without AspectJ configuration. + +=== "@Tracing annotation" ```java hl_lines="3 10 15" public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @@ -146,6 +150,25 @@ segment name that appears in traces. } ``` +=== "Functional API" + + ```java hl_lines="1 6 7 8 10 11 12" + import software.amazon.lambda.powertools.tracing.TracingUtils; + + public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + TracingUtils.withSubsegment("businessLogic1", subsegment -> { + // Business logic 1 + }); + + TracingUtils.withSubsegment("businessLogic2", subsegment -> { + // Business logic 2 + }); + } + } + ``` + === "Custom Segment names" ```java hl_lines="3" @@ -157,22 +180,25 @@ segment name that appears in traces. } ``` -When using this `@Tracing` annotation, Utility performs these additional tasks to ease operations: +When using the `@Tracing` annotation, the utility performs these additional tasks to ease operations: * Creates a `ColdStart` annotation to easily filter traces that have had an initialization overhead. * Creates a `Service` annotation if service parameter or `POWERTOOLS_SERVICE_NAME` is set. * Captures any response, or full exceptions generated by the handler, and include as tracing metadata. +By default, the `@Tracing` annotation uses `captureMode=ENVIRONMENT_VAR`, which means it will only record method responses and exceptions if you set +the environment variables `POWERTOOLS_TRACER_CAPTURE_RESPONSE` and `POWERTOOLS_TRACER_CAPTURE_ERROR` to `true`. You can override this behavior by +specifying a different `captureMode` to always record response, exception, both, or neither. -By default, this annotation will automatically record method responses and exceptions. You can change the default behavior by setting -the environment variables `POWERTOOLS_TRACER_CAPTURE_RESPONSE` and `POWERTOOLS_TRACER_CAPTURE_ERROR` as needed. Optionally, you can override behavior by -different supported `captureMode` to record response, exception or both. +!!! note + When using the functional API with `TracingUtils.withSubsegment()`, response and exception capture is not automatic. You can manually add metadata using `TracingUtils.putMetadata()` as needed. -!!! warning "Returning sensitive information from your Lambda handler or functions, where `Tracing` is used?" - You can disable annotation from capturing their responses and exception as tracing metadata with **`captureMode=DISABLED`** - or globally by setting environment variables **`POWERTOOLS_TRACER_CAPTURE_RESPONSE`** and **`POWERTOOLS_TRACER_CAPTURE_ERROR`** to **`false`** +!!! warning "Returning sensitive information from your Lambda handler or functions?" + When using the `@Tracing` annotation, you can disable it from capturing responses and exceptions as tracing metadata with **`captureMode=DISABLED`** + or globally by setting the environment variables **`POWERTOOLS_TRACER_CAPTURE_RESPONSE`** and **`POWERTOOLS_TRACER_CAPTURE_ERROR`** to **`false`**. + When using the functional API, you have full control over what metadata is captured. -=== "Disable on annotation" +=== "@Tracing annotation - Disable on method" ```java hl_lines="3" public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @@ -183,7 +209,7 @@ different supported `captureMode` to record response, exception or both. } ``` -=== "Disable Globally" +=== "@Tracing annotation - Disable Globally" ```yaml hl_lines="11 12" Resources: @@ -200,6 +226,20 @@ different supported `captureMode` to record response, exception or both. POWERTOOLS_TRACER_CAPTURE_ERROR: false ``` +=== "Functional API" + + ```java hl_lines="6 7 8" + import software.amazon.lambda.powertools.tracing.TracingUtils; + + public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + TracingUtils.withSubsegment("businessLogic", subsegment -> { + // With functional API, you control what metadata is captured + }); + } + ``` + ### Annotations & Metadata **Annotations** are key-values associated with traces and indexed by AWS X-Ray. You can use them to filter traces and to @@ -272,32 +312,13 @@ specific fields from received event due to security. } ``` -## Utilities - -Tracing modules comes with certain utility method when you don't want to use annotation for capturing a code block -under a subsegment, or you are doing multithreaded programming. Refer examples below. +## Advanced usage -=== "Functional Api" +### Multi-threaded programming - ```java hl_lines="7 8 9 11 12 13" - import software.amazon.lambda.powertools.tracing.Tracing; - import software.amazon.lambda.powertools.tracing.TracingUtils; - - public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { - - public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { - TracingUtils.withSubsegment("loggingResponse", subsegment -> { - // Some business logic - }); - - TracingUtils.withSubsegment("localNamespace", "loggingResponse", subsegment -> { - // Some business logic - }); - } - } - ``` +When working with multiple threads, you need to pass the trace entity to ensure proper trace context propagation. -=== "Multi Threaded Programming" +=== "Multi-threaded example" ```java hl_lines="7 9 10 11" import static software.amazon.lambda.powertools.tracing.TracingUtils.withEntitySubsegment; @@ -317,25 +338,33 @@ under a subsegment, or you are doing multithreaded programming. Refer examples b ## Instrumenting SDK clients and HTTP calls -Powertools for Lambda (Java) cannot intercept SDK clients instantiation to add X-Ray instrumentation. You should make sure to instrument the SDK clients explicitly. Refer details on -[how to instrument SDK client with Xray](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java.html#xray-sdk-java-awssdkclients) -and [outgoing http calls](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java.html#xray-sdk-java-httpclients). For example: +### AWS SDK for Java 2.x -=== "LambdaHandler.java" +Powertools for AWS Lambda (Java) includes the `aws-xray-recorder-sdk-aws-sdk-v2-instrumentor` library, which **automatically instruments all AWS SDK v2 clients** when you add the `powertools-tracing` dependency to your project. This means downstream calls to AWS services are traced without any additional configuration. - ```java hl_lines="1 2 7" - import com.amazonaws.xray.AWSXRay; - import com.amazonaws.xray.handlers.TracingHandler; +If you need more control over which clients are instrumented, you can manually add the `TracingInterceptor` to specific clients: + +=== "Manual instrumentation (optional)" + + ```java hl_lines="1 2 3 8 9 10 11" + import com.amazonaws.xray.interceptors.TracingInterceptor; + import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; + import software.amazon.awssdk.services.dynamodb.DynamoDbClient; public class LambdaHandler { - private AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard() - .withRegion(Regions.fromName(System.getenv("AWS_REGION"))) - .withRequestHandlers(new TracingHandler(AWSXRay.getGlobalRecorder())) + private DynamoDbClient client = DynamoDbClient.builder() + .region(Region.US_WEST_2) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .addExecutionInterceptor(new TracingInterceptor()) + .build() + ) .build(); // ... } ``` +For more details, refer to the [AWS X-Ray documentation on tracing AWS SDK calls](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-awssdkclients.html) and [outgoing HTTP calls](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java-httpclients.html). + ## Testing your code When using `@Tracing` annotation, your Junit test cases needs to be configured to create parent Segment required by [AWS X-Ray SDK for Java](https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-java.html). @@ -351,7 +380,7 @@ used internally via AWS X-Ray SDK to configure itself properly for lambda runtim === "Maven (pom.xml)" - ```xml hl_lines="4-13" + ```xml <build> ... <plugins> @@ -370,9 +399,9 @@ used internally via AWS X-Ray SDK to configure itself properly for lambda runtim ``` -=== "Gradle (build.gradle) " +=== "Gradle (build.gradle)" - ```json hl_lines="2-4" + ```json // Configures environment variable to avoid initialization of AWS X-Ray segments for each tests test { environment "LAMBDA_TASK_ROOT", "handler" @@ -418,6 +447,3 @@ Below is an example configuration needed for each test case. // test logic } ``` - - - diff --git a/docs/index.md b/docs/index.md index 9c5c803cb..655c16e03 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,6 +26,7 @@ This project separates core utilities that will be available in other runtimes v ## Install +<!-- TODO: Uncomment when SAM template is updated - https://github.com/aws-powertools/powertools-lambda-java/issues/1889 **Quick hello world example using SAM CLI** You can use [SAM](https://aws.amazon.com/serverless/sam/) to quickly setup a serverless project including Powertools for AWS Lambda (Java). @@ -71,8 +72,8 @@ Which runtime would you like to use? 12 - python3.10 Runtime: 2, 3, 4 or 5 ``` +--> -**Manual installation** Powertools for AWS Lambda (Java) dependencies are available in Maven Central. You can use your favourite dependency management tool to install it * [Maven](https://maven.apache.org/) @@ -90,7 +91,7 @@ Powertools for AWS Lambda (Java) dependencies are available in Maven Central. Yo </dependency> <dependency> <groupId>software.amazon.lambda</groupId> - <artifactId>powertools-logging</artifactId> + <artifactId>powertools-logging-log4j</artifactId> <version>{{ powertools.version }}</version> </dependency> <dependency> @@ -107,7 +108,8 @@ Powertools for AWS Lambda (Java) dependencies are available in Maven Central. Yo ... </dependencies> ... - <!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project --> + <!-- Configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project --> + <!-- Note: This AspectJ configuration is not needed when using the functional approach --> <build> <plugins> ... @@ -175,7 +177,8 @@ Powertools for AWS Lambda (Java) dependencies are available in Maven Central. Yo } dependencies { - aspect 'software.amazon.lambda:powertools-logging:{{ powertools.version }}' + // Note: This AspectJ configuration is not needed when using the functional approach + aspect 'software.amazon.lambda:powertools-logging-log4j:{{ powertools.version }}' aspect 'software.amazon.lambda:powertools-tracing:{{ powertools.version }}' aspect 'software.amazon.lambda:powertools-metrics:{{ powertools.version }}' } @@ -184,28 +187,15 @@ Powertools for AWS Lambda (Java) dependencies are available in Maven Central. Yo targetCompatibility = 11 ``` -???+ tip "Why a different configuration?" - Powertools for AWS Lambda (Java) is using [AspectJ](https://eclipse.dev/aspectj/doc/released/progguide/starting.html) internally - to handle annotations. Recently, in order to support Java 17 we had to move to `dev.aspectj:aspectj-maven-plugin` because - `org.codehaus.mojo:aspectj-maven-plugin` does not support Java 17. - Under the hood, `org.codehaus.mojo:aspectj-maven-plugin` is based on AspectJ 1.9.7, - while `dev.aspectj:aspectj-maven-plugin` is based on AspectJ 1.9.8, compiled for Java 11+. +???+ tip "Don't want to use AspectJ?" + Powertools for AWS Lambda (Java) now provides a functional API that doesn't require AspectJ configuration. Learn more about the [functional approach](./usage-patterns.md#functional-approach). ### Java Compatibility -Powertools for AWS Lambda (Java) supports all Java version from 11 up to 21 as well as the -[corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). +Powertools for AWS Lambda (Java) supports all Java versions from 11 to 25 in line with the [corresponding Lambda runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html). -For the following modules, Powertools for AWS Lambda (Java) leverages the **aspectj** library to provide annotations: -- Logging -- Metrics -- Tracing -- Parameters -- Idempotency -- Validation -- Large messages +In addition to the functional approach, [Logging](./core/logging.md), [Metrics](./core/metrics.md), [Tracing](./core/tracing.md), [Parameters](./utilities/parameters.md), [Idempotency](./utilities/idempotency.md), [Validation](./utilities/validation.md), and [Large Messages](./utilities/large_messages.md) utilities support annotations using AspectJ, which require configuration of the `aspectjrt` runtime library. - -You may need to add the good version of `aspectjrt` to your dependencies based on the jdk used for building your function: +You may need to add the appropriate version of `aspectjrt` to your dependencies based on the JDK used for building your function: ```xml <dependency> @@ -215,17 +205,18 @@ You may need to add the good version of `aspectjrt` to your dependencies based o </dependency> ``` -Use the following [dependency matrix](https://github.com/eclipse-aspectj/aspectj/blob/master/docs/dist/doc/JavaVersionCompatibility.md) between this library and the JDK: +Use the following [dependency matrix](https://github.com/eclipse-aspectj/aspectj/blob/master/docs/release/JavaVersionCompatibility.adoc) to understand which AspectJ version to use based on your JDK version: | JDK version | aspectj version | |-------------|------------------------| | `11-17` | `1.9.20.1` (or higher) | | `21` | `1.9.21` (or higher) | +| `25` | `1.9.25` (or higher) | ## Environment variables !!! info - **Explicit parameters take precedence over environment variables.** + Explicit parameters take precedence over environment variables. | Environment variable | Description | Utility | | -------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------- | diff --git a/docs/processes/maintainers.md b/docs/processes/maintainers.md index 8f7f6a8fd..f2839c532 100644 --- a/docs/processes/maintainers.md +++ b/docs/processes/maintainers.md @@ -17,7 +17,6 @@ This is document explains who the maintainers are, their responsibilities, and h | Maintainer | GitHub ID | Affiliation | | --------------- | -------------------------------------------------------------------- | ----------- | | Philipp Page | [phipag](https://github.com/phipag){target="\_blank" rel="nofollow"} | Amazon | -| Simon Thulbourn | [sthulb](https://github.com/sthulb){target="\_blank" rel="nofollow"} | Amazon | ## Emeritus @@ -25,6 +24,7 @@ Previous active maintainers who contributed to this project. | Maintainer | GitHub ID | Affiliation | | --------------------- | -------------------------------------------------------------------------------------- | ------------- | +| Simon Thulbourn | [sthulb](https://github.com/sthulb){target="\_blank" rel="nofollow"} | Former Amazon | | Jerome Van Der Linden | [jeromevdl](https://github.com/jeromevdl){target="\_blank" rel="nofollow"} | Amazon | | Michele Ricciardi | [mriccia](https://github.com/mriccia){target="\_blank" rel="nofollow"} | Amazon | | Scott Gerring | [scottgerring](https://github.com/scottgerring){target="\_blank" rel="nofollow"} | DataDog | diff --git a/docs/usage-patterns.md b/docs/usage-patterns.md new file mode 100644 index 000000000..e66538937 --- /dev/null +++ b/docs/usage-patterns.md @@ -0,0 +1,183 @@ +--- +title: Usage patterns +description: Getting to know the Powertools for AWS Lambda toolkit +--- + +<!-- markdownlint-disable MD043 --> + +Powertools for AWS Lambda (Java) is a collection of utilities designed to help you build serverless applications on AWS. + +The toolkit is modular, so you can pick and choose the utilities you need for your application, but also combine them for a complete solution for your serverless applications. + +## Patterns + +Many of the utilities provided can be used with different patterns, depending on your preferences and the structure of your code. + +### AspectJ Annotation + +If you prefer using annotations to apply cross-cutting concerns to your Lambda handlers, the AspectJ annotation pattern is a good fit. This approach lets you decorate methods with Powertools utilities using annotations, applying their functionality with minimal code changes. + +This pattern works well when you want to keep your business logic clean and separate concerns using aspect-oriented programming. + +<!-- prettier-ignore --> +!!! note + This approach requires configuring AspectJ compile-time weaving in your build tool (Maven or Gradle). See the [installation guide](./index.md#install) for setup instructions. + +=== "Logging" + + ```java + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.logging.CorrelationIdPaths; + import software.amazon.lambda.powertools.logging.Logging; + + public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + private static final Logger log = LoggerFactory.getLogger(App.class); + + @Logging(logEvent = true, correlationIdPath = CorrelationIdPaths.API_GATEWAY_REST) + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + log.info("Processing request"); + return new APIGatewayProxyResponseEvent().withStatusCode(200).withBody("Success"); + } + } + ``` + +=== "Metrics" + + ```java + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + import software.amazon.lambda.powertools.metrics.FlushMetrics; + import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.MetricsFactory; + import software.amazon.lambda.powertools.metrics.model.MetricUnit; + + public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + + @FlushMetrics(namespace = "ServerlessApp", service = "payment") + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + metrics.addMetric("SuccessfulBooking", 1, MetricUnit.COUNT); + return new APIGatewayProxyResponseEvent().withStatusCode(200).withBody("Success"); + } + } + ``` + +=== "Tracing" + + ```java + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + import software.amazon.lambda.powertools.tracing.Tracing; + import software.amazon.lambda.powertools.tracing.TracingUtils; + + public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + @Tracing + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + TracingUtils.putAnnotation("operation", "payment"); + return processPayment(); + } + + @Tracing + private APIGatewayProxyResponseEvent processPayment() { + return new APIGatewayProxyResponseEvent().withStatusCode(200).withBody("Success"); + } + } + ``` + +### Functional Approach + +If you prefer a more functional programming style or want to avoid AspectJ configuration, you can use the Powertools for AWS Lambda (Java) utilities directly in your code. This approach is more explicit and provides full control over how the utilities are applied. + +This pattern is ideal when you want to avoid AspectJ setup or prefer a more imperative style. It also eliminates the AspectJ runtime dependency, making your deployment package more lightweight. + +=== "Logging" + + ```java + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import software.amazon.lambda.powertools.logging.CorrelationIdPaths; + import software.amazon.lambda.powertools.logging.PowertoolsLogging; + + public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + private static final Logger log = LoggerFactory.getLogger(App.class); + + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + return PowertoolsLogging.withLogging( + context, + 0.7, + CorrelationIdPaths.API_GATEWAY_REST, + input, + () -> processRequest(input)); + } + + private APIGatewayProxyResponseEvent processRequest(APIGatewayProxyRequestEvent input) { + // do something with input + log.info("Processing request"); + return new APIGatewayProxyResponseEvent().withStatusCode(200).withBody("Success"); + } + } + ``` + +=== "Metrics" + + ```java + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + import software.amazon.lambda.powertools.metrics.Metrics; + import software.amazon.lambda.powertools.metrics.MetricsFactory; + import software.amazon.lambda.powertools.metrics.model.MetricUnit; + + public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + private static final Metrics metrics = MetricsFactory.getMetricsInstance(); + + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + try { + metrics.addMetric("SuccessfulBooking", 1, MetricUnit.COUNT); + return new APIGatewayProxyResponseEvent().withStatusCode(200).withBody("Success"); + } finally { + metrics.flush(); + } + } + } + ``` + +=== "Tracing" + + ```java + import com.amazonaws.services.lambda.runtime.Context; + import com.amazonaws.services.lambda.runtime.RequestHandler; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; + import software.amazon.lambda.powertools.tracing.TracingUtils; + + public class App implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { + TracingUtils.withSubsegment("processPayment", subsegment -> { + subsegment.putAnnotation("operation", "payment"); + // Business logic here + }); + return new APIGatewayProxyResponseEvent().withStatusCode(200).withBody("Success"); + } + } + ``` + +<!-- prettier-ignore --> +!!! note + The functional approach is available for all utilities. Further examples and detailed usage can be found in the individual documentation pages for each utility. diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index 83f256e6b..cecc65d7b 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -29,7 +29,7 @@ times with the same parameters**. This makes idempotent operations safe to retry === "Maven" - ```xml hl_lines="3-7 16 18 24-27" + ```xml hl_lines="3-7 16 18 25-28" <dependencies> ... <dependency> @@ -41,6 +41,7 @@ times with the same parameters**. This makes idempotent operations safe to retry </dependencies> ... <!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project --> + <!-- Note: This AspectJ configuration is not needed when using the functional approach --> <build> <plugins> ... @@ -82,10 +83,10 @@ times with the same parameters**. This makes idempotent operations safe to retry === "Gradle" - ```groovy hl_lines="3 11" + ```groovy hl_lines="3 11 12" plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' // Not needed when using the functional approach } repositories { @@ -93,7 +94,8 @@ times with the same parameters**. This makes idempotent operations safe to retry } dependencies { - aspect 'software.amazon.lambda:powertools-idempotency-dynamodb:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-idempotency-core:{{ powertools.version }}' // Not needed when using the functional approach + implementation 'software.amazon.lambda:powertools-idempotency-dynamodb:{{ powertools.version }}' } sourceCompatibility = 11 // or higher @@ -104,7 +106,7 @@ times with the same parameters**. This makes idempotent operations safe to retry Before getting started, you need to create a persistent storage layer where the idempotency utility can store its state - your Lambda functions will need read and write access to it. -As of now, Amazon DynamoDB is the only supported persistent storage layer, so you'll need to create a table first. +As of now, Amazon DynamoDB is the only supported persistent storage layer, so you'll need to create a table first or [bring your own persistence store](#bring-your-own-persistent-store). **Default table configuration** @@ -148,29 +150,29 @@ Resources: ``` !!! warning "Warning: Large responses with DynamoDB persistence layer" - When using this utility with DynamoDB, your function's responses must be [smaller than 400KB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html#limits-items). + When using this utility with DynamoDB, your function's responses must be [smaller than 400KB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Constraints.html#limits-items). Larger items cannot be written to DynamoDB and will cause exceptions. !!! info "Info: DynamoDB" - Each function invocation will generally make 2 requests to DynamoDB. If the - result returned by your Lambda is less than 1kb, you can expect 2 WCUs per invocation. For retried invocations, you will - see 1WCU and 1RCU. Review the [DynamoDB pricing documentation](https://aws.amazon.com/dynamodb/pricing/) to + Each function invocation will generally make 1 request to DynamoDB. If the + result returned by your Lambda is less than 1kb, you can expect 1 WCUs per invocation. For retried invocations, you will + see 1 WCU. In some cases, the utility might make 2 requests to DynamoDB in which case you will see 1 RCU and 1 WCU. Review the [DynamoDB pricing documentation](https://aws.amazon.com/dynamodb/pricing/) to estimate the cost. -### Idempotent annotation +### Basic usage -You can quickly start by initializing the `DynamoDBPersistenceStore` and using it with the `@Idempotent` annotation on your Lambda handler. +You can use Powertools for AWS Lambda Idempotency with either the `@Idempotent` annotation or the functional API. !!! warning "Important" Initialization and configuration of the `DynamoDBPersistenceStore` must be performed outside the handler, preferably in the constructor. -=== "App.java" +=== "@Idempotent annotation" ```java hl_lines="5-9 12 19" public class App implements RequestHandler<Subscription, SubscriptionResult> { public App() { - // we need to initialize idempotency store before the handleRequest method is called + // We need to initialize idempotency store before the handleRequest method is called Idempotency.config().withPersistenceStore( DynamoDBPersistenceStore.builder() .withTableName(System.getenv("TABLE_NAME")) @@ -191,6 +193,33 @@ You can quickly start by initializing the `DynamoDBPersistenceStore` and using i ``` +=== "Functional API" + + ```java hl_lines="5-9 13-14" + public class App implements RequestHandler<Subscription, SubscriptionResult> { + + public App() { + // We need to initialize idempotency store before the handleRequest method is called + Idempotency.config().withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withTableName(System.getenv("TABLE_NAME")) + .build() + ).configure(); + } + + public SubscriptionResult handleRequest(final Subscription event, final Context context) { + Idempotency.registerLambdaContext(context); + return Idempotency.makeIdempotent(this::processSubscription, event, SubscriptionResult.class); + } + + private SubscriptionResult processSubscription(Subscription event) { + SubscriptionPayment payment = createSubscriptionPayment(event.getUsername(), event.getProductId()); + return new SubscriptionResult(payment.getId(), "success", 200); + } + } + + ``` + === "Example event" ```json @@ -200,25 +229,32 @@ You can quickly start by initializing the `DynamoDBPersistenceStore` and using i } ``` -#### Idempotent annotation on another method +#### Making non-handler methods idempotent -You can use the `@Idempotent` annotation for any synchronous Java function, not only the `handleRequest` one. +You can make any synchronous Java function idempotent, not only the `handleRequest` handler. -When using `@Idempotent` annotation on another method, you must tell which parameter in the method signature has the data we should use: +**With the `@Idempotent` annotation**, you must specify which parameter contains the idempotency key: - If the method only has one parameter, it will be used by default. - If there are 2 or more parameters, you must set the `@IdempotencyKey` on the parameter to use. +**With the functional API**, you explicitly pass the idempotency key: + + - For single-parameter methods, use `Idempotency.makeIdempotent(this::method, param, ReturnType.class)` + - For multi-parameter methods, use `Idempotency.makeIdempotent(idempotencyKey, () -> method(param1, param2), ReturnType.class)` + !!! info "The parameter must be serializable in JSON. We use Jackson internally to (de)serialize objects" -=== "AppSqsEvent.java" +=== "@Idempotent annotation" This example also demonstrates how you can integrate with [Batch utility](batch.md), so you can process each record in an idempotent manner. - ```java hl_lines="19 23-25 30-31" - public class AppSqsEvent implements RequestHandler<SQSEvent, String> { + ```java hl_lines="6-15 17-19 27-28" + public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { + + private final BatchMessageHandler<SQSEvent, SQSBatchResponse> handler; - public AppSqsEvent() { + public SqsBatchHandler() { Idempotency.config() .withPersistenceStore( DynamoDBPersistenceStore.builder() @@ -226,31 +262,66 @@ When using `@Idempotent` annotation on another method, you must tell which param .build() ).withConfig( IdempotencyConfig.builder() - .withEventKeyJMESPath("messageId") // see Choosing a payload subset section + .withEventKeyJMESPath("messageId") .build() ).configure(); - } + + handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithRawMessageHandler(this::processMessage); + } @Override - @SqsBatch(SampleMessageHandler.class) - public String handleRequest(SQSEvent input, Context context) { - dummy("hello", "world"); - return "{\"statusCode\": 200}"; + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + return handler.processBatch(sqsEvent, context); } @Idempotent - private String dummy(String argOne, @IdempotencyKey String argTwo) { - return "something"; + private void processMessage(@IdempotencyKey SQSEvent.SQSMessage message) { + // Process message } + } + ``` + +=== "Functional API" + + This example also demonstrates how you can integrate with the [Batch utility](batch.md), so you can process each record in an idempotent manner. **Note: The JMESPath function still applies even when passing the idempotency key manually.** + + ```java hl_lines="6-15 17-19 24 29" + public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { - public static class SampleMessageHandler implements SqsMessageHandler<Object> { - @Override - @Idempotent - // no need to use @IdempotencyKey as there is only one parameter - public String process(SQSMessage message) { - String returnVal = doSomething(message.getBody()); - return returnVal; - } + private final BatchMessageHandler<SQSEvent, SQSBatchResponse> handler; + + public SqsBatchHandler() { + Idempotency.config() + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withTableName(System.getenv("TABLE_NAME")) + .build() + ).withConfig( + IdempotencyConfig.builder() + .withEventKeyJMESPath("messageId") + .build() + ).configure(); + + handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithRawMessageHandler(this::processMessage); + } + + @Override + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + Idempotency.registerLambdaContext(context); + return handler.processBatch(sqsEvent, context); + } + + private void processMessage(SQSEvent.SQSMessage message) { + Idempotency.makeIdempotent(this::handleMessage, message, Void.class); + } + + private Void handleMessage(SQSEvent.SQSMessage message) { + // Process message + return null; } } ``` @@ -304,9 +375,9 @@ Imagine the function executes successfully, but the client never receives the re To alter this behaviour, you can use the [JMESPath built-in function](serialization.md#jmespath-functions) `powertools_json()` to treat the payload as a JSON object rather than a string. -=== "PaymentFunction.java" +=== "@Idempotent annotation" - ```java hl_lines="5-7 16 29-31" + ```java hl_lines="7 16" public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { public PaymentFunction() { @@ -344,6 +415,50 @@ Imagine the function executes successfully, but the client never receives the re } ``` +=== "Functional API" + + ```java hl_lines="7 17-18" + public class PaymentFunction implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { + + public PaymentFunction() { + Idempotency.config() + .withConfig( + IdempotencyConfig.builder() + .withEventKeyJMESPath("powertools_json(body)") + .build()) + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withTableName(System.getenv("TABLE_NAME")) + .build()) + .configure(); + } + + public APIGatewayProxyResponseEvent handleRequest(final APIGatewayProxyRequestEvent event, final Context context) { + Idempotency.registerLambdaContext(context); + return Idempotency.makeIdempotent(this::processPayment, event, APIGatewayProxyResponseEvent.class); + } + + private APIGatewayProxyResponseEvent processPayment(APIGatewayProxyRequestEvent event) { + APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent(); + + try { + Subscription subscription = JsonConfig.get().getObjectMapper().readValue(event.getBody(), Subscription.class); + + SubscriptionPayment payment = createSubscriptionPayment( + subscription.getUsername(), + subscription.getProductId() + ); + + return response + .withStatusCode(200) + .withBody(String.format("{\"paymentId\":\"%s\"}", payment.getId())); + + } catch (JsonProcessingException e) { + return response.withStatusCode(500); + } + } + ``` + === "Example event" ```json hl_lines="3" @@ -417,46 +532,82 @@ The client was successful in receiving the result after the retry. Since the Lam #### Lambda timeouts -This is automatically done when you annotate your Lambda handler with [@Idempotent annotation](#idempotent-annotation). - To prevent against extended failed retries when a [Lambda function times out](https://aws.amazon.com/premiumsupport/knowledge-center/lambda-verify-invocation-timeouts/), Powertools for AWS Lambda (Java) calculates and includes the remaining invocation available time as part of the idempotency record. !!! example If a second invocation happens **after** this timestamp, and the record is marked as `INPROGRESS`, we will execute the invocation again as if it was in the `EXPIRED` state. This means that if an invocation expired during execution, it will be quickly executed again on the next retry. -!!! important - If you are using the [@Idempotent annotation on another method](#idempotent-annotation-on-another-method) to guard isolated parts of your code, you must use `registerLambdaContext` method available in the `Idempotency` object to benefit from this protection. +**With the `@Idempotent` annotation**, this is automatically done when you annotate your Lambda handler. + +**With the functional API** or when using the `@Idempotent` annotation on methods other than the handler, you must call `Idempotency.registerLambdaContext(context)` to benefit from this protection. +!!! important Here is an example on how you register the Lambda context in your handler: - ```java hl_lines="13-19" title="Registering the Lambda context" - public class PaymentHandler implements RequestHandler<SQSEvent, List<String>> { - - public PaymentHandler() { - Idempotency.config() - .withPersistenceStore( - DynamoDBPersistenceStore.builder() - .withTableName(System.getenv("TABLE_NAME")) - .build()) - .configure(); - } + === "@Idempotent annotation" + + ```java hl_lines="14" title="Registering the Lambda context" + public class PaymentHandler implements RequestHandler<SQSEvent, List<String>> { + + public PaymentHandler() { + Idempotency.config() + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withTableName(System.getenv("TABLE_NAME")) + .build()) + .configure(); + } + + @Override + public List<String> handleRequest(SQSEvent sqsEvent, Context context) { + Idempotency.registerLambdaContext(context); + return sqsEvent.getRecords().stream().map(record -> process(record.getMessageId(), record.getBody())).collect(Collectors.toList()); + } + + @Idempotent + private String process(String messageId, @IdempotencyKey String messageBody) { + logger.info("Processing messageId: {}", messageId); + PaymentRequest request = extractDataFrom(messageBody).as(PaymentRequest.class); + return paymentService.process(request); + } - @Override - public List<String> handleRequest(SQSEvent sqsEvent, Context context) { - Idempotency.registerLambdaContext(context); - return sqsEvent.getRecords().stream().map(record -> process(record.getMessageId(), record.getBody())).collect(Collectors.toList()); } - - @Idempotent - private String process(String messageId, @IdempotencyKey String messageBody) { - logger.info("Processing messageId: {}", messageId); - PaymentRequest request = extractDataFrom(messageBody).as(PaymentRequest.class); - return paymentService.process(request); + ``` + + === "Functional API" + + ```java hl_lines="14" title="Registering the Lambda context" + public class PaymentHandler implements RequestHandler<SQSEvent, List<String>> { + + public PaymentHandler() { + Idempotency.config() + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withTableName(System.getenv("TABLE_NAME")) + .build()) + .configure(); + } + + @Override + public List<String> handleRequest(SQSEvent sqsEvent, Context context) { + Idempotency.registerLambdaContext(context); + return sqsEvent.getRecords().stream() + .map(record -> Idempotency.makeIdempotent( + record.getBody(), + () -> process(record.getMessageId(), record.getBody()), + String.class)) + .collect(Collectors.toList()); + } + + private String process(String messageId, String messageBody) { + logger.info("Processing messageId: {}", messageId); + PaymentRequest request = extractDataFrom(messageBody).as(PaymentRequest.class); + return paymentService.process(request); + } + } - - } - ``` + ``` #### Lambda timeout sequence diagram @@ -499,9 +650,11 @@ sequenceDiagram ### Handling exceptions -If you are using the `@Idempotent` annotation on your Lambda handler or any other method, any unhandled exceptions that are thrown during the code execution will cause **the record in the persistence layer to be deleted**. +**With the `@Idempotent` annotation**, any unhandled exceptions that are thrown during the code execution will cause **the record in the persistence layer to be deleted**. This means that new invocations will execute your code again despite having the same payload. If you don't want the record to be deleted, you need to catch exceptions within the idempotent function and return a successful response. +**With the functional API**, exceptions are handled the same way - unhandled exceptions will cause the record to be deleted. You should catch and handle exceptions within your idempotent function if you want to preserve the record. + <center> ```mermaid sequenceDiagram @@ -553,7 +706,7 @@ If an Exception is raised _outside_ the scope of a decorated method and after yo This persistence store is built-in, and you can either use an existing DynamoDB table or create a new one dedicated for idempotency state (recommended). Use the builder to customize the table structure: -```java hl_lines="3-7" title="Customizing DynamoDBPersistenceStore to suit your table structure" +```java hl_lines="2-7" title="Customizing DynamoDBPersistenceStore to suit your table structure" DynamoDBPersistenceStore.builder() .withTableName(System.getenv("TABLE_NAME")) .withKeyAttr("idempotency_key") @@ -579,11 +732,68 @@ When using DynamoDB as a persistence layer, you can alter the attribute names by ## Advanced +### Using explicit function names + +When using the functional API, if you need to call different methods with the same payload as the idempotency key, you must provide explicit function names to differentiate between them. This ensures each function has its own idempotency scope. + +=== "Functional API with explicit names" + + ```java hl_lines="5-9 11-15" + public Response handleRequest(Order order, Context context) { + Idempotency.registerLambdaContext(context); + + // Same orderId, different operations - need explicit function names + Idempotency.makeIdempotent( + "processPayment", + order.getId(), + () -> processPayment(order), + PaymentResult.class); + + Idempotency.makeIdempotent( + "sendConfirmation", + order.getId(), + () -> sendEmail(order), + EmailResult.class); + + return new Response("success"); + } + ``` + +!!! note + When using the `@Idempotent` annotation, the function name is automatically inferred from the method name, so this is not needed. + +### Generic return types support + +The functional API supports making methods with generic return types idempotent using Jackson's `TypeReference`. This is not possible with the `@Idempotent` annotation due to type erasure. + +=== "Functional API with TypeReference" + + ```java hl_lines="1 6-10" + import com.fasterxml.jackson.core.type.TypeReference; + + public Map<String, Basket> handleRequest(Product input, Context context) { + Idempotency.registerLambdaContext(context); + + return Idempotency.makeIdempotent( + this::processProduct, + input, + new TypeReference<Map<String, Basket>>() {} + ); + } + + private Map<String, Basket> processProduct(Product product) { + // business logic returning generic type + Map<String, Basket> result = new HashMap<>(); + // ... + return result; + } + ``` + ### Customizing the default behavior Idempotency behavior can be further configured with **`IdempotencyConfig`** using a builder: -```java hl_lines="2-8" title="Customizing IdempotencyConfig" +```java hl_lines="2-9" title="Customizing IdempotencyConfig" IdempotencyConfig.builder() .withEventKeyJMESPath("id") .withPayloadValidationJMESPath("paymentId") @@ -667,7 +877,7 @@ By default, we will return the same result as it returned before, however in thi With **`PayloadValidationJMESPath`**, you can provide an additional JMESPath expression to specify which part of the event body should be validated against previous idempotent invocations -=== "App.java" +=== "@Idempotent annotation" ```java hl_lines="8 13 20 26" public App() { @@ -700,6 +910,43 @@ With **`PayloadValidationJMESPath`**, you can provide an additional JMESPath exp } ``` +=== "Functional API" + + ```java hl_lines="8 14-15 24 30" + public App() { + Idempotency.config() + .withPersistenceStore(DynamoDBPersistenceStore.builder() + .withTableName(System.getenv("TABLE_NAME")) + .build()) + .withConfig(IdempotencyConfig.builder() + .withEventKeyJMESPath("[userDetail, productId]") + .withPayloadValidationJMESPath("amount") + .build()) + .configure(); + } + + public SubscriptionResult handleRequest(final Subscription input, final Context context) { + Idempotency.registerLambdaContext(context); + return Idempotency.makeIdempotent(this::processSubscription, input, SubscriptionResult.class); + } + + private SubscriptionResult processSubscription(Subscription input) { + // Creating a subscription payment is a side + // effect of calling this function! + SubscriptionPayment payment = createSubscriptionPayment( + input.getUserDetail().getUsername(), + input.getProductId(), + input.getAmount() + ) + // ... + return new SubscriptionResult( + "success", 200, + payment.getId(), + payment.getAmount() + ); + } + ``` + === "Example Event 1" ```json hl_lines="8" @@ -745,9 +992,9 @@ This means that we will throw **`IdempotencyKeyException`** if the evaluation of When set to `false` (the default), if the idempotency key is null, then the data is not persisted in the store. -=== "App.java" +=== "@Idempotent annotation" - ```java hl_lines="9-10 13" + ```java hl_lines="9" public App() { Idempotency.config() .withPersistenceStore(DynamoDBPersistenceStore.builder() @@ -767,6 +1014,32 @@ When set to `false` (the default), if the idempotency key is null, then the data } ``` +=== "Functional API" + + ```java hl_lines="9" + public App() { + Idempotency.config() + .withPersistenceStore(DynamoDBPersistenceStore.builder() + .withTableName(System.getenv("TABLE_NAME")) + .build()) + .withConfig(IdempotencyConfig.builder() + // Requires "user"."uid" and "orderId" to be present + .withEventKeyJMESPath("[user.uid, orderId]") + .withThrowOnNoIdempotencyKey(true) + .build()) + .configure(); + } + + public OrderResult handleRequest(final Order input, final Context context) { + Idempotency.registerLambdaContext(context); + return Idempotency.makeIdempotent(this::processOrder, input, OrderResult.class); + } + + private OrderResult processOrder(Order input) { + // ... + } + ``` + === "Success Event" ```json hl_lines="3 6" @@ -977,7 +1250,7 @@ To unit test your function with DynamoDB Local, you can refer to this guide to [ === "pom.xml" - ```xml hl_lines="4-6 24-26 28-31 42 45-47" + ```xml <dependencies> <!-- maven dependency for DynamoDB local --> <dependency> @@ -1046,7 +1319,7 @@ To unit test your function with DynamoDB Local, you can refer to this guide to [ === "AppTest.java" - ```java hl_lines="13-18 24-30 34" + ```java public class AppTest { @Mock private Context context; @@ -1143,7 +1416,7 @@ To unit test your function with DynamoDB Local, you can refer to this guide to [ === "App.java" - ```java hl_lines="8 9 16" + ```java public class App implements RequestHandler<Subscription, SubscriptionResult> { public App() { @@ -1174,7 +1447,7 @@ To unit test your function with DynamoDB Local, you can refer to this guide to [ === "shell" - ```shell hl_lines="2 6 7 12 16 21 22" + ```shell # use or create a docker network docker network inspect sam-local || docker network create sam-local @@ -1201,7 +1474,7 @@ To unit test your function with DynamoDB Local, you can refer to this guide to [ === "env.json" - ```json hl_lines="3" + ```json { "IdempotentFunction": { "TABLE_NAME": "idempotency" diff --git a/docs/utilities/large_messages.md b/docs/utilities/large_messages.md index 38228afe9..9d14c8228 100644 --- a/docs/utilities/large_messages.md +++ b/docs/utilities/large_messages.md @@ -4,7 +4,7 @@ description: Utility --- The large message utility handles SQS and SNS messages which have had their payloads -offloaded to S3 if they are larger than the maximum allowed size (256 KB). +offloaded to S3 if they are larger than the maximum allowed size (1 MB). ## Features @@ -27,12 +27,12 @@ stateDiagram-v2 sendMsg --> extendLib state extendLib { state if_big <<choice>> - bigMsg: MessageBody > 256KB ? + bigMsg: MessageBody > 1MB ? putObject: putObject(S3Bucket, S3Key, Body) updateMsg: Update MessageBody<br>with a pointer to S3<br>and add a message attribute bigMsg --> if_big - if_big --> [*]: size(body) <= 256kb - if_big --> putObject: size(body) > 256kb + if_big --> [*]: size(body) <= 1MB + if_big --> putObject: size(body) > 1MB putObject --> updateMsg updateMsg --> [*] } @@ -72,7 +72,7 @@ stateDiagram-v2 ``` -SQS and SNS message payload is limited to 256KB. If you wish to send messages with a larger payload, you can leverage the +SQS and SNS message payload is limited to 1MB. If you wish to send messages with a larger payload, you can leverage the [amazon-sqs-java-extended-client-lib](https://github.com/awslabs/amazon-sqs-java-extended-client-lib) or [amazon-sns-java-extended-client-lib](https://github.com/awslabs/amazon-sns-java-extended-client-lib) which offload the message to Amazon S3. See documentation @@ -87,16 +87,14 @@ extended client libraries. Once a message's payload has been processed successfu utility deletes the payload from S3. This utility is compatible with -versions *[1.1.0+](https://github.com/awslabs/amazon-sqs-java-extended-client-lib/releases/tag/1.1.0)* -of amazon-sqs-java-extended-client-lib -and *[1.0.0+](https://github.com/awslabs/amazon-sns-java-extended-client-lib/releases/tag/1.0.0)* -of amazon-sns-java-extended-client-lib. +versions *[1.1.0+](https://github.com/awslabs/amazon-sqs-java-extended-client-lib/releases/tag/1.1.0)* and *[2.0.0+](https://github.com/awslabs/amazon-sqs-java-extended-client-lib/releases/tag/2.0.0)* +of [amazon-sqs-java-extended-client-lib](https://github.com/awslabs/amazon-sqs-java-extended-client-lib) / [amazon-sns-java-extended-client-lib](https://github.com/awslabs/amazon-sns-java-extended-client-lib). ## Install === "Maven" - ```xml hl_lines="3-7 16 18 24-27" + ```xml hl_lines="3-7 25-28" <dependencies> ... <dependency> @@ -108,6 +106,7 @@ of amazon-sns-java-extended-client-lib. </dependencies> ... <!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project --> + <!-- Note: This AspectJ configuration is not needed when using the functional approach --> <build> <plugins> ... @@ -152,7 +151,7 @@ of amazon-sns-java-extended-client-lib. ```groovy hl_lines="3 11" plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' // Not needed when using the functional approach } repositories { @@ -160,7 +159,7 @@ of amazon-sns-java-extended-client-lib. } dependencies { - aspect 'software.amazon.lambda:powertools-large-messages:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-large-messages:{{ powertools.version }}' // Use 'implementation' instead of 'aspect' when using the functional approach } sourceCompatibility = 11 // or higher @@ -175,14 +174,20 @@ on the S3 bucket used for the large messages offloading: - `s3:GetObject` - `s3:DeleteObject` -## Annotation +## Usage -The annotation `@LargeMessage` can be used on any method where the *first* parameter is one of: +You can use the Large Messages utility with either the `@LargeMessage` annotation or the functional API. + +The `@LargeMessage` annotation can be used on any method where the *first* parameter is one of: - `SQSEvent.SQSMessage` - `SNSEvent.SNSRecord` -=== "SQS Example" +The functional API `LargeMessages.processLargeMessage()` accepts the same message types. + +### Basic usage + +=== "@LargeMessage annotation - SQS" ```java hl_lines="8 13 15" import software.amazon.lambda.powertools.largemessages.LargeMessage; @@ -204,7 +209,28 @@ The annotation `@LargeMessage` can be used on any method where the *first* param } ``` -=== "SNS Example" +=== "Functional API - SQS" + + ```java hl_lines="1 8" + import software.amazon.lambda.powertools.largemessages.LargeMessages; + + public class SqsMessageHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { + + @Override + public SQSBatchResponse handleRequest(SQSEvent event, Context context) { + for (SQSMessage message: event.getRecords()) { + LargeMessages.processLargeMessage(message, this::processRawMessage); + } + return SQSBatchResponse.builder().build(); + } + + private void processRawMessage(SQSEvent.SQSMessage sqsMessage) { + // sqsMessage.getBody() will contain the content of the S3 object + } + } + ``` + +=== "@LargeMessage annotation - SNS" ```java hl_lines="7 11 13" import software.amazon.lambda.powertools.largemessages.LargeMessage; @@ -224,6 +250,25 @@ The annotation `@LargeMessage` can be used on any method where the *first* param } ``` +=== "Functional API - SNS" + + ```java hl_lines="1 7" + import software.amazon.lambda.powertools.largemessages.LargeMessages; + + public class SnsRecordHandler implements RequestHandler<SNSEvent, String> { + + @Override + public String handleRequest(SNSEvent event, Context context) { + return LargeMessages.processLargeMessage(event.records.get(0), this::processSNSRecord); + } + + private String processSNSRecord(SNSEvent.SNSRecord snsRecord) { + // snsRecord.getSNS().getMessage() will contain the content of the S3 object + return "Hello World"; + } + } + ``` + When the Lambda function is invoked with a SQS or SNS event, the utility first checks if the content was offloaded to S3. In the case of a large message, there is a message attribute specifying the size of the offloaded message and the message contains a pointer to the S3 object. @@ -233,9 +278,9 @@ and place the content of the object in the message payload. You can then directl If there was an error during the S3 download, the function will fail with a `LargeMessageProcessingException`. After your code is invoked and returns without error, the object is deleted from S3 -using the `deleteObject(bucket, key)` API. You can disable the deletion of S3 objects with the following configuration: +using the `deleteObject(bucket, key)` API. You can disable the deletion of S3 objects: -=== "Don't delete S3 Objects" +=== "@LargeMessage annotation" ```java @LargeMessage(deleteS3Object = false) private void processRawMessage(SQSEvent.SQSMessage sqsMessage) { @@ -243,71 +288,143 @@ using the `deleteObject(bucket, key)` API. You can disable the deletion of S3 ob } ``` +=== "Functional API" + ```java + LargeMessages.processLargeMessage(message, this::processRawMessage, false); + ``` + !!! tip "Use together with batch module" This utility works perfectly together with the batch module (`powertools-batch`), especially for SQS: - ```java hl_lines="2 5-7 12 15 16" title="Combining batch and large message modules" - public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { - private final BatchMessageHandler<SQSEvent, SQSBatchResponse> handler; - - public SqsBatchHandler() { - handler = new BatchMessageHandlerBuilder() - .withSqsBatchHandler() - .buildWithRawMessageHandler(this::processMessage); - } + === "@LargeMessage annotation" + ```java hl_lines="2 5-7 12 15 16" title="Combining batch and large message modules" + public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { + private final BatchMessageHandler<SQSEvent, SQSBatchResponse> handler; + + public SqsBatchHandler() { + handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithRawMessageHandler(this::processMessage); + } - @Override - public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { - return handler.processBatch(sqsEvent, context); + @Override + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + return handler.processBatch(sqsEvent, context); + } + + @LargeMessage + private void processMessage(SQSEvent.SQSMessage sqsMessage) { + // do something with the message + } } + ``` - @LargeMessage - private void processMessage(SQSEvent.SQSMessage sqsMessage) { - // do something with the message + === "Functional API" + ```java hl_lines="7-9 14 18" title="Combining batch and large message modules" + import software.amazon.lambda.powertools.largemessages.LargeMessages; + + public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { + private final BatchMessageHandler<SQSEvent, SQSBatchResponse> handler; + + public SqsBatchHandler() { + handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithRawMessageHandler(this::processMessage); + } + + @Override + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + return handler.processBatch(sqsEvent, context); + } + + private void processMessage(SQSEvent.SQSMessage sqsMessage) { + LargeMessages.processLargeMessage(sqsMessage, this::handleProcessedMessage); + } + + private void handleProcessedMessage(SQSEvent.SQSMessage processedMessage) { + // do something with the message + } } - } - ``` + ``` !!! tip "Use together with idempotency module" - This utility also works together with the idempotency module (`powertools-idempotency`). - You can add both the `@LargeMessage` and `@Idempotent` annotations, in any order, to the same method. - The `@Idempotent` takes precedence over the `@LargeMessage` annotation. - It means Idempotency module will use the initial raw message (containing the S3 pointer) and not the large message. + When using the `@LargeMessage` annotation, you can combine it with the `@Idempotent` annotation on the same method. + The `@Idempotent` takes precedence over the `@LargeMessage` annotation, meaning the Idempotency module will use the initial raw message (containing the S3 pointer) and not the large message. + + When using the functional API, call `LargeMessages.processLargeMessage()` from within the `@Idempotent` method to ensure idempotency is based on the S3 pointer, not the unwrapped large blob. - ```java hl_lines="6 23-25" title="Combining idempotency and large message modules" - public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { + === "@LargeMessage annotation" + ```java hl_lines="6 23-25" title="Combining idempotency and large message modules" + public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { - public SqsBatchHandler() { - Idempotency.config().withConfig( - IdempotencyConfig.builder() - .withEventKeyJMESPath("body") // get the body of the message for the idempotency key - .build()) - .withPersistenceStore( - DynamoDBPersistenceStore.builder() - .withTableName(System.getenv("IDEMPOTENCY_TABLE")) - .build() - ).configure(); - } + public SqsBatchHandler() { + Idempotency.config().withConfig( + IdempotencyConfig.builder() + .withEventKeyJMESPath("body") // get the body of the message for the idempotency key + .build()) + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withTableName(System.getenv("IDEMPOTENCY_TABLE")) + .build() + ).configure(); + } - @Override - public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { - for (SQSMessage message: event.getRecords()) { - processRawMessage(message, context); + @Override + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + for (SQSMessage message: event.getRecords()) { + processRawMessage(message, context); + } + return SQSBatchResponse.builder().build(); + } + + @Idempotent + @LargeMessage + private String processRawMessage(@IdempotencyKey SQSEvent.SQSMessage sqsMessage, Context context) { + // do something with the message } - return SQSBatchResponse.builder().build(); } + ``` - @Idempotent - @LargeMessage - private String processRawMessage(@IdempotencyKey SQSEvent.SQSMessage sqsMessage, Context context) { - // do something with the message + === "Functional API" + ```java hl_lines="8 25 27" title="Combining idempotency and large message modules" + import software.amazon.lambda.powertools.largemessages.LargeMessages; + + public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { + + public SqsBatchHandler() { + Idempotency.config().withConfig( + IdempotencyConfig.builder() + .withEventKeyJMESPath("body") // get the body of the message for the idempotency key + .build()) + .withPersistenceStore( + DynamoDBPersistenceStore.builder() + .withTableName(System.getenv("IDEMPOTENCY_TABLE")) + .build() + ).configure(); + } + + @Override + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + for (SQSMessage message: event.getRecords()) { + processRawMessage(message, context); + } + return SQSBatchResponse.builder().build(); + } + + @Idempotent + private String processRawMessage(@IdempotencyKey SQSEvent.SQSMessage sqsMessage, Context context) { + return LargeMessages.processLargeMessage(sqsMessage, this::handleProcessedMessage); + } + + private String handleProcessedMessage(SQSEvent.SQSMessage processedMessage) { + // do something with the message + } } - } - ``` + ``` ## Customizing S3 client configuration -To interact with S3, the utility creates a default S3 Client : +To interact with S3, the utility creates a default S3 Client: === "Default S3 Client" ```java @@ -317,9 +434,9 @@ To interact with S3, the utility creates a default S3 Client : .build(); ``` -If you need to customize this `S3Client`, you can leverage the `LargeMessageConfig` singleton: +If you need to customize this `S3Client`, you can leverage the `LargeMessageConfig` singleton. This works with both the annotation and functional API: -=== "Custom S3 Client" +=== "@LargeMessage annotation" ```java hl_lines="6" import software.amazon.lambda.powertools.largemessages.LargeMessage; @@ -342,6 +459,28 @@ If you need to customize this `S3Client`, you can leverage the `LargeMessageConf } ``` +=== "Functional API" + ```java hl_lines="1 6" + import software.amazon.lambda.powertools.largemessages.LargeMessages; + + public class SnsRecordHandler implements RequestHandler<SNSEvent, String> { + + public SnsRecordHandler() { + LargeMessageConfig.init().withS3Client(/* put your custom S3Client here */); + } + + @Override + public String handleRequest(SNSEvent event, Context context) { + return LargeMessages.processLargeMessage(event.records.get(0), this::processSNSRecord); + } + + private String processSNSRecord(SNSEvent.SNSRecord snsRecord) { + // snsRecord.getSNS().getMessage() will contain the content of the S3 object + return "Hello World"; + } + } + ``` + ## Migration from the SQS Large Message utility - Replace the dependency in maven / gradle: `powertools-sqs` ==> `powertools-large-messages` diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index beb460aa6..6de47df68 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -49,6 +49,7 @@ Note that you must provide the concrete parameters module you want to use below </dependencies> ... <!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project --> + <!-- Note: This AspectJ configuration is not needed when using the provider classes directly (without annotations) --> <build> <plugins> ... @@ -91,10 +92,10 @@ Note that you must provide the concrete parameters module you want to use below === "Gradle" - ```groovy hl_lines="3 11 12" + ```groovy hl_lines="3 11-13" plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' // Not needed when using provider classes directly (without annotations) } repositories { @@ -103,7 +104,8 @@ Note that you must provide the concrete parameters module you want to use below dependencies { // TODO! Provide the parameters module you want to use here - aspect 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}' // Not needed when using provider classes directly (without annotations) + implementation 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}' // Use this instead of 'aspect' when using provider classes directly } sourceCompatibility = 11 // or higher @@ -124,19 +126,18 @@ This utility requires additional permissions to work as expected. See the table | AppConfig | `AppConfigProvider.get(String)` `AppConfigProvider.getMultiple(string)` | `appconfig:StartConfigurationSession`, `appConfig:GetLatestConfiguration` | ## Retrieving Parameters -You can retrieve parameters either using annotations or by using the `xParamProvider` class for each parameter -provider directly. The latter is useful if you need to configure the underlying SDK client, for example to use -a different region or credentials, the former is simpler to use. +You can retrieve parameters using either annotations or provider classes directly: + +- **Annotations** (e.g., `@SecretsParam`, `@SSMParam`) - Simpler syntax with field injection, but requires AspectJ configuration +- **Provider classes** (e.g., `SecretsProvider`, `SSMProvider`) - No AspectJ required, useful when you need to configure the underlying SDK client (e.g., different region or credentials), or prefer avoiding AspectJ setup ## Built-in provider classes -This section describes the built-in provider classes for each parameter store, providing -examples showing how to inject parameters using annotations, and how to use the provider -interface. In cases where a provider supports extra features, these will also be described. +This section describes the built-in provider classes for each parameter store. For each provider, examples are shown for both the annotation-based approach and the provider class approach. In cases where a provider supports extra features, these will also be described. ### Secrets Manager -=== "Secrets Manager: @SecretsParam" +=== "@SecretsParam annotation" ```java hl_lines="8 9" import com.amazonaws.services.lambda.runtime.Context; @@ -156,7 +157,7 @@ interface. In cases where a provider supports extra features, these will also be } ``` -=== "Secrets Manager: SecretsProvider" +=== "SecretsProvider class" ```java hl_lines="12-15 19" import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; @@ -195,7 +196,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen | **recursive()** | `False` | For `getMultiple()` only, will fetch all parameter values recursively based on a path prefix. | -=== "SSM Parameter Store: @SSMParam" +=== "@SSMParam annotation" ```java hl_lines="8 9" import com.amazonaws.services.lambda.runtime.Context; @@ -214,7 +215,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen } ``` -=== "SSM Parameter Store: SSMProvider" +=== "SSMProvider class" ```java hl_lines="12-15 19-20 22" import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; @@ -246,15 +247,14 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen } ``` -=== "SSM Parameter Store: Additional Options" +=== "Additional Options" - ```java hl_lines="9 12" - import software.amazon.lambda.powertools.parameters.SSMProvider; - import software.amazon.lambda.powertools.parameters.ParamManager; + ```java hl_lines="5 9 12" + import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; public class AppWithSSM implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { // Get an instance of the SSM Provider - SSMProvider ssmProvider = ParamManager.getSsmProvider(); + SSMProvider ssmProvider = SSMProvider.builder().build(); // Retrieve a single parameter and decrypt it String value = ssmProvider.withDecryption().get("/my/parameter"); @@ -267,7 +267,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen ### DynamoDB -=== "DynamoDB: @DyanmoDbParam" +=== "@DynamoDbParam annotation" ```java hl_lines="8 9" import com.amazonaws.services.lambda.runtime.Context; @@ -286,7 +286,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen } ``` -=== "DynamoDB: DynamoDbProvider" +=== "DynamoDbProvider class" ```java hl_lines="12-15 19-20 22" import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; @@ -320,7 +320,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen ### AppConfig -=== "AppConfig: @AppConfigParam" +=== "@AppConfigParam annotation" ```java hl_lines="8 9" import com.amazonaws.services.lambda.runtime.Context; @@ -339,7 +339,7 @@ The AWS Systems Manager Parameter Store provider supports two additional argumen } ``` -=== "AppConfig: AppConfigProvider" +=== "AppConfigProvider class" ```java hl_lines="12-15 19-20" import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64; diff --git a/docs/utilities/validation.md b/docs/utilities/validation.md index ec35b7034..8e0d2c631 100644 --- a/docs/utilities/validation.md +++ b/docs/utilities/validation.md @@ -26,6 +26,7 @@ This utility provides JSON Schema validation for payloads held within events and </dependencies> ... <!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project --> + <!-- Note: This AspectJ configuration is not needed when using the functional approach with ValidationUtils.validate() --> <build> <plugins> ... @@ -67,10 +68,10 @@ This utility provides JSON Schema validation for payloads held within events and === "Gradle" - ```groovy hl_lines="3 11" + ```groovy hl_lines="3 11 12" plugins { id 'java' - id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' + id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' // Not needed when using the functional approach with ValidationUtils.validate() } repositories { @@ -78,7 +79,8 @@ This utility provides JSON Schema validation for payloads held within events and } dependencies { - aspect 'software.amazon.lambda:powertools-validation:{{ powertools.version }}' + aspect 'software.amazon.lambda:powertools-validation:{{ powertools.version }}' // Not needed when using the functional approach with ValidationUtils.validate() + implementation 'software.amazon.lambda:powertools-validation:{{ powertools.version }}' // Use this instead of 'aspect' when using the functional approach } sourceCompatibility = 11 // or higher @@ -87,17 +89,18 @@ This utility provides JSON Schema validation for payloads held within events and ## Validating events -You can validate inbound and outbound events using `@Validation` annotation. +You can validate inbound and outbound events using either the `@Validation` annotation or the functional approach with `ValidationUtils.validate()` methods: -You can also use the `Validator#validate()` methods, if you want more control over the validation process such as handling a validation error. +- **@Validation annotation** - Simpler syntax with automatic validation, but requires AspectJ configuration +- **ValidationUtils.validate()** - No AspectJ required, provides more control over the validation process such as handling validation errors -We support JSON schema version 4, 6, 7, 2019-09 and 2020-12 using the [NetworkNT JSON Schema Validator](https://github.com/networknt/json-schema-validator). ([Compatibility with JSON Schema versions](https://github.com/networknt/json-schema-validator/blob/master/doc/compatibility.md)). +We support JSON schema version 4, 6, 7, 2019-09 and 2020-12 using the [NetworkNT JSON Schema Validator](https://github.com/networknt/json-schema-validator) ([Compatibility with JSON Schema versions](https://github.com/networknt/json-schema-validator/blob/master/doc/compatibility.md)). The validator is configured to enable format assertions by default even for 2019-09 and 2020-12. ### Validation annotation -`@Validation` annotation is used to validate either inbound events or functions' response. +The `@Validation` annotation is used to validate either inbound events or functions' response. It will fail fast if an event or response doesn't conform with given JSON Schema. For most type of events a `ValidationException` will be thrown. @@ -129,11 +132,11 @@ While it is easier to specify a json schema file in the classpath (using the not **NOTE**: It's not a requirement to validate both inbound and outbound schemas - You can either use one, or both. -### Validate function +### Functional approach with ValidationUtils -Validate standalone function is used within the Lambda handler, or any other methods that perform data validation. +The `ValidationUtils.validate()` method provides a functional approach that can be used within the Lambda handler or any other methods that perform data validation. This approach does not require AspectJ configuration. -You can also gracefully handle schema validation errors by catching `ValidationException`. +With this approach, you can gracefully handle schema validation errors by catching `ValidationException`. === "MyFunctionHandler.java" diff --git a/mkdocs.yml b/mkdocs.yml index da4303c38..3914cfa1a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,9 +1,10 @@ site_name: Powertools for AWS Lambda (Java) site_description: Powertools for AWS Lambda (Java) site_author: Amazon Web Services -site_url: https://docs.powertools.aws.dev/lambda/java/latest/ +site_url: https://docs.aws.amazon.com/powertools/java/latest/ nav: - Homepage: index.md + - Usage patterns: usage-patterns.md - Changelog: changelog.md - Upgrade Guide: upgrade.md - FAQs: FAQs.md @@ -99,6 +100,7 @@ plugins: sections: Project Overview: - index.md + - usage-patterns.md - changelog.md - FAQs.md - roadmap.md From c2763c5a7db3ad63472d54b128d2a1dc74deb810 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 13 Nov 2025 10:35:58 +0100 Subject: [PATCH 533/577] chore(ci): Enable Java 25 builds. (#2285) --- .github/workflows/check-build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index e1d949aad..88f1eabee 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -47,6 +47,7 @@ on: - 'powertools-large-messages/**' - 'powertools-logging/**' - 'powertools-metrics/**' + - 'powertools-kafka/**' - 'powertools-parameters/**' - 'powertools-serialization/**' - 'powertools-sqs/**' @@ -72,6 +73,7 @@ jobs: - 11 - 17 - 21 + - 25 steps: - id: checkout name: Checkout repository From 464490dd6e08c01b3e92507a05a34b555730fdaa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 13:42:28 +0100 Subject: [PATCH 534/577] chore(ci): bump version to 2.7.0 (#2286) * chore(ci): bump version to 2.7.0 * Restore CHANGELOG.md from main. --------- Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Philipp Page <pagejep@amazon.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/README.md | 4 ++-- .../infra/sam-graalvm/README.md | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- .../powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- .../powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/handlers/batch/pom.xml | 2 +- .../handlers/idempotency-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency-generics/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency/pom.xml | 2 +- .../handlers/largemessage-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/largemessage/pom.xml | 2 +- .../handlers/largemessage_idempotent/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-log4j/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-logback/pom.xml | 2 +- powertools-e2e-tests/handlers/metrics/pom.xml | 2 +- powertools-e2e-tests/handlers/parameters/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/handlers/tracing/pom.xml | 2 +- powertools-e2e-tests/handlers/validation-alb-event/pom.xml | 2 +- .../handlers/validation-apigw-event/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 62 files changed, 69 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index e771db05c..6d3689092 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging-log4j</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-metrics</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </dependency> ... </dependencies> diff --git a/examples/pom.xml b/examples/pom.xml index 9ce451a33..c02d318cc 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-examples</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Examples</name> diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 518cdbdd4..5226166fb 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-batch</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Batch</name> diff --git a/examples/powertools-examples-cloudformation/README.md b/examples/powertools-examples-cloudformation/README.md index 35184b6d2..84d9d7fac 100644 --- a/examples/powertools-examples-cloudformation/README.md +++ b/examples/powertools-examples-cloudformation/README.md @@ -15,7 +15,7 @@ Run the following in your shell: ```bash cd infra/sam sam build -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.6.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.7.0718 ``` ### Deploy with CDK @@ -32,5 +32,5 @@ To build and deploy this application for the first time, run the following in yo cd infra/cdk mvn package cdk synth -cdk deploy -c BucketNameParam=my-unique-bucket-2.6.0718 +cdk deploy -c BucketNameParam=my-unique-bucket-2.7.0718 ``` \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md index 01365932e..85c8b386f 100644 --- a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md +++ b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md @@ -40,7 +40,7 @@ sam build ## Deploy the sample application ```shell -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.6.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.7.0718 ``` This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting started with SAM in [the examples directory](../../../README.md) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 392d08b4b..74ced3a4f 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-cloudformation</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 756c082b8..dbd6743a8 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ <groupId>software.amazon.lambda.examples</groupId> <!-- TODO TODO TODO this should build from SNAPSHOT, but it doesn't, because the snapshots don't appear in the docker environment CDK builds it in in our CDK tests. How to procede? V2 blocker --> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-core-utilities-cdk</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 4ca38877d..87dc26169 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <artifactId>cdk</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.223.0</cdk.version> diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 36524f0b1..0b7951f11 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.6.0' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.6.0' - aspect 'software.amazon.lambda:powertools-metrics:2.6.0' + aspect 'software.amazon.lambda:powertools-tracing:2.7.0' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.7.0' + aspect 'software.amazon.lambda:powertools-metrics:2.7.0' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index c3713c344..47e82c5b8 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.6.0") - aspect("software.amazon.lambda:powertools-logging-log4j:2.6.0") - aspect("software.amazon.lambda:powertools-metrics:2.6.0") + aspect("software.amazon.lambda:powertools-tracing:2.7.0") + aspect("software.amazon.lambda:powertools-logging-log4j:2.7.0") + aspect("software.amazon.lambda:powertools-metrics:2.7.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index cfd640aa1..682e1a10b 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-core-utilities-sam-graalvm</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index a5e3881b2..d03cafcfb 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-core-utilities-sam</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 8ef3b556d..996f77d4b 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-core-utilities-serverless</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index d320a1d40..d28835a8a 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-core-utilities-terraform</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index dff0082f1..205958c9a 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-idempotency-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency GraalVM</name> diff --git a/examples/powertools-examples-idempotency/sam/pom.xml b/examples/powertools-examples-idempotency/sam/pom.xml index 0654867f9..694b79342 100644 --- a/examples/powertools-examples-idempotency/sam/pom.xml +++ b/examples/powertools-examples-idempotency/sam/pom.xml @@ -17,7 +17,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-idempotency</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency</name> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 5428655bd..184025be8 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-kafka</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Kafka</name> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 9c62498d5..a83ddddb8 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-parameters-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 17a1efa79..83efef4d2 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-parameters-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters</name> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index 7df5805ce..b77ce975e 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-serialization-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 7120d3a91..789d9969f 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-serialization-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization</name> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 5826e7456..abcdd4e3a 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <artifactId>powertools-examples-validation</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Validation</name> diff --git a/mkdocs.yml b/mkdocs.yml index 3914cfa1a..98f6945d7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -129,7 +129,7 @@ extra_javascript: extra: powertools: - version: 2.6.0 + version: 2.7.0 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index 4d5ff7248..48be39d47 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Parent</name> diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index ccf926d39..bce58ab58 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <description>A suite of utilities that makes batch message processing using AWS Lambda easier.</description> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 015179833..a3270563a 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Cloudformation</name> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 2610a8c4f..d4e9f6213 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Common Internal Utilities</name> diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index a630ba09b..2c726340a 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-batch</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency-functional/pom.xml b/powertools-e2e-tests/handlers/idempotency-functional/pom.xml index 73c8780d3..133a0ccff 100644 --- a/powertools-e2e-tests/handlers/idempotency-functional/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-idempotency-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency-generics/pom.xml b/powertools-e2e-tests/handlers/idempotency-generics/pom.xml index d89aa33e2..a69babd0d 100644 --- a/powertools-e2e-tests/handlers/idempotency-generics/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency-generics/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-idempotency-generics</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index ea84e7b26..cbe7e0cac 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-idempotency</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage-functional/pom.xml b/powertools-e2e-tests/handlers/largemessage-functional/pom.xml index 094c54841..e2e67b2da 100644 --- a/powertools-e2e-tests/handlers/largemessage-functional/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-largemessage-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index 3004a884c..56d179c3b 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-largemessage</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index 74a7b2999..9896db217 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-large-msg-idempotent</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-functional/pom.xml b/powertools-e2e-tests/handlers/logging-functional/pom.xml index a8f79df30..ba532c3db 100644 --- a/powertools-e2e-tests/handlers/logging-functional/pom.xml +++ b/powertools-e2e-tests/handlers/logging-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-logging-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-log4j/pom.xml b/powertools-e2e-tests/handlers/logging-log4j/pom.xml index 0ed761274..445da94e2 100644 --- a/powertools-e2e-tests/handlers/logging-log4j/pom.xml +++ b/powertools-e2e-tests/handlers/logging-log4j/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-logging-log4j</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-logback/pom.xml b/powertools-e2e-tests/handlers/logging-logback/pom.xml index d8523f721..9f5035722 100644 --- a/powertools-e2e-tests/handlers/logging-logback/pom.xml +++ b/powertools-e2e-tests/handlers/logging-logback/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-logging-logback</artifactId> diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 3b60d2aba..5bf3bd5ef 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-metrics</artifactId> diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index 495b51311..e30a51150 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-parameters</artifactId> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index bf2e78f8c..afc21131f 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -4,7 +4,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> <packaging>pom</packaging> <name>Handlers for End-to-End tests</name> <description>Fake handlers that use Powertools for AWS Lambda (Java).</description> diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index 2aaae55f5..1a3b56a77 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-tracing</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml index c966194b1..d2e1266fc 100644 --- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-validation-alb-event</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml index 85b8f47dc..6832280a6 100644 --- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>e2e-test-handler-validation-apigw-event</artifactId> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 860593819..998c6a803 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>powertools-e2e-tests</artifactId> diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index 7bfe38ef4..f119ca445 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>powertools-idempotency</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 0e784c0f5..5e57ee136 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>powertools-idempotency-core</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index ea562ea89..25f6f77c7 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>powertools-idempotency-dynamodb</artifactId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index ac8c95f05..a07d4e0d6 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>powertools-kafka</artifactId> diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index e29327c7d..6353cb089 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>powertools-large-messages</artifactId> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index bcc28c6c2..9fd7b1e62 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Logging</name> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index fc47ac84d..8006baa7d 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 2269303f5..70bbbdfc4 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index ae2871b41..1ea59493c 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Metrics</name> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 72d3133d3..158fdc978 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>powertools-parameters</artifactId> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 454102ede..9d9adc16b 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 594761bee..d66153da6 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index 4b4616cb2..f126716d6 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index 0e31ed729..e6bf1ea27 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index b1b655fe8..b40046bde 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 79b6653fa..d7f33df28 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <artifactId>powertools-serialization</artifactId> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 3b1e58ccd..68231dbe1 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Tracing</name> diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 2c119972d..74051989e 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.6.0</version> + <version>2.7.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Validation</name> From 286a2d06d510e0799511b1c20340071b86979295 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Thu, 13 Nov 2025 17:22:33 +0100 Subject: [PATCH 535/577] =?UTF-8?q?improv(parameters):=20Make=20parameters?= =?UTF-8?q?=20top-level=20provider=20thread-safe=20fo=E2=80=A6=20(#2284)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * improv(parameters): Make parameters top-level provider thread-safe for cache and transformer management. * Use countdown latch instead of Thread.sleep for transformation manager tests. * Make SSMProvider and AppConfigProvider thread-safe. * Make all tests package-private. * Fix sonar finding AZp41z3q7Kei0U644EOS. * Fix sonar finding AZp41z3q7Kei0U644EOS for real now. * Fix PMD findings. * Fix PMD findings. * Fix PMD findings. --- .../appconfig/AppConfigProvider.java | 4 +- .../appconfig/AppConfigParamAspectTest.java | 4 +- .../dynamodb/DynamoDbParamAspectTest.java | 4 +- .../dynamodb/DynamoDbProviderE2ETest.java | 26 ++-- .../dynamodb/DynamoDbProviderTest.java | 44 +++--- .../secrets/SecretsParamAspectTest.java | 4 +- .../secrets/SecretsProviderTest.java | 14 +- .../parameters/ssm/SSMProvider.java | 30 ++-- .../parameters/ssm/SSMParamAspectTest.java | 4 +- .../parameters/ssm/SSMProviderTest.java | 132 ++++++++++++++--- .../parameters/BaseProviderTest.java | 62 ++++---- .../ParamProvidersIntegrationTest.java | 8 +- .../parameters/cache/CacheManagerTest.java | 110 ++++++++++++-- .../parameters/cache/DataStoreTest.java | 14 +- .../transform/Base64TransformerTest.java | 6 +- .../transform/JsonTransformerTest.java | 10 +- .../transform/TransformationManagerTest.java | 140 ++++++++++++++++-- .../powertools/parameters/BaseProvider.java | 31 ++-- .../parameters/cache/CacheManager.java | 23 ++- .../parameters/cache/DataStore.java | 13 +- .../transform/TransformationManager.java | 43 ++++-- 21 files changed, 535 insertions(+), 191 deletions(-) diff --git a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java index 37f07ae7a..06d00ffbe 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/main/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigProvider.java @@ -14,8 +14,8 @@ package software.amazon.lambda.powertools.parameters.appconfig; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import software.amazon.awssdk.core.SdkBytes; import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient; @@ -46,7 +46,7 @@ public class AppConfigProvider extends BaseProvider { private final AppConfigDataClient client; private final String application; private final String environment; - private final Map<String, EstablishedSession> establishedSessions = new HashMap<>(); + private final Map<String, EstablishedSession> establishedSessions = new ConcurrentHashMap<>(); AppConfigProvider(CacheManager cacheManager, TransformationManager transformationManager, AppConfigDataClient client, String environment, String application) { diff --git a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java index df3191632..a32cc20a5 100644 --- a/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java +++ b/powertools-parameters/powertools-parameters-appconfig/src/test/java/software/amazon/lambda/powertools/parameters/appconfig/AppConfigParamAspectTest.java @@ -22,10 +22,10 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; -public class AppConfigParamAspectTest { +class AppConfigParamAspectTest { @Test - public void parameterInjectedByProvider() throws Exception { + void parameterInjectedByProvider() throws Exception { // Setup our aspect to return a mocked AppConfigProvider String environment = "myEnvironment"; String appName = "myApp"; diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java index 07e93a7c1..4294eca48 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbParamAspectTest.java @@ -21,10 +21,10 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; -public class DynamoDbParamAspectTest { +class DynamoDbParamAspectTest { @Test - public void parameterInjectedByProvider() throws Exception { + void parameterInjectedByProvider() throws Exception { // Setup our aspect to return a mocked DynamoDbProvider String tableName = "my-test-tablename"; String key = "myKey"; diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java index 2695938d8..af2617edf 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderE2ETest.java @@ -36,10 +36,10 @@ * will move this across. */ @Disabled -public class DynamoDbProviderE2ETest { +class DynamoDbProviderE2ETest { - final String ParamsTestTable = "ddb-params-test"; - final String MultiparamsTestTable = "ddb-multiparams-test"; + private static final String PARAMS_TEST_TABLE = "ddb-params-test"; + private static final String MULTI_PARAMS_TEST_TABLE = "ddb-multiparams-test"; private final DynamoDbClient ddbClient; public DynamoDbProviderE2ETest() { @@ -52,19 +52,19 @@ public DynamoDbProviderE2ETest() { } @Test - public void TestGetValue() { + void TestGetValue() { // Arrange - HashMap<String, AttributeValue> testItem = new HashMap<String, AttributeValue>(); + Map<String, AttributeValue> testItem = new HashMap<>(); testItem.put("id", AttributeValue.fromS("test_param")); testItem.put("value", AttributeValue.fromS("the_value_is_hello!")); ddbClient.putItem(PutItemRequest.builder() - .tableName(ParamsTestTable) + .tableName(PARAMS_TEST_TABLE) .item(testItem) .build()); // Act - DynamoDbProvider provider = makeProvider(ParamsTestTable); + DynamoDbProvider provider = makeProvider(PARAMS_TEST_TABLE); String value = provider.getValue("test_param"); // Assert @@ -72,29 +72,29 @@ public void TestGetValue() { } @Test - public void TestGetValues() { + void TestGetValues() { // Arrange - HashMap<String, AttributeValue> testItem = new HashMap<String, AttributeValue>(); + Map<String, AttributeValue> testItem = new HashMap<>(); testItem.put("id", AttributeValue.fromS("test_param")); testItem.put("sk", AttributeValue.fromS("test_param_part_1")); testItem.put("value", AttributeValue.fromS("the_value_is_hello!")); ddbClient.putItem(PutItemRequest.builder() - .tableName(MultiparamsTestTable) + .tableName(MULTI_PARAMS_TEST_TABLE) .item(testItem) .build()); - HashMap<String, AttributeValue> testItem2 = new HashMap<String, AttributeValue>(); + Map<String, AttributeValue> testItem2 = new HashMap<>(); testItem2.put("id", AttributeValue.fromS("test_param")); testItem2.put("sk", AttributeValue.fromS("test_param_part_2")); testItem2.put("value", AttributeValue.fromS("the_value_is_still_hello!")); ddbClient.putItem(PutItemRequest.builder() - .tableName(MultiparamsTestTable) + .tableName(MULTI_PARAMS_TEST_TABLE) .item(testItem2) .build()); // Act - DynamoDbProvider provider = makeProvider(MultiparamsTestTable); + DynamoDbProvider provider = makeProvider(MULTI_PARAMS_TEST_TABLE); Map<String, String> values = provider.getMultipleValues("test_param"); // Assert diff --git a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java index 68d48b01c..64f29db79 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java +++ b/powertools-parameters/powertools-parameters-dynamodb/src/test/java/software/amazon/lambda/powertools/parameters/dynamodb/DynamoDbProviderTest.java @@ -45,9 +45,9 @@ import software.amazon.lambda.powertools.parameters.transform.TransformationManager; @ExtendWith(MockitoExtension.class) -public class DynamoDbProviderTest { +class DynamoDbProviderTest { - private final String tableName = "ddb-test-table"; + private static final String TABLE_NAME = "ddb-test-table"; @Mock DynamoDbClient client; @@ -64,19 +64,19 @@ public class DynamoDbProviderTest { private DynamoDbProvider provider; @BeforeEach - public void init() { + void init() { openMocks(this); CacheManager cacheManager = new CacheManager(); - provider = new DynamoDbProvider(cacheManager, transformationManager, client, tableName); + provider = new DynamoDbProvider(cacheManager, transformationManager, client, TABLE_NAME); } @Test - public void getValue() { + void getValue() { // Arrange String key = "Key1"; String expectedValue = "Value1"; - HashMap<String, AttributeValue> responseData = new HashMap<String, AttributeValue>(); + Map<String, AttributeValue> responseData = new HashMap<>(); responseData.put("id", AttributeValue.fromS(key)); responseData.put("value", AttributeValue.fromS(expectedValue)); GetItemResponse response = GetItemResponse.builder() @@ -89,12 +89,12 @@ public void getValue() { // Assert assertThat(value).isEqualTo(expectedValue); - assertThat(getItemValueCaptor.getValue().tableName()).isEqualTo(tableName); + assertThat(getItemValueCaptor.getValue().tableName()).isEqualTo(TABLE_NAME); assertThat(getItemValueCaptor.getValue().key().get("id").s()).isEqualTo(key); } @Test - public void getValueWithNullResultsReturnsNull() { + void getValueWithNullResultsReturnsNull() { // Arrange Mockito.when(client.getItem(getItemValueCaptor.capture())).thenReturn(GetItemResponse.builder() .item(null) @@ -108,7 +108,7 @@ public void getValueWithNullResultsReturnsNull() { } @Test - public void getValueWithoutResultsReturnsNull() { + void getValueWithoutResultsReturnsNull() { // Arrange Mockito.when(client.getItem(getItemValueCaptor.capture())).thenReturn(GetItemResponse.builder() .item(new HashMap<>()) @@ -122,10 +122,10 @@ public void getValueWithoutResultsReturnsNull() { } @Test - public void getValueWithMalformedRowThrows() { + void getValueWithMalformedRowThrows() { // Arrange String key = "Key1"; - HashMap<String, AttributeValue> responseData = new HashMap<String, AttributeValue>(); + Map<String, AttributeValue> responseData = new HashMap<>(); responseData.put("id", AttributeValue.fromS(key)); responseData.put("not-value", AttributeValue.fromS("something")); Mockito.when(client.getItem(getItemValueCaptor.capture())).thenReturn(GetItemResponse.builder() @@ -138,7 +138,7 @@ public void getValueWithMalformedRowThrows() { } @Test - public void getValues() { + void getValues() { // Arrange String key = "Key1"; @@ -146,11 +146,11 @@ public void getValues() { String val1 = "Val1"; String subkey2 = "Subkey2"; String val2 = "Val2"; - HashMap<String, AttributeValue> item1 = new HashMap<String, AttributeValue>(); + Map<String, AttributeValue> item1 = new HashMap<>(); item1.put("id", AttributeValue.fromS(key)); item1.put("sk", AttributeValue.fromS(subkey1)); item1.put("value", AttributeValue.fromS(val1)); - HashMap<String, AttributeValue> item2 = new HashMap<String, AttributeValue>(); + Map<String, AttributeValue> item2 = new HashMap<>(); item2.put("id", AttributeValue.fromS(key)); item2.put("sk", AttributeValue.fromS(subkey2)); item2.put("value", AttributeValue.fromS(val2)); @@ -166,13 +166,13 @@ public void getValues() { assertThat(values.size()).isEqualTo(2); assertThat(values.get(subkey1)).isEqualTo(val1); assertThat(values.get(subkey2)).isEqualTo(val2); - assertThat(queryRequestCaptor.getValue().tableName()).isEqualTo(tableName); + assertThat(queryRequestCaptor.getValue().tableName()).isEqualTo(TABLE_NAME); assertThat(queryRequestCaptor.getValue().keyConditionExpression()).isEqualTo("id = :v_id"); assertThat(queryRequestCaptor.getValue().expressionAttributeValues().get(":v_id").s()).isEqualTo(key); } @Test - public void getValuesWithoutResultsReturnsNull() { + void getValuesWithoutResultsReturnsNull() { // Arrange Mockito.when(client.query(queryRequestCaptor.capture())).thenReturn( QueryResponse.builder().items().build()); @@ -185,10 +185,10 @@ public void getValuesWithoutResultsReturnsNull() { } @Test - public void getMultipleValuesMissingSortKey_throwsException() { + void getMultipleValuesMissingSortKey_throwsException() { // Arrange String key = "Key1"; - HashMap<String, AttributeValue> item = new HashMap<String, AttributeValue>(); + Map<String, AttributeValue> item = new HashMap<>(); item.put("id", AttributeValue.fromS(key)); item.put("value", AttributeValue.fromS("somevalue")); QueryResponse response = QueryResponse.builder() @@ -204,10 +204,10 @@ public void getMultipleValuesMissingSortKey_throwsException() { } @Test - public void getValuesWithMalformedRowThrows() { + void getValuesWithMalformedRowThrows() { // Arrange String key = "Key1"; - HashMap<String, AttributeValue> item1 = new HashMap<String, AttributeValue>(); + Map<String, AttributeValue> item1 = new HashMap<>(); item1.put("id", AttributeValue.fromS(key)); item1.put("sk", AttributeValue.fromS("some-subkey")); item1.put("not-value", AttributeValue.fromS("somevalue")); @@ -224,7 +224,7 @@ public void getValuesWithMalformedRowThrows() { } @Test - public void testDynamoDBBuilderMissingTable_throwsException() { + void testDynamoDBBuilderMissingTable_throwsException() { // Act & Assert assertThatIllegalStateException().isThrownBy(() -> DynamoDbProvider.builder() @@ -233,7 +233,7 @@ public void testDynamoDBBuilderMissingTable_throwsException() { } @Test - public void testDynamoDBBuilder_withoutParameter_shouldHaveDefaultTransformationManager() { + void testDynamoDBBuilder_withoutParameter_shouldHaveDefaultTransformationManager() { // Act DynamoDbProvider dynamoDbProvider = DynamoDbProvider.builder().withTable("test-table") diff --git a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java index 7aa0f0872..5523cbb0e 100644 --- a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java +++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsParamAspectTest.java @@ -21,10 +21,10 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; -public class SecretsParamAspectTest { +class SecretsParamAspectTest { @Test - public void parameterInjectedByProvider() throws Exception { + void parameterInjectedByProvider() throws Exception { // Setup our aspect to return a mocked SecretsProvider String key = "myKey"; String value = "mySecretValue"; diff --git a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java index d0b32874a..a6fbe1c8e 100644 --- a/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java +++ b/powertools-parameters/powertools-parameters-secrets/src/test/java/software/amazon/lambda/powertools/parameters/secrets/SecretsProviderTest.java @@ -40,7 +40,7 @@ import software.amazon.lambda.powertools.parameters.transform.TransformationManager; @ExtendWith(MockitoExtension.class) -public class SecretsProviderTest { +class SecretsProviderTest { @Mock SecretsManagerClient client; @@ -56,13 +56,13 @@ public class SecretsProviderTest { SecretsProvider provider; @BeforeEach - public void init() { + void init() { cacheManager = new CacheManager(); provider = new SecretsProvider(cacheManager, transformationManager, client); } @Test - public void getValue() { + void getValue() { String key = "Key1"; String expectedValue = "Value1"; GetSecretValueResponse response = GetSecretValueResponse.builder().secretString(expectedValue).build(); @@ -76,7 +76,7 @@ public void getValue() { } @Test - public void getValueBase64() { + void getValueBase64() { String key = "Key2"; String expectedValue = "Value2"; byte[] valueb64 = Base64.getEncoder().encode(expectedValue.getBytes()); @@ -91,14 +91,14 @@ public void getValueBase64() { } @Test - public void getMultipleValuesThrowsException() { + void getMultipleValuesThrowsException() { // Act & Assert assertThatRuntimeException().isThrownBy(() -> provider.getMultipleValues("path")) .withMessage("Impossible to get multiple values from AWS Secrets Manager"); } @Test - public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() { + void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() { // Act SecretsProvider secretsProvider = SecretsProvider.builder() .build(); @@ -109,7 +109,7 @@ public void testGetSecretsProvider_withoutParameter_shouldCreateDefaultClient() } @Test - public void testGetSecretsProvider_withoutParameter_shouldHaveDefaultTransformationManager() { + void testGetSecretsProvider_withoutParameter_shouldHaveDefaultTransformationManager() { // Act SecretsProvider secretsProvider = SecretsProvider.builder() .build(); diff --git a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java index c24b08b84..3cf728219 100644 --- a/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java +++ b/powertools-parameters/powertools-parameters-ssm/src/main/java/software/amazon/lambda/powertools/parameters/ssm/SSMProvider.java @@ -66,8 +66,8 @@ public class SSMProvider extends BaseProvider { private final SsmClient client; - private boolean decrypt = false; - private boolean recursive = false; + private final ThreadLocal<Boolean> decrypt = ThreadLocal.withInitial(() -> false); + private final ThreadLocal<Boolean> recursive = ThreadLocal.withInitial(() -> false); /** * Constructor with custom {@link SsmClient}. <br/> @@ -109,7 +109,7 @@ public static SSMProvider create() { public String getValue(String key) { GetParameterRequest request = GetParameterRequest.builder() .name(key) - .withDecryption(decrypt) + .withDecryption(decrypt.get()) .build(); return client.getParameter(request).parameter().value(); } @@ -122,7 +122,7 @@ public String getValue(String key) { * @return the provider itself in order to chain calls (eg. <pre>provider.withDecryption().get("key")</pre>). */ public SSMProvider withDecryption() { - this.decrypt = true; + this.decrypt.set(true); return this; } @@ -133,7 +133,7 @@ public SSMProvider withDecryption() { * @return the provider itself in order to chain calls (eg. <pre>provider.recursive().getMultiple("key")</pre>). */ public SSMProvider recursive() { - this.recursive = true; + this.recursive.set(true); return this; } @@ -160,8 +160,8 @@ protected Map<String, String> getMultipleValues(String path) { private Map<String, String> getMultipleBis(String path, String nextToken) { GetParametersByPathRequest request = GetParametersByPathRequest.builder() .path(path) - .withDecryption(decrypt) - .recursive(recursive) + .withDecryption(decrypt.get()) + .recursive(recursive.get()) .nextToken(nextToken) .build(); @@ -170,12 +170,12 @@ private Map<String, String> getMultipleBis(String path, String nextToken) { // not using the client.getParametersByPathPaginator() as hardly testable GetParametersByPathResponse res = client.getParametersByPath(request); if (res.hasParameters()) { - res.parameters().forEach(parameter -> - { - /* Standardize the parameter name - The parameter name returned by SSM will contain the full path. - However, for readability, we should return only the part after - the path. + res.parameters().forEach(parameter -> { + /* + * Standardize the parameter name + * The parameter name returned by SSM will contain the full path. + * However, for readability, we should return only the part after + * the path. */ String name = parameter.name(); if (name.startsWith(path)) { @@ -196,8 +196,8 @@ private Map<String, String> getMultipleBis(String path, String nextToken) { @Override protected void resetToDefaults() { super.resetToDefaults(); - recursive = false; - decrypt = false; + decrypt.remove(); + recursive.remove(); } // For tests purpose only diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java index e56d20ffa..abfc1d7fa 100644 --- a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java +++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMParamAspectTest.java @@ -21,13 +21,13 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; -public class SSMParamAspectTest { +class SSMParamAspectTest { // This class tests the SSM Param aspect in the same fashion // as the tests for the aspects for the other providers. @Test - public void parameterInjectedByProvider() throws Exception { + void parameterInjectedByProvider() throws Exception { String key = "myKey"; String value = "mySecretValue"; diff --git a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java index db45dc21c..fb475a737 100644 --- a/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java +++ b/powertools-parameters/powertools-parameters-ssm/src/test/java/software/amazon/lambda/powertools/parameters/ssm/SSMProviderTest.java @@ -23,6 +23,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.CountDownLatch; + import org.assertj.core.data.MapEntry; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -32,6 +34,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; + import software.amazon.awssdk.services.ssm.SsmClient; import software.amazon.awssdk.services.ssm.model.GetParameterRequest; import software.amazon.awssdk.services.ssm.model.GetParameterResponse; @@ -41,7 +44,7 @@ import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.transform.TransformationManager; -public class SSMProviderTest { +class SSMProviderTest { @Mock SsmClient client; @@ -60,14 +63,14 @@ public class SSMProviderTest { SSMProvider provider; @BeforeEach - public void init() { + void init() { MockitoAnnotations.openMocks(this); cacheManager = new CacheManager(); provider = new SSMProvider(cacheManager, null, client); } @Test - public void getValue() { + void getValue() { String key = "Key1"; String expectedValue = "Value1"; initMock(expectedValue); @@ -80,7 +83,7 @@ public void getValue() { } @Test - public void getValueDecrypted() { + void getValueDecrypted() { String key = "Key2"; String expectedValue = "Value2"; initMock(expectedValue); @@ -93,7 +96,7 @@ public void getValueDecrypted() { } @Test - public void getMultiple() { + void getMultiple() { List<Parameter> parameters = new ArrayList<>(); parameters.add(Parameter.builder().name("/prod/app1/key1").value("foo1").build()); parameters.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build()); @@ -116,7 +119,7 @@ public void getMultiple() { } @Test - public void getMultipleWithTrailingSlash() { + void getMultipleWithTrailingSlash() { List<Parameter> parameters = new ArrayList<>(); parameters.add(Parameter.builder().name("/prod/app1/key1").value("foo1").build()); parameters.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build()); @@ -139,7 +142,7 @@ public void getMultipleWithTrailingSlash() { } @Test - public void getMultiple_cached_shouldNotCallSSM() { + void getMultiple_cached_shouldNotCallSSM() { List<Parameter> parameters = new ArrayList<>(); parameters.add(Parameter.builder().name("/prod/app1/key1").value("foo1").build()); parameters.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build()); @@ -161,12 +164,12 @@ public void getMultiple_cached_shouldNotCallSSM() { } @Test - public void getMultipleWithNextToken() { + void getMultipleWithNextToken() { List<Parameter> parameters1 = new ArrayList<>(); parameters1.add(Parameter.builder().name("/prod/app1/key1").value("foo1").build()); parameters1.add(Parameter.builder().name("/prod/app1/key2").value("foo2").build()); - GetParametersByPathResponse response1 = - GetParametersByPathResponse.builder().parameters(parameters1).nextToken("123abc").build(); + GetParametersByPathResponse response1 = GetParametersByPathResponse.builder().parameters(parameters1) + .nextToken("123abc").build(); List<Parameter> parameters2 = new ArrayList<>(); parameters2.add(Parameter.builder().name("/prod/app1/key3").value("foo3").build()); @@ -185,25 +188,118 @@ public void getMultipleWithNextToken() { GetParametersByPathRequest request1 = requestParams.get(0); GetParametersByPathRequest request2 = requestParams.get(1); - assertThat(asList(request1, request2)).allSatisfy(req -> - { - assertThat(req.path()).isEqualTo("/prod/app1"); - assertThat(req.withDecryption()).isFalse(); - assertThat(req.recursive()).isFalse(); - }); + assertThat(asList(request1, request2)) + .isNotEmpty() + .allSatisfy(req -> { + assertThat(req.path()).isEqualTo("/prod/app1"); + assertThat(req.withDecryption()).isFalse(); + assertThat(req.recursive()).isFalse(); + }); assertThat(request1.nextToken()).isNull(); assertThat(request2.nextToken()).isEqualTo("123abc"); } @Test - public void testSSMProvider_withoutParameter_shouldHaveDefaultTransformationManager() { + void testSSMProvider_withoutParameter_shouldHaveDefaultTransformationManager() { // Act SSMProvider ssmProvider = SSMProvider.builder() .build(); // Assert - assertDoesNotThrow(()->ssmProvider.withTransformation(json)); + assertDoesNotThrow(() -> ssmProvider.withTransformation(json)); + } + + @Test + void withDecryption_concurrentCalls_shouldBeThreadSafe() throws InterruptedException { + // GIVEN + Parameter param1 = Parameter.builder().value("value1").build(); + Parameter param2 = Parameter.builder().value("value2").build(); + GetParameterResponse response1 = GetParameterResponse.builder().parameter(param1).build(); + GetParameterResponse response2 = GetParameterResponse.builder().parameter(param2).build(); + CountDownLatch latch = new CountDownLatch(2); + Mockito.when(client.getParameter(paramCaptor.capture())) + .thenReturn(response1, response2); + + // WHEN + Thread thread1 = new Thread(() -> { + try { + latch.countDown(); + latch.await(); + provider.withDecryption().getValue("key1"); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + + Thread thread2 = new Thread(() -> { + try { + latch.countDown(); + latch.await(); + provider.getValue("key2"); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + // THEN + List<GetParameterRequest> requests = paramCaptor.getAllValues(); + assertThat(requests) + .hasSize(2) + .anyMatch(GetParameterRequest::withDecryption) + .anyMatch(r -> !r.withDecryption()); + } + + @Test + void recursive_concurrentCalls_shouldBeThreadSafe() throws InterruptedException { + // GIVEN + List<Parameter> params1 = new ArrayList<>(); + params1.add(Parameter.builder().name("/path1/key1").value("value1").build()); + List<Parameter> params2 = new ArrayList<>(); + params2.add(Parameter.builder().name("/path2/key2").value("value2").build()); + GetParametersByPathResponse response1 = GetParametersByPathResponse.builder().parameters(params1).build(); + GetParametersByPathResponse response2 = GetParametersByPathResponse.builder().parameters(params2).build(); + CountDownLatch latch = new CountDownLatch(2); + Mockito.when(client.getParametersByPath(paramByPathCaptor.capture())) + .thenReturn(response1, response2); + + // WHEN + Thread thread1 = new Thread(() -> { + try { + latch.countDown(); + latch.await(); + provider.recursive().getMultiple("/path1"); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + + Thread thread2 = new Thread(() -> { + try { + latch.countDown(); + latch.await(); + provider.getMultiple("/path2"); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + + thread1.start(); + thread2.start(); + thread1.join(); + thread2.join(); + + // THEN + List<GetParametersByPathRequest> requests = paramByPathCaptor.getAllValues(); + assertThat(requests) + .hasSize(2) + .anyMatch(GetParametersByPathRequest::recursive) + .anyMatch(r -> !r.recursive()); } private void initMock(String expectedValue) { diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java index cbc8f5b30..dd31ce016 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/BaseProviderTest.java @@ -38,7 +38,7 @@ import software.amazon.lambda.powertools.parameters.transform.TransformationManager; import software.amazon.lambda.powertools.parameters.transform.Transformer; -public class BaseProviderTest { +class BaseProviderTest { Clock clock; CacheManager cacheManager; @@ -47,7 +47,7 @@ public class BaseProviderTest { boolean getFromStore = false; @BeforeEach - public void setup() { + void setup() { clock = Clock.systemDefaultZone(); cacheManager = new CacheManager(); transformationManager = new TransformationManager(); @@ -55,7 +55,7 @@ public void setup() { } @Test - public void get_notCached_shouldGetValue() { + void get_notCached_shouldGetValue() { String foo = provider.get("toto"); assertThat(foo).isEqualTo("valueFromStore"); @@ -63,7 +63,7 @@ public void get_notCached_shouldGetValue() { } @Test - public void get_cached_shouldGetFromCache() { + void get_cached_shouldGetFromCache() { provider.get("foo"); getFromStore = false; @@ -73,7 +73,7 @@ public void get_cached_shouldGetFromCache() { } @Test - public void get_expired_shouldGetValue() { + void get_expired_shouldGetValue() { provider.get("bar"); getFromStore = false; @@ -84,7 +84,7 @@ public void get_expired_shouldGetValue() { } @Test - public void getMultiple_notCached_shouldGetValue() { + void getMultiple_notCached_shouldGetValue() { Map<String, String> foo = provider.getMultiple("toto"); assertThat(foo.get("toto")).isEqualTo("valueFromStore"); @@ -92,7 +92,7 @@ public void getMultiple_notCached_shouldGetValue() { } @Test - public void getMultiple_cached_shouldGetFromCache() { + void getMultiple_cached_shouldGetFromCache() { provider.getMultiple("foo"); getFromStore = false; @@ -102,7 +102,7 @@ public void getMultiple_cached_shouldGetFromCache() { } @Test - public void getMultiple_expired_shouldGetValue() { + void getMultiple_expired_shouldGetValue() { provider.getMultiple("bar"); getFromStore = false; @@ -113,7 +113,7 @@ public void getMultiple_expired_shouldGetValue() { } @Test - public void get_customTTL_cached_shouldGetFromCache() { + void get_customTTL_cached_shouldGetFromCache() { provider.withMaxAge(12, ChronoUnit.MINUTES).get("key"); getFromStore = false; @@ -124,7 +124,7 @@ public void get_customTTL_cached_shouldGetFromCache() { } @Test - public void get_customTTL_expired_shouldGetValue() { + void get_customTTL_expired_shouldGetValue() { provider.withMaxAge(2, ChronoUnit.MINUTES).get("mykey"); getFromStore = false; @@ -135,7 +135,7 @@ public void get_customTTL_expired_shouldGetValue() { } @Test - public void get_customDefaultTTL_cached_shouldGetFromCache() { + void get_customDefaultTTL_cached_shouldGetFromCache() { provider.cacheManager.setDefaultExpirationTime(Duration.of(12, MINUTES)); provider.get("foobar"); getFromStore = false; @@ -147,7 +147,7 @@ public void get_customDefaultTTL_cached_shouldGetFromCache() { } @Test - public void get_customDefaultTTL_expired_shouldGetValue() { + void get_customDefaultTTL_expired_shouldGetValue() { provider.cacheManager.setDefaultExpirationTime(Duration.of(2, MINUTES)); getFromStore = false; @@ -158,7 +158,7 @@ public void get_customDefaultTTL_expired_shouldGetValue() { } @Test - public void get_customDefaultTTLAndTTL_cached_shouldGetFromCache() { + void get_customDefaultTTLAndTTL_cached_shouldGetFromCache() { provider.get("foobaz"); getFromStore = false; @@ -169,7 +169,7 @@ public void get_customDefaultTTLAndTTL_cached_shouldGetFromCache() { } @Test - public void get_customDefaultTTLAndTTL_expired_shouldGetValue() { + void get_customDefaultTTLAndTTL_expired_shouldGetValue() { provider.cacheManager.setDefaultExpirationTime(Duration.ofMinutes(2)); @@ -183,7 +183,7 @@ public void get_customDefaultTTLAndTTL_expired_shouldGetValue() { } @Test - public void get_basicTransformation_shouldTransformInString() { + void get_basicTransformation_shouldTransformInString() { provider.setValue(Base64.getEncoder().encodeToString("bar".getBytes())); String value = provider.withTransformation(Transformer.base64).get("base64"); @@ -192,20 +192,20 @@ public void get_basicTransformation_shouldTransformInString() { } @Test - public void get_complexTransformation_shouldTransformInObject() { + void get_complexTransformation_shouldTransformInObject() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); ObjectToDeserialize objectToDeserialize = provider.withTransformation(json).get("foo", ObjectToDeserialize.class); assertThat(objectToDeserialize).matches( - o -> o.getFoo().equals("Foo") + o -> "Foo".equals(o.getFoo()) && o.getBar() == 42 && o.getBaz() == 123456789); } @Test - public void getObject_notCached_shouldGetValue() { + void getObject_notCached_shouldGetValue() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); ObjectToDeserialize foo = provider.withTransformation(json).get("foo", ObjectToDeserialize.class); @@ -215,7 +215,7 @@ public void getObject_notCached_shouldGetValue() { } @Test - public void getObject_cached_shouldGetFromCache() { + void getObject_cached_shouldGetFromCache() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); provider.withTransformation(json).get("foo", ObjectToDeserialize.class); @@ -227,7 +227,7 @@ public void getObject_cached_shouldGetFromCache() { } @Test - public void getObject_expired_shouldGetValue() { + void getObject_expired_shouldGetValue() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); provider.withTransformation(json).get("foo", ObjectToDeserialize.class); @@ -240,7 +240,7 @@ public void getObject_expired_shouldGetValue() { } @Test - public void getObject_customTTL_cached_shouldGetFromCache() { + void getObject_customTTL_cached_shouldGetFromCache() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); provider.withMaxAge(12, ChronoUnit.MINUTES) @@ -255,7 +255,7 @@ public void getObject_customTTL_cached_shouldGetFromCache() { } @Test - public void getObject_customTTL_expired_shouldGetValue() { + void getObject_customTTL_expired_shouldGetValue() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); provider.withMaxAge(2, ChronoUnit.MINUTES) @@ -270,7 +270,7 @@ public void getObject_customTTL_expired_shouldGetValue() { } @Test - public void getObject_customDefaultTTL_cached_shouldGetFromCache() { + void getObject_customDefaultTTL_cached_shouldGetFromCache() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); provider.cacheManager.setDefaultExpirationTime(Duration.of(12, MINUTES)); @@ -286,7 +286,7 @@ public void getObject_customDefaultTTL_cached_shouldGetFromCache() { } @Test - public void getObject_customDefaultTTL_expired_shouldGetValue() { + void getObject_customDefaultTTL_expired_shouldGetValue() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); provider.cacheManager.setDefaultExpirationTime(Duration.of(2, MINUTES)); @@ -302,7 +302,7 @@ public void getObject_customDefaultTTL_expired_shouldGetValue() { } @Test - public void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() { + void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); provider.cacheManager.setDefaultExpirationTime(Duration.ofSeconds(5)); @@ -319,7 +319,7 @@ public void getObject_customDefaultTTLAndTTL_cached_shouldGetFromCache() { } @Test - public void getObject_customDefaultTTLAndTTL_expired_shouldGetValue() { + void getObject_customDefaultTTLAndTTL_expired_shouldGetValue() { provider.setValue("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}"); provider.cacheManager.setDefaultExpirationTime(Duration.ofMinutes(2)); @@ -336,7 +336,7 @@ public void getObject_customDefaultTTLAndTTL_expired_shouldGetValue() { } @Test - public void get_noTransformationManager_shouldThrowException() { + void get_noTransformationManager_shouldThrowException() { provider = new BasicProvider(new CacheManager(), null); assertThatIllegalStateException() @@ -344,14 +344,14 @@ public void get_noTransformationManager_shouldThrowException() { } @Test - public void getObject_noTransformationManager_shouldThrowException() { + void getObject_noTransformationManager_shouldThrowException() { assertThatIllegalStateException() .isThrownBy(() -> provider.get("foo", ObjectToDeserialize.class)); } @Test - public void getTwoParams_shouldResetTTLOptionsInBetween() { + void getTwoParams_shouldResetTTLOptionsInBetween() { provider.withMaxAge(50, SECONDS).get("foo50"); provider.get("foo5"); @@ -365,7 +365,7 @@ public void getTwoParams_shouldResetTTLOptionsInBetween() { } @Test - public void getTwoParams_shouldResetTransformationOptionsInBetween() { + void getTwoParams_shouldResetTransformationOptionsInBetween() { provider.setValue(Base64.getEncoder().encodeToString("base64encoded".getBytes())); String foob64 = provider.withTransformation(base64).get("foob64"); @@ -384,7 +384,7 @@ public BasicProvider(CacheManager cacheManager, TransformationManager transforma super(cacheManager, transformationManager); } - public void setValue(String value) { + void setValue(String value) { this.value = value; } diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java index 6b3cf7641..5bc609777 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/ParamProvidersIntegrationTest.java @@ -46,7 +46,7 @@ import software.amazon.lambda.powertools.parameters.ssm.SSMProvider; @ExtendWith(MockitoExtension.class) -public class ParamProvidersIntegrationTest { +class ParamProvidersIntegrationTest { @Mock SsmClient ssmClient; @@ -66,7 +66,7 @@ public class ParamProvidersIntegrationTest { ArgumentCaptor<GetSecretValueRequest> secretsCaptor; @Test - public void ssmProvider_get() { + void ssmProvider_get() { SSMProvider ssmProvider = SSMProvider.builder() .withClient(ssmClient) .build(); @@ -84,7 +84,7 @@ public void ssmProvider_get() { } @Test - public void ssmProvider_getMultiple() { + void ssmProvider_getMultiple() { SSMProvider ssmProvider = SSMProvider.builder() .withClient(ssmClient) .build(); @@ -111,7 +111,7 @@ public void ssmProvider_getMultiple() { } @Test - public void secretsProvider_get() { + void secretsProvider_get() { SecretsProvider secretsProvider = SecretsProvider.builder() .withClient(secretsManagerClient) .build(); diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java index 2bcfcc566..d22572fad 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/CacheManagerTest.java @@ -21,23 +21,24 @@ import java.time.Clock; import java.util.Optional; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class CacheManagerTest { +class CacheManagerTest { CacheManager manager; Clock clock; @BeforeEach - public void setup() { + void setup() { clock = Clock.systemDefaultZone(); manager = new CacheManager(); } @Test - public void getIfNotExpired_notExpired_shouldReturnValue() { + void getIfNotExpired_notExpired_shouldReturnValue() { manager.putInCache("key", "value"); Optional<String> value = manager.getIfNotExpired("key", clock.instant()); @@ -46,7 +47,7 @@ public void getIfNotExpired_notExpired_shouldReturnValue() { } @Test - public void getIfNotExpired_expired_shouldReturnNothing() { + void getIfNotExpired_expired_shouldReturnNothing() { manager.putInCache("key", "value"); Optional<String> value = manager.getIfNotExpired("key", offset(clock, of(6, SECONDS)).instant()); @@ -55,7 +56,7 @@ public void getIfNotExpired_expired_shouldReturnNothing() { } @Test - public void getIfNotExpired_withCustomExpirationTime_notExpired_shouldReturnValue() { + void getIfNotExpired_withCustomExpirationTime_notExpired_shouldReturnValue() { manager.setExpirationTime(of(42, SECONDS)); manager.putInCache("key", "value"); @@ -65,18 +66,17 @@ public void getIfNotExpired_withCustomExpirationTime_notExpired_shouldReturnValu } @Test - public void getIfNotExpired_withCustomDefaultExpirationTime_notExpired_shouldReturnValue() { + void getIfNotExpired_withCustomDefaultExpirationTime_notExpired_shouldReturnValue() { manager.setDefaultExpirationTime(of(42, SECONDS)); manager.putInCache("key", "value"); - Optional<String> value = manager.getIfNotExpired("key", offset(clock, of(40, SECONDS)).instant()); assertThat(value).isPresent().contains("value"); } @Test - public void getIfNotExpired_customDefaultExpirationTime_customExpirationTime_shouldUseExpirationTime() { + void getIfNotExpired_customDefaultExpirationTime_customExpirationTime_shouldUseExpirationTime() { manager.setDefaultExpirationTime(of(42, SECONDS)); manager.setExpirationTime(of(2, SECONDS)); manager.putInCache("key", "value"); @@ -87,7 +87,7 @@ public void getIfNotExpired_customDefaultExpirationTime_customExpirationTime_sho } @Test - public void getIfNotExpired_resetExpirationTime_shouldUseDefaultExpirationTime() { + void getIfNotExpired_resetExpirationTime_shouldUseDefaultExpirationTime() { manager.setDefaultExpirationTime(of(42, SECONDS)); manager.setExpirationTime(of(2, SECONDS)); manager.putInCache("key", "value"); @@ -101,4 +101,96 @@ public void getIfNotExpired_resetExpirationTime_shouldUseDefaultExpirationTime() assertThat(value2).isPresent().contains("value2"); } + @Test + void putInCache_sharedCache_shouldBeAccessibleAcrossThreads() throws InterruptedException { + // GIVEN + Thread thread1 = new Thread(() -> { + manager.setExpirationTime(of(60, SECONDS)); + manager.putInCache("sharedKey", "valueFromThread1"); + manager.resetExpirationTime(); + }); + + Thread thread2 = new Thread(() -> { + manager.setExpirationTime(of(10, SECONDS)); + // Thread 2 should be able to read the value cached by Thread 1 + Optional<String> value = manager.getIfNotExpired("sharedKey", clock.instant()); + assertThat(value).isPresent().contains("valueFromThread1"); + manager.resetExpirationTime(); + }); + + // WHEN + thread1.start(); + thread1.join(); + thread2.start(); + thread2.join(); + + // THEN - Both threads should be able to access the same cached value + Optional<String> value = manager.getIfNotExpired("sharedKey", clock.instant()); + assertThat(value).isPresent().contains("valueFromThread1"); + } + + @Test + void putInCache_concurrentCalls_shouldBeThreadSafe() throws InterruptedException { + // GIVEN + int threadCount = 10; + Thread[] threads = new Thread[threadCount]; + boolean[] success = new boolean[threadCount]; + Clock testClock = Clock.systemDefaultZone(); + + // WHEN - Multiple threads set different expiration times and cache values concurrently + for (int i = 0; i < threadCount; i++) { + final int threadIndex = i; + final int expirationSeconds = (i % 2 == 0) ? 60 : 10; // Alternate between 60s and 10s + + threads[i] = new Thread(() -> { + try { + manager.setExpirationTime(of(expirationSeconds, SECONDS)); + manager.putInCache("key" + threadIndex, "value" + threadIndex); + manager.resetExpirationTime(); + success[threadIndex] = true; + } catch (Exception e) { + success[threadIndex] = false; + } + }); + } + + // Start all threads + for (Thread thread : threads) { + thread.start(); + } + + // Wait for all threads to complete + for (Thread thread : threads) { + thread.join(); + } + + // THEN - All threads should complete successfully + for (boolean result : success) { + assertThat(result).isTrue(); + } + + // THEN - Each cached value should have the correct expiration time + // Values with 60s TTL should still be present after 9s, values with 10s should expire after 11s + for (int i = 0; i < threadCount; i++) { + final int expirationSeconds = (i % 2 == 0) ? 60 : 10; + + // Check that value is still present just before expiration + Optional<String> valueBeforeExpiry = manager.getIfNotExpired("key" + i, + offset(testClock, of(expirationSeconds - 1, SECONDS)).instant()); + assertThat(valueBeforeExpiry) + .as("Thread %d with %ds expiration should still have value after %ds", i, expirationSeconds, + expirationSeconds - 1) + .isPresent() + .contains("value" + i); + + // Check that value expires after the TTL + Optional<String> valueAfterExpiry = manager.getIfNotExpired("key" + i, + offset(testClock, of(expirationSeconds + 1, SECONDS)).instant()); + assertThat(valueAfterExpiry) + .as("Thread %d with %ds expiration should not have value after %ds", i, expirationSeconds, + expirationSeconds + 1) + .isNotPresent(); + } + } + } diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java index e86ded9be..0de31e63d 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/cache/DataStoreTest.java @@ -24,35 +24,35 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class DataStoreTest { +class DataStoreTest { Clock clock; DataStore store; @BeforeEach - public void setup() { + void setup() { clock = Clock.systemDefaultZone(); store = new DataStore(); } @Test - public void put_shouldInsertInStore() { + void put_shouldInsertInStore() { store.put("key", "value", Instant.now()); assertThat(store.get("key")).isEqualTo("value"); } @Test - public void get_invalidKey_shouldReturnNull() { + void get_invalidKey_shouldReturnNull() { assertThat(store.get("key")).isNull(); } @Test - public void hasExpired_invalidKey_shouldReturnTrue() { + void hasExpired_invalidKey_shouldReturnTrue() { assertThat(store.hasExpired("key", clock.instant())).isTrue(); } @Test - public void hasExpired_notExpired_shouldReturnFalse() { + void hasExpired_notExpired_shouldReturnFalse() { Instant now = Instant.now(); store.put("key", "value", now.plus(10, SECONDS)); @@ -61,7 +61,7 @@ public void hasExpired_notExpired_shouldReturnFalse() { } @Test - public void hasExpired_expired_shouldReturnTrueAndRemoveElement() { + void hasExpired_expired_shouldReturnTrueAndRemoveElement() { Instant now = Instant.now(); store.put("key", "value", now.plus(10, SECONDS)); diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java index ea713b552..8dbddacf6 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/Base64TransformerTest.java @@ -21,10 +21,10 @@ import org.junit.jupiter.api.Test; import software.amazon.lambda.powertools.parameters.exception.TransformationException; -public class Base64TransformerTest { +class Base64TransformerTest { @Test - public void transform_base64_shouldTransformInString() { + void transform_base64_shouldTransformInString() { Base64Transformer transformer = new Base64Transformer(); String s = transformer.applyTransformation(Base64.getEncoder().encodeToString("foobar".getBytes())); @@ -33,7 +33,7 @@ public void transform_base64_shouldTransformInString() { } @Test - public void transform_base64WrongFormat_shouldThrowException() { + void transform_base64WrongFormat_shouldThrowException() { Base64Transformer transformer = new Base64Transformer(); assertThatExceptionOfType(TransformationException.class) diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java index 5cb980cc7..48cebb6b0 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/JsonTransformerTest.java @@ -22,23 +22,23 @@ import org.junit.jupiter.api.Test; import software.amazon.lambda.powertools.parameters.exception.TransformationException; -public class JsonTransformerTest { +class JsonTransformerTest { @Test - public void transform_json_shouldTransformInObject() throws TransformationException { + void transform_json_shouldTransformInObject() throws TransformationException { JsonTransformer<ObjectToDeserialize> transformation = new JsonTransformer<>(); ObjectToDeserialize objectToDeserialize = transformation.applyTransformation("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}", ObjectToDeserialize.class); assertThat(objectToDeserialize).matches( - o -> o.getFoo().equals("Foo") + o -> "Foo".equals(o.getFoo()) && o.getBar() == 42 && o.getBaz() == 123456789); } @Test - public void transform_json_shouldTransformInHashMap() throws TransformationException { + void transform_json_shouldTransformInHashMap() throws TransformationException { JsonTransformer<Map> transformation = new JsonTransformer<>(); Map<String, Object> map = @@ -50,7 +50,7 @@ public void transform_json_shouldTransformInHashMap() throws TransformationExcep } @Test - public void transform_badJson_shouldThrowException() { + void transform_badJson_shouldThrowException() { JsonTransformer<ObjectToDeserialize> transformation = new JsonTransformer<>(); assertThatExceptionOfType(TransformationException.class) diff --git a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java index 39e69f9e0..fad6f5391 100644 --- a/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java +++ b/powertools-parameters/powertools-parameters-tests/src/test/java/software/amazon/lambda/powertools/parameters/transform/TransformationManagerTest.java @@ -21,41 +21,44 @@ import static software.amazon.lambda.powertools.parameters.transform.Transformer.json; import java.util.Base64; +import java.util.concurrent.CountDownLatch; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; + import software.amazon.lambda.powertools.parameters.exception.TransformationException; -public class TransformationManagerTest { +class TransformationManagerTest { TransformationManager manager; Class<BasicTransformer> basicTransformer = BasicTransformer.class; @BeforeEach - public void setup() { + void setup() { manager = new TransformationManager(); } @Test - public void setTransformer_shouldTransform() { + void setTransformer_shouldTransform() { manager.setTransformer(json); assertThat(manager.shouldTransform()).isTrue(); } @Test - public void notSetTransformer_shouldNotTransform() { + void notSetTransformer_shouldNotTransform() { assertThat(manager.shouldTransform()).isFalse(); } @Test - public void performBasicTransformation_noTransformer_shouldThrowException() { + void performBasicTransformation_noTransformer_shouldThrowException() { assertThatIllegalStateException() .isThrownBy(() -> manager.performBasicTransformation("value")); } @Test - public void performBasicTransformation_notBasicTransformer_shouldThrowException() { + void performBasicTransformation_notBasicTransformer_shouldThrowException() { manager.setTransformer(json); assertThatIllegalStateException() @@ -63,7 +66,7 @@ public void performBasicTransformation_notBasicTransformer_shouldThrowException( } @Test - public void performBasicTransformation_abstractTransformer_throwsTransformationException() { + void performBasicTransformation_abstractTransformer_throwsTransformationException() { manager.setTransformer(basicTransformer); assertThatExceptionOfType(TransformationException.class) @@ -71,7 +74,7 @@ public void performBasicTransformation_abstractTransformer_throwsTransformationE } @Test - public void performBasicTransformation_shouldPerformTransformation() { + void performBasicTransformation_shouldPerformTransformation() { manager.setTransformer(base64); String expectedValue = "bar"; @@ -81,27 +84,136 @@ public void performBasicTransformation_shouldPerformTransformation() { } @Test - public void performComplexTransformation_noTransformer_shouldThrowException() { + void performComplexTransformation_noTransformer_shouldThrowException() { assertThatIllegalStateException() .isThrownBy(() -> manager.performComplexTransformation("value", ObjectToDeserialize.class)); } @Test - public void performComplexTransformation_shouldPerformTransformation() { + void performComplexTransformation_shouldPerformTransformation() { manager.setTransformer(json); - ObjectToDeserialize object = - manager.performComplexTransformation("{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}", - ObjectToDeserialize.class); + ObjectToDeserialize object = manager.performComplexTransformation( + "{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}", + ObjectToDeserialize.class); assertThat(object).isNotNull(); } @Test - public void performComplexTransformation_throwsTransformationException() { + void performComplexTransformation_throwsTransformationException() { manager.setTransformer(basicTransformer); assertThatExceptionOfType(TransformationException.class) .isThrownBy(() -> manager.performComplexTransformation("value", ObjectToDeserialize.class)); } + + @Test + void unsetTransformer_shouldCleanUpThreadLocal() { + // GIVEN + manager.setTransformer(json); + assertThat(manager.shouldTransform()).isTrue(); + + // WHEN + manager.unsetTransformer(); + + // THEN + assertThat(manager.shouldTransform()).isFalse(); + } + + @Test + void setTransformer_concurrentCalls_shouldBeThreadSafe() throws InterruptedException { + // GIVEN + boolean[] success = new boolean[2]; + CountDownLatch latch = new CountDownLatch(2); + + Thread thread1 = new Thread(() -> { + try { + latch.countDown(); + latch.await(); + manager.setTransformer(json); + // Thread 1 expects json transformer + String result = manager.performComplexTransformation( + "{\"foo\":\"Foo\", \"bar\":42, \"baz\":123456789}", + ObjectToDeserialize.class).getFoo(); + success[0] = "Foo".equals(result); + } catch (Exception e) { + e.printStackTrace(); + success[0] = false; + } + }); + + Thread thread2 = new Thread(() -> { + try { + latch.countDown(); + latch.await(); + manager.setTransformer(base64); + // Thread 2 expects base64 transformer + String result = manager.performBasicTransformation( + Base64.getEncoder().encodeToString("bar".getBytes())); + success[1] = "bar".equals(result); + } catch (Exception e) { + e.printStackTrace(); + success[1] = false; + } + }); + + // WHEN - Start both threads concurrently + thread1.start(); + thread2.start(); + + // THEN - Both threads should complete without errors + thread1.join(); + thread2.join(); + + assertThat(success[0]).as("Thread 1 with JSON transformer should succeed").isTrue(); + assertThat(success[1]).as("Thread 2 with Base64 transformer should succeed").isTrue(); + } + + @Test + void unsetTransformer_concurrentCalls_shouldNotAffectOtherThreads() throws InterruptedException { + // GIVEN + boolean[] success = new boolean[2]; + CountDownLatch latch = new CountDownLatch(2); + + Thread thread1 = new Thread(() -> { + try { + latch.countDown(); + latch.await(); + manager.setTransformer(json); + // Thread 1 should still have json transformer even if thread 2 unsets + assertThat(manager.shouldTransform()).isTrue(); + success[0] = true; + } catch (Exception e) { + e.printStackTrace(); + success[0] = false; + } + }); + + Thread thread2 = new Thread(() -> { + try { + latch.countDown(); + latch.await(); + manager.setTransformer(base64); + manager.unsetTransformer(); + // Thread 2 should have no transformer after unset + assertThat(manager.shouldTransform()).isFalse(); + success[1] = true; + } catch (Exception e) { + e.printStackTrace(); + success[1] = false; + } + }); + + // WHEN + thread1.start(); + thread2.start(); + + // THEN + thread1.join(); + thread2.join(); + + assertThat(success[0]).as("Thread 1 should still have transformer").isTrue(); + assertThat(success[1]).as("Thread 2 should have unset transformer").isTrue(); + } } diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java index bedace28c..d83ff0298 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/BaseProvider.java @@ -19,7 +19,8 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Map; -import software.amazon.awssdk.annotations.NotThreadSafe; + +import software.amazon.awssdk.annotations.ThreadSafe; import software.amazon.lambda.powertools.parameters.cache.CacheManager; import software.amazon.lambda.powertools.parameters.exception.TransformationException; import software.amazon.lambda.powertools.parameters.transform.BasicTransformer; @@ -28,8 +29,20 @@ /** * Base class for all parameter providers. + * <p> + * This class is thread-safe when used as a singleton in multi-threaded environments. + * Configuration methods ({@link #withMaxAge(int, ChronoUnit)}, {@link #withTransformation(Class)}) + * use thread-local storage to support concurrent requests with different requirements. + * <p> + * The cache and transformation managers are thread-safe with zero synchronization overhead, + * using lock-free data structures (ThreadLocal, AtomicReference, ConcurrentHashMap) for optimal performance. + * The cache storage is shared across all threads, allowing cached values to be reused across requests. + * <p> + * <b>Implementation Requirements:</b> Subclasses must ensure that implementations of + * {@link #getValue(String)} and {@link #getMultipleValues(String)} are thread-safe to + * guarantee overall thread-safety of the provider. */ -@NotThreadSafe +@ThreadSafe public abstract class BaseProvider implements ParamProvider { public static final String PARAMETERS = "parameters"; @@ -91,6 +104,7 @@ public BaseProvider withMaxAge(int maxAge, ChronoUnit unit) { * @param transformerClass Class of the transformer to apply. For convenience, you can use {@link Transformer#json} or {@link Transformer#base64} shortcuts. * @return the provider itself in order to chain calls (eg. <pre>provider.withTransformation(json).get("key", MyObject.class)</pre>). */ + @SuppressWarnings("rawtypes") // Transformer type parameter determined at runtime public BaseProvider withTransformation(Class<? extends Transformer> transformerClass) { if (transformationManager == null) { throw new IllegalStateException( @@ -110,12 +124,12 @@ public BaseProvider withTransformation(Class<? extends Transformer> transformerC * eg. getMultiple("/foo/bar") will retrieve [key="baz", value="valuebaz"] for parameter "/foo/bar/baz" */ @Override + @SuppressWarnings("unchecked") // Cache stores Object, safe cast as we control what's stored public Map<String, String> getMultiple(String path) { // remove trailing whitespace String pathWithoutTrailingSlash = path.replaceAll("\\/+$", ""); try { - return (Map<String, String>) cacheManager.getIfNotExpired(pathWithoutTrailingSlash, now()).orElseGet(() -> - { + return (Map<String, String>) cacheManager.getIfNotExpired(pathWithoutTrailingSlash, now()).orElseGet(() -> { Map<String, String> params = getMultipleValues(pathWithoutTrailingSlash); cacheManager.putInCache(pathWithoutTrailingSlash, params); @@ -143,8 +157,7 @@ public Map<String, String> getMultiple(String path) { @Override public String get(final String key) { try { - return (String) cacheManager.getIfNotExpired(key, now()).orElseGet(() -> - { + return (String) cacheManager.getIfNotExpired(key, now()).orElseGet(() -> { String value = getValue(key); String transformedValue = value; @@ -175,10 +188,10 @@ public String get(final String key) { * @throws TransformationException if the transformation could not be done, because of a wrong format or an error during transformation. */ @Override + @SuppressWarnings("unchecked") // Cache stores Object, safe cast as we control what's stored public <T> T get(final String key, final Class<T> targetClass) { try { - return (T) cacheManager.getIfNotExpired(key, now()).orElseGet(() -> - { + return (T) cacheManager.getIfNotExpired(key, now()).orElseGet(() -> { String value = getValue(key); if (transformationManager == null) { @@ -207,7 +220,7 @@ protected Instant now() { protected void resetToDefaults() { cacheManager.resetExpirationTime(); if (transformationManager != null) { - transformationManager.setTransformer(null); + transformationManager.unsetTransformer(); } } diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/CacheManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/CacheManager.java index b868cb642..99c281b3d 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/CacheManager.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/CacheManager.java @@ -20,18 +20,27 @@ import java.time.Duration; import java.time.Instant; import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; +/** + * Manages caching of parameter values with configurable expiration times. + * <p> + * This class is thread-safe. The cache storage is shared across all threads, + * while expiration time configuration is thread-local to support concurrent + * requests with different cache TTL requirements. + */ public class CacheManager { static final Duration DEFAULT_MAX_AGE_SECS = Duration.of(5, SECONDS); private final DataStore store; - private Duration defaultMaxAge = DEFAULT_MAX_AGE_SECS; - private Duration maxAge = defaultMaxAge; + private final AtomicReference<Duration> defaultMaxAge = new AtomicReference<>(DEFAULT_MAX_AGE_SECS); + private final ThreadLocal<Duration> maxAge = ThreadLocal.withInitial(() -> null); public CacheManager() { store = new DataStore(); } + @SuppressWarnings("unchecked") // DataStore stores Object, safe cast as we control what's stored public <T> Optional<T> getIfNotExpired(String key, Instant now) { if (store.hasExpired(key, now)) { return Optional.empty(); @@ -40,19 +49,19 @@ public <T> Optional<T> getIfNotExpired(String key, Instant now) { } public void setExpirationTime(Duration duration) { - this.maxAge = duration; + this.maxAge.set(duration); } public void setDefaultExpirationTime(Duration duration) { - this.defaultMaxAge = duration; - this.maxAge = duration; + this.defaultMaxAge.set(duration); } public <T> void putInCache(String key, T value) { - store.put(key, value, Clock.systemDefaultZone().instant().plus(maxAge)); + Duration effectiveMaxAge = maxAge.get() != null ? maxAge.get() : defaultMaxAge.get(); + store.put(key, value, Clock.systemDefaultZone().instant().plus(effectiveMaxAge)); } public void resetExpirationTime() { - maxAge = defaultMaxAge; + maxAge.remove(); } } diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/DataStore.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/DataStore.java index 737faa353..4b6350cb5 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/DataStore.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/cache/DataStore.java @@ -15,6 +15,7 @@ package software.amazon.lambda.powertools.parameters.cache; import java.time.Instant; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** @@ -22,7 +23,7 @@ */ public class DataStore { - private final ConcurrentHashMap<String, ValueNode> store; + private final Map<String, ValueNode> store; public DataStore() { this.store = new ConcurrentHashMap<>(); @@ -32,8 +33,8 @@ public void put(String key, Object value, Instant time) { store.put(key, new ValueNode(value, time)); } - public void remove(String Key) { - store.remove(Key); + public void remove(String key) { + store.remove(key); } public Object get(String key) { @@ -42,7 +43,11 @@ public Object get(String key) { } public boolean hasExpired(String key, Instant now) { - boolean hasExpired = !store.containsKey(key) || now.isAfter(store.get(key).time); + ValueNode node = store.get(key); + if (node == null) { + return true; + } + boolean hasExpired = now.isAfter(node.time); // Auto-clean if the parameter has expired if (hasExpired) { remove(key); diff --git a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/TransformationManager.java b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/TransformationManager.java index d3fbce14f..bddbf81d9 100644 --- a/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/TransformationManager.java +++ b/powertools-parameters/src/main/java/software/amazon/lambda/powertools/parameters/transform/TransformationManager.java @@ -15,31 +15,44 @@ package software.amazon.lambda.powertools.parameters.transform; import java.lang.reflect.InvocationTargetException; + import software.amazon.lambda.powertools.parameters.exception.TransformationException; /** * Manager in charge of transforming parameter values in another format. <br/> * Leverages a {@link Transformer} in order to perform the transformation. <br/> * The transformer must be passed with {@link #setTransformer(Class)} before performing any transform operation. + * <p> + * This class is thread-safe. Transformer configuration is thread-local to support concurrent + * requests with different transformation requirements. */ public class TransformationManager { - private Class<? extends Transformer> transformer = null; + private final ThreadLocal<Class<? extends Transformer>> transformer = ThreadLocal.withInitial(() -> null); /** * Set the {@link Transformer} to use for transformation. Must be called before any transformation. * * @param transformerClass class of the {@link Transformer} */ + @SuppressWarnings("rawtypes") // Transformer type parameter determined at runtime public void setTransformer(Class<? extends Transformer> transformerClass) { - this.transformer = transformerClass; + this.transformer.set(transformerClass); + } + + /** + * Unset the {@link Transformer} and clean up thread-local storage. + * Should be called after transformation is complete to prevent memory leaks. + */ + public void unsetTransformer() { + this.transformer.remove(); } /** * @return true if a {@link Transformer} has been passed to the Manager */ public boolean shouldTransform() { - return transformer != null; + return transformer.get() != null; } /** @@ -48,20 +61,22 @@ public boolean shouldTransform() { * @param value the value to transform * @return the value transformed */ + @SuppressWarnings("rawtypes") // Transformer type parameter determined at runtime public String performBasicTransformation(String value) { - if (transformer == null) { + Class<? extends Transformer> transformerClass = transformer.get(); + if (transformerClass == null) { throw new IllegalStateException( "You cannot perform a transformation without Transformer, use the provider.withTransformation() method to specify it."); } - if (!BasicTransformer.class.isAssignableFrom(transformer)) { + if (!BasicTransformer.class.isAssignableFrom(transformerClass)) { throw new IllegalStateException("Wrong Transformer for a String, choose a BasicTransformer."); } try { - BasicTransformer basicTransformer = - (BasicTransformer) transformer.getDeclaredConstructor().newInstance(null); + BasicTransformer basicTransformer = (BasicTransformer) transformerClass.getDeclaredConstructor() + .newInstance(null); return basicTransformer.applyTransformation(value); - } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | - InvocationTargetException e) { + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException + | InvocationTargetException e) { throw new TransformationException(e); } } @@ -73,17 +88,19 @@ public String performBasicTransformation(String value) { * @param targetClass the type of the target object. * @return the value transformed in an object ot type T. */ + @SuppressWarnings("rawtypes") // Transformer type parameter determined at runtime public <T> T performComplexTransformation(String value, Class<T> targetClass) { - if (transformer == null) { + Class<? extends Transformer> transformerClass = transformer.get(); + if (transformerClass == null) { throw new IllegalStateException( "You cannot perform a transformation without Transformer, use the provider.withTransformation() method to specify it."); } try { - Transformer<T> complexTransformer = transformer.getDeclaredConstructor().newInstance(null); + Transformer<T> complexTransformer = transformerClass.getDeclaredConstructor().newInstance(null); return complexTransformer.applyTransformation(value, targetClass); - } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | - InvocationTargetException e) { + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException + | InvocationTargetException e) { throw new TransformationException(e); } } From 03ca72b27463e5848f582c689b474cdb92643f61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Nov 2025 09:27:22 +0100 Subject: [PATCH 536/577] chore: bump aws.sdk.version from 2.38.3 to 2.38.5 (#2287) Bumps `aws.sdk.version` from 2.38.3 to 2.38.5. Updates `software.amazon.awssdk:bom` from 2.38.3 to 2.38.5 Updates `software.amazon.awssdk:http-client-spi` from 2.38.3 to 2.38.5 Updates `software.amazon.awssdk:url-connection-client` from 2.38.2 to 2.38.5 Updates `software.amazon.awssdk:s3` from 2.38.2 to 2.38.5 Updates `software.amazon.awssdk:dynamodb` from 2.38.3 to 2.38.5 Updates `software.amazon.awssdk:lambda` from 2.38.3 to 2.38.5 Updates `software.amazon.awssdk:kinesis` from 2.38.2 to 2.38.5 Updates `software.amazon.awssdk:cloudwatch` from 2.38.3 to 2.38.5 Updates `software.amazon.awssdk:xray` from 2.38.3 to 2.38.5 Updates `software.amazon.awssdk:sqs` from 2.38.2 to 2.38.5 Updates `software.amazon.awssdk:cloudformation` from 2.38.3 to 2.38.5 Updates `software.amazon.awssdk:sts` from 2.38.3 to 2.38.5 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.38.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.38.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.38.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.38.5 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.38.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.38.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.38.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.38.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.38.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.38.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.38.5 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.38.5 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 74ced3a4f..824b98da9 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.38.3</aws.sdk.version> + <aws.sdk.version>2.38.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 48be39d47..536ba6002 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.1</jackson.version> - <aws.sdk.version>2.38.3</aws.sdk.version> + <aws.sdk.version>2.38.5</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index afc21131f..7838dfc03 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.38.3</aws.sdk.version> + <aws.sdk.version>2.38.5</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 4e83d8a3b5cfbdb26d6ae5db81393d9c47c78df5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Nov 2025 09:27:30 +0100 Subject: [PATCH 537/577] chore: bump commons-io:commons-io from 2.20.0 to 2.21.0 (#2288) Bumps [commons-io:commons-io](https://github.com/apache/commons-io) from 2.20.0 to 2.21.0. - [Changelog](https://github.com/apache/commons-io/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-io/compare/rel/commons-io-2.20.0...rel/commons-io-2.21.0) --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-version: 2.21.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 998c6a803..6dd94910a 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -95,7 +95,7 @@ <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> - <version>2.20.0</version> + <version>2.21.0</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> From 3ed0e0dea3f5c5988dbc8e34ccfb7ffb207f6133 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Mon, 17 Nov 2025 10:56:22 +0100 Subject: [PATCH 538/577] improv(metrics): Add thread-safety to Metrics utility through request-scoped Metrics instance management (#2294) * Add proxy to manage thread local metrics provider instances to achieve zero-lock thread-safety. * Refactor from inheritable thread local to tracking by trace id. Similar to log buffer. * Do not hard code JVM system property for trace id. * Fix PMD findings. --- .../powertools/metrics/MetricsFactory.java | 18 +- .../internal/RequestScopedMetricsProxy.java | 156 ++++++++++ .../metrics/ConfigurationPrecedenceTest.java | 13 +- .../metrics/MetricsBuilderTest.java | 18 +- .../metrics/MetricsFactoryTest.java | 70 ++++- .../metrics/RequestHandlerTest.java | 2 +- .../internal/EmfMetricsLoggerTest.java | 14 +- .../internal/LambdaMetricsAspectTest.java | 8 +- .../RequestScopedMetricsProxyTest.java | 277 ++++++++++++++++++ 9 files changed, 536 insertions(+), 40 deletions(-) create mode 100644 powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/RequestScopedMetricsProxy.java create mode 100644 powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/RequestScopedMetricsProxyTest.java diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java index 67ab17b7b..0644329c9 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/MetricsFactory.java @@ -16,9 +16,11 @@ import org.crac.Core; import org.crac.Resource; + import software.amazon.lambda.powertools.common.internal.ClassPreLoader; import software.amazon.lambda.powertools.common.internal.LambdaConstants; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.metrics.internal.RequestScopedMetricsProxy; import software.amazon.lambda.powertools.metrics.model.DimensionSet; import software.amazon.lambda.powertools.metrics.provider.EmfMetricsProvider; import software.amazon.lambda.powertools.metrics.provider.MetricsProvider; @@ -28,7 +30,7 @@ */ public final class MetricsFactory implements Resource { private static MetricsProvider provider = new EmfMetricsProvider(); - private static Metrics metrics; + private static RequestScopedMetricsProxy metricsProxy; // Dummy instance to register MetricsFactory with CRaC private static final MetricsFactory INSTANCE = new MetricsFactory(); @@ -44,23 +46,23 @@ public final class MetricsFactory implements Resource { * @return the singleton Metrics instance */ public static synchronized Metrics getMetricsInstance() { - if (metrics == null) { - metrics = provider.getMetricsInstance(); + if (metricsProxy == null) { + metricsProxy = new RequestScopedMetricsProxy(provider); // Apply default configuration from environment variables String envNamespace = System.getenv("POWERTOOLS_METRICS_NAMESPACE"); if (envNamespace != null) { - metrics.setNamespace(envNamespace); + metricsProxy.setNamespace(envNamespace); } // Only set Service dimension if it's not the default undefined value String serviceName = LambdaHandlerProcessor.serviceName(); if (!LambdaConstants.SERVICE_UNDEFINED.equals(serviceName)) { - metrics.setDefaultDimensions(DimensionSet.of("Service", serviceName)); + metricsProxy.setDefaultDimensions(DimensionSet.of("Service", serviceName)); } } - return metrics; + return metricsProxy; } /** @@ -73,8 +75,8 @@ public static synchronized void setMetricsProvider(MetricsProvider metricsProvid throw new IllegalArgumentException("Metrics provider cannot be null"); } provider = metricsProvider; - // Reset the metrics instance so it will be recreated with the new provider - metrics = null; + // Reset the metrics proxy so it will be recreated with the new provider + metricsProxy = null; } @Override diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/RequestScopedMetricsProxy.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/RequestScopedMetricsProxy.java new file mode 100644 index 000000000..61c83be17 --- /dev/null +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/RequestScopedMetricsProxy.java @@ -0,0 +1,156 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.metrics.internal; + +import java.time.Instant; +import java.util.HashMap; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import com.amazonaws.services.lambda.runtime.Context; + +import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricResolution; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; +import software.amazon.lambda.powertools.metrics.provider.MetricsProvider; + +public class RequestScopedMetricsProxy implements Metrics { + private static final String DEFAULT_TRACE_ID = "DEFAULT"; + private final ConcurrentMap<String, Metrics> metricsMap = new ConcurrentHashMap<>(); + private final MetricsProvider provider; + private final AtomicReference<String> initialNamespace = new AtomicReference<>(); + private final AtomicReference<DimensionSet> initialDefaultDimensions = new AtomicReference<>(); + private final AtomicBoolean initialRaiseOnEmptyMetrics = new AtomicBoolean(false); + + public RequestScopedMetricsProxy(MetricsProvider provider) { + this.provider = provider; + } + + private String getTraceId() { + return LambdaHandlerProcessor.getXrayTraceId().orElse(DEFAULT_TRACE_ID); + } + + private Metrics getOrCreateMetrics() { + String traceId = getTraceId(); + return metricsMap.computeIfAbsent(traceId, key -> { + Metrics metrics = provider.getMetricsInstance(); + String namespace = initialNamespace.get(); + if (namespace != null) { + metrics.setNamespace(namespace); + } + DimensionSet dimensions = initialDefaultDimensions.get(); + if (dimensions != null) { + metrics.setDefaultDimensions(dimensions); + } + metrics.setRaiseOnEmptyMetrics(initialRaiseOnEmptyMetrics.get()); + return metrics; + }); + } + + // Configuration methods - called by MetricsFactory and MetricsBuilder + // These methods DO NOT eagerly create instances because they are typically called + // outside the Lambda handler (e.g., during class initialization) potentially on a different thread. + // We delay instance creation until the first operation that needs the metrics backend (e.g., addMetric). + // See {@link software.amazon.lambda.powertools.metrics.MetricsFactory#getMetricsInstance()} + // and {@link software.amazon.lambda.powertools.metrics.MetricsBuilder#build()} + + @Override + public void setNamespace(String namespace) { + this.initialNamespace.set(namespace); + Optional.ofNullable(metricsMap.get(getTraceId())).ifPresent(m -> m.setNamespace(namespace)); + } + + @Override + public void setDefaultDimensions(DimensionSet dimensionSet) { + if (dimensionSet == null) { + throw new IllegalArgumentException("DimensionSet cannot be null"); + } + this.initialDefaultDimensions.set(dimensionSet); + Optional.ofNullable(metricsMap.get(getTraceId())).ifPresent(m -> m.setDefaultDimensions(dimensionSet)); + } + + @Override + public void setRaiseOnEmptyMetrics(boolean raiseOnEmptyMetrics) { + this.initialRaiseOnEmptyMetrics.set(raiseOnEmptyMetrics); + Optional.ofNullable(metricsMap.get(getTraceId())).ifPresent(m -> m.setRaiseOnEmptyMetrics(raiseOnEmptyMetrics)); + } + + @Override + public DimensionSet getDefaultDimensions() { + Metrics metrics = metricsMap.get(getTraceId()); + if (metrics != null) { + return metrics.getDefaultDimensions(); + } + DimensionSet dimensions = initialDefaultDimensions.get(); + return dimensions != null ? dimensions : DimensionSet.of(new HashMap<>()); + } + + // Metrics operations - these eagerly create instances + + @Override + public void addMetric(String key, double value, MetricUnit unit, MetricResolution resolution) { + getOrCreateMetrics().addMetric(key, value, unit, resolution); + } + + @Override + public void addDimension(DimensionSet dimensionSet) { + getOrCreateMetrics().addDimension(dimensionSet); + } + + @Override + public void setTimestamp(Instant timestamp) { + getOrCreateMetrics().setTimestamp(timestamp); + } + + @Override + public void addMetadata(String key, Object value) { + getOrCreateMetrics().addMetadata(key, value); + } + + @Override + public void clearDefaultDimensions() { + getOrCreateMetrics().clearDefaultDimensions(); + } + + @Override + public void flush() { + // Always create instance to ensure validation and warnings are triggered. E.g. when raiseOnEmptyMetrics + // is enabled. + Metrics metrics = getOrCreateMetrics(); + metrics.flush(); + metricsMap.remove(getTraceId()); + } + + @Override + public void captureColdStartMetric(Context context, DimensionSet dimensions) { + getOrCreateMetrics().captureColdStartMetric(context, dimensions); + } + + @Override + public void captureColdStartMetric(DimensionSet dimensions) { + getOrCreateMetrics().captureColdStartMetric(dimensions); + } + + @Override + public void flushMetrics(Consumer<Metrics> metricsConsumer) { + getOrCreateMetrics().flushMetrics(metricsConsumer); + } +} diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java index c9c772313..492ecfc1e 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/ConfigurationPrecedenceTest.java @@ -33,8 +33,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; -import software.amazon.lambda.powertools.metrics.model.MetricUnit; import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; /** * Tests to verify the hierarchy of precedence for configuration: @@ -44,7 +44,7 @@ */ class ConfigurationPrecedenceTest { - private final PrintStream standardOut = System.out; + private static final PrintStream STANDARD_OUT = System.out; private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); private final ObjectMapper objectMapper = new ObjectMapper(); @@ -65,10 +65,10 @@ void setUp() throws Exception { @AfterEach void tearDown() throws Exception { - System.setOut(standardOut); + System.setOut(STANDARD_OUT); // Reset the singleton state between tests - java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metricsProxy"); field.setAccessible(true); field.set(null, null); @@ -183,7 +183,7 @@ void shouldUseDefaultsWhenNoConfiguration() throws Exception { assertThat(rootNode.has("Service")).isFalse(); } - private static class HandlerWithMetricsAnnotation implements RequestHandler<Map<String, Object>, String> { + private static final class HandlerWithMetricsAnnotation implements RequestHandler<Map<String, Object>, String> { @Override @FlushMetrics(namespace = "AnnotationNamespace", service = "AnnotationService") public String handleRequest(Map<String, Object> input, Context context) { @@ -193,7 +193,8 @@ public String handleRequest(Map<String, Object> input, Context context) { } } - private static class HandlerWithDefaultMetricsAnnotation implements RequestHandler<Map<String, Object>, String> { + private static final class HandlerWithDefaultMetricsAnnotation + implements RequestHandler<Map<String, Object>, String> { @Override @FlushMetrics public String handleRequest(Map<String, Object> input, Context context) { diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsBuilderTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsBuilderTest.java index bd300fb6b..12ac46e43 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsBuilderTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsBuilderTest.java @@ -27,15 +27,15 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import software.amazon.lambda.powertools.metrics.internal.RequestScopedMetricsProxy; import software.amazon.lambda.powertools.metrics.model.DimensionSet; import software.amazon.lambda.powertools.metrics.model.MetricUnit; import software.amazon.lambda.powertools.metrics.provider.MetricsProvider; -import software.amazon.lambda.powertools.metrics.testutils.TestMetrics; import software.amazon.lambda.powertools.metrics.testutils.TestMetricsProvider; class MetricsBuilderTest { - private final PrintStream standardOut = System.out; + private static final PrintStream STANDARD_OUT = System.out; private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); private final ObjectMapper objectMapper = new ObjectMapper(); @@ -46,10 +46,10 @@ void setUp() { @AfterEach void tearDown() throws Exception { - System.setOut(standardOut); + System.setOut(STANDARD_OUT); // Reset the singleton state between tests - java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metricsProxy"); field.setAccessible(true); field.set(null, null); @@ -151,7 +151,7 @@ void shouldBuildWithMultipleDefaultDimensions() throws Exception { } @Test - void shouldBuildWithCustomMetricsProvider() { + void shouldBuildWithCustomMetricsProvider() throws Exception { // Given MetricsProvider testProvider = new TestMetricsProvider(); @@ -161,7 +161,13 @@ void shouldBuildWithCustomMetricsProvider() { .build(); // Then - assertThat(metrics).isInstanceOf(TestMetrics.class); + assertThat(metrics) + .isInstanceOf(RequestScopedMetricsProxy.class); + + java.lang.reflect.Field providerField = metrics.getClass().getDeclaredField("provider"); + providerField.setAccessible(true); + MetricsProvider actualProvider = (MetricsProvider) providerField.get(metrics); + assertThat(actualProvider).isSameAs(testProvider); } @Test diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java index 4fc98d2a5..c9b183a1a 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/MetricsFactoryTest.java @@ -29,10 +29,11 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import software.amazon.lambda.powertools.common.internal.LambdaConstants; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.metrics.internal.RequestScopedMetricsProxy; import software.amazon.lambda.powertools.metrics.model.MetricUnit; import software.amazon.lambda.powertools.metrics.provider.MetricsProvider; -import software.amazon.lambda.powertools.metrics.testutils.TestMetrics; import software.amazon.lambda.powertools.metrics.testutils.TestMetricsProvider; class MetricsFactoryTest { @@ -40,7 +41,7 @@ class MetricsFactoryTest { private static final String TEST_NAMESPACE = "TestNamespace"; private static final String TEST_SERVICE = "TestService"; - private final PrintStream standardOut = System.out; + private static final PrintStream STANDARD_OUT = System.out; private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); private final ObjectMapper objectMapper = new ObjectMapper(); @@ -61,10 +62,11 @@ void setUp() throws Exception { @AfterEach void tearDown() throws Exception { - System.setOut(standardOut); + System.setOut(STANDARD_OUT); + System.clearProperty(LambdaConstants.XRAY_TRACE_HEADER); // Reset the singleton state between tests - java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metricsProxy"); field.setAccessible(true); field.set(null, null); @@ -126,7 +128,7 @@ void shouldUseServiceNameFromEnvironmentVariable() throws Exception { } @Test - void shouldSetCustomMetricsProvider() { + void shouldSetCustomMetricsProvider() throws Exception { // Given MetricsProvider testProvider = new TestMetricsProvider(); @@ -135,7 +137,13 @@ void shouldSetCustomMetricsProvider() { Metrics metrics = MetricsFactory.getMetricsInstance(); // Then - assertThat(metrics).isInstanceOf(TestMetrics.class); + assertThat(metrics) + .isInstanceOf(RequestScopedMetricsProxy.class); + + java.lang.reflect.Field providerField = metrics.getClass().getDeclaredField("provider"); + providerField.setAccessible(true); + MetricsProvider actualProvider = (MetricsProvider) providerField.get(metrics); + assertThat(actualProvider).isSameAs(testProvider); } @Test @@ -163,4 +171,54 @@ void shouldNotSetServiceDimensionWhenServiceUndefined() throws Exception { // Service dimension should not be present assertThat(rootNode.has("Service")).isFalse(); } + + @Test + void shouldIsolateMetricsByTraceId() throws Exception { + // GIVEN + Metrics metrics = MetricsFactory.getMetricsInstance(); + + // WHEN - Simulate Lambda invocation 1 with trace ID 1 + System.setProperty(LambdaConstants.XRAY_TRACE_HEADER, "Root=1-trace-id-1"); + metrics.setNamespace("TestNamespace"); + metrics.addDimension("userId", "user123"); + metrics.addMetric("ProcessedOrder", 1, MetricUnit.COUNT); + metrics.flush(); + + // WHEN - Simulate Lambda invocation 2 with trace ID 2 + System.setProperty(LambdaConstants.XRAY_TRACE_HEADER, "Root=1-trace-id-2"); + metrics.setNamespace("TestNamespace"); + metrics.addDimension("userId", "user456"); + metrics.addMetric("ProcessedOrder", 1, MetricUnit.COUNT); + metrics.flush(); + + // THEN - Verify each invocation has isolated metrics + String emfOutput = outputStreamCaptor.toString().trim(); + String[] jsonLines = emfOutput.split("\n"); + assertThat(jsonLines).hasSize(2); + + JsonNode output1 = objectMapper.readTree(jsonLines[0]); + JsonNode output2 = objectMapper.readTree(jsonLines[1]); + + assertThat(output1.get("userId").asText()).isEqualTo("user123"); + assertThat(output2.get("userId").asText()).isEqualTo("user456"); + } + + @Test + void shouldUseDefaultKeyWhenNoTraceId() throws Exception { + // GIVEN - No trace ID set + System.clearProperty(LambdaConstants.XRAY_TRACE_HEADER); + + // WHEN + Metrics metrics = MetricsFactory.getMetricsInstance(); + metrics.setNamespace("TestNamespace"); + metrics.addMetric("TestMetric", 1, MetricUnit.COUNT); + metrics.flush(); + + // THEN - Should work without X-Ray trace ID + String emfOutput = outputStreamCaptor.toString().trim(); + assertThat(emfOutput).isNotEmpty(); + + JsonNode rootNode = objectMapper.readTree(emfOutput); + assertThat(rootNode.get("TestMetric").asDouble()).isEqualTo(1.0); + } } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java index d3ed64fe3..fcd677c02 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/RequestHandlerTest.java @@ -56,7 +56,7 @@ void tearDown() throws Exception { System.setOut(STDOUT); // Reset the singleton state between tests - java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metricsProxy"); field.setAccessible(true); field.set(null, null); diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java index bab039640..c2238711a 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java @@ -38,14 +38,15 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import software.amazon.cloudwatchlogs.emf.environment.EnvironmentProvider; +import software.amazon.cloudwatchlogs.emf.model.MetricsContext; import software.amazon.cloudwatchlogs.emf.model.Unit; import software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor; +import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; import software.amazon.lambda.powertools.metrics.Metrics; -import software.amazon.lambda.powertools.metrics.MetricsFactory; import software.amazon.lambda.powertools.metrics.model.DimensionSet; import software.amazon.lambda.powertools.metrics.model.MetricResolution; import software.amazon.lambda.powertools.metrics.model.MetricUnit; -import software.amazon.lambda.powertools.common.stubs.TestLambdaContext; class EmfMetricsLoggerTest { @@ -66,19 +67,14 @@ void setUp() throws Exception { coldStartField.setAccessible(true); coldStartField.set(null, null); - metrics = MetricsFactory.getMetricsInstance(); + metrics = new EmfMetricsLogger(new EnvironmentProvider(), new MetricsContext()); metrics.setNamespace("TestNamespace"); System.setOut(new PrintStream(outputStreamCaptor)); } @AfterEach - void tearDown() throws Exception { + void tearDown() { System.setOut(standardOut); - - // Reset the singleton state between tests - java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); - field.setAccessible(true); - field.set(null, null); } @ParameterizedTest diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java index 031fe4553..119e094a9 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/LambdaMetricsAspectTest.java @@ -41,7 +41,7 @@ class LambdaMetricsAspectTest { - private final PrintStream standardOut = System.out; + private static final PrintStream STANDARD_OUT = System.out; private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream(); private final ObjectMapper objectMapper = new ObjectMapper(); @@ -62,10 +62,10 @@ void setUp() throws Exception { @AfterEach void tearDown() throws Exception { - System.setOut(standardOut); + System.setOut(STANDARD_OUT); // Reset the singleton state between tests - java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metrics"); + java.lang.reflect.Field field = MetricsFactory.class.getDeclaredField("metricsProxy"); field.setAccessible(true); field.set(null, null); } @@ -216,7 +216,7 @@ void shouldUseCustomFunctionNameWhenProvidedForColdStartMetric() throws Exceptio JsonNode dimensions = coldStartNode.get("_aws").get("CloudWatchMetrics").get(0).get("Dimensions").get(0); boolean hasFunctionName = false; for (JsonNode dimension : dimensions) { - if (dimension.asText().equals("FunctionName")) { + if ("FunctionName".equals(dimension.asText())) { hasFunctionName = true; break; } diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/RequestScopedMetricsProxyTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/RequestScopedMetricsProxyTest.java new file mode 100644 index 000000000..848222bae --- /dev/null +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/RequestScopedMetricsProxyTest.java @@ -0,0 +1,277 @@ +package software.amazon.lambda.powertools.metrics.internal; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.time.Instant; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mock.Strictness; +import org.mockito.junit.jupiter.MockitoExtension; + +import software.amazon.lambda.powertools.common.internal.LambdaConstants; +import software.amazon.lambda.powertools.metrics.Metrics; +import software.amazon.lambda.powertools.metrics.model.DimensionSet; +import software.amazon.lambda.powertools.metrics.model.MetricResolution; +import software.amazon.lambda.powertools.metrics.model.MetricUnit; +import software.amazon.lambda.powertools.metrics.provider.MetricsProvider; + +/** + * Tests for RequestScopedMetricsProxy focusing on lazy vs eager initialization behavior. + * + * CRITICAL: These tests ensure configuration methods (setNamespace, setDefaultDimensions, + * setRaiseOnEmptyMetrics) do NOT eagerly create instances, while metrics operations + * (addMetric, addDimension, flush) DO eagerly create instances. + */ +@ExtendWith(MockitoExtension.class) +class RequestScopedMetricsProxyTest { + + @Mock(strictness = Strictness.LENIENT) + private MetricsProvider mockProvider; + + @Mock(strictness = Strictness.LENIENT) + private Metrics mockMetrics; + + private RequestScopedMetricsProxy proxy; + + @BeforeEach + void setUp() { + when(mockProvider.getMetricsInstance()).thenReturn(mockMetrics); + proxy = new RequestScopedMetricsProxy(mockProvider); + } + + @AfterEach + void tearDown() { + System.clearProperty(LambdaConstants.XRAY_TRACE_HEADER); + } + + // ========== LAZY INITIALIZATION TESTS (Configuration Methods) ========== + + @Test + void setNamespace_shouldNotEagerlyCreateInstance() { + // WHEN + proxy.setNamespace("TestNamespace"); + + // THEN - Provider should NOT be called (lazy initialization) + verify(mockProvider, never()).getMetricsInstance(); + } + + @Test + void setDefaultDimensions_shouldNotEagerlyCreateInstance() { + // WHEN + proxy.setDefaultDimensions(DimensionSet.of("key", "value")); + + // THEN - Provider should NOT be called (lazy initialization) + verify(mockProvider, never()).getMetricsInstance(); + } + + @Test + void setDefaultDimensions_shouldThrowExceptionWhenNull() { + // When/Then + assertThatThrownBy(() -> proxy.setDefaultDimensions(null)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("DimensionSet cannot be null"); + } + + @Test + void setRaiseOnEmptyMetrics_shouldNotEagerlyCreateInstance() { + // WHEN + proxy.setRaiseOnEmptyMetrics(true); + + // THEN - Provider should NOT be called (lazy initialization) + verify(mockProvider, never()).getMetricsInstance(); + } + + // ========== EAGER INITIALIZATION TESTS (Metrics Operations) ========== + + @Test + void addMetric_shouldEagerlyCreateInstance() { + // WHEN + proxy.addMetric("test", 1, MetricUnit.COUNT, MetricResolution.HIGH); + + // THEN - Provider SHOULD be called (eager initialization) + verify(mockProvider, times(1)).getMetricsInstance(); + verify(mockMetrics).addMetric("test", 1, MetricUnit.COUNT, MetricResolution.HIGH); + } + + @Test + void addDimension_shouldEagerlyCreateInstance() { + // WHEN + proxy.addDimension(DimensionSet.of("key", "value")); + + // THEN - Provider SHOULD be called (eager initialization) + verify(mockProvider, times(1)).getMetricsInstance(); + verify(mockMetrics).addDimension(any(DimensionSet.class)); + } + + @Test + void addMetadata_shouldEagerlyCreateInstance() { + // WHEN + proxy.addMetadata("key", "value"); + + // THEN - Provider SHOULD be called (eager initialization) + verify(mockProvider, times(1)).getMetricsInstance(); + verify(mockMetrics).addMetadata("key", "value"); + } + + @Test + void flush_shouldAlwaysCreateInstance() { + // WHEN + proxy.flush(); + + // THEN - Provider SHOULD be called even if no metrics added + verify(mockProvider, times(1)).getMetricsInstance(); + verify(mockMetrics).flush(); + } + + // ========== CONFIGURATION APPLIED ON FIRST METRICS OPERATION ========== + + @Test + void firstMetricsOperation_shouldApplyStoredConfiguration() { + // GIVEN - Set configuration without creating instance + proxy.setNamespace("TestNamespace"); + proxy.setDefaultDimensions(DimensionSet.of("Service", "TestService")); + proxy.setRaiseOnEmptyMetrics(true); + verify(mockProvider, never()).getMetricsInstance(); + + // WHEN - First metrics operation + proxy.addMetric("test", 1, MetricUnit.COUNT); + + // THEN - Instance created and configuration applied + verify(mockProvider, times(1)).getMetricsInstance(); + verify(mockMetrics).setNamespace("TestNamespace"); + verify(mockMetrics).setDefaultDimensions(any(DimensionSet.class)); + verify(mockMetrics).setRaiseOnEmptyMetrics(true); + verify(mockMetrics).addMetric("test", 1, MetricUnit.COUNT, MetricResolution.STANDARD); + } + + // ========== THREAD ISOLATION TESTS ========== + + @Test + void shouldShareInstanceAcrossThreadsWithSameTraceId() throws Exception { + // GIVEN - Set trace ID + System.setProperty(LambdaConstants.XRAY_TRACE_HEADER, "Root=1-test-trace-id"); + + // WHEN - Parent thread adds metric + proxy.addMetric("metric1", 1, MetricUnit.COUNT); + verify(mockProvider, times(1)).getMetricsInstance(); + + // WHEN - Child thread adds metric (same trace ID) + Thread thread2 = new Thread(() -> { + proxy.addMetric("metric2", 2, MetricUnit.COUNT); + }); + thread2.start(); + thread2.join(); + + // THEN - Only one instance created (same trace ID = shared instance) + verify(mockProvider, times(1)).getMetricsInstance(); + } + + @Test + void flush_shouldRemoveThreadLocalInstance() { + // GIVEN - Create instance + proxy.addMetric("test", 1, MetricUnit.COUNT); + verify(mockProvider, times(1)).getMetricsInstance(); + + // WHEN - Flush + proxy.flush(); + + // WHEN - Add another metric (should create new instance) + proxy.addMetric("test2", 2, MetricUnit.COUNT); + + // THEN - Provider called twice (instance was removed after flush) + verify(mockProvider, times(2)).getMetricsInstance(); + } + + // ========== EDGE CASES ========== + + @Test + void multipleConfigurationCalls_shouldUpdateAtomicReferences() { + // WHEN + proxy.setNamespace("Namespace1"); + proxy.setNamespace("Namespace2"); + proxy.setNamespace("Namespace3"); + + // THEN - No instance created + verify(mockProvider, never()).getMetricsInstance(); + + // WHEN - First metrics operation + proxy.addMetric("test", 1, MetricUnit.COUNT); + + // THEN - Only last namespace applied + verify(mockMetrics).setNamespace("Namespace3"); + verify(mockMetrics, never()).setNamespace("Namespace1"); + verify(mockMetrics, never()).setNamespace("Namespace2"); + } + + @Test + void configurationAfterInstanceCreation_shouldApplyImmediately() { + // GIVEN - Instance already created + proxy.addMetric("test", 1, MetricUnit.COUNT); + + // WHEN - Set configuration + proxy.setNamespace("NewNamespace"); + + // THEN - Applied immediately to existing instance + verify(mockMetrics).setNamespace("NewNamespace"); + } + + @Test + void setTimestamp_shouldEagerlyCreateInstance() { + // When + proxy.setTimestamp(Instant.now()); + + // Then + verify(mockProvider, times(1)).getMetricsInstance(); + verify(mockMetrics).setTimestamp(any()); + } + + @Test + void getDefaultDimensions_shouldNotEagerlyCreateInstance() { + // WHEN + DimensionSet result = proxy.getDefaultDimensions(); + + // THEN - Provider should NOT be called (returns stored config or empty) + verify(mockProvider, never()).getMetricsInstance(); + assertThat(result).isNotNull(); + } + + @Test + void captureColdStartMetric_shouldEagerlyCreateInstance() { + // WHEN + proxy.captureColdStartMetric(DimensionSet.of("key", "value")); + + // THEN - Provider SHOULD be called (eager initialization) + verify(mockProvider, times(1)).getMetricsInstance(); + verify(mockMetrics).captureColdStartMetric(any(DimensionSet.class)); + } + + @Test + void flushMetrics_shouldEagerlyCreateInstance() { + // WHEN + proxy.flushMetrics(m -> m.addMetric("test", 1, MetricUnit.COUNT)); + + // THEN - Provider SHOULD be called (eager initialization) + verify(mockProvider, times(1)).getMetricsInstance(); + verify(mockMetrics).flushMetrics(any()); + } + + @Test + void clearDefaultDimensions_shouldEagerlyCreateInstance() { + // WHEN + proxy.clearDefaultDimensions(); + + // THEN - Provider SHOULD be called (eager initialization) + verify(mockProvider, times(1)).getMetricsInstance(); + verify(mockMetrics).clearDefaultDimensions(); + } +} From 0af0ba445821cdd810da4eef2fb3de8ef0770c77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 10:58:59 +0100 Subject: [PATCH 539/577] chore: bump aws.sdk.version from 2.38.5 to 2.38.6 (#2290) Bumps `aws.sdk.version` from 2.38.5 to 2.38.6. Updates `software.amazon.awssdk:bom` from 2.38.5 to 2.38.6 Updates `software.amazon.awssdk:http-client-spi` from 2.38.5 to 2.38.6 Updates `software.amazon.awssdk:url-connection-client` from 2.38.2 to 2.38.6 Updates `software.amazon.awssdk:s3` from 2.38.2 to 2.38.6 Updates `software.amazon.awssdk:dynamodb` from 2.38.5 to 2.38.6 Updates `software.amazon.awssdk:lambda` from 2.38.5 to 2.38.6 Updates `software.amazon.awssdk:kinesis` from 2.38.2 to 2.38.6 Updates `software.amazon.awssdk:cloudwatch` from 2.38.5 to 2.38.6 Updates `software.amazon.awssdk:xray` from 2.38.5 to 2.38.6 Updates `software.amazon.awssdk:sqs` from 2.38.2 to 2.38.6 Updates `software.amazon.awssdk:cloudformation` from 2.38.5 to 2.38.6 Updates `software.amazon.awssdk:sts` from 2.38.5 to 2.38.6 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.38.6 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.38.6 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.38.6 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.38.6 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.38.6 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.38.6 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.38.6 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.38.6 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:xray dependency-version: 2.38.6 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.38.6 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.38.6 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sts dependency-version: 2.38.6 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 824b98da9..9ca4e8dc2 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.38.5</aws.sdk.version> + <aws.sdk.version>2.38.6</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 536ba6002..ba206feae 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.1</jackson.version> - <aws.sdk.version>2.38.5</aws.sdk.version> + <aws.sdk.version>2.38.6</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 7838dfc03..11eedca85 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.38.5</aws.sdk.version> + <aws.sdk.version>2.38.6</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From f7e3b1bddf79e9031cb8e258a05d4272255638e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 10:59:16 +0100 Subject: [PATCH 540/577] chore: bump org.apache.kafka:kafka-clients from 4.1.0 to 4.1.1 (#2291) Bumps org.apache.kafka:kafka-clients from 4.1.0 to 4.1.1. --- updated-dependencies: - dependency-name: org.apache.kafka:kafka-clients dependency-version: 4.1.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 184025be8..24856f80d 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -24,7 +24,7 @@ <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-clients</artifactId> - <version>4.1.0</version> <!-- Supports >= 3.0.0 --> + <version>4.1.1</version> <!-- Supports >= 3.0.0 --> </dependency> <dependency> <groupId>org.apache.avro</groupId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index a07d4e0d6..0a76f0d2e 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -34,7 +34,7 @@ </description> <properties> - <kafka-clients.version>4.1.0</kafka-clients.version> + <kafka-clients.version>4.1.1</kafka-clients.version> <avro.version>1.12.1</avro.version> <protobuf.version>4.33.0</protobuf.version> <lambda-serialization.version>1.1.6</lambda-serialization.version> From 4966668537b189e7eb2f10bace1c63516807ffab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 10:59:39 +0100 Subject: [PATCH 541/577] chore: bump sam/build-java21 (#2292) Bumps sam/build-java21 from `51709ae` to `ced5388`. --- updated-dependencies: - dependency-name: sam/build-java21 dependency-version: ced538830c78a0f45f91abe5f7963cb73005ad933aee7dd1160bd77d9fd3c4f3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index 1abb53643..7d47b5331 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:51709ae612478654f833998a3455519d0524157230757cf6327e402213811e38 +FROM public.ecr.aws/sam/build-java21@sha256:ced538830c78a0f45f91abe5f7963cb73005ad933aee7dd1160bd77d9fd3c4f3 # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz From 14572398c67e2b7e4405aa51ea4bf547cc54b42d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 10:59:57 +0100 Subject: [PATCH 542/577] chore: bump github/codeql-action from 4.31.2 to 4.31.3 (#2293) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.2 to 4.31.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/0499de31b99561a6d14a36a5f662c2a54f91beee...014f16e7ab1402f30e7c3329d33797e7948572db) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 996135fa9..bbf9490c4 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # v3.29.5 + uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v3.29.5 with: sarif_file: results.sarif From f449a570236ed51ddb7f35f7a35835c5a66b26bf Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 18 Nov 2025 18:00:51 +0100 Subject: [PATCH 543/577] chore(ci): Enable Java 25 E2E tests on Java 25 Lambda runtime and upgrade to GraalVM 25. (#2298) * chore(ci): Enable Java 25 E2E tests on Java 25 Lambda runtime. * Only run for GraalVM 25. * Retain log groups according to retention policy of E2E tests to allow for easier debugging. * Add unsafeAllocated: true to allow native calls from Lambda runtime. --- .github/workflows/check-e2e.yml | 9 ++++----- .../reflect-config.json | 18 ++++++++++++++---- .../reflect-config.json | 18 ++++++++++++++---- .../reflect-config.json | 18 ++++++++++++++---- .../reflect-config.json | 18 ++++++++++++++---- .../reflect-config.json | 16 +++++++++++++--- .../reflect-config.json | 3 ++- .../reflect-config.json | 3 ++- .../reflect-config.json | 3 ++- .../reflect-config.json | 3 ++- .../reflect-config.json | 3 ++- .../reflect-config.json | 3 ++- .../reflect-config.json | 3 ++- .../reflect-config.json | 3 ++- powertools-e2e-tests/handlers/pom.xml | 9 +++++++++ .../reflect-config.json | 3 ++- .../powertools/testutils/Infrastructure.java | 4 +++- .../powertools/testutils/JavaRuntime.java | 3 ++- .../src/test/resources/docker/Dockerfile | 8 ++++---- 19 files changed, 109 insertions(+), 39 deletions(-) diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index a3c4a7542..54e7cd023 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -48,12 +48,13 @@ jobs: environment: E2E strategy: fail-fast: false - max-parallel: 3 + max-parallel: 4 matrix: java: - 11 - 17 - 21 + - 25 steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 @@ -81,12 +82,10 @@ jobs: environment: E2E strategy: fail-fast: false - max-parallel: 3 + max-parallel: 1 matrix: java: - - 11 - - 17 - - 21 + - 25 steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 diff --git a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index 10152cc64..e97baa294 100644 --- a/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/examples/powertools-examples-cloudformation/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -27,8 +27,18 @@ "fields":[{"name":"theUnsafe"}] }, { - "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", - "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], - "allPublicMethods":true + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true, + "unsafeAllocated": true } -] \ No newline at end of file +] diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index 10152cc64..e97baa294 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/examples/powertools-examples-core-utilities/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -27,8 +27,18 @@ "fields":[{"name":"theUnsafe"}] }, { - "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", - "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], - "allPublicMethods":true + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true, + "unsafeAllocated": true } -] \ No newline at end of file +] diff --git a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index 10152cc64..e97baa294 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/examples/powertools-examples-idempotency/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -27,8 +27,18 @@ "fields":[{"name":"theUnsafe"}] }, { - "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", - "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], - "allPublicMethods":true + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true, + "unsafeAllocated": true } -] \ No newline at end of file +] diff --git a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index 10152cc64..e97baa294 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/examples/powertools-examples-parameters/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -27,8 +27,18 @@ "fields":[{"name":"theUnsafe"}] }, { - "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", - "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], - "allPublicMethods":true + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true, + "unsafeAllocated": true } -] \ No newline at end of file +] diff --git a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index 8d3f375f2..7d38fc57d 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/examples/powertools-examples-serialization/sam-graalvm/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -27,9 +27,19 @@ "fields":[{"name":"theUnsafe"}] }, { - "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", - "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name": "tenantId"}, {"name":"content"}], - "allPublicMethods":true + "name": "com.amazonaws.services.lambda.runtime.api.client.runtimeapi.dto.InvocationRequest", + "fields": [ + { "name": "id" }, + { "name": "invokedFunctionArn" }, + { "name": "deadlineTimeInMs" }, + { "name": "xrayTraceId" }, + { "name": "clientContext" }, + { "name": "cognitoIdentity" }, + { "name": "tenantId" }, + { "name": "content" } + ], + "allPublicMethods": true, + "unsafeAllocated": true }, { "name":"software.amazon.lambda.powertools.common.internal.LambdaHandlerProcessor", diff --git a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index e69fa735c..467af67a0 100644 --- a/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/powertools-e2e-tests/handlers/idempotency-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -56,6 +56,7 @@ { "name": "tenantId" }, { "name": "content" } ], - "allPublicMethods": true + "allPublicMethods": true, + "unsafeAllocated": true } ] diff --git a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index e69fa735c..467af67a0 100644 --- a/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/powertools-e2e-tests/handlers/idempotency-generics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -56,6 +56,7 @@ { "name": "tenantId" }, { "name": "content" } ], - "allPublicMethods": true + "allPublicMethods": true, + "unsafeAllocated": true } ] diff --git a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index e69fa735c..467af67a0 100644 --- a/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/powertools-e2e-tests/handlers/idempotency/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -56,6 +56,7 @@ { "name": "tenantId" }, { "name": "content" } ], - "allPublicMethods": true + "allPublicMethods": true, + "unsafeAllocated": true } ] diff --git a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index e69fa735c..467af67a0 100644 --- a/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/powertools-e2e-tests/handlers/logging-functional/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -56,6 +56,7 @@ { "name": "tenantId" }, { "name": "content" } ], - "allPublicMethods": true + "allPublicMethods": true, + "unsafeAllocated": true } ] diff --git a/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index e69fa735c..467af67a0 100644 --- a/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/powertools-e2e-tests/handlers/logging-log4j/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -56,6 +56,7 @@ { "name": "tenantId" }, { "name": "content" } ], - "allPublicMethods": true + "allPublicMethods": true, + "unsafeAllocated": true } ] diff --git a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index e69fa735c..467af67a0 100644 --- a/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/powertools-e2e-tests/handlers/logging-logback/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -56,6 +56,7 @@ { "name": "tenantId" }, { "name": "content" } ], - "allPublicMethods": true + "allPublicMethods": true, + "unsafeAllocated": true } ] diff --git a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index e69fa735c..467af67a0 100644 --- a/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/powertools-e2e-tests/handlers/metrics/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -56,6 +56,7 @@ { "name": "tenantId" }, { "name": "content" } ], - "allPublicMethods": true + "allPublicMethods": true, + "unsafeAllocated": true } ] diff --git a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index e69fa735c..467af67a0 100644 --- a/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/powertools-e2e-tests/handlers/parameters/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -56,6 +56,7 @@ { "name": "tenantId" }, { "name": "content" } ], - "allPublicMethods": true + "allPublicMethods": true, + "unsafeAllocated": true } ] diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 11eedca85..ef1d3e65f 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -261,6 +261,15 @@ <aspectj.version>1.9.21</aspectj.version> </properties> </profile> + <profile> + <id>jdk25</id> + <activation> + <jdk>[25,)</jdk> + </activation> + <properties> + <aspectj.version>1.9.25</aspectj.version> + </properties> + </profile> </profiles> </project> diff --git a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index e69fa735c..467af67a0 100644 --- a/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json +++ b/powertools-e2e-tests/handlers/tracing/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -56,6 +56,7 @@ { "name": "tenantId" }, { "name": "content" } ], - "allPublicMethods": true + "allPublicMethods": true, + "unsafeAllocated": true } ] diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java index ea5ac3342..ae96943c2 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/Infrastructure.java @@ -247,7 +247,7 @@ private Stack createStackWithLambda() { .create(e2eStack, functionName + "-logs") .logGroupName("/aws/lambda/" + functionName) .retention(RetentionDays.ONE_DAY) - .removalPolicy(RemovalPolicy.DESTROY) + .removalPolicy(RemovalPolicy.RETAIN) .build(); if (!StringUtils.isEmpty(idempotencyTable)) { @@ -522,6 +522,8 @@ private JavaRuntime mapRuntimeVersion(String environmentVariableName) { ret = JavaRuntime.JAVA17; } else if (javaVersion.startsWith("21")) { ret = JavaRuntime.JAVA21; + } else if (javaVersion.startsWith("25")) { + ret = JavaRuntime.JAVA25; } else { throw new IllegalArgumentException("Unsupported Java version " + javaVersion); } diff --git a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java index 53d35e86d..625a222aa 100644 --- a/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java +++ b/powertools-e2e-tests/src/test/java/software/amazon/lambda/powertools/testutils/JavaRuntime.java @@ -19,7 +19,8 @@ public enum JavaRuntime { JAVA11("java11", Runtime.JAVA_11, "11"), JAVA17("java17", Runtime.JAVA_17, "17"), - JAVA21("java21", Runtime.JAVA_21, "21"); + JAVA21("java21", Runtime.JAVA_21, "21"), + JAVA25("java25", Runtime.JAVA_25, "25"); private final String runtime; private final Runtime cdkRuntime; diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index 7d47b5331..5d374eaa8 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,9 +1,9 @@ -# Use the official AWS SAM base image for Java 21 -FROM public.ecr.aws/sam/build-java21@sha256:ced538830c78a0f45f91abe5f7963cb73005ad933aee7dd1160bd77d9fd3c4f3 +# Use the official AWS SAM base image for Java 25 +FROM public.ecr.aws/sam/build-java25@sha256:2ef9e5b950cc79489691be16c7edff904bf196955633dc7fbbc282a1ea421ba8 # Install GraalVM dependencies -RUN curl -4 -L https://download.oracle.com/graalvm/21/latest/graalvm-jdk-21_linux-x64_bin.tar.gz | tar -xvz -RUN mv graalvm-jdk-21.* /usr/lib/graalvm +RUN curl -4 -L https://download.oracle.com/graalvm/25/latest/graalvm-jdk-25_linux-x64_bin.tar.gz | tar -xvz +RUN mv graalvm-jdk-25.* /usr/lib/graalvm # Make native image and mvn available on CLI RUN ln -s /usr/lib/graalvm/bin/native-image /usr/bin/native-image From 044b96d149816f52a247be42d929241380bfd7ba Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Fri, 21 Nov 2025 10:37:45 +0100 Subject: [PATCH 544/577] improv(batch): Propagate trace entity to worker threads during parallel batch processing. (#2300) --- docs/utilities/batch.md | 82 +++++++++++++++++- .../handler/DynamoDbBatchMessageHandler.java | 54 ++++++++---- .../KinesisStreamsBatchMessageHandler.java | 60 +++++++++----- .../batch/handler/SqsBatchMessageHandler.java | 70 ++++++++++------ .../internal/XRayTraceEntityPropagator.java | 83 +++++++++++++++++++ 5 files changed, 288 insertions(+), 61 deletions(-) create mode 100644 powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/XRayTraceEntityPropagator.java diff --git a/docs/utilities/batch.md b/docs/utilities/batch.md index 3f9b6e53d..b535a90f6 100644 --- a/docs/utilities/batch.md +++ b/docs/utilities/batch.md @@ -484,7 +484,9 @@ used with SQS FIFO. In that case, an `UnsupportedOperationException` is thrown. in most cases the defaults work well, and changing them is more likely to decrease performance (see [here](https://www.baeldung.com/java-when-to-use-parallel-stream#fork-join-framework) and [here](https://dzone.com/articles/be-aware-of-forkjoinpoolcommonpool)). - In situations where this may be useful - such as performing IO-bound work in parallel - make sure to measure before and after! + In situations where this may be useful, such as performing IO-bound work in parallel, make sure to measure before and after! + +When using parallel processing with X-Ray tracing enabled, the Tracing utility automatically handles trace context propagation to worker threads. This ensures that subsegments created during parallel message processing appear under the correct parent segment in your X-Ray trace, maintaining proper trace hierarchy and visibility into your batch processing performance. === "Example with SQS" @@ -536,6 +538,84 @@ used with SQS FIFO. In that case, an `UnsupportedOperationException` is thrown. } ``` +=== "Example with X-Ray Tracing" + + ```java hl_lines="12 17" + public class SqsBatchHandler implements RequestHandler<SQSEvent, SQSBatchResponse> { + + private final BatchMessageHandler<SQSEvent, SQSBatchResponse> handler; + + public SqsBatchHandler() { + handler = new BatchMessageHandlerBuilder() + .withSqsBatchHandler() + .buildWithMessageHandler(this::processMessage, Product.class); + } + + @Override + @Tracing + public SQSBatchResponse handleRequest(SQSEvent sqsEvent, Context context) { + return handler.processBatchInParallel(sqsEvent, context); + } + + @Tracing // This will appear correctly under the handleRequest subsegment + private void processMessage(Product p, Context c) { + // Process the product - subsegments will appear under handleRequest + } + } + ``` + +### Choosing the right concurrency model + +The `processBatchInParallel` method has two overloads with different concurrency characteristics: + +#### Without custom executor (parallelStream) + +When you call `processBatchInParallel(event, context)` without providing an executor, the implementation uses Java's `parallelStream()` which leverages the common `ForkJoinPool`. + +**Best for: CPU-bound workloads** + +- Thread pool size matches available CPU cores +- Optimized for computational tasks (data transformation, calculations, parsing) +- Main thread participates in work-stealing +- Simple to use with no configuration needed + +```java +// Good for CPU-intensive processing +return handler.processBatchInParallel(sqsEvent, context); +``` + +#### With custom executor (CompletableFuture) + +When you call `processBatchInParallel(event, context, executor)` with a custom executor, the implementation uses `CompletableFuture` which gives you full control over the thread pool. + +**Best for: I/O-bound workloads** + +- You control thread pool size and characteristics +- Ideal for I/O operations (HTTP calls, database queries, S3 operations) +- Can use larger thread pools since threads spend time waiting, not computing +- Main thread only waits; worker threads do all processing + +```java +// Good for I/O-intensive processing (API calls, DB queries, etc.) +ExecutorService executor = Executors.newFixedThreadPool(50); +return handler.processBatchInParallel(sqsEvent, context, executor); +``` + +**For Java 21+: Virtual Threads** + +If you're using Java 21 or later, virtual threads are ideal for I/O-bound workloads: + +```java +ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); +return handler.processBatchInParallel(sqsEvent, context, executor); +``` + +Virtual threads are lightweight and can handle thousands of concurrent I/O operations efficiently without the overhead of platform threads. + +**Recommendation for typical Lambda SQS processing:** + +Most Lambda functions processing SQS messages perform I/O operations (calling APIs, querying databases, writing to S3). For these workloads, use the custom executor approach with a thread pool sized appropriately for your I/O operations or virtual threads for Java 21+. + ## Handling Messages diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java index df7179a88..dbfdf63cd 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/DynamoDbBatchMessageHandler.java @@ -14,21 +14,25 @@ package software.amazon.lambda.powertools.batch.handler; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; -import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; - import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.stream.Collectors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.DynamodbEvent; +import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; + import software.amazon.lambda.powertools.batch.internal.MultiThreadMDC; +import software.amazon.lambda.powertools.batch.internal.XRayTraceEntityPropagator; /** * A batch message processor for DynamoDB Streams batches. @@ -43,8 +47,8 @@ public class DynamoDbBatchMessageHandler implements BatchMessageHandler<Dynamodb private final BiConsumer<DynamodbEvent.DynamodbStreamRecord, Context> rawMessageHandler; public DynamoDbBatchMessageHandler(Consumer<DynamodbEvent.DynamodbStreamRecord> successHandler, - BiConsumer<DynamodbEvent.DynamodbStreamRecord, Throwable> failureHandler, - BiConsumer<DynamodbEvent.DynamodbStreamRecord, Context> rawMessageHandler) { + BiConsumer<DynamodbEvent.DynamodbStreamRecord, Throwable> failureHandler, + BiConsumer<DynamodbEvent.DynamodbStreamRecord, Context> rawMessageHandler) { this.successHandler = successHandler; this.failureHandler = failureHandler; this.rawMessageHandler = rawMessageHandler; @@ -65,14 +69,23 @@ public StreamsEventResponse processBatch(DynamodbEvent event, Context context) { @Override public StreamsEventResponse processBatchInParallel(DynamodbEvent event, Context context) { MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + Object capturedSubsegment = XRayTraceEntityPropagator.captureTraceEntity(); List<StreamsEventResponse.BatchItemFailure> batchItemFailures = event.getRecords() .parallelStream() // Parallel processing .map(eventRecord -> { - multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); - Optional<StreamsEventResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, context); - multiThreadMDC.removeThread(Thread.currentThread().getName()); - return failureOpt; + AtomicReference<Optional<StreamsEventResponse.BatchItemFailure>> result = new AtomicReference<>(); + + XRayTraceEntityPropagator.runWithEntity(capturedSubsegment, () -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + try { + result.set(processBatchItem(eventRecord, context)); + } finally { + multiThreadMDC.removeThread(Thread.currentThread().getName()); + } + }); + + return result.get(); }) .filter(Optional::isPresent) .map(Optional::get) @@ -84,21 +97,29 @@ public StreamsEventResponse processBatchInParallel(DynamodbEvent event, Context @Override public StreamsEventResponse processBatchInParallel(DynamodbEvent event, Context context, Executor executor) { MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + Object capturedSubsegment = XRayTraceEntityPropagator.captureTraceEntity(); List<StreamsEventResponse.BatchItemFailure> batchItemFailures = new ArrayList<>(); List<CompletableFuture<Void>> futures = event.getRecords().stream() .map(eventRecord -> CompletableFuture.runAsync(() -> { - multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); - Optional<StreamsEventResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, context); - failureOpt.ifPresent(batchItemFailures::add); - multiThreadMDC.removeThread(Thread.currentThread().getName()); + XRayTraceEntityPropagator.runWithEntity(capturedSubsegment, () -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + try { + Optional<StreamsEventResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, + context); + failureOpt.ifPresent(batchItemFailures::add); + } finally { + multiThreadMDC.removeThread(Thread.currentThread().getName()); + } + }); }, executor)) .collect(Collectors.toList()); futures.forEach(CompletableFuture::join); return StreamsEventResponse.builder().withBatchItemFailures(batchItemFailures).build(); } - private Optional<StreamsEventResponse.BatchItemFailure> processBatchItem(DynamodbEvent.DynamodbStreamRecord streamRecord, Context context) { + private Optional<StreamsEventResponse.BatchItemFailure> processBatchItem( + DynamodbEvent.DynamodbStreamRecord streamRecord, Context context) { try { LOGGER.debug("Processing item {}", streamRecord.getEventID()); @@ -124,7 +145,8 @@ private Optional<StreamsEventResponse.BatchItemFailure> processBatchItem(Dynamod LOGGER.warn("failureHandler threw handling failure", e2); } } - return Optional.of(StreamsEventResponse.BatchItemFailure.builder().withItemIdentifier(sequenceNumber).build()); + return Optional + .of(StreamsEventResponse.BatchItemFailure.builder().withItemIdentifier(sequenceNumber).build()); } } } diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java index 233830462..f147578d4 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/KinesisStreamsBatchMessageHandler.java @@ -14,22 +14,25 @@ package software.amazon.lambda.powertools.batch.handler; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.KinesisEvent; -import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; - import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.stream.Collectors; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.KinesisEvent; +import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; + import software.amazon.lambda.powertools.batch.internal.MultiThreadMDC; +import software.amazon.lambda.powertools.batch.internal.XRayTraceEntityPropagator; import software.amazon.lambda.powertools.utilities.EventDeserializer; /** @@ -49,10 +52,10 @@ public class KinesisStreamsBatchMessageHandler<M> implements BatchMessageHandler private final BiConsumer<KinesisEvent.KinesisEventRecord, Throwable> failureHandler; public KinesisStreamsBatchMessageHandler(BiConsumer<KinesisEvent.KinesisEventRecord, Context> rawMessageHandler, - BiConsumer<M, Context> messageHandler, - Class<M> messageClass, - Consumer<KinesisEvent.KinesisEventRecord> successHandler, - BiConsumer<KinesisEvent.KinesisEventRecord, Throwable> failureHandler) { + BiConsumer<M, Context> messageHandler, + Class<M> messageClass, + Consumer<KinesisEvent.KinesisEventRecord> successHandler, + BiConsumer<KinesisEvent.KinesisEventRecord, Throwable> failureHandler) { this.rawMessageHandler = rawMessageHandler; this.messageHandler = messageHandler; @@ -76,14 +79,23 @@ public StreamsEventResponse processBatch(KinesisEvent event, Context context) { @Override public StreamsEventResponse processBatchInParallel(KinesisEvent event, Context context) { MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + Object capturedSubsegment = XRayTraceEntityPropagator.captureTraceEntity(); List<StreamsEventResponse.BatchItemFailure> batchItemFailures = event.getRecords() .parallelStream() // Parallel processing .map(eventRecord -> { - multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); - Optional<StreamsEventResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, context); - multiThreadMDC.removeThread(Thread.currentThread().getName()); - return failureOpt; + AtomicReference<Optional<StreamsEventResponse.BatchItemFailure>> result = new AtomicReference<>(); + + XRayTraceEntityPropagator.runWithEntity(capturedSubsegment, () -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + try { + result.set(processBatchItem(eventRecord, context)); + } finally { + multiThreadMDC.removeThread(Thread.currentThread().getName()); + } + }); + + return result.get(); }) .filter(Optional::isPresent) .map(Optional::get) @@ -95,21 +107,29 @@ public StreamsEventResponse processBatchInParallel(KinesisEvent event, Context c @Override public StreamsEventResponse processBatchInParallel(KinesisEvent event, Context context, Executor executor) { MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + Object capturedSubsegment = XRayTraceEntityPropagator.captureTraceEntity(); List<StreamsEventResponse.BatchItemFailure> batchItemFailures = new ArrayList<>(); List<CompletableFuture<Void>> futures = event.getRecords().stream() .map(eventRecord -> CompletableFuture.runAsync(() -> { - multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); - Optional<StreamsEventResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, context); - failureOpt.ifPresent(batchItemFailures::add); - multiThreadMDC.removeThread(Thread.currentThread().getName()); + XRayTraceEntityPropagator.runWithEntity(capturedSubsegment, () -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + try { + Optional<StreamsEventResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, + context); + failureOpt.ifPresent(batchItemFailures::add); + } finally { + multiThreadMDC.removeThread(Thread.currentThread().getName()); + } + }); }, executor)) .collect(Collectors.toList()); futures.forEach(CompletableFuture::join); return StreamsEventResponse.builder().withBatchItemFailures(batchItemFailures).build(); } - private Optional<StreamsEventResponse.BatchItemFailure> processBatchItem(KinesisEvent.KinesisEventRecord eventRecord, Context context) { + private Optional<StreamsEventResponse.BatchItemFailure> processBatchItem( + KinesisEvent.KinesisEventRecord eventRecord, Context context) { try { LOGGER.debug("Processing item {}", eventRecord.getEventID()); @@ -141,8 +161,8 @@ private Optional<StreamsEventResponse.BatchItemFailure> processBatchItem(Kinesis } } - return Optional.of(StreamsEventResponse.BatchItemFailure.builder().withItemIdentifier(eventRecord.getKinesis().getSequenceNumber()).build()); + return Optional.of(StreamsEventResponse.BatchItemFailure.builder() + .withItemIdentifier(eventRecord.getKinesis().getSequenceNumber()).build()); } } } - diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java index ccb6a6dd7..737c7cceb 100644 --- a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/handler/SqsBatchMessageHandler.java @@ -14,24 +14,26 @@ package software.amazon.lambda.powertools.batch.handler; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.KinesisEvent; -import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; -import com.amazonaws.services.lambda.runtime.events.SQSEvent; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.stream.Collectors; -import com.amazonaws.services.lambda.runtime.events.StreamsEventResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.SQSBatchResponse; +import com.amazonaws.services.lambda.runtime.events.SQSEvent; + import software.amazon.lambda.powertools.batch.internal.MultiThreadMDC; +import software.amazon.lambda.powertools.batch.internal.XRayTraceEntityPropagator; import software.amazon.lambda.powertools.utilities.EventDeserializer; /** @@ -54,9 +56,9 @@ public class SqsBatchMessageHandler<M> implements BatchMessageHandler<SQSEvent, private final BiConsumer<SQSEvent.SQSMessage, Throwable> failureHandler; public SqsBatchMessageHandler(BiConsumer<M, Context> messageHandler, Class<M> messageClass, - BiConsumer<SQSEvent.SQSMessage, Context> rawMessageHandler, - Consumer<SQSEvent.SQSMessage> successHandler, - BiConsumer<SQSEvent.SQSMessage, Throwable> failureHandler) { + BiConsumer<SQSEvent.SQSMessage, Context> rawMessageHandler, + Consumer<SQSEvent.SQSMessage> successHandler, + BiConsumer<SQSEvent.SQSMessage, Throwable> failureHandler) { this.messageHandler = messageHandler; this.messageClass = messageClass; this.rawMessageHandler = rawMessageHandler; @@ -77,16 +79,16 @@ public SQSBatchResponse processBatch(SQSEvent event, Context context) { for (; messageCursor < event.getRecords().size() && !failWholeBatch.get(); messageCursor++) { SQSEvent.SQSMessage message = event.getRecords().get(messageCursor); - String messageGroupId = message.getAttributes() != null ? - message.getAttributes().get(MESSAGE_GROUP_ID_KEY) : null; + String messageGroupId = message.getAttributes() != null ? message.getAttributes().get(MESSAGE_GROUP_ID_KEY) + : null; processBatchItem(message, context).ifPresent(batchItemFailure -> { response.getBatchItemFailures().add(batchItemFailure); if (messageGroupId != null) { failWholeBatch.set(true); LOGGER.info( - "A message in a batch with messageGroupId {} and messageId {} failed; failing the rest of the batch too" - , messageGroupId, message.getMessageId()); + "A message in a batch with messageGroupId {} and messageId {} failed; failing the rest of the batch too", + messageGroupId, message.getMessageId()); } }); } @@ -105,18 +107,28 @@ public SQSBatchResponse processBatch(SQSEvent event, Context context) { @Override public SQSBatchResponse processBatchInParallel(SQSEvent event, Context context) { if (isFIFOEnabled(event)) { - throw new UnsupportedOperationException("FIFO queues are not supported in parallel mode, use the processBatch method instead"); + throw new UnsupportedOperationException( + "FIFO queues are not supported in parallel mode, use the processBatch method instead"); } MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + Object capturedSubsegment = XRayTraceEntityPropagator.captureTraceEntity(); + List<SQSBatchResponse.BatchItemFailure> batchItemFailures = event.getRecords() .parallelStream() // Parallel processing .map(sqsMessage -> { - - multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); - Optional<SQSBatchResponse.BatchItemFailure> failureOpt = processBatchItem(sqsMessage, context); - multiThreadMDC.removeThread(Thread.currentThread().getName()); - return failureOpt; + AtomicReference<Optional<SQSBatchResponse.BatchItemFailure>> result = new AtomicReference<>(); + + XRayTraceEntityPropagator.runWithEntity(capturedSubsegment, () -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + try { + result.set(processBatchItem(sqsMessage, context)); + } finally { + multiThreadMDC.removeThread(Thread.currentThread().getName()); + } + }); + + return result.get(); }) .filter(Optional::isPresent) .map(Optional::get) @@ -128,17 +140,26 @@ public SQSBatchResponse processBatchInParallel(SQSEvent event, Context context) @Override public SQSBatchResponse processBatchInParallel(SQSEvent event, Context context, Executor executor) { if (isFIFOEnabled(event)) { - throw new UnsupportedOperationException("FIFO queues are not supported in parallel mode, use the processBatch method instead"); + throw new UnsupportedOperationException( + "FIFO queues are not supported in parallel mode, use the processBatch method instead"); } MultiThreadMDC multiThreadMDC = new MultiThreadMDC(); + Object capturedSubsegment = XRayTraceEntityPropagator.captureTraceEntity(); + List<SQSBatchResponse.BatchItemFailure> batchItemFailures = new ArrayList<>(); List<CompletableFuture<Void>> futures = event.getRecords().stream() .map(eventRecord -> CompletableFuture.runAsync(() -> { - multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); - Optional<SQSBatchResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, context); - failureOpt.ifPresent(batchItemFailures::add); - multiThreadMDC.removeThread(Thread.currentThread().getName()); + XRayTraceEntityPropagator.runWithEntity(capturedSubsegment, () -> { + multiThreadMDC.copyMDCToThread(Thread.currentThread().getName()); + try { + Optional<SQSBatchResponse.BatchItemFailure> failureOpt = processBatchItem(eventRecord, + context); + failureOpt.ifPresent(batchItemFailures::add); + } finally { + multiThreadMDC.removeThread(Thread.currentThread().getName()); + } + }); }, executor)) .collect(Collectors.toList()); futures.forEach(CompletableFuture::join); @@ -182,6 +203,7 @@ private Optional<SQSBatchResponse.BatchItemFailure> processBatchItem(SQSEvent.SQ } private boolean isFIFOEnabled(SQSEvent sqsEvent) { - return !sqsEvent.getRecords().isEmpty() && sqsEvent.getRecords().get(0).getAttributes().get(MESSAGE_GROUP_ID_KEY) != null; + return !sqsEvent.getRecords().isEmpty() + && sqsEvent.getRecords().get(0).getAttributes().get(MESSAGE_GROUP_ID_KEY) != null; } } diff --git a/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/XRayTraceEntityPropagator.java b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/XRayTraceEntityPropagator.java new file mode 100644 index 000000000..2858f4756 --- /dev/null +++ b/powertools-batch/src/main/java/software/amazon/lambda/powertools/batch/internal/XRayTraceEntityPropagator.java @@ -0,0 +1,83 @@ +/* + * Copyright 2023 Amazon.com, Inc. or its affiliates. + * Licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package software.amazon.lambda.powertools.batch.internal; + +import java.lang.reflect.Method; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class to propagate X-Ray trace entity context to worker threads using reflection. + * Reflection is used to avoid taking a dependency on X-RAY SDK. + */ +public final class XRayTraceEntityPropagator { + private static final Logger LOGGER = LoggerFactory.getLogger(XRayTraceEntityPropagator.class); + private static final boolean XRAY_AVAILABLE; + private static final Method GET_TRACE_ENTITY_METHOD; + + // We do the more "expensive" Class.forName in this static block to detect exactly once at import time if X-RAY + // is available or not. Subsequent <method>.invoke() are very fast on modern JDKs. + static { + Method method = null; + boolean available = false; + + try { + Class<?> awsXRayClass = Class.forName("com.amazonaws.xray.AWSXRay"); + method = awsXRayClass.getMethod("getTraceEntity"); + available = true; + LOGGER.debug("X-Ray SDK detected. Trace context will be propagated to worker threads."); + } catch (ClassNotFoundException | NoSuchMethodException e) { + LOGGER.debug("X-Ray SDK not detected. Trace context propagation disabled"); + } + + GET_TRACE_ENTITY_METHOD = method; + XRAY_AVAILABLE = available; + } + + private XRayTraceEntityPropagator() { + // Utility class + } + + public static Object captureTraceEntity() { + if (!XRAY_AVAILABLE) { + return null; + } + + try { + return GET_TRACE_ENTITY_METHOD.invoke(null); + } catch (Exception e) { + // We don't want to break batch processing if this fails. + LOGGER.warn("Failed to capture trace entity.", e); + return null; + } + } + + // See https://docs.aws.amazon.com/xray/latest/devguide/scorekeep-workerthreads.html + public static void runWithEntity(Object traceEntity, Runnable runnable) { + if (!XRAY_AVAILABLE || traceEntity == null) { + runnable.run(); + return; + } + + try { + traceEntity.getClass().getMethod("run", Runnable.class).invoke(traceEntity, runnable); + } catch (Exception e) { + // We don't want to break batch processing if this fails. + LOGGER.warn("Failed to run with trace entity, falling back to direct execution.", e); + runnable.run(); + } + } +} From 39c26fe3db8bc7c8869e7e1c0900fdb16d03915b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 10:38:12 +0100 Subject: [PATCH 545/577] chore: bump io.github.ascopes:protobuf-maven-plugin (#2296) Bumps [io.github.ascopes:protobuf-maven-plugin](https://github.com/ascopes/protobuf-maven-plugin) from 3.10.2 to 3.10.3. - [Release notes](https://github.com/ascopes/protobuf-maven-plugin/releases) - [Commits](https://github.com/ascopes/protobuf-maven-plugin/compare/v3.10.2...v3.10.3) --- updated-dependencies: - dependency-name: io.github.ascopes:protobuf-maven-plugin dependency-version: 3.10.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 24856f80d..1e7450679 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -141,7 +141,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.10.2</version> + <version>3.10.3</version> <executions> <execution> <goals> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 0a76f0d2e..0d7a4c13b 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -200,7 +200,7 @@ <plugin> <groupId>io.github.ascopes</groupId> <artifactId>protobuf-maven-plugin</artifactId> - <version>3.10.2</version> + <version>3.10.3</version> <executions> <execution> <id>generate-test-sources</id> From 3575cbfa1377480ea212cefd84d7f75755c8565c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 10:39:11 +0100 Subject: [PATCH 546/577] chore: bump software.amazon.awscdk:aws-cdk-lib from 2.223.0 to 2.224.0 (#2297) Bumps [software.amazon.awscdk:aws-cdk-lib](https://github.com/aws/aws-cdk) from 2.223.0 to 2.224.0. - [Release notes](https://github.com/aws/aws-cdk/releases) - [Changelog](https://github.com/aws/aws-cdk/blob/main/CHANGELOG.v2.alpha.md) - [Commits](https://github.com/aws/aws-cdk/compare/v2.223.0...v2.224.0) --- updated-dependencies: - dependency-name: software.amazon.awscdk:aws-cdk-lib dependency-version: 2.224.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 87dc26169..35e07bc62 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -7,7 +7,7 @@ <version>2.7.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <cdk.version>2.223.0</cdk.version> + <cdk.version>2.224.0</cdk.version> <constructs.version>[10.0.0,11.0.0)</constructs.version> <junit.version>5.14.1</junit.version> </properties> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 6dd94910a..0fd169845 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -31,7 +31,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <constructs.version>10.4.3</constructs.version> - <cdk.version>2.223.0</cdk.version> + <cdk.version>2.224.0</cdk.version> </properties> <dependencies> From 0c0401f6ca9ca15e5bf75a46c151081ab009a459 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 10:39:33 +0100 Subject: [PATCH 547/577] chore: bump github/codeql-action from 4.31.3 to 4.31.4 (#2301) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.3 to 4.31.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/014f16e7ab1402f30e7c3329d33797e7948572db...e12f0178983d466f2f6028f5cc7a6d786fd97f4b) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index bbf9490c4..205cb0ddc 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v3.29.5 + uses: github/codeql-action/upload-sarif@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v3.29.5 with: sarif_file: results.sarif From 5b3f0f583f46033edf5512d1b4472993f01fee6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 10:39:52 +0100 Subject: [PATCH 548/577] chore: bump aws.sdk.version from 2.38.2 to 2.38.7 (#2295) Bumps `aws.sdk.version` from 2.38.2 to 2.38.7. Updates `software.amazon.awssdk:url-connection-client` from 2.38.2 to 2.38.7 Updates `software.amazon.awssdk:sdk-core` from 2.38.2 to 2.38.7 Updates `software.amazon.awssdk:s3` from 2.38.2 to 2.38.7 Updates `software.amazon.awssdk:kinesis` from 2.38.2 to 2.38.7 Updates `software.amazon.awssdk:sqs` from 2.38.2 to 2.38.7 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.38.2 to 2.38.7 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.38.7 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.38.7 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.38.7 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.38.7 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.38.7 dependency-type: direct:development update-type: version-update:semver-patch - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.38.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 5226166fb..ec075cf87 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.38.2</sdk.version> + <sdk.version>2.38.7</sdk.version> </properties> <dependencies> From e523a7eb42ddc7c7353f777a47a9167f7f46f803 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 12:27:48 +0100 Subject: [PATCH 549/577] chore(ci): bump version to 2.8.0 (#2303) * chore(ci): bump version to 2.8.0 * Restore CHANGELOG.md from main. --------- Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Philipp Page <pagejep@amazon.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/README.md | 4 ++-- .../infra/sam-graalvm/README.md | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- .../powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- .../powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/handlers/batch/pom.xml | 2 +- .../handlers/idempotency-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency-generics/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency/pom.xml | 2 +- .../handlers/largemessage-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/largemessage/pom.xml | 2 +- .../handlers/largemessage_idempotent/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-log4j/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-logback/pom.xml | 2 +- powertools-e2e-tests/handlers/metrics/pom.xml | 2 +- powertools-e2e-tests/handlers/parameters/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/handlers/tracing/pom.xml | 2 +- powertools-e2e-tests/handlers/validation-alb-event/pom.xml | 2 +- .../handlers/validation-apigw-event/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 62 files changed, 69 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 6d3689092..2644c47ab 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging-log4j</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-metrics</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </dependency> ... </dependencies> diff --git a/examples/pom.xml b/examples/pom.xml index c02d318cc..511cdd5a9 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-examples</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Examples</name> diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index ec075cf87..6d941a31f 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-batch</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Batch</name> diff --git a/examples/powertools-examples-cloudformation/README.md b/examples/powertools-examples-cloudformation/README.md index 84d9d7fac..b9e58eb82 100644 --- a/examples/powertools-examples-cloudformation/README.md +++ b/examples/powertools-examples-cloudformation/README.md @@ -15,7 +15,7 @@ Run the following in your shell: ```bash cd infra/sam sam build -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.7.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.8.0718 ``` ### Deploy with CDK @@ -32,5 +32,5 @@ To build and deploy this application for the first time, run the following in yo cd infra/cdk mvn package cdk synth -cdk deploy -c BucketNameParam=my-unique-bucket-2.7.0718 +cdk deploy -c BucketNameParam=my-unique-bucket-2.8.0718 ``` \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md index 85c8b386f..c2a9e2ffd 100644 --- a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md +++ b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md @@ -40,7 +40,7 @@ sam build ## Deploy the sample application ```shell -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.7.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.8.0718 ``` This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting started with SAM in [the examples directory](../../../README.md) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 9ca4e8dc2..8dde0a034 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-cloudformation</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index dbd6743a8..29acef5e2 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ <groupId>software.amazon.lambda.examples</groupId> <!-- TODO TODO TODO this should build from SNAPSHOT, but it doesn't, because the snapshots don't appear in the docker environment CDK builds it in in our CDK tests. How to procede? V2 blocker --> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-core-utilities-cdk</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 35e07bc62..7daf3153f 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <artifactId>cdk</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.224.0</cdk.version> diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 0b7951f11..6841d20ab 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.7.0' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.7.0' - aspect 'software.amazon.lambda:powertools-metrics:2.7.0' + aspect 'software.amazon.lambda:powertools-tracing:2.8.0' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.8.0' + aspect 'software.amazon.lambda:powertools-metrics:2.8.0' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index 47e82c5b8..bc11eb32e 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.7.0") - aspect("software.amazon.lambda:powertools-logging-log4j:2.7.0") - aspect("software.amazon.lambda:powertools-metrics:2.7.0") + aspect("software.amazon.lambda:powertools-tracing:2.8.0") + aspect("software.amazon.lambda:powertools-logging-log4j:2.8.0") + aspect("software.amazon.lambda:powertools-metrics:2.8.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index 682e1a10b..fceb4a322 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-core-utilities-sam-graalvm</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index d03cafcfb..b8606a227 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-core-utilities-sam</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index 996f77d4b..d77b0ccd6 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-core-utilities-serverless</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index d28835a8a..14c0e223e 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-core-utilities-terraform</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index 205958c9a..d1c0205ff 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-idempotency-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency GraalVM</name> diff --git a/examples/powertools-examples-idempotency/sam/pom.xml b/examples/powertools-examples-idempotency/sam/pom.xml index 694b79342..b90705c67 100644 --- a/examples/powertools-examples-idempotency/sam/pom.xml +++ b/examples/powertools-examples-idempotency/sam/pom.xml @@ -17,7 +17,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-idempotency</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency</name> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 1e7450679..f4b75722c 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-kafka</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Kafka</name> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index a83ddddb8..6d0c3f4a2 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-parameters-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 83efef4d2..15d68ffcd 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-parameters-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters</name> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index b77ce975e..44661fb71 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-serialization-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 789d9969f..93c60a2cb 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-serialization-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization</name> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index abcdd4e3a..1337bc2ee 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <artifactId>powertools-examples-validation</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Validation</name> diff --git a/mkdocs.yml b/mkdocs.yml index 98f6945d7..5f35b96c0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -129,7 +129,7 @@ extra_javascript: extra: powertools: - version: 2.7.0 + version: 2.8.0 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index ba206feae..ed1d2aff9 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Parent</name> diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index bce58ab58..07d11d41c 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <description>A suite of utilities that makes batch message processing using AWS Lambda easier.</description> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index a3270563a..09e3299fd 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Cloudformation</name> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index d4e9f6213..f14783b5b 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Common Internal Utilities</name> diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index 2c726340a..f8e0a037f 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-batch</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency-functional/pom.xml b/powertools-e2e-tests/handlers/idempotency-functional/pom.xml index 133a0ccff..2b53dc275 100644 --- a/powertools-e2e-tests/handlers/idempotency-functional/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-idempotency-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency-generics/pom.xml b/powertools-e2e-tests/handlers/idempotency-generics/pom.xml index a69babd0d..76e65edb1 100644 --- a/powertools-e2e-tests/handlers/idempotency-generics/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency-generics/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-idempotency-generics</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index cbe7e0cac..36181ea01 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-idempotency</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage-functional/pom.xml b/powertools-e2e-tests/handlers/largemessage-functional/pom.xml index e2e67b2da..d29017074 100644 --- a/powertools-e2e-tests/handlers/largemessage-functional/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-largemessage-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index 56d179c3b..53b1e7c10 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-largemessage</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index 9896db217..9f6f23389 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-large-msg-idempotent</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-functional/pom.xml b/powertools-e2e-tests/handlers/logging-functional/pom.xml index ba532c3db..4616af233 100644 --- a/powertools-e2e-tests/handlers/logging-functional/pom.xml +++ b/powertools-e2e-tests/handlers/logging-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-logging-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-log4j/pom.xml b/powertools-e2e-tests/handlers/logging-log4j/pom.xml index 445da94e2..bba711163 100644 --- a/powertools-e2e-tests/handlers/logging-log4j/pom.xml +++ b/powertools-e2e-tests/handlers/logging-log4j/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-logging-log4j</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-logback/pom.xml b/powertools-e2e-tests/handlers/logging-logback/pom.xml index 9f5035722..bd442fe88 100644 --- a/powertools-e2e-tests/handlers/logging-logback/pom.xml +++ b/powertools-e2e-tests/handlers/logging-logback/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-logging-logback</artifactId> diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 5bf3bd5ef..90704c6d9 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-metrics</artifactId> diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index e30a51150..670eeb9c0 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-parameters</artifactId> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index ef1d3e65f..f06db02f0 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -4,7 +4,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> <packaging>pom</packaging> <name>Handlers for End-to-End tests</name> <description>Fake handlers that use Powertools for AWS Lambda (Java).</description> diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index 1a3b56a77..89891df8c 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-tracing</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml index d2e1266fc..8e5e4dadb 100644 --- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-validation-alb-event</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml index 6832280a6..97e967c3b 100644 --- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>e2e-test-handler-validation-apigw-event</artifactId> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 0fd169845..484e3b4c2 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>powertools-e2e-tests</artifactId> diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index f119ca445..d15d3445d 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>powertools-idempotency</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 5e57ee136..801664b4a 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>powertools-idempotency-core</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index 25f6f77c7..a9cf5739b 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>powertools-idempotency-dynamodb</artifactId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 0d7a4c13b..ad564897f 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>powertools-kafka</artifactId> diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index 6353cb089..d72877552 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>powertools-large-messages</artifactId> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 9fd7b1e62..ae5788291 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Logging</name> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 8006baa7d..1cf3bf265 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 70bbbdfc4..b5a50573d 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 1ea59493c..4da0c0a9f 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Metrics</name> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 158fdc978..a2c4a65dc 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>powertools-parameters</artifactId> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 9d9adc16b..ab8ae0e67 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index d66153da6..76a7b8845 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index f126716d6..fbe4905be 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index e6bf1ea27..c9de1db51 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index b40046bde..3bcd4d604 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.7.0</version> + <version>2.8.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index d7f33df28..c1eea4df7 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <artifactId>powertools-serialization</artifactId> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 68231dbe1..ed2596059 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Tracing</name> diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 74051989e..37063cf6d 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.7.0</version> + <version>2.8.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Validation</name> From dfca97e5f1ebcc3cd293ea9f386246b88caec04d Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Mon, 24 Nov 2025 13:38:29 +0100 Subject: [PATCH 550/577] chore(ci): Remove branch protection workflow. (#2311) --- .github/branch_protection_settings/1.x.x.json | 53 -------------- .github/branch_protection_settings/main.json | 63 ---------------- .github/branch_protection_settings/v2.json | 63 ---------------- .../workflows/security-branch-protections.yml | 72 ------------------- 4 files changed, 251 deletions(-) delete mode 100644 .github/branch_protection_settings/1.x.x.json delete mode 100644 .github/branch_protection_settings/main.json delete mode 100644 .github/branch_protection_settings/v2.json delete mode 100644 .github/workflows/security-branch-protections.yml diff --git a/.github/branch_protection_settings/1.x.x.json b/.github/branch_protection_settings/1.x.x.json deleted file mode 100644 index e52aba745..000000000 --- a/.github/branch_protection_settings/1.x.x.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection", - "required_status_checks": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection/required_status_checks", - "strict": true, - "contexts": [ - "SonarCloud" - ], - "contexts_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection/required_status_checks/contexts", - "checks": [ - { - "context": "SonarCloud", - "app_id": null - } - ] - }, - "required_pull_request_reviews": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection/required_pull_request_reviews", - "dismiss_stale_reviews": false, - "require_code_owner_reviews": false, - "require_last_push_approval": false, - "required_approving_review_count": 0 - }, - "required_signatures": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection/required_signatures", - "enabled": false - }, - "enforce_admins": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/1.x.x/protection/enforce_admins", - "enabled": true - }, - "required_linear_history": { - "enabled": false - }, - "allow_force_pushes": { - "enabled": false - }, - "allow_deletions": { - "enabled": false - }, - "block_creations": { - "enabled": false - }, - "required_conversation_resolution": { - "enabled": false - }, - "lock_branch": { - "enabled": false - }, - "allow_fork_syncing": { - "enabled": false - } -} diff --git a/.github/branch_protection_settings/main.json b/.github/branch_protection_settings/main.json deleted file mode 100644 index 8ca32bb45..000000000 --- a/.github/branch_protection_settings/main.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection", - "required_status_checks": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_status_checks", - "strict": true, - "contexts": [], - "contexts_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_status_checks/contexts", - "checks": [] - }, - "restrictions": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/restrictions", - "users_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/restrictions/users", - "teams_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/restrictions/teams", - "apps_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/restrictions/apps", - "users": [], - "teams": [], - "apps": [] - }, - "required_pull_request_reviews": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_pull_request_reviews", - "dismiss_stale_reviews": true, - "require_code_owner_reviews": true, - "require_last_push_approval": true, - "required_approving_review_count": 1, - "dismissal_restrictions": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/dismissal_restrictions", - "users_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/dismissal_restrictions/users", - "teams_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/dismissal_restrictions/teams", - "users": [], - "teams": [], - "apps": [] - } - }, - "required_signatures": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/required_signatures", - "enabled": false - }, - "enforce_admins": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/main/protection/enforce_admins", - "enabled": true - }, - "required_linear_history": { - "enabled": true - }, - "allow_force_pushes": { - "enabled": false - }, - "allow_deletions": { - "enabled": false - }, - "block_creations": { - "enabled": true - }, - "required_conversation_resolution": { - "enabled": true - }, - "lock_branch": { - "enabled": false - }, - "allow_fork_syncing": { - "enabled": false - } -} diff --git a/.github/branch_protection_settings/v2.json b/.github/branch_protection_settings/v2.json deleted file mode 100644 index fb9fdebcd..000000000 --- a/.github/branch_protection_settings/v2.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection", - "required_status_checks": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/required_status_checks", - "strict": true, - "contexts": [], - "contexts_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/required_status_checks/contexts", - "checks": [] - }, - "restrictions": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/restrictions", - "users_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/restrictions/users", - "teams_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/restrictions/teams", - "apps_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/restrictions/apps", - "users": [], - "teams": [], - "apps": [] - }, - "required_pull_request_reviews": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/required_pull_request_reviews", - "dismiss_stale_reviews": true, - "require_code_owner_reviews": false, - "require_last_push_approval": true, - "required_approving_review_count": 1, - "dismissal_restrictions": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/dismissal_restrictions", - "users_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/dismissal_restrictions/users", - "teams_url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/dismissal_restrictions/teams", - "users": [], - "teams": [], - "apps": [] - } - }, - "required_signatures": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/required_signatures", - "enabled": false - }, - "enforce_admins": { - "url": "https://api.github.com/repos/aws-powertools/powertools-lambda-java/branches/v2/protection/enforce_admins", - "enabled": false - }, - "required_linear_history": { - "enabled": true - }, - "allow_force_pushes": { - "enabled": false - }, - "allow_deletions": { - "enabled": false - }, - "block_creations": { - "enabled": true - }, - "required_conversation_resolution": { - "enabled": true - }, - "lock_branch": { - "enabled": false - }, - "allow_fork_syncing": { - "enabled": false - } -} diff --git a/.github/workflows/security-branch-protections.yml b/.github/workflows/security-branch-protections.yml deleted file mode 100644 index af6477802..000000000 --- a/.github/workflows/security-branch-protections.yml +++ /dev/null @@ -1,72 +0,0 @@ -# Branch Protections -# -# Description: -# This workflow compares current security branch protections against those stored, -# if there's any changes, it'll fail the job and alert using a Slack webhook -# -# Triggers: -# - pull_request -# - branch_protection_rule -# - cron: daily at 16:40 -# -# Secrets: -# - SECURITY.BRANCH_PROTECTION_TOKEN -# - SECURITY.SLACK_WEBHOOK_URL -# -# Notes: -# Modified copy of: https://github.com/github/docs/blob/main/.github/workflows/alert-changed-branch-protections.yml - -on: - branch_protection_rule: - schedule: - - cron: '20 16 * * *' # Run daily at 16:20 UTC - pull_request: - paths: - - .github/workflows/security-branch-protections.yml - - .github/branch_protection_settings/*.json - -name: Alert Changed Branch Protections -run-name: Alert Changed Branch Protections - -permissions: - contents: read - -jobs: - check-branch-protections: - runs-on: ubuntu-latest - permissions: - contents: write - environment: Security - if: ${{ github.repository == 'aws-powertools/powertools-lambda-java' }} - strategy: - matrix: - # List of branches we want to monitor for protection changes - branch: - - main - - v1 - steps: - - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - name: Fetch branch protections - id: fetch - env: - GH_TOKEN: ${{ secrets.BRANCH_PROTECTION_TOKEN }} - run: | - # Fetch branch protections and store them in a file - gh api /repos/${{ github.repository }}/branches/${{ matrix.branch }}/protection | jq \ - > .github/branch_protection_settings/${{ matrix.branch }}.json - - name: Compare branch protections - id: compare - run: | - git diff --quiet .github/branch_protection_settings/${{ matrix.branch }}.json \ - || echo "diff_failed=true" >> $GITHUB_ENV - - name: Send webhook - if: ${{ env.diff_failed == 'true' }} - run: | - curl -X POST -d '{"message": "Branch protections have changed for ${{ github.repository }} on ${{ matrix.branch }}. Please review the changes or revert the changes in GitHub. https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"}' \ - ${{ secrets.SLACK_WEBHOOK_URL }} - - name: Fail workflow - if: ${{ env.diff_failed == 'true' }} - run: | - git diff .github/branch_protection_settings/${{ matrix.branch }}.json - echo "::error::Branch protections have been changed" \ No newline at end of file From 8208272fb8839eba312e27c1ee5a73a466ae7800 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:44:16 +0100 Subject: [PATCH 551/577] chore: bump org.wiremock:wiremock from 3.13.1 to 3.13.2 (#2306) Bumps [org.wiremock:wiremock](https://github.com/wiremock/wiremock) from 3.13.1 to 3.13.2. - [Release notes](https://github.com/wiremock/wiremock/releases) - [Commits](https://github.com/wiremock/wiremock/compare/3.13.1...3.13.2) --- updated-dependencies: - dependency-name: org.wiremock:wiremock dependency-version: 3.13.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ed1d2aff9..64b6e0e0d 100644 --- a/pom.xml +++ b/pom.xml @@ -389,7 +389,7 @@ <dependency> <groupId>org.wiremock</groupId> <artifactId>wiremock</artifactId> - <version>3.13.1</version> + <version>3.13.2</version> <scope>test</scope> </dependency> </dependencies> From df4a757bdaaad2dd90093e95416a3ac8a435e30b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:44:53 +0100 Subject: [PATCH 552/577] chore: bump aws.sdk.version from 2.38.6 to 2.39.1 (#2305) Bumps `aws.sdk.version` from 2.38.6 to 2.39.1. Updates `software.amazon.awssdk:bom` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:http-client-spi` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:url-connection-client` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:s3` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:dynamodb` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:lambda` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:kinesis` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:cloudwatch` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:xray` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:sqs` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:cloudformation` from 2.38.6 to 2.39.1 Updates `software.amazon.awssdk:sts` from 2.38.6 to 2.39.1 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.39.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.39.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.39.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.39.1 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.39.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.39.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.39.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.39.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-version: 2.39.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.39.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.39.1 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-version: 2.39.1 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 8dde0a034..09adbfa18 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.38.6</aws.sdk.version> + <aws.sdk.version>2.39.1</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index 64b6e0e0d..dc2decfd6 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.1</jackson.version> - <aws.sdk.version>2.38.6</aws.sdk.version> + <aws.sdk.version>2.39.1</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index f06db02f0..a9d3c3ab5 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.38.6</aws.sdk.version> + <aws.sdk.version>2.39.1</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From 51eeaf47431f6a7d93bc3bd67942849595ebbf37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:45:08 +0100 Subject: [PATCH 553/577] chore: bump org.apache.commons:commons-lang3 from 3.19.0 to 3.20.0 (#2304) Bumps org.apache.commons:commons-lang3 from 3.19.0 to 3.20.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.20.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index dc2decfd6..1e4c3a9fd 100644 --- a/pom.xml +++ b/pom.xml @@ -310,7 +310,7 @@ <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> - <version>3.19.0</version> + <version>3.20.0</version> </dependency> <!-- Test dependencies --> From ca96cd82ac46b8e54fdd4271570d6c2e5941fd85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:58:09 +0100 Subject: [PATCH 554/577] chore: bump actions/checkout from 5.0.0 to 6.0.0 (#2308) Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.0 to 6.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/08c6903cd8c0fde910a37f88322edcfb5dd907a8...1af3b93b6815bc44a9784bd300feb67ff0d1eeb3) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 2 +- .github/workflows/check-build.yml | 4 ++-- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/check-pmd.yml | 2 +- .github/workflows/check-spotbugs.yml | 2 +- .github/workflows/release.yml | 6 +++--- .github/workflows/security-dependencies-check.yml | 2 +- .github/workflows/security-scorecard.yml | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 8cef6040e..be53fbfaa 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -32,7 +32,7 @@ jobs: environment: Docs steps: - name: Checkout Repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 with: fetch-depth: 0 - name: Build diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 88f1eabee..a972084a6 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -77,7 +77,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup Java uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 with: @@ -94,7 +94,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: fetch-depth: 0 - name: Get changed files diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 54e7cd023..6ed3b248e 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -57,7 +57,7 @@ jobs: - 25 steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup java uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: @@ -88,7 +88,7 @@ jobs: - 25 steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup java uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: diff --git a/.github/workflows/check-pmd.yml b/.github/workflows/check-pmd.yml index 41983f89b..66150821d 100644 --- a/.github/workflows/check-pmd.yml +++ b/.github/workflows/check-pmd.yml @@ -29,7 +29,7 @@ jobs: id-token: write steps: - name: Checkout Repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup Java uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: diff --git a/.github/workflows/check-spotbugs.yml b/.github/workflows/check-spotbugs.yml index bf746320d..8af0e4d9d 100644 --- a/.github/workflows/check-spotbugs.yml +++ b/.github/workflows/check-spotbugs.yml @@ -41,7 +41,7 @@ jobs: codecheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Setup Java uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 79cb5b04f..bd2e23487 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -103,7 +103,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - id: version name: version uses: ./.github/actions/version @@ -224,7 +224,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: ref: ${{ env.RELEASE_COMMIT }} - id: download_source @@ -272,7 +272,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: # Checkout PR branch to make sure we build the version-bumped docs ref: ci-${{ github.run_id }} diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml index c6e06950f..1e85d9e96 100644 --- a/.github/workflows/security-dependencies-check.yml +++ b/.github/workflows/security-dependencies-check.yml @@ -24,7 +24,7 @@ jobs: pull-requests: write steps: - name: Checkout Repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: Verify Contents uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 with: diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 205cb0ddc..d59367015 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -35,7 +35,7 @@ jobs: id-token: write steps: - name: Checkout Repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: persist-credentials: false - name: Run Analysis From 54991e6bf589ac29b26960b53782ab5a8fe13371 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:58:32 +0100 Subject: [PATCH 555/577] chore: bump sam/build-java25 (#2309) Bumps sam/build-java25 from `2ef9e5b` to `af599d0`. --- updated-dependencies: - dependency-name: sam/build-java25 dependency-version: af599d010afef63c83a04265dee9adbd4557d94b4a81941f28ae42657af7890d dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index 5d374eaa8..6643760b4 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 25 -FROM public.ecr.aws/sam/build-java25@sha256:2ef9e5b950cc79489691be16c7edff904bf196955633dc7fbbc282a1ea421ba8 +FROM public.ecr.aws/sam/build-java25@sha256:af599d010afef63c83a04265dee9adbd4557d94b4a81941f28ae42657af7890d # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/25/latest/graalvm-jdk-25_linux-x64_bin.tar.gz | tar -xvz From 93d302f09fbb37770bccedb96ab1e1acc5ea260e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:58:58 +0100 Subject: [PATCH 556/577] chore: bump github/codeql-action from 4.31.4 to 4.31.5 (#2312) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.4 to 4.31.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/e12f0178983d466f2f6028f5cc7a6d786fd97f4b...fdbfb4d2750291e159f0156def62b853c2798ca2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index d59367015..0944694f7 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # v3.29.5 + uses: github/codeql-action/upload-sarif@fdbfb4d2750291e159f0156def62b853c2798ca2 # v3.29.5 with: sarif_file: results.sarif From 7ea89ded9d25796e9acc0ae1a4b68b5ae4193481 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Nov 2025 11:54:38 +0100 Subject: [PATCH 557/577] chore: bump aws-actions/configure-aws-credentials from 5.1.0 to 5.1.1 (#2316) Bumps [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) from 5.1.0 to 5.1.1. - [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases) - [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md) - [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/00943011d9042930efac3dcd3a170e4273319bc8...61815dcd50bd041e203e49132bacad1fd04d2708) --- updated-dependencies: - dependency-name: aws-actions/configure-aws-credentials dependency-version: 5.1.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 2 +- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/release.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index be53fbfaa..417f21c48 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -41,7 +41,7 @@ jobs: docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 + uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 6ed3b248e..2ddb78ec0 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -65,7 +65,7 @@ jobs: java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 # v5.1.0 + uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 @@ -96,7 +96,7 @@ jobs: java-version: ${{ matrix.java }} cache: maven - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 # v5.1.0 + uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1 with: role-to-assume: ${{ secrets.AWS_IAM_ROLE }} aws-region: us-east-1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bd2e23487..20ff19a69 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -282,7 +282,7 @@ jobs: docker build -t squidfunk/mkdocs-material ./docs/ docker run --rm -t -v ${PWD}:/docs squidfunk/mkdocs-material build - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 + uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} From bb70c1be87072674a46456cfb73cd86818f45d46 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Wed, 10 Dec 2025 16:21:53 +0100 Subject: [PATCH 558/577] fix(metrics): Clear custom dimensions when flushing. (#2328) --- .../metrics/internal/EmfMetricsLogger.java | 24 ++- .../internal/EmfMetricsLoggerTest.java | 189 ++++++++++++++++++ 2 files changed, 212 insertions(+), 1 deletion(-) diff --git a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java index 37f2d193a..611d4dcc6 100644 --- a/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java +++ b/powertools-metrics/src/main/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLogger.java @@ -164,6 +164,27 @@ public void flush() { } } else { emfLogger.flush(); + + // Clear custom dimensions after flush while preserving default dimensions + clearCustomDimensions(); + } + } + + private void clearCustomDimensions() { + // Reset all dimensions in the EMF logger + emfLogger.resetDimensions(false); + + // Re-apply default dimensions if they exist + if (!defaultDimensions.isEmpty()) { + DimensionSet emfDimensionSet = new DimensionSet(); + defaultDimensions.forEach((key, value) -> { + try { + emfDimensionSet.addDimension(key, value); + } catch (Exception e) { + // Ignore dimension errors + } + }); + emfLogger.setDimensions(emfDimensionSet); } } @@ -198,7 +219,8 @@ public void flushMetrics(Consumer<Metrics> metricsConsumer) { metrics.setNamespace(this.namespace); } if (!defaultDimensions.isEmpty()) { - metrics.setDefaultDimensions(software.amazon.lambda.powertools.metrics.model.DimensionSet.of(defaultDimensions)); + metrics.setDefaultDimensions( + software.amazon.lambda.powertools.metrics.model.DimensionSet.of(defaultDimensions)); } properties.forEach(metrics::addMetadata); diff --git a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java index c2238711a..5e597e835 100644 --- a/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java +++ b/powertools-metrics/src/test/java/software/amazon/lambda/powertools/metrics/internal/EmfMetricsLoggerTest.java @@ -263,6 +263,65 @@ void shouldAddMetadata() throws Exception { assertThat(rootNode.get("CustomMetadata").asText()).isEqualTo("MetadataValue"); } + @Test + void shouldClearMetadataAfterFlush() throws Exception { + // Given - Add metadata and flush first time + metrics.addMetadata("RequestId", "req-123"); + metrics.addMetadata("UserAgent", "test-agent"); + metrics.addMetric("FirstMetric", 1.0); + metrics.flush(); + + // Capture first flush output and reset for second flush + String firstFlushOutput = outputStreamCaptor.toString().trim(); + outputStreamCaptor.reset(); + + // When - Add another metric and flush again using the SAME metrics instance + metrics.addMetric("SecondMetric", 2.0); + metrics.flush(); + + // Then - Verify first flush had metadata + JsonNode firstRootNode = objectMapper.readTree(firstFlushOutput); + assertThat(firstRootNode.has("RequestId")).isTrue(); + assertThat(firstRootNode.get("RequestId").asText()).isEqualTo("req-123"); + assertThat(firstRootNode.has("UserAgent")).isTrue(); + assertThat(firstRootNode.get("UserAgent").asText()).isEqualTo("test-agent"); + assertThat(firstRootNode.has("FirstMetric")).isTrue(); + + // Verify second flush does NOT have metadata from first flush + // The EMF library automatically clears metadata after flush + String secondFlushOutput = outputStreamCaptor.toString().trim(); + JsonNode secondRootNode = objectMapper.readTree(secondFlushOutput); + + // Metadata should be cleared after first flush by the EMF library + assertThat(secondRootNode.has("RequestId")).isFalse(); + assertThat(secondRootNode.has("UserAgent")).isFalse(); + assertThat(secondRootNode.has("SecondMetric")).isTrue(); + } + + @Test + void shouldInheritMetadataInFlushMetricsMethod() throws Exception { + // Given - Add metadata to the main metrics instance + metrics.addMetadata("PersistentMetadata", "should-inherit"); + metrics.addMetadata("GlobalContext", "main-instance"); + + // When - Use flushMetrics to create a separate metrics context + metrics.flushMetrics(separateMetrics -> { + separateMetrics.addMetric("SeparateMetric", 1.0); + // Don't add any metadata to the separate instance + }); + + // Then - The separate metrics context SHOULD inherit metadata from main instance + String flushMetricsOutput = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(flushMetricsOutput); + + // The separate metrics should have inherited metadata (this is expected behavior) + assertThat(rootNode.has("PersistentMetadata")).isTrue(); + assertThat(rootNode.get("PersistentMetadata").asText()).isEqualTo("should-inherit"); + assertThat(rootNode.has("GlobalContext")).isTrue(); + assertThat(rootNode.get("GlobalContext").asText()).isEqualTo("main-instance"); + assertThat(rootNode.has("SeparateMetric")).isTrue(); + } + @Test void shouldSetDefaultDimensions() throws Exception { // Given @@ -547,4 +606,134 @@ void shouldNotFlushSingleMetricWhenDisabled() { String emfOutput = outputStreamCaptor.toString().trim(); assertThat(emfOutput).isEmpty(); } + + @Test + void shouldClearCustomDimensionsAfterFlush() throws Exception { + // Given - Set up default dimensions that should persist + DimensionSet defaultDimensions = DimensionSet.of("Service", "TestService", "Environment", "Test"); + metrics.setDefaultDimensions(defaultDimensions); + + // First invocation - add custom dimensions and flush + DimensionSet customDimensions = DimensionSet.of("EXAMPLE_KEY", "EXAMPLE_VALUE"); + metrics.addDimension(customDimensions); + metrics.addMetric("SERL", 1.0); + metrics.flush(); + + // Capture first flush output + String firstFlushOutput = outputStreamCaptor.toString().trim(); + outputStreamCaptor.reset(); // Clear for second flush + + // Second invocation - should NOT have custom dimensions from first invocation + metrics.addMetric("Expected", 1.0); + metrics.flush(); + + // Then - Verify first flush had both default and custom dimensions + JsonNode firstRootNode = objectMapper.readTree(firstFlushOutput); + assertThat(firstRootNode.has("Service")).isTrue(); + assertThat(firstRootNode.get("Service").asText()).isEqualTo("TestService"); + assertThat(firstRootNode.has("Environment")).isTrue(); + assertThat(firstRootNode.get("Environment").asText()).isEqualTo("Test"); + assertThat(firstRootNode.has("EXAMPLE_KEY")).isTrue(); + assertThat(firstRootNode.get("EXAMPLE_KEY").asText()).isEqualTo("EXAMPLE_VALUE"); + assertThat(firstRootNode.has("SERL")).isTrue(); + + // Verify second flush has ONLY default dimensions (custom dimensions should be cleared) + String secondFlushOutput = outputStreamCaptor.toString().trim(); + JsonNode secondRootNode = objectMapper.readTree(secondFlushOutput); + + // Default dimensions should still be present + assertThat(secondRootNode.has("Service")).isTrue(); + assertThat(secondRootNode.get("Service").asText()).isEqualTo("TestService"); + assertThat(secondRootNode.has("Environment")).isTrue(); + assertThat(secondRootNode.get("Environment").asText()).isEqualTo("Test"); + + // Custom dimensions should be cleared (this is the failing assertion that demonstrates the bug) + assertThat(secondRootNode.has("EXAMPLE_KEY")).isFalse(); + assertThat(secondRootNode.has("Expected")).isTrue(); + + // Verify dimensions in CloudWatchMetrics section + JsonNode secondDimensions = secondRootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Dimensions").get(0); + boolean hasExampleKey = false; + boolean hasService = false; + boolean hasEnvironment = false; + + for (JsonNode dimension : secondDimensions) { + String dimName = dimension.asText(); + if ("EXAMPLE_KEY".equals(dimName)) { + hasExampleKey = true; + } else if ("Service".equals(dimName)) { + hasService = true; + } else if ("Environment".equals(dimName)) { + hasEnvironment = true; + } + } + + // Default dimensions should be in CloudWatchMetrics + assertThat(hasService).isTrue(); + assertThat(hasEnvironment).isTrue(); + // Custom dimension should NOT be in CloudWatchMetrics (this should fail initially) + assertThat(hasExampleKey).isFalse(); + } + + @Test + void shouldHandleEmptyCustomDimensionsGracefully() throws Exception { + // Given - Only default dimensions, no custom dimensions + metrics.setDefaultDimensions(DimensionSet.of("Service", "TestService")); + + // When - Flush without adding custom dimensions + metrics.addMetric("TestMetric", 1.0); + metrics.flush(); + outputStreamCaptor.reset(); + + // Second flush + metrics.addMetric("TestMetric2", 2.0); + metrics.flush(); + + // Then - Should work normally with only default dimensions + String output = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(output); + + assertThat(rootNode.has("Service")).isTrue(); + assertThat(rootNode.get("Service").asText()).isEqualTo("TestService"); + assertThat(rootNode.has("TestMetric2")).isTrue(); + } + + @Test + void shouldClearCustomDimensionsWhenNoDefaultDimensionsSet() throws Exception { + // Given - No default dimensions set + metrics.clearDefaultDimensions(); + + // When - Add custom dimensions and flush + metrics.addDimension("CustomDim", "CustomValue"); + metrics.addMetric("Metric1", 1.0); + metrics.flush(); + outputStreamCaptor.reset(); + + // Second flush without custom dimensions + metrics.addMetric("Metric2", 2.0); + metrics.flush(); + + // Then - Custom dimensions should be cleared + String output = outputStreamCaptor.toString().trim(); + JsonNode rootNode = objectMapper.readTree(output); + + assertThat(rootNode.has("CustomDim")).isFalse(); + assertThat(rootNode.has("Metric2")).isTrue(); + + // Verify no custom dimensions in CloudWatchMetrics section + JsonNode dimensionsArray = rootNode.get("_aws").get("CloudWatchMetrics").get(0).get("Dimensions"); + boolean hasCustomDim = false; + if (dimensionsArray != null && dimensionsArray.size() > 0) { + JsonNode dimensions = dimensionsArray.get(0); + if (dimensions != null) { + for (JsonNode dimension : dimensions) { + if ("CustomDim".equals(dimension.asText())) { + hasCustomDim = true; + break; + } + } + } + } + assertThat(hasCustomDim).isFalse(); + } } From 79e31370cf85d1c44b304930b4f063272a5e3a68 Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Mon, 15 Dec 2025 13:12:40 +0100 Subject: [PATCH 559/577] feat(cold-start-detection): Suppress cold start detection for non ON-DEMAND invocations (#2329) * fix: cold start only on on-demand invocation * fix: cold start only on on-demand invocation * fix: cold start only on on-demand invocation * mvn clean test is successful * reversed the sqllite changes * feat(cold-start-detection): Suppress cold start for non ON-DEMAND invocation (since there are no cold starts). --------- Co-authored-by: Attyuttam <attyuttam@gmail.com> --- .../terraform/pom.xml | 6 +++--- .../sam-graalvm/pom.xml | 7 +++---- .../powertools-examples-parameters/sam/pom.xml | 4 +--- pom.xml | 2 -- powertools-common/pom.xml | 1 - .../common/internal/LambdaConstants.java | 2 ++ .../common/internal/LambdaHandlerProcessor.java | 9 ++++++++- .../internal/LambdaHandlerProcessorTest.java | 1 + powertools-e2e-tests/pom.xml | 2 -- powertools-logging/pom.xml | 3 +-- .../powertools-logging-log4j/pom.xml | 3 +-- .../powertools-logging-logback/pom.xml | 3 +-- powertools-metrics/pom.xml | 1 + powertools-parameters/pom.xml | 2 -- .../powertools-parameters-appconfig/pom.xml | 2 -- .../powertools-parameters-dynamodb/pom.xml | 2 -- .../powertools-parameters-secrets/pom.xml | 2 -- .../powertools-parameters-ssm/pom.xml | 2 -- .../powertools-parameters-tests/pom.xml | 1 - powertools-serialization/pom.xml | 1 - powertools-tracing/pom.xml | 15 ++++++++++++++- 21 files changed, 36 insertions(+), 35 deletions(-) diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index 14c0e223e..a6237b00f 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -1,5 +1,5 @@ <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 http://maven.apache.org/maven-v4_0_0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform</name> @@ -101,7 +101,8 @@ <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> <transformers> - <transformer implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer"/> + <transformer + implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer" /> </transformers> </configuration> </execution> @@ -126,7 +127,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <environmentVariables> <LAMBDA_TASK_ROOT>handler</LAMBDA_TASK_ROOT> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 6d0c3f4a2..09401eeff 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -1,5 +1,5 @@ <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 http://maven.apache.org/maven-v4_0_0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <version>2.8.0</version> @@ -98,8 +98,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <!-- JUnit 5 requires Surefire version 3.1.0 or higher --> - <version>3.5.4</version> </plugin> <plugin> <groupId>dev.aspectj</groupId> @@ -144,7 +142,8 @@ <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> <transformers> - <transformer implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer"/> + <transformer + implementation="org.apache.logging.log4j.maven.plugins.shade.transformer.Log4j2PluginCacheFileTransformer" /> </transformers> </configuration> </execution> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 15d68ffcd..3e8f99aa0 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -1,5 +1,5 @@ <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 http://maven.apache.org/maven-v4_0_0.xsd"> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <version>2.8.0</version> @@ -72,8 +72,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <!-- JUnit 5 requires Surefire version 3.1.0 or higher --> - <version>3.5.4</version> </plugin> <plugin> <groupId>dev.aspectj</groupId> diff --git a/pom.xml b/pom.xml index 1e4c3a9fd..6f6a9ce10 100644 --- a/pom.xml +++ b/pom.xml @@ -95,7 +95,6 @@ <maven-compiler-plugin.version>3.14.1</maven-compiler-plugin.version> <aspectj.version>1.9.7</aspectj.version> <aspectj-maven-plugin.version>1.13.1</aspectj-maven-plugin.version> - <maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version> <jacoco-maven-plugin.version>0.8.11</jacoco-maven-plugin.version> <nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version> <maven-javadoc-plugin.version>3.12.0</maven-javadoc-plugin.version> @@ -625,7 +624,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> @{argLine} diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index f14783b5b..551fae8bc 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -106,7 +106,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java index 69fc1283a..4c4e8e9db 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaConstants.java @@ -28,4 +28,6 @@ private LambdaConstants() { public static final String ROOT_EQUALS = "Root="; public static final String POWERTOOLS_SERVICE_NAME = "POWERTOOLS_SERVICE_NAME"; public static final String SERVICE_UNDEFINED = "service_undefined"; + public static final String AWS_LAMBDA_INITIALIZATION_TYPE = "AWS_LAMBDA_INITIALIZATION_TYPE"; + public static final String ON_DEMAND_INVOCATION_TYPE = "on-demand"; } diff --git a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java index 393835d1e..15bff15d6 100644 --- a/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java +++ b/powertools-common/src/main/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessor.java @@ -93,7 +93,14 @@ protected static void resetServiceName() { } public static boolean isColdStart() { - return isColdStart == null; + if (isColdStart != null) { + return isColdStart; + } + + String initType = System.getenv(LambdaConstants.AWS_LAMBDA_INITIALIZATION_TYPE); + isColdStart = LambdaConstants.ON_DEMAND_INVOCATION_TYPE.equals(initType); + + return isColdStart; } public static void coldStartDone() { diff --git a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java index 5c6bdc020..0726a9e77 100644 --- a/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java +++ b/powertools-common/src/test/java/software/amazon/lambda/powertools/common/internal/LambdaHandlerProcessorTest.java @@ -216,6 +216,7 @@ void extractContext_notKnownHandler() { } @Test + @SetEnvironmentVariable(key = LambdaConstants.AWS_LAMBDA_INITIALIZATION_TYPE, value = LambdaConstants.ON_DEMAND_INVOCATION_TYPE) void isColdStart() { boolean isColdStart = LambdaHandlerProcessor.isColdStart(); diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index 484e3b4c2..bfd4350a0 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -214,7 +214,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> - <version>3.5.4</version> <executions> <execution> <goals> @@ -241,7 +240,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> - <version>3.5.4</version> <executions> <execution> <goals> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index ae5788291..923d6d133 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -123,7 +123,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -182,11 +181,11 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <environmentVariables> <AWS_LAMBDA_LOG_FORMAT>JSON</AWS_LAMBDA_LOG_FORMAT> <POWERTOOLS_SERVICE_NAME>testService</POWERTOOLS_SERVICE_NAME> + <AWS_LAMBDA_INITIALIZATION_TYPE>on-demand</AWS_LAMBDA_INITIALIZATION_TYPE> </environmentVariables> </configuration> </plugin> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 1cf3bf265..19a8b9428 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -112,7 +112,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -204,12 +203,12 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <environmentVariables> <POWERTOOLS_SERVICE_NAME>testLog4j</POWERTOOLS_SERVICE_NAME> <AWS_REGION>eu-central-1</AWS_REGION> <_X_AMZN_TRACE_ID>Root=1-63441c4a-abcdef012345678912345678</_X_AMZN_TRACE_ID> + <AWS_LAMBDA_INITIALIZATION_TYPE>on-demand</AWS_LAMBDA_INITIALIZATION_TYPE> </environmentVariables> </configuration> </plugin> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index b5a50573d..7ed1f1a17 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -110,7 +110,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -203,12 +202,12 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <environmentVariables> <POWERTOOLS_SERVICE_NAME>testLogback</POWERTOOLS_SERVICE_NAME> <AWS_REGION>eu-central-1</AWS_REGION> <_X_AMZN_TRACE_ID>Root=1-63441c4a-abcdef012345678912345678</_X_AMZN_TRACE_ID> + <AWS_LAMBDA_INITIALIZATION_TYPE>on-demand</AWS_LAMBDA_INITIALIZATION_TYPE> </environmentVariables> </configuration> </plugin> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 4da0c0a9f..86bdcc560 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -231,6 +231,7 @@ <configuration> <environmentVariables> <AWS_EMF_ENVIRONMENT>Lambda</AWS_EMF_ENVIRONMENT> + <AWS_LAMBDA_INITIALIZATION_TYPE>on-demand</AWS_LAMBDA_INITIALIZATION_TYPE> </environmentVariables> </configuration> </plugin> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index a2c4a65dc..78234b5cc 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -80,7 +80,6 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> @@ -98,7 +97,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index ab8ae0e67..3c38963a1 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -108,7 +108,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -175,7 +174,6 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index 76a7b8845..b9e48567a 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -109,7 +109,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -176,7 +175,6 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index fbe4905be..c83c674d5 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -109,7 +109,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent @@ -176,7 +175,6 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index c9de1db51..d23b84bf6 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -98,7 +98,6 @@ <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <environmentVariables> <AWS_REGION>eu-central-1</AWS_REGION> @@ -123,7 +122,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 3bcd4d604..9b93b3f79 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -110,7 +110,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index c1eea4df7..535f23190 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -107,7 +107,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index ed2596059..9e5603d70 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -129,6 +129,20 @@ </dependency> </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <environmentVariables> + <AWS_LAMBDA_INITIALIZATION_TYPE>on-demand</AWS_LAMBDA_INITIALIZATION_TYPE> + </environmentVariables> + </configuration> + </plugin> + </plugins> + </build> + <profiles> <profile> <id>generate-graalvm-files</id> @@ -137,7 +151,6 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.5.4</version> <configuration> <argLine> -Dorg.graalvm.nativeimage.imagecode=agent From e6f6a92892291670387274d1d83253e577008722 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:09:57 +0100 Subject: [PATCH 560/577] chore: bump aws.sdk.version from 2.38.7 to 2.39.3 (#2313) Bumps `aws.sdk.version` from 2.38.7 to 2.39.3. Updates `software.amazon.awssdk:url-connection-client` from 2.38.7 to 2.39.3 Updates `software.amazon.awssdk:sdk-core` from 2.38.7 to 2.39.3 Updates `software.amazon.awssdk:s3` from 2.38.7 to 2.39.3 Updates `software.amazon.awssdk:kinesis` from 2.38.7 to 2.39.3 Updates `software.amazon.awssdk:sqs` from 2.38.7 to 2.39.3 Updates `software.amazon.awssdk:dynamodb-enhanced` from 2.38.7 to 2.39.3 --- updated-dependencies: - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.39.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sdk-core dependency-version: 2.39.3 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.39.3 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.39.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.39.3 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb-enhanced dependency-version: 2.39.3 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-batch/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 6d941a31f..3a8e3ad8d 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> - <sdk.version>2.38.7</sdk.version> + <sdk.version>2.39.3</sdk.version> </properties> <dependencies> From 314e56997a34273107ba4e13d5f1143a77d59600 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:10:23 +0100 Subject: [PATCH 561/577] chore: bump com.google.protobuf:protobuf-java from 4.33.0 to 4.33.1 (#2314) Bumps [com.google.protobuf:protobuf-java](https://github.com/protocolbuffers/protobuf) from 4.33.0 to 4.33.1. - [Release notes](https://github.com/protocolbuffers/protobuf/releases) - [Changelog](https://github.com/protocolbuffers/protobuf/blob/main/protobuf_release.bzl) - [Commits](https://github.com/protocolbuffers/protobuf/commits) --- updated-dependencies: - dependency-name: com.google.protobuf:protobuf-java dependency-version: 4.33.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-kafka/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index f4b75722c..1b8e8f09d 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -12,7 +12,7 @@ <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> <avro.version>1.12.1</avro.version> - <protobuf.version>4.33.0</protobuf.version> + <protobuf.version>4.33.1</protobuf.version> </properties> <dependencies> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index ad564897f..82f6b8021 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -36,7 +36,7 @@ <properties> <kafka-clients.version>4.1.1</kafka-clients.version> <avro.version>1.12.1</avro.version> - <protobuf.version>4.33.0</protobuf.version> + <protobuf.version>4.33.1</protobuf.version> <lambda-serialization.version>1.1.6</lambda-serialization.version> </properties> From ff8122d90e4ef686613207fd91daf036e317babc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:10:33 +0100 Subject: [PATCH 562/577] chore: bump org.codehaus.mojo:versions-maven-plugin (#2315) Bumps [org.codehaus.mojo:versions-maven-plugin](https://github.com/mojohaus/versions) from 2.19.1 to 2.20.1. - [Release notes](https://github.com/mojohaus/versions/releases) - [Changelog](https://github.com/mojohaus/versions/blob/master/ReleaseNotes.md) - [Commits](https://github.com/mojohaus/versions/compare/2.19.1...2.20.1) --- updated-dependencies: - dependency-name: org.codehaus.mojo:versions-maven-plugin dependency-version: 2.20.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Andrea Amorosi <dreamorosi@gmail.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6f6a9ce10..f400e0b26 100644 --- a/pom.xml +++ b/pom.xml @@ -111,7 +111,7 @@ <aws-embedded-metrics.version>4.1.2</aws-embedded-metrics.version> <jmespath.version>0.6.0</jmespath.version> <aws.sdk.v1.version>1.12.781</aws.sdk.v1.version> - <versions-maven-plugin.version>2.19.1</versions-maven-plugin.version> + <versions-maven-plugin.version>2.20.1</versions-maven-plugin.version> <elastic.version>1.7.0</elastic.version> <mockito.version>5.20.0</mockito.version> <mockito-junit-jupiter.version>5.20.0</mockito-junit-jupiter.version> From 057f94e2e2028291b88331c135c16093cc58fc86 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:10:44 +0100 Subject: [PATCH 563/577] chore: bump graalvm/setup-graalvm from 1.4.2 to 1.4.4 (#2322) Bumps [graalvm/setup-graalvm](https://github.com/graalvm/setup-graalvm) from 1.4.2 to 1.4.4. - [Release notes](https://github.com/graalvm/setup-graalvm/releases) - [Commits](https://github.com/graalvm/setup-graalvm/compare/eec48106e0bf45f2976c2ff0c3e22395cced8243...790e28947b79a9c09c3391c0f18bf8d0f102ed69) --- updated-dependencies: - dependency-name: graalvm/setup-graalvm dependency-version: 1.4.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index a972084a6..f23968815 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -105,7 +105,7 @@ jobs: powertools-*/** pom.xml - name: Setup GraalVM - uses: graalvm/setup-graalvm@eec48106e0bf45f2976c2ff0c3e22395cced8243 # v1.4.2 + uses: graalvm/setup-graalvm@790e28947b79a9c09c3391c0f18bf8d0f102ed69 # v1.4.4 with: java-version: "21" distribution: "graalvm" From 9f4668a7d75285a529893abd28415b578a9aab5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:10:56 +0100 Subject: [PATCH 564/577] chore: bump actions/checkout from 6.0.0 to 6.0.1 (#2323) Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.0 to 6.0.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/1af3b93b6815bc44a9784bd300feb67ff0d1eeb3...8e8c483db84b4bee98b60c0593521ed34d9990e8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-docs.yml | 2 +- .github/workflows/check-build.yml | 4 ++-- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/check-pmd.yml | 2 +- .github/workflows/check-spotbugs.yml | 2 +- .github/workflows/release.yml | 6 +++--- .github/workflows/security-dependencies-check.yml | 2 +- .github/workflows/security-scorecard.yml | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 417f21c48..a94ace711 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -32,7 +32,7 @@ jobs: environment: Docs steps: - name: Checkout Repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 with: fetch-depth: 0 - name: Build diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index f23968815..108a32a11 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -77,7 +77,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup Java uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 with: @@ -94,7 +94,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: fetch-depth: 0 - name: Get changed files diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 2ddb78ec0..8a527835d 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -57,7 +57,7 @@ jobs: - 25 steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup java uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: @@ -88,7 +88,7 @@ jobs: - 25 steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup java uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: diff --git a/.github/workflows/check-pmd.yml b/.github/workflows/check-pmd.yml index 66150821d..cab6c16a8 100644 --- a/.github/workflows/check-pmd.yml +++ b/.github/workflows/check-pmd.yml @@ -29,7 +29,7 @@ jobs: id-token: write steps: - name: Checkout Repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup Java uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: diff --git a/.github/workflows/check-spotbugs.yml b/.github/workflows/check-spotbugs.yml index 8af0e4d9d..db4014aea 100644 --- a/.github/workflows/check-spotbugs.yml +++ b/.github/workflows/check-spotbugs.yml @@ -41,7 +41,7 @@ jobs: codecheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup Java uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 20ff19a69..a59cab7cb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -103,7 +103,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - id: version name: version uses: ./.github/actions/version @@ -224,7 +224,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: ref: ${{ env.RELEASE_COMMIT }} - id: download_source @@ -272,7 +272,7 @@ jobs: steps: - id: checkout name: Checkout repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: # Checkout PR branch to make sure we build the version-bumped docs ref: ci-${{ github.run_id }} diff --git a/.github/workflows/security-dependencies-check.yml b/.github/workflows/security-dependencies-check.yml index 1e85d9e96..6729fd304 100644 --- a/.github/workflows/security-dependencies-check.yml +++ b/.github/workflows/security-dependencies-check.yml @@ -24,7 +24,7 @@ jobs: pull-requests: write steps: - name: Checkout Repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Verify Contents uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 with: diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 0944694f7..e15b0b5dc 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -35,7 +35,7 @@ jobs: id-token: write steps: - name: Checkout Repository - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: Run Analysis From 8fd60742bd06c695c9ab55f63701a38630a3d9fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:11:08 +0100 Subject: [PATCH 565/577] chore: bump sam/build-java25 (#2324) Bumps sam/build-java25 from `af599d0` to `b34fc78`. --- updated-dependencies: - dependency-name: sam/build-java25 dependency-version: b34fc789a70464f080232ee96590a6d0c7249eb59b1c33deccaae08a882cac23 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index 6643760b4..fbefe46dd 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 25 -FROM public.ecr.aws/sam/build-java25@sha256:af599d010afef63c83a04265dee9adbd4557d94b4a81941f28ae42657af7890d +FROM public.ecr.aws/sam/build-java25@sha256:b34fc789a70464f080232ee96590a6d0c7249eb59b1c33deccaae08a882cac23 # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/25/latest/graalvm-jdk-25_linux-x64_bin.tar.gz | tar -xvz From 8d5a364e795cfa28c9911fd89d8d8283c029a308 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:11:21 +0100 Subject: [PATCH 566/577] chore: bump actions/setup-java from 5.0.0 to 5.1.0 (#2325) Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.0.0 to 5.1.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/dded0888837ed1f317902acf8a20df0ad188d165...f2beeb24e141e01a676f977032f5a29d81c9e27e) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 2 +- .github/workflows/check-e2e.yml | 4 ++-- .github/workflows/check-pmd.yml | 2 +- .github/workflows/check-spotbugs.yml | 2 +- .github/workflows/release.yml | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index 108a32a11..cdfd5aea5 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -79,7 +79,7 @@ jobs: name: Checkout repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup Java - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e with: distribution: corretto java-version: ${{ matrix.java }} diff --git a/.github/workflows/check-e2e.yml b/.github/workflows/check-e2e.yml index 8a527835d..378d48a60 100644 --- a/.github/workflows/check-e2e.yml +++ b/.github/workflows/check-e2e.yml @@ -59,7 +59,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup java - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 with: distribution: 'corretto' java-version: ${{ matrix.java }} @@ -90,7 +90,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup java - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 with: distribution: 'corretto' java-version: ${{ matrix.java }} diff --git a/.github/workflows/check-pmd.yml b/.github/workflows/check-pmd.yml index cab6c16a8..7e7dce429 100644 --- a/.github/workflows/check-pmd.yml +++ b/.github/workflows/check-pmd.yml @@ -31,7 +31,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup Java - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 with: java-version: 21 distribution: corretto diff --git a/.github/workflows/check-spotbugs.yml b/.github/workflows/check-spotbugs.yml index db4014aea..c5c8197f9 100644 --- a/.github/workflows/check-spotbugs.yml +++ b/.github/workflows/check-spotbugs.yml @@ -43,7 +43,7 @@ jobs: steps: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Setup Java - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 with: distribution: 'corretto' java-version: 21 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a59cab7cb..c9b2d80c6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -137,7 +137,7 @@ jobs: with: name: source - name: Setup Java - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e with: distribution: corretto java-version: 21 @@ -172,7 +172,7 @@ jobs: with: name: source - name: Setup Java - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e with: distribution: corretto java-version: ${{ matrix.java }} @@ -195,7 +195,7 @@ jobs: with: name: source - name: Setup Java - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e with: distribution: corretto java-version: 21 From a94274eba5ca1bf04432910db7776e551f236799 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:11:32 +0100 Subject: [PATCH 567/577] chore: bump tj-actions/changed-files from 47.0.0 to 47.0.1 (#2330) Bumps [tj-actions/changed-files](https://github.com/tj-actions/changed-files) from 47.0.0 to 47.0.1. - [Release notes](https://github.com/tj-actions/changed-files/releases) - [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/changed-files/compare/24d32ffd492484c1d75e0c0b894501ddb9d30d62...e0021407031f5be11a464abee9a0776171c79891) --- updated-dependencies: - dependency-name: tj-actions/changed-files dependency-version: 47.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check-build.yml b/.github/workflows/check-build.yml index cdfd5aea5..339d6fab8 100644 --- a/.github/workflows/check-build.yml +++ b/.github/workflows/check-build.yml @@ -99,7 +99,7 @@ jobs: fetch-depth: 0 - name: Get changed files id: changed-files - uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 + uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1 with: files: | powertools-*/** From ff3e3e6a3470199773715e51626f60d99338598a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 10:11:42 +0100 Subject: [PATCH 568/577] chore: bump github/codeql-action from 4.31.5 to 4.31.8 (#2331) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.5 to 4.31.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/fdbfb4d2750291e159f0156def62b853c2798ca2...1b168cd39490f61582a9beae412bb7057a6b2c4e) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index e15b0b5dc..7f3286dfe 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@fdbfb4d2750291e159f0156def62b853c2798ca2 # v3.29.5 + uses: github/codeql-action/upload-sarif@1b168cd39490f61582a9beae412bb7057a6b2c4e # v3.29.5 with: sarif_file: results.sarif From 42567838f53a764516f12126fe76d3bb289fb09a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 11:34:12 +0100 Subject: [PATCH 569/577] chore(ci): bump version to 2.9.0 (#2332) * chore(ci): bump version to 2.9.0 * Restore CHANGELOG.md from main. --------- Co-authored-by: Powertools for AWS Lambda (Java) Bot <151832416+aws-powertools-bot@users.noreply.github.com> Co-authored-by: Philipp Page <pagejep@amazon.com> --- README.md | 6 +++--- examples/pom.xml | 2 +- examples/powertools-examples-batch/pom.xml | 2 +- examples/powertools-examples-cloudformation/README.md | 4 ++-- .../infra/sam-graalvm/README.md | 2 +- examples/powertools-examples-cloudformation/pom.xml | 2 +- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- .../powertools-examples-core-utilities/cdk/infra/pom.xml | 2 +- .../powertools-examples-core-utilities/gradle/build.gradle | 6 +++--- .../kotlin/build.gradle.kts | 6 +++--- .../powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam/pom.xml | 2 +- .../powertools-examples-core-utilities/serverless/pom.xml | 2 +- .../powertools-examples-core-utilities/terraform/pom.xml | 2 +- .../powertools-examples-idempotency/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-idempotency/sam/pom.xml | 2 +- examples/powertools-examples-kafka/pom.xml | 2 +- .../main/java/org/demo/kafka/protobuf/ProtobufProduct.java | 4 ++-- .../org/demo/kafka/protobuf/ProtobufProductOrBuilder.java | 2 +- .../org/demo/kafka/protobuf/ProtobufProductOuterClass.java | 4 ++-- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam/pom.xml | 2 +- .../powertools-examples-serialization/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-serialization/sam/pom.xml | 2 +- examples/powertools-examples-validation/pom.xml | 2 +- mkdocs.yml | 2 +- pom.xml | 2 +- powertools-batch/pom.xml | 2 +- powertools-cloudformation/pom.xml | 2 +- powertools-common/pom.xml | 2 +- powertools-e2e-tests/handlers/batch/pom.xml | 2 +- .../handlers/idempotency-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency-generics/pom.xml | 2 +- powertools-e2e-tests/handlers/idempotency/pom.xml | 2 +- .../handlers/largemessage-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/largemessage/pom.xml | 2 +- .../handlers/largemessage_idempotent/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-functional/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-log4j/pom.xml | 2 +- powertools-e2e-tests/handlers/logging-logback/pom.xml | 2 +- powertools-e2e-tests/handlers/metrics/pom.xml | 2 +- powertools-e2e-tests/handlers/parameters/pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- powertools-e2e-tests/handlers/tracing/pom.xml | 2 +- powertools-e2e-tests/handlers/validation-alb-event/pom.xml | 2 +- .../handlers/validation-apigw-event/pom.xml | 2 +- powertools-e2e-tests/pom.xml | 2 +- powertools-idempotency/pom.xml | 2 +- powertools-idempotency/powertools-idempotency-core/pom.xml | 2 +- .../powertools-idempotency-dynamodb/pom.xml | 2 +- powertools-kafka/pom.xml | 2 +- powertools-large-messages/pom.xml | 2 +- powertools-logging/pom.xml | 2 +- powertools-logging/powertools-logging-log4j/pom.xml | 2 +- powertools-logging/powertools-logging-logback/pom.xml | 2 +- powertools-metrics/pom.xml | 2 +- powertools-parameters/pom.xml | 2 +- .../powertools-parameters-appconfig/pom.xml | 2 +- .../powertools-parameters-dynamodb/pom.xml | 2 +- powertools-parameters/powertools-parameters-secrets/pom.xml | 2 +- powertools-parameters/powertools-parameters-ssm/pom.xml | 2 +- powertools-parameters/powertools-parameters-tests/pom.xml | 2 +- powertools-serialization/pom.xml | 2 +- powertools-tracing/pom.xml | 2 +- powertools-validation/pom.xml | 2 +- 65 files changed, 74 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 2644c47ab..4c02e2d1f 100644 --- a/README.md +++ b/README.md @@ -22,17 +22,17 @@ Powertools for AWS Lambda (Java) is available in Maven Central. You can use your <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-tracing</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-logging-log4j</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </dependency> <dependency> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-metrics</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </dependency> ... </dependencies> diff --git a/examples/pom.xml b/examples/pom.xml index 511cdd5a9..5d191063f 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-examples</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Examples</name> diff --git a/examples/powertools-examples-batch/pom.xml b/examples/powertools-examples-batch/pom.xml index 3a8e3ad8d..0091fb5ca 100644 --- a/examples/powertools-examples-batch/pom.xml +++ b/examples/powertools-examples-batch/pom.xml @@ -5,7 +5,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-batch</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Batch</name> diff --git a/examples/powertools-examples-cloudformation/README.md b/examples/powertools-examples-cloudformation/README.md index b9e58eb82..27e564bf3 100644 --- a/examples/powertools-examples-cloudformation/README.md +++ b/examples/powertools-examples-cloudformation/README.md @@ -15,7 +15,7 @@ Run the following in your shell: ```bash cd infra/sam sam build -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.8.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.9.0718 ``` ### Deploy with CDK @@ -32,5 +32,5 @@ To build and deploy this application for the first time, run the following in yo cd infra/cdk mvn package cdk synth -cdk deploy -c BucketNameParam=my-unique-bucket-2.8.0718 +cdk deploy -c BucketNameParam=my-unique-bucket-2.9.0718 ``` \ No newline at end of file diff --git a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md index c2a9e2ffd..3aca1408a 100644 --- a/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md +++ b/examples/powertools-examples-cloudformation/infra/sam-graalvm/README.md @@ -40,7 +40,7 @@ sam build ## Deploy the sample application ```shell -sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.8.0718 +sam deploy --guided --parameter-overrides BucketNameParam=my-unique-bucket-2.9.0718 ``` This sample is based on Serverless Application Model (SAM). To deploy it, check out the instructions for getting started with SAM in [the examples directory](../../../README.md) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 09adbfa18..8581a6ceb 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -3,7 +3,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-cloudformation</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 29acef5e2..28be679a5 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -6,7 +6,7 @@ <groupId>software.amazon.lambda.examples</groupId> <!-- TODO TODO TODO this should build from SNAPSHOT, but it doesn't, because the snapshots don't appear in the docker environment CDK builds it in in our CDK tests. How to procede? V2 blocker --> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-core-utilities-cdk</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml index 7daf3153f..e3ceb7e65 100644 --- a/examples/powertools-examples-core-utilities/cdk/infra/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/infra/pom.xml @@ -4,7 +4,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> <artifactId>cdk</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <cdk.version>2.224.0</cdk.version> diff --git a/examples/powertools-examples-core-utilities/gradle/build.gradle b/examples/powertools-examples-core-utilities/gradle/build.gradle index 6841d20ab..b01fdcfaa 100644 --- a/examples/powertools-examples-core-utilities/gradle/build.gradle +++ b/examples/powertools-examples-core-utilities/gradle/build.gradle @@ -29,8 +29,8 @@ dependencies { implementation 'com.amazonaws:aws-lambda-java-events:3.16.0' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2' implementation 'org.aspectj:aspectjrt:1.9.20.1' - aspect 'software.amazon.lambda:powertools-tracing:2.8.0' - aspect 'software.amazon.lambda:powertools-logging-log4j:2.8.0' - aspect 'software.amazon.lambda:powertools-metrics:2.8.0' + aspect 'software.amazon.lambda:powertools-tracing:2.9.0' + aspect 'software.amazon.lambda:powertools-logging-log4j:2.9.0' + aspect 'software.amazon.lambda:powertools-metrics:2.9.0' } diff --git a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts index bc11eb32e..3dae5015e 100644 --- a/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts +++ b/examples/powertools-examples-core-utilities/kotlin/build.gradle.kts @@ -15,9 +15,9 @@ dependencies { implementation("com.amazonaws:aws-lambda-java-events:3.16.0") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.2") implementation("org.aspectj:aspectjrt:1.9.20.1") - aspect("software.amazon.lambda:powertools-tracing:2.8.0") - aspect("software.amazon.lambda:powertools-logging-log4j:2.8.0") - aspect("software.amazon.lambda:powertools-metrics:2.8.0") + aspect("software.amazon.lambda:powertools-tracing:2.9.0") + aspect("software.amazon.lambda:powertools-logging-log4j:2.9.0") + aspect("software.amazon.lambda:powertools-metrics:2.9.0") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.24") } diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index fceb4a322..e7a3f202d 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM GraalVM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-core-utilities-sam-graalvm</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/sam/pom.xml b/examples/powertools-examples-core-utilities/sam/pom.xml index b8606a227..2d6a00161 100644 --- a/examples/powertools-examples-core-utilities/sam/pom.xml +++ b/examples/powertools-examples-core-utilities/sam/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with SAM</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-core-utilities-sam</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/serverless/pom.xml b/examples/powertools-examples-core-utilities/serverless/pom.xml index d77b0ccd6..26e647dad 100644 --- a/examples/powertools-examples-core-utilities/serverless/pom.xml +++ b/examples/powertools-examples-core-utilities/serverless/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Serverless</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-core-utilities-serverless</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-core-utilities/terraform/pom.xml b/examples/powertools-examples-core-utilities/terraform/pom.xml index a6237b00f..4de1e415c 100644 --- a/examples/powertools-examples-core-utilities/terraform/pom.xml +++ b/examples/powertools-examples-core-utilities/terraform/pom.xml @@ -4,7 +4,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Core Utilities (logging, tracing, metrics) with Terraform</name> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-core-utilities-terraform</artifactId> <packaging>jar</packaging> diff --git a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml index d1c0205ff..0536951aa 100644 --- a/examples/powertools-examples-idempotency/sam-graalvm/pom.xml +++ b/examples/powertools-examples-idempotency/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-idempotency-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency GraalVM</name> diff --git a/examples/powertools-examples-idempotency/sam/pom.xml b/examples/powertools-examples-idempotency/sam/pom.xml index b90705c67..22d6a9c81 100644 --- a/examples/powertools-examples-idempotency/sam/pom.xml +++ b/examples/powertools-examples-idempotency/sam/pom.xml @@ -17,7 +17,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-idempotency</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Idempotency</name> diff --git a/examples/powertools-examples-kafka/pom.xml b/examples/powertools-examples-kafka/pom.xml index 1b8e8f09d..d152f46c0 100644 --- a/examples/powertools-examples-kafka/pom.xml +++ b/examples/powertools-examples-kafka/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-kafka</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Kafka</name> diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java index 13d8905f2..2bf5db844 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProduct.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.33.0 +// Protobuf Java Version: 4.33.1 package org.demo.kafka.protobuf; @@ -19,7 +19,7 @@ public final class ProtobufProduct extends com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 33, - /* patch= */ 0, + /* patch= */ 1, /* suffix= */ "", "ProtobufProduct"); } diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java index ae7cb2182..caf17ad50 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOrBuilder.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.33.0 +// Protobuf Java Version: 4.33.1 package org.demo.kafka.protobuf; diff --git a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java index 4fcac7bd7..ce3214777 100644 --- a/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java +++ b/examples/powertools-examples-kafka/src/main/java/org/demo/kafka/protobuf/ProtobufProductOuterClass.java @@ -1,7 +1,7 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // NO CHECKED-IN PROTOBUF GENCODE // source: ProtobufProduct.proto -// Protobuf Java Version: 4.33.0 +// Protobuf Java Version: 4.33.1 package org.demo.kafka.protobuf; @@ -13,7 +13,7 @@ private ProtobufProductOuterClass() {} com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, /* major= */ 4, /* minor= */ 33, - /* patch= */ 0, + /* patch= */ 1, /* suffix= */ "", "ProtobufProductOuterClass"); } diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 09401eeff..7fc652bca 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-parameters-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> diff --git a/examples/powertools-examples-parameters/sam/pom.xml b/examples/powertools-examples-parameters/sam/pom.xml index 3e8f99aa0..d2c3e68d2 100644 --- a/examples/powertools-examples-parameters/sam/pom.xml +++ b/examples/powertools-examples-parameters/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-parameters-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Parameters</name> diff --git a/examples/powertools-examples-serialization/sam-graalvm/pom.xml b/examples/powertools-examples-serialization/sam-graalvm/pom.xml index 44661fb71..5077c8989 100644 --- a/examples/powertools-examples-serialization/sam-graalvm/pom.xml +++ b/examples/powertools-examples-serialization/sam-graalvm/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-serialization-sam-graalvm</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization GraalVM</name> diff --git a/examples/powertools-examples-serialization/sam/pom.xml b/examples/powertools-examples-serialization/sam/pom.xml index 93c60a2cb..cf66c3e14 100644 --- a/examples/powertools-examples-serialization/sam/pom.xml +++ b/examples/powertools-examples-serialization/sam/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-serialization-sam</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Serialization</name> diff --git a/examples/powertools-examples-validation/pom.xml b/examples/powertools-examples-validation/pom.xml index 1337bc2ee..2fa8462a5 100644 --- a/examples/powertools-examples-validation/pom.xml +++ b/examples/powertools-examples-validation/pom.xml @@ -16,7 +16,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>software.amazon.lambda.examples</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <artifactId>powertools-examples-validation</artifactId> <packaging>jar</packaging> <name>Powertools for AWS Lambda (Java) - Examples - Validation</name> diff --git a/mkdocs.yml b/mkdocs.yml index 5f35b96c0..b52b88cca 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -129,7 +129,7 @@ extra_javascript: extra: powertools: - version: 2.8.0 + version: 2.9.0 version: provider: mike default: latest diff --git a/pom.xml b/pom.xml index f400e0b26..b300e911d 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> <packaging>pom</packaging> <name>Powertools for AWS Lambda (Java) - Parent</name> diff --git a/powertools-batch/pom.xml b/powertools-batch/pom.xml index 07d11d41c..37cfdf7b2 100644 --- a/powertools-batch/pom.xml +++ b/powertools-batch/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <description>A suite of utilities that makes batch message processing using AWS Lambda easier.</description> diff --git a/powertools-cloudformation/pom.xml b/powertools-cloudformation/pom.xml index 09e3299fd..cb06dc1f3 100644 --- a/powertools-cloudformation/pom.xml +++ b/powertools-cloudformation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Cloudformation</name> diff --git a/powertools-common/pom.xml b/powertools-common/pom.xml index 551fae8bc..75ef10beb 100644 --- a/powertools-common/pom.xml +++ b/powertools-common/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Common Internal Utilities</name> diff --git a/powertools-e2e-tests/handlers/batch/pom.xml b/powertools-e2e-tests/handlers/batch/pom.xml index f8e0a037f..3e89aadd2 100644 --- a/powertools-e2e-tests/handlers/batch/pom.xml +++ b/powertools-e2e-tests/handlers/batch/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-batch</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency-functional/pom.xml b/powertools-e2e-tests/handlers/idempotency-functional/pom.xml index 2b53dc275..b5669b21f 100644 --- a/powertools-e2e-tests/handlers/idempotency-functional/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-idempotency-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency-generics/pom.xml b/powertools-e2e-tests/handlers/idempotency-generics/pom.xml index 76e65edb1..21a658e6c 100644 --- a/powertools-e2e-tests/handlers/idempotency-generics/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency-generics/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-idempotency-generics</artifactId> diff --git a/powertools-e2e-tests/handlers/idempotency/pom.xml b/powertools-e2e-tests/handlers/idempotency/pom.xml index 36181ea01..921599bdb 100644 --- a/powertools-e2e-tests/handlers/idempotency/pom.xml +++ b/powertools-e2e-tests/handlers/idempotency/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-idempotency</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage-functional/pom.xml b/powertools-e2e-tests/handlers/largemessage-functional/pom.xml index d29017074..ddfe39a5e 100644 --- a/powertools-e2e-tests/handlers/largemessage-functional/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-largemessage-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage/pom.xml b/powertools-e2e-tests/handlers/largemessage/pom.xml index 53b1e7c10..bee253988 100644 --- a/powertools-e2e-tests/handlers/largemessage/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-largemessage</artifactId> diff --git a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml index 9f6f23389..5ef7e1963 100644 --- a/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml +++ b/powertools-e2e-tests/handlers/largemessage_idempotent/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-large-msg-idempotent</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-functional/pom.xml b/powertools-e2e-tests/handlers/logging-functional/pom.xml index 4616af233..4ec6e5008 100644 --- a/powertools-e2e-tests/handlers/logging-functional/pom.xml +++ b/powertools-e2e-tests/handlers/logging-functional/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-logging-functional</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-log4j/pom.xml b/powertools-e2e-tests/handlers/logging-log4j/pom.xml index bba711163..022f029e6 100644 --- a/powertools-e2e-tests/handlers/logging-log4j/pom.xml +++ b/powertools-e2e-tests/handlers/logging-log4j/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-logging-log4j</artifactId> diff --git a/powertools-e2e-tests/handlers/logging-logback/pom.xml b/powertools-e2e-tests/handlers/logging-logback/pom.xml index bd442fe88..f8458db25 100644 --- a/powertools-e2e-tests/handlers/logging-logback/pom.xml +++ b/powertools-e2e-tests/handlers/logging-logback/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-logging-logback</artifactId> diff --git a/powertools-e2e-tests/handlers/metrics/pom.xml b/powertools-e2e-tests/handlers/metrics/pom.xml index 90704c6d9..ddc6ae1bd 100644 --- a/powertools-e2e-tests/handlers/metrics/pom.xml +++ b/powertools-e2e-tests/handlers/metrics/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-metrics</artifactId> diff --git a/powertools-e2e-tests/handlers/parameters/pom.xml b/powertools-e2e-tests/handlers/parameters/pom.xml index 670eeb9c0..fb2deb2aa 100644 --- a/powertools-e2e-tests/handlers/parameters/pom.xml +++ b/powertools-e2e-tests/handlers/parameters/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-parameters</artifactId> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index a9d3c3ab5..54f07d681 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -4,7 +4,7 @@ <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> <packaging>pom</packaging> <name>Handlers for End-to-End tests</name> <description>Fake handlers that use Powertools for AWS Lambda (Java).</description> diff --git a/powertools-e2e-tests/handlers/tracing/pom.xml b/powertools-e2e-tests/handlers/tracing/pom.xml index 89891df8c..9874ce986 100644 --- a/powertools-e2e-tests/handlers/tracing/pom.xml +++ b/powertools-e2e-tests/handlers/tracing/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-tracing</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml index 8e5e4dadb..14dbb9b13 100644 --- a/powertools-e2e-tests/handlers/validation-alb-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-alb-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-validation-alb-event</artifactId> diff --git a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml index 97e967c3b..290e47b13 100644 --- a/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml +++ b/powertools-e2e-tests/handlers/validation-apigw-event/pom.xml @@ -5,7 +5,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>e2e-test-handlers-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>e2e-test-handler-validation-apigw-event</artifactId> diff --git a/powertools-e2e-tests/pom.xml b/powertools-e2e-tests/pom.xml index bfd4350a0..fec4dec92 100644 --- a/powertools-e2e-tests/pom.xml +++ b/powertools-e2e-tests/pom.xml @@ -20,7 +20,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>powertools-e2e-tests</artifactId> diff --git a/powertools-idempotency/pom.xml b/powertools-idempotency/pom.xml index d15d3445d..cbe2384ba 100644 --- a/powertools-idempotency/pom.xml +++ b/powertools-idempotency/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>powertools-idempotency</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-core/pom.xml b/powertools-idempotency/powertools-idempotency-core/pom.xml index 801664b4a..4cba1956f 100644 --- a/powertools-idempotency/powertools-idempotency-core/pom.xml +++ b/powertools-idempotency/powertools-idempotency-core/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>powertools-idempotency-core</artifactId> diff --git a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml index a9cf5739b..d223e0d2f 100644 --- a/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml +++ b/powertools-idempotency/powertools-idempotency-dynamodb/pom.xml @@ -21,7 +21,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-idempotency</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>powertools-idempotency-dynamodb</artifactId> diff --git a/powertools-kafka/pom.xml b/powertools-kafka/pom.xml index 82f6b8021..c71ef94f6 100644 --- a/powertools-kafka/pom.xml +++ b/powertools-kafka/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>powertools-kafka</artifactId> diff --git a/powertools-large-messages/pom.xml b/powertools-large-messages/pom.xml index d72877552..ad5910ec1 100644 --- a/powertools-large-messages/pom.xml +++ b/powertools-large-messages/pom.xml @@ -23,7 +23,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>powertools-large-messages</artifactId> diff --git a/powertools-logging/pom.xml b/powertools-logging/pom.xml index 923d6d133..200358e0b 100644 --- a/powertools-logging/pom.xml +++ b/powertools-logging/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Logging</name> diff --git a/powertools-logging/powertools-logging-log4j/pom.xml b/powertools-logging/powertools-logging-log4j/pom.xml index 19a8b9428..aa4aca181 100644 --- a/powertools-logging/powertools-logging-log4j/pom.xml +++ b/powertools-logging/powertools-logging-log4j/pom.xml @@ -7,7 +7,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-logging/powertools-logging-logback/pom.xml b/powertools-logging/powertools-logging-logback/pom.xml index 7ed1f1a17..dbf7f5207 100644 --- a/powertools-logging/powertools-logging-logback/pom.xml +++ b/powertools-logging/powertools-logging-logback/pom.xml @@ -6,7 +6,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-metrics/pom.xml b/powertools-metrics/pom.xml index 86bdcc560..5f6c971e3 100644 --- a/powertools-metrics/pom.xml +++ b/powertools-metrics/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Metrics</name> diff --git a/powertools-parameters/pom.xml b/powertools-parameters/pom.xml index 78234b5cc..124e22186 100644 --- a/powertools-parameters/pom.xml +++ b/powertools-parameters/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>powertools-parameters</artifactId> diff --git a/powertools-parameters/powertools-parameters-appconfig/pom.xml b/powertools-parameters/powertools-parameters-appconfig/pom.xml index 3c38963a1..406f715d3 100644 --- a/powertools-parameters/powertools-parameters-appconfig/pom.xml +++ b/powertools-parameters/powertools-parameters-appconfig/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-dynamodb/pom.xml b/powertools-parameters/powertools-parameters-dynamodb/pom.xml index b9e48567a..eb5604046 100644 --- a/powertools-parameters/powertools-parameters-dynamodb/pom.xml +++ b/powertools-parameters/powertools-parameters-dynamodb/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-secrets/pom.xml b/powertools-parameters/powertools-parameters-secrets/pom.xml index c83c674d5..b9535269e 100644 --- a/powertools-parameters/powertools-parameters-secrets/pom.xml +++ b/powertools-parameters/powertools-parameters-secrets/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-ssm/pom.xml b/powertools-parameters/powertools-parameters-ssm/pom.xml index d23b84bf6..e0253e10b 100644 --- a/powertools-parameters/powertools-parameters-ssm/pom.xml +++ b/powertools-parameters/powertools-parameters-ssm/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-parameters/powertools-parameters-tests/pom.xml b/powertools-parameters/powertools-parameters-tests/pom.xml index 9b93b3f79..fa2542730 100644 --- a/powertools-parameters/powertools-parameters-tests/pom.xml +++ b/powertools-parameters/powertools-parameters-tests/pom.xml @@ -6,7 +6,7 @@ <parent> <groupId>software.amazon.lambda</groupId> <artifactId>powertools-parent</artifactId> - <version>2.8.0</version> + <version>2.9.0</version> <relativePath>../../pom.xml</relativePath> </parent> diff --git a/powertools-serialization/pom.xml b/powertools-serialization/pom.xml index 535f23190..81603cd4f 100644 --- a/powertools-serialization/pom.xml +++ b/powertools-serialization/pom.xml @@ -21,7 +21,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <artifactId>powertools-serialization</artifactId> diff --git a/powertools-tracing/pom.xml b/powertools-tracing/pom.xml index 9e5603d70..545633c50 100644 --- a/powertools-tracing/pom.xml +++ b/powertools-tracing/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Tracing</name> diff --git a/powertools-validation/pom.xml b/powertools-validation/pom.xml index 37063cf6d..8dfce6b6a 100644 --- a/powertools-validation/pom.xml +++ b/powertools-validation/pom.xml @@ -24,7 +24,7 @@ <parent> <artifactId>powertools-parent</artifactId> <groupId>software.amazon.lambda</groupId> - <version>2.8.0</version> + <version>2.9.0</version> </parent> <name>Powertools for AWS Lambda (Java) - Validation</name> From 058c61f57f172715328b2c76dc5a32b4fd765a1c Mon Sep 17 00:00:00 2001 From: Philipp Page <github@philipp.page> Date: Tue, 16 Dec 2025 11:46:06 +0100 Subject: [PATCH 570/577] docs: Announce end-of-life of version 1.x.x (#2333) --- docs/processes/versioning.md | 8 ++++---- docs/upgrade.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/processes/versioning.md b/docs/processes/versioning.md index bbb60f507..d20269001 100644 --- a/docs/processes/versioning.md +++ b/docs/processes/versioning.md @@ -55,7 +55,7 @@ To see the list of available major versions of Powertools for AWS Lambda and whe ### Version support matrix -| SDK | Major version | Current Phase | General Availability Date | Notes | -| -------------------------------- | ------------- | -------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------- | -| Powertools for AWS Lambda (Java) | 2.x | General Availability | 06/12/2025 | See [Release notes](https://github.com/aws-powertools/powertools-lambda-java/releases/tag/v2.0.0) | -| Powertools for AWS Lambda (Java) | 1.x | Maintenance | 11/04/2020 | End-of-support: December 12, 2025. See [upgrade guide](https://docs.powertools.aws.dev/lambda/java/latest/upgrade/) | +| SDK | Major version | Current Phase | General Availability Date | Notes | +| -------------------------------- | ------------- | -------------------- | ------------------------- | ------------------------------------------------------------------------------------------------- | +| Powertools for AWS Lambda (Java) | 2.x | General Availability | 06/12/2025 | See [Release notes](https://github.com/aws-powertools/powertools-lambda-java/releases/tag/v2.0.0) | +| Powertools for AWS Lambda (Java) | 1.x | End-of-life | 11/04/2020 | See [announcement](https://github.com/aws-powertools/powertools-lambda-java/issues/1895) | diff --git a/docs/upgrade.md b/docs/upgrade.md index 5b6d16d99..c9662a3db 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -7,7 +7,7 @@ description: Guide to update between major Powertools for AWS Lambda (Java) vers <!-- prettier-ignore-start --> !!! warning "End of support notice" - On December 12th, 2025, Powertools for AWS Lambda (Java) v1 will reach end of support and will no longer receive updates or releases. If you are still using v1, we strongly recommend you to read our upgrade guide and update to the latest version. + On December 12th, 2025, Powertools for AWS Lambda (Java) v1 reached end-of-life and will no longer receive updates or releases. If you are still using v1, we strongly recommend you to read our upgrade guide and update to the latest version. Refer to [our announcement](https://github.com/aws-powertools/powertools-lambda-java/issues/1895) for details. <!-- prettier-ignore-end --> Given our commitment to all of our customers using Powertools for AWS Lambda (Java), we will keep [Maven Central](https://central.sonatype.com/search?q=powertools){target="\_blank"} `v1` releases and a `v1` documentation archive to prevent any disruption. From df51f8b56ce63af4e2fc86a31ba90daaf2a9d38b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Dec 2025 14:23:43 +0000 Subject: [PATCH 571/577] chore: bump aws.sdk.version from 2.39.1 to 2.40.9 (#2335) Bumps `aws.sdk.version` from 2.39.1 to 2.40.9. Updates `software.amazon.awssdk:bom` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:http-client-spi` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:url-connection-client` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:s3` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:dynamodb` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:lambda` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:kinesis` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:cloudwatch` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:xray` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:sqs` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:cloudformation` from 2.39.1 to 2.40.9 Updates `software.amazon.awssdk:sts` from 2.39.1 to 2.40.9 --- updated-dependencies: - dependency-name: software.amazon.awssdk:bom dependency-version: 2.40.9 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:http-client-spi dependency-version: 2.40.9 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:url-connection-client dependency-version: 2.40.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:s3 dependency-version: 2.40.9 dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:dynamodb dependency-version: 2.40.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:lambda dependency-version: 2.40.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:kinesis dependency-version: 2.40.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudwatch dependency-version: 2.40.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:xray dependency-version: 2.40.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sqs dependency-version: 2.40.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:cloudformation dependency-version: 2.40.9 dependency-type: direct:development update-type: version-update:semver-minor - dependency-name: software.amazon.awssdk:sts dependency-version: 2.40.9 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-cloudformation/pom.xml | 2 +- pom.xml | 2 +- powertools-e2e-tests/handlers/pom.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/powertools-examples-cloudformation/pom.xml b/examples/powertools-examples-cloudformation/pom.xml index 8581a6ceb..212c0966b 100644 --- a/examples/powertools-examples-cloudformation/pom.xml +++ b/examples/powertools-examples-cloudformation/pom.xml @@ -14,7 +14,7 @@ <maven.compiler.target>11</maven.compiler.target> <lambda.core.version>1.4.0</lambda.core.version> <lambda.events.version>3.16.1</lambda.events.version> - <aws.sdk.version>2.39.1</aws.sdk.version> + <aws.sdk.version>2.40.9</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> </properties> diff --git a/pom.xml b/pom.xml index b300e911d..a7b3d2fee 100644 --- a/pom.xml +++ b/pom.xml @@ -85,7 +85,7 @@ <log4j.version>2.25.2</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.1</jackson.version> - <aws.sdk.version>2.39.1</aws.sdk.version> + <aws.sdk.version>2.40.9</aws.sdk.version> <aws.xray.recorder.version>2.20.0</aws.xray.recorder.version> <payloadoffloading-common.version>2.2.0</payloadoffloading-common.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> diff --git a/powertools-e2e-tests/handlers/pom.xml b/powertools-e2e-tests/handlers/pom.xml index 54f07d681..477b49dc0 100644 --- a/powertools-e2e-tests/handlers/pom.xml +++ b/powertools-e2e-tests/handlers/pom.xml @@ -19,7 +19,7 @@ <maven.shade.version>3.6.1</maven.shade.version> <aspectj.plugin.version>1.14.1</aspectj.plugin.version> <maven.compiler.version>3.14.1</maven.compiler.version> - <aws.sdk.version>2.39.1</aws.sdk.version> + <aws.sdk.version>2.40.9</aws.sdk.version> <aspectj.version>1.9.20.1</aspectj.version> <maven.deploy.skip>true</maven.deploy.skip> </properties> From e8b1bb7cd74ab69a2c98c1afc0299ad6e683ae5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Dec 2025 14:24:37 +0000 Subject: [PATCH 572/577] chore: bump org.mockito:mockito-junit-jupiter from 5.20.0 to 5.21.0 (#2336) Bumps [org.mockito:mockito-junit-jupiter](https://github.com/mockito/mockito) from 5.20.0 to 5.21.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.20.0...v5.21.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-junit-jupiter dependency-version: 5.21.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a7b3d2fee..6188b47a4 100644 --- a/pom.xml +++ b/pom.xml @@ -114,7 +114,7 @@ <versions-maven-plugin.version>2.20.1</versions-maven-plugin.version> <elastic.version>1.7.0</elastic.version> <mockito.version>5.20.0</mockito.version> - <mockito-junit-jupiter.version>5.20.0</mockito-junit-jupiter.version> + <mockito-junit-jupiter.version>5.21.0</mockito-junit-jupiter.version> <junit-pioneer.version>2.3.0</junit-pioneer.version> <crac.version>1.5.0</crac.version> From 9a18c5d5356053993e60bfdc3a4a94212b9d68d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Dec 2025 14:24:48 +0000 Subject: [PATCH 573/577] chore: bump actions/upload-artifact from 5.0.0 to 6.0.0 (#2338) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5.0.0 to 6.0.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/330a01c490aca151604b8cf639adc76d48f6c5d4...b7c566a772e6b6bfb58ed0dc250532a479d7789f) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- .github/workflows/security-scorecard.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c9b2d80c6..9e52301dd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -112,7 +112,7 @@ jobs: snapshot: ${{ inputs.snapshot}} - id: upload_source name: Upload artifacts - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: if-no-files-found: error name: source diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index 7f3286dfe..f9aaaea52 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -46,7 +46,7 @@ jobs: publish_results: true repo_token: ${{ secrets.SCORECARD_TOKEN }} - name: Upload Results - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: SARIF file path: results.sarif From 9ee9a95081f1559fa86f04221cbf6aa5b8c692dd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Dec 2025 14:24:59 +0000 Subject: [PATCH 574/577] chore: bump actions/download-artifact from 6.0.0 to 7.0.0 (#2339) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6.0.0 to 7.0.0. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/018cc2cf5baa6db3ef3c5f8a56943fffe632ef53...37930b1c2abaa49bbe596cd826c3c89aef350131) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9e52301dd..630b91321 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -133,7 +133,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v4.6.1 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v4.6.1 with: name: source - name: Setup Java @@ -168,7 +168,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v4.6.1 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v4.6.1 with: name: source - name: Setup Java @@ -191,7 +191,7 @@ jobs: steps: - id: download_source name: Download artifacts - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v4.6.1 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v4.6.1 with: name: source - name: Setup Java @@ -229,7 +229,7 @@ jobs: ref: ${{ env.RELEASE_COMMIT }} - id: download_source name: Download artifacts - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v4.6.1 + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v4.6.1 with: name: source - id: setup-git From ad640f7a61385f20208c8dc3a0296e162934e138 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Dec 2025 14:25:08 +0000 Subject: [PATCH 575/577] chore: bump github/codeql-action from 4.31.8 to 4.31.9 (#2340) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.8 to 4.31.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/1b168cd39490f61582a9beae412bb7057a6b2c4e...5d4e8d1aca955e8d8589aabd499c5cae939e33c7) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-scorecard.yml b/.github/workflows/security-scorecard.yml index f9aaaea52..b91e78c69 100644 --- a/.github/workflows/security-scorecard.yml +++ b/.github/workflows/security-scorecard.yml @@ -52,6 +52,6 @@ jobs: path: results.sarif retention-days: 5 - name: Upload to Code-Scanning - uses: github/codeql-action/upload-sarif@1b168cd39490f61582a9beae412bb7057a6b2c4e # v3.29.5 + uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v3.29.5 with: sarif_file: results.sarif From 21e1fcffc3793c51235bcfd6778c483d57320dae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Dec 2025 14:25:44 +0000 Subject: [PATCH 576/577] chore: bump sam/build-java25 (#2342) Bumps sam/build-java25 from `b34fc78` to `bffac7d`. --- updated-dependencies: - dependency-name: sam/build-java25 dependency-version: bffac7de6e418a93d2aefc1e8e7c79eda0971e7a026725fe618b58ddfba7a128 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- powertools-e2e-tests/src/test/resources/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powertools-e2e-tests/src/test/resources/docker/Dockerfile b/powertools-e2e-tests/src/test/resources/docker/Dockerfile index fbefe46dd..1ceb29aa0 100644 --- a/powertools-e2e-tests/src/test/resources/docker/Dockerfile +++ b/powertools-e2e-tests/src/test/resources/docker/Dockerfile @@ -1,5 +1,5 @@ # Use the official AWS SAM base image for Java 25 -FROM public.ecr.aws/sam/build-java25@sha256:b34fc789a70464f080232ee96590a6d0c7249eb59b1c33deccaae08a882cac23 +FROM public.ecr.aws/sam/build-java25@sha256:bffac7de6e418a93d2aefc1e8e7c79eda0971e7a026725fe618b58ddfba7a128 # Install GraalVM dependencies RUN curl -4 -L https://download.oracle.com/graalvm/25/latest/graalvm-jdk-25_linux-x64_bin.tar.gz | tar -xvz From 54fe0be69938dbecb0d4efaa6c0152ee20c34eac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 21 Dec 2025 14:25:57 +0000 Subject: [PATCH 577/577] chore: bump org.apache.logging.log4j:log4j-core from 2.25.2 to 2.25.3 (#2344) Bumps org.apache.logging.log4j:log4j-core from 2.25.2 to 2.25.3. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-version: 2.25.3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- examples/powertools-examples-core-utilities/cdk/app/pom.xml | 2 +- examples/powertools-examples-core-utilities/sam-graalvm/pom.xml | 2 +- examples/powertools-examples-parameters/sam-graalvm/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/powertools-examples-core-utilities/cdk/app/pom.xml b/examples/powertools-examples-core-utilities/cdk/app/pom.xml index 28be679a5..c02b73026 100644 --- a/examples/powertools-examples-core-utilities/cdk/app/pom.xml +++ b/examples/powertools-examples-core-utilities/cdk/app/pom.xml @@ -11,7 +11,7 @@ <packaging>jar</packaging> <properties> - <log4j.version>2.25.2</log4j.version> + <log4j.version>2.25.3</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml index e7a3f202d..eea0357e9 100644 --- a/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml +++ b/examples/powertools-examples-core-utilities/sam-graalvm/pom.xml @@ -9,7 +9,7 @@ <packaging>jar</packaging> <properties> - <log4j.version>2.25.2</log4j.version> + <log4j.version>2.25.3</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/examples/powertools-examples-parameters/sam-graalvm/pom.xml b/examples/powertools-examples-parameters/sam-graalvm/pom.xml index 7fc652bca..2aaffd9d1 100644 --- a/examples/powertools-examples-parameters/sam-graalvm/pom.xml +++ b/examples/powertools-examples-parameters/sam-graalvm/pom.xml @@ -8,7 +8,7 @@ <name>Powertools for AWS Lambda (Java) - Examples - Parameters GraalVM</name> <properties> - <log4j.version>2.25.2</log4j.version> + <log4j.version>2.25.3</log4j.version> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <aspectj.version>1.9.20.1</aspectj.version> diff --git a/pom.xml b/pom.xml index 6188b47a4..e6cf78b14 100644 --- a/pom.xml +++ b/pom.xml @@ -82,7 +82,7 @@ <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <maven.deploy.plugin.version>3.1.2</maven.deploy.plugin.version> - <log4j.version>2.25.2</log4j.version> + <log4j.version>2.25.3</log4j.version> <slf4j.version>2.0.17</slf4j.version> <jackson.version>2.20.1</jackson.version> <aws.sdk.version>2.40.9</aws.sdk.version>